| Michael Buesch | 424047e | 2008-01-09 16:13:56 +0100 | [diff] [blame] | 1 | /* | 
|  | 2 |  | 
|  | 3 | Broadcom B43 wireless driver | 
|  | 4 | IEEE 802.11n PHY support | 
|  | 5 |  | 
|  | 6 | Copyright (c) 2008 Michael Buesch <mb@bu3sch.de> | 
|  | 7 |  | 
|  | 8 | This program is free software; you can redistribute it and/or modify | 
|  | 9 | it under the terms of the GNU General Public License as published by | 
|  | 10 | the Free Software Foundation; either version 2 of the License, or | 
|  | 11 | (at your option) any later version. | 
|  | 12 |  | 
|  | 13 | This program is distributed in the hope that it will be useful, | 
|  | 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 16 | GNU General Public License for more details. | 
|  | 17 |  | 
|  | 18 | You should have received a copy of the GNU General Public License | 
|  | 19 | along with this program; see the file COPYING.  If not, write to | 
|  | 20 | the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, | 
|  | 21 | Boston, MA 02110-1301, USA. | 
|  | 22 |  | 
|  | 23 | */ | 
|  | 24 |  | 
| John W. Linville | 819d772 | 2008-01-17 16:57:10 -0500 | [diff] [blame] | 25 | #include <linux/delay.h> | 
|  | 26 | #include <linux/types.h> | 
|  | 27 |  | 
| Michael Buesch | 424047e | 2008-01-09 16:13:56 +0100 | [diff] [blame] | 28 | #include "b43.h" | 
|  | 29 | #include "nphy.h" | 
| Michael Buesch | 53a6e23 | 2008-01-13 21:23:44 +0100 | [diff] [blame] | 30 | #include "tables_nphy.h" | 
| Michael Buesch | 424047e | 2008-01-09 16:13:56 +0100 | [diff] [blame] | 31 |  | 
|  | 32 |  | 
| Michael Buesch | 53a6e23 | 2008-01-13 21:23:44 +0100 | [diff] [blame] | 33 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | 
|  | 34 | {//TODO | 
|  | 35 | } | 
|  | 36 |  | 
|  | 37 | void b43_nphy_xmitpower(struct b43_wldev *dev) | 
|  | 38 | {//TODO | 
|  | 39 | } | 
|  | 40 |  | 
| Michael Buesch | d159131 | 2008-01-14 00:05:57 +0100 | [diff] [blame] | 41 | static void b43_chantab_radio_upload(struct b43_wldev *dev, | 
|  | 42 | const struct b43_nphy_channeltab_entry *e) | 
|  | 43 | { | 
|  | 44 | b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref); | 
|  | 45 | b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); | 
|  | 46 | b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); | 
|  | 47 | b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); | 
|  | 48 | b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1); | 
|  | 49 | b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2); | 
|  | 50 | b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); | 
|  | 51 | b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); | 
|  | 52 | b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); | 
|  | 53 | b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); | 
|  | 54 | b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); | 
|  | 55 | b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); | 
|  | 56 | b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); | 
|  | 57 | b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); | 
|  | 58 | b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); | 
|  | 59 | b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); | 
|  | 60 | b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); | 
|  | 61 | b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); | 
|  | 62 | b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); | 
|  | 63 | b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); | 
|  | 64 | b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); | 
|  | 65 | b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); | 
|  | 66 | } | 
|  | 67 |  | 
|  | 68 | static void b43_chantab_phy_upload(struct b43_wldev *dev, | 
|  | 69 | const struct b43_nphy_channeltab_entry *e) | 
|  | 70 | { | 
|  | 71 | b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); | 
|  | 72 | b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); | 
|  | 73 | b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3); | 
|  | 74 | b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4); | 
|  | 75 | b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5); | 
|  | 76 | b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); | 
|  | 77 | } | 
|  | 78 |  | 
|  | 79 | static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | 
|  | 80 | { | 
|  | 81 | //TODO | 
|  | 82 | } | 
|  | 83 |  | 
| Michael Buesch | 53a6e23 | 2008-01-13 21:23:44 +0100 | [diff] [blame] | 84 | /* Tune the hardware to a new channel. Don't call this directly. | 
|  | 85 | * Use b43_radio_selectchannel() */ | 
| Michael Buesch | d159131 | 2008-01-14 00:05:57 +0100 | [diff] [blame] | 86 | int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel) | 
| Michael Buesch | 53a6e23 | 2008-01-13 21:23:44 +0100 | [diff] [blame] | 87 | { | 
| Michael Buesch | d159131 | 2008-01-14 00:05:57 +0100 | [diff] [blame] | 88 | const struct b43_nphy_channeltab_entry *tabent; | 
| Michael Buesch | 53a6e23 | 2008-01-13 21:23:44 +0100 | [diff] [blame] | 89 |  | 
| Michael Buesch | d159131 | 2008-01-14 00:05:57 +0100 | [diff] [blame] | 90 | tabent = b43_nphy_get_chantabent(dev, channel); | 
|  | 91 | if (!tabent) | 
|  | 92 | return -ESRCH; | 
|  | 93 |  | 
|  | 94 | //FIXME enable/disable band select upper20 in RXCTL | 
|  | 95 | if (0 /*FIXME 5Ghz*/) | 
|  | 96 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20); | 
|  | 97 | else | 
|  | 98 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50); | 
|  | 99 | b43_chantab_radio_upload(dev, tabent); | 
|  | 100 | udelay(50); | 
|  | 101 | b43_radio_write16(dev, B2055_VCO_CAL10, 5); | 
|  | 102 | b43_radio_write16(dev, B2055_VCO_CAL10, 45); | 
|  | 103 | b43_radio_write16(dev, B2055_VCO_CAL10, 65); | 
|  | 104 | udelay(300); | 
|  | 105 | if (0 /*FIXME 5Ghz*/) | 
|  | 106 | b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); | 
|  | 107 | else | 
|  | 108 | b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); | 
|  | 109 | b43_chantab_phy_upload(dev, tabent); | 
|  | 110 | b43_nphy_tx_power_fix(dev); | 
|  | 111 |  | 
|  | 112 | return 0; | 
| Michael Buesch | 53a6e23 | 2008-01-13 21:23:44 +0100 | [diff] [blame] | 113 | } | 
|  | 114 |  | 
|  | 115 | static void b43_radio_init2055_pre(struct b43_wldev *dev) | 
|  | 116 | { | 
|  | 117 | b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, | 
|  | 118 | ~B43_NPHY_RFCTL_CMD_PORFORCE); | 
|  | 119 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, | 
|  | 120 | B43_NPHY_RFCTL_CMD_CHIP0PU | | 
|  | 121 | B43_NPHY_RFCTL_CMD_OEPORFORCE); | 
|  | 122 | b43_phy_set(dev, B43_NPHY_RFCTL_CMD, | 
|  | 123 | B43_NPHY_RFCTL_CMD_PORFORCE); | 
|  | 124 | } | 
|  | 125 |  | 
|  | 126 | static void b43_radio_init2055_post(struct b43_wldev *dev) | 
|  | 127 | { | 
|  | 128 | struct ssb_sprom *sprom = &(dev->dev->bus->sprom); | 
|  | 129 | struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); | 
|  | 130 | int i; | 
|  | 131 | u16 val; | 
|  | 132 |  | 
|  | 133 | b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); | 
|  | 134 | msleep(1); | 
|  | 135 | if ((sprom->revision != 4) || !(sprom->boardflags_hi & 0x0002)) { | 
|  | 136 | if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || | 
|  | 137 | (binfo->type != 0x46D) || | 
|  | 138 | (binfo->rev < 0x41)) { | 
|  | 139 | b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); | 
|  | 140 | b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); | 
|  | 141 | msleep(1); | 
|  | 142 | } | 
|  | 143 | } | 
|  | 144 | b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C); | 
|  | 145 | msleep(1); | 
|  | 146 | b43_radio_write16(dev, B2055_CAL_MISC, 0x3C); | 
|  | 147 | msleep(1); | 
|  | 148 | b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); | 
|  | 149 | msleep(1); | 
|  | 150 | b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); | 
|  | 151 | msleep(1); | 
|  | 152 | b43_radio_set(dev, B2055_CAL_MISC, 0x1); | 
|  | 153 | msleep(1); | 
|  | 154 | b43_radio_set(dev, B2055_CAL_MISC, 0x40); | 
|  | 155 | msleep(1); | 
|  | 156 | for (i = 0; i < 100; i++) { | 
|  | 157 | val = b43_radio_read16(dev, B2055_CAL_COUT2); | 
|  | 158 | if (val & 0x80) | 
|  | 159 | break; | 
|  | 160 | udelay(10); | 
|  | 161 | } | 
|  | 162 | msleep(1); | 
|  | 163 | b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); | 
|  | 164 | msleep(1); | 
|  | 165 | b43_radio_selectchannel(dev, dev->phy.channel, 0); | 
|  | 166 | b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); | 
|  | 167 | b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); | 
|  | 168 | b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); | 
|  | 169 | b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83); | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | /* Initialize a Broadcom 2055 N-radio */ | 
|  | 173 | static void b43_radio_init2055(struct b43_wldev *dev) | 
|  | 174 | { | 
|  | 175 | b43_radio_init2055_pre(dev); | 
|  | 176 | if (b43_status(dev) < B43_STAT_INITIALIZED) | 
|  | 177 | b2055_upload_inittab(dev, 0, 1); | 
|  | 178 | else | 
|  | 179 | b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0); | 
|  | 180 | b43_radio_init2055_post(dev); | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | void b43_nphy_radio_turn_on(struct b43_wldev *dev) | 
|  | 184 | { | 
|  | 185 | b43_radio_init2055(dev); | 
|  | 186 | } | 
|  | 187 |  | 
|  | 188 | void b43_nphy_radio_turn_off(struct b43_wldev *dev) | 
|  | 189 | { | 
|  | 190 | b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, | 
|  | 191 | ~B43_NPHY_RFCTL_CMD_EN); | 
|  | 192 | } | 
|  | 193 |  | 
| Michael Buesch | 95b66ba | 2008-01-18 01:09:25 +0100 | [diff] [blame] | 194 | #define ntab_upload(dev, offset, data) do { \ | 
|  | 195 | unsigned int i;						\ | 
|  | 196 | for (i = 0; i < (offset##_SIZE); i++)			\ | 
|  | 197 | b43_ntab_write(dev, (offset) + i, (data)[i]);	\ | 
|  | 198 | } while (0) | 
|  | 199 |  | 
|  | 200 | /* Upload the N-PHY tables. */ | 
|  | 201 | static void b43_nphy_tables_init(struct b43_wldev *dev) | 
|  | 202 | { | 
|  | 203 | /* Static tables */ | 
|  | 204 | ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct); | 
|  | 205 | ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup); | 
|  | 206 | ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap); | 
|  | 207 | ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn); | 
|  | 208 | ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel); | 
|  | 209 | ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot); | 
|  | 210 | ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt); | 
|  | 211 | ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0); | 
|  | 212 | ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1); | 
|  | 213 | ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0); | 
|  | 214 | ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1); | 
|  | 215 | ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi); | 
|  | 216 | ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest); | 
|  | 217 | ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs); | 
|  | 218 |  | 
|  | 219 | /* Volatile tables */ | 
|  | 220 | ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10); | 
|  | 221 | ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11); | 
|  | 222 | ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0); | 
|  | 223 | ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1); | 
|  | 224 | ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0); | 
|  | 225 | ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1); | 
|  | 226 | ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0); | 
|  | 227 | ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1); | 
|  | 228 | ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0); | 
|  | 229 | ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1); | 
|  | 230 | ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0); | 
|  | 231 | ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1); | 
|  | 232 | } | 
|  | 233 |  | 
|  | 234 | static void b43_nphy_workarounds(struct b43_wldev *dev) | 
|  | 235 | { | 
|  | 236 | struct b43_phy *phy = &dev->phy; | 
|  | 237 | unsigned int i; | 
|  | 238 |  | 
|  | 239 | b43_phy_set(dev, B43_NPHY_IQFLIP, | 
|  | 240 | B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); | 
| Michael Buesch | 95b66ba | 2008-01-18 01:09:25 +0100 | [diff] [blame] | 241 | if (1 /* FIXME band is 2.4GHz */) { | 
|  | 242 | b43_phy_set(dev, B43_NPHY_CLASSCTL, | 
|  | 243 | B43_NPHY_CLASSCTL_CCKEN); | 
|  | 244 | } else { | 
|  | 245 | b43_phy_mask(dev, B43_NPHY_CLASSCTL, | 
|  | 246 | ~B43_NPHY_CLASSCTL_CCKEN); | 
|  | 247 | } | 
|  | 248 | b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); | 
|  | 249 | b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8); | 
|  | 250 |  | 
|  | 251 | /* Fixup some tables */ | 
|  | 252 | b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA); | 
|  | 253 | b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA); | 
|  | 254 | b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); | 
|  | 255 | b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); | 
|  | 256 | b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0); | 
|  | 257 | b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0); | 
|  | 258 | b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); | 
|  | 259 | b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); | 
|  | 260 | b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800); | 
|  | 261 | b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800); | 
|  | 262 |  | 
|  | 263 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); | 
|  | 264 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); | 
|  | 265 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); | 
|  | 266 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); | 
|  | 267 |  | 
|  | 268 | //TODO set RF sequence | 
|  | 269 |  | 
|  | 270 | /* Set narrowband clip threshold */ | 
|  | 271 | b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66); | 
|  | 272 | b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66); | 
|  | 273 |  | 
|  | 274 | /* Set wideband clip 2 threshold */ | 
|  | 275 | b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, | 
|  | 276 | ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, | 
|  | 277 | 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT); | 
|  | 278 | b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, | 
|  | 279 | ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, | 
|  | 280 | 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT); | 
|  | 281 |  | 
|  | 282 | /* Set Clip 2 detect */ | 
|  | 283 | b43_phy_set(dev, B43_NPHY_C1_CGAINI, | 
|  | 284 | B43_NPHY_C1_CGAINI_CL2DETECT); | 
|  | 285 | b43_phy_set(dev, B43_NPHY_C2_CGAINI, | 
|  | 286 | B43_NPHY_C2_CGAINI_CL2DETECT); | 
|  | 287 |  | 
|  | 288 | if (0 /*FIXME*/) { | 
|  | 289 | /* Set dwell lengths */ | 
|  | 290 | b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43); | 
|  | 291 | b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43); | 
|  | 292 | b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9); | 
|  | 293 | b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9); | 
|  | 294 |  | 
|  | 295 | /* Set gain backoff */ | 
|  | 296 | b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, | 
|  | 297 | ~B43_NPHY_C1_CGAINI_GAINBKOFF, | 
|  | 298 | 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT); | 
|  | 299 | b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, | 
|  | 300 | ~B43_NPHY_C2_CGAINI_GAINBKOFF, | 
|  | 301 | 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT); | 
|  | 302 |  | 
|  | 303 | /* Set HPVGA2 index */ | 
|  | 304 | b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, | 
|  | 305 | ~B43_NPHY_C1_INITGAIN_HPVGA2, | 
|  | 306 | 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); | 
|  | 307 | b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, | 
|  | 308 | ~B43_NPHY_C2_INITGAIN_HPVGA2, | 
|  | 309 | 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); | 
|  | 310 |  | 
|  | 311 | //FIXME verify that the specs really mean to use autoinc here. | 
|  | 312 | for (i = 0; i < 3; i++) | 
|  | 313 | b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673); | 
|  | 314 | } | 
|  | 315 |  | 
|  | 316 | /* Set minimum gain value */ | 
|  | 317 | b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, | 
|  | 318 | ~B43_NPHY_C1_MINGAIN, | 
|  | 319 | 23 << B43_NPHY_C1_MINGAIN_SHIFT); | 
|  | 320 | b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, | 
|  | 321 | ~B43_NPHY_C2_MINGAIN, | 
|  | 322 | 23 << B43_NPHY_C2_MINGAIN_SHIFT); | 
|  | 323 |  | 
|  | 324 | if (phy->rev < 2) { | 
|  | 325 | b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, | 
|  | 326 | ~B43_NPHY_SCRAM_SIGCTL_SCM); | 
|  | 327 | } | 
|  | 328 |  | 
|  | 329 | /* Set phase track alpha and beta */ | 
|  | 330 | b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); | 
|  | 331 | b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); | 
|  | 332 | b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); | 
|  | 333 | b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); | 
|  | 334 | b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); | 
|  | 335 | b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); | 
|  | 336 | } | 
|  | 337 |  | 
|  | 338 | static void b43_nphy_reset_cca(struct b43_wldev *dev) | 
|  | 339 | { | 
|  | 340 | u16 bbcfg; | 
|  | 341 |  | 
|  | 342 | ssb_write32(dev->dev, SSB_TMSLOW, | 
|  | 343 | ssb_read32(dev->dev, SSB_TMSLOW) | SSB_TMSLOW_FGC); | 
|  | 344 | bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); | 
|  | 345 | b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTCCA); | 
|  | 346 | b43_phy_write(dev, B43_NPHY_BBCFG, | 
|  | 347 | bbcfg & ~B43_NPHY_BBCFG_RSTCCA); | 
|  | 348 | ssb_write32(dev->dev, SSB_TMSLOW, | 
|  | 349 | ssb_read32(dev->dev, SSB_TMSLOW) & ~SSB_TMSLOW_FGC); | 
|  | 350 | } | 
|  | 351 |  | 
|  | 352 | enum b43_nphy_rf_sequence { | 
|  | 353 | B43_RFSEQ_RX2TX, | 
|  | 354 | B43_RFSEQ_TX2RX, | 
|  | 355 | B43_RFSEQ_RESET2RX, | 
|  | 356 | B43_RFSEQ_UPDATE_GAINH, | 
|  | 357 | B43_RFSEQ_UPDATE_GAINL, | 
|  | 358 | B43_RFSEQ_UPDATE_GAINU, | 
|  | 359 | }; | 
|  | 360 |  | 
|  | 361 | static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, | 
|  | 362 | enum b43_nphy_rf_sequence seq) | 
|  | 363 | { | 
|  | 364 | static const u16 trigger[] = { | 
|  | 365 | [B43_RFSEQ_RX2TX]		= B43_NPHY_RFSEQTR_RX2TX, | 
|  | 366 | [B43_RFSEQ_TX2RX]		= B43_NPHY_RFSEQTR_TX2RX, | 
|  | 367 | [B43_RFSEQ_RESET2RX]		= B43_NPHY_RFSEQTR_RST2RX, | 
|  | 368 | [B43_RFSEQ_UPDATE_GAINH]	= B43_NPHY_RFSEQTR_UPGH, | 
|  | 369 | [B43_RFSEQ_UPDATE_GAINL]	= B43_NPHY_RFSEQTR_UPGL, | 
|  | 370 | [B43_RFSEQ_UPDATE_GAINU]	= B43_NPHY_RFSEQTR_UPGU, | 
|  | 371 | }; | 
|  | 372 | int i; | 
|  | 373 |  | 
|  | 374 | B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); | 
|  | 375 |  | 
|  | 376 | b43_phy_set(dev, B43_NPHY_RFSEQMODE, | 
|  | 377 | B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER); | 
|  | 378 | b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]); | 
|  | 379 | for (i = 0; i < 200; i++) { | 
|  | 380 | if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq])) | 
|  | 381 | goto ok; | 
|  | 382 | msleep(1); | 
|  | 383 | } | 
|  | 384 | b43err(dev->wl, "RF sequence status timeout\n"); | 
|  | 385 | ok: | 
|  | 386 | b43_phy_mask(dev, B43_NPHY_RFSEQMODE, | 
|  | 387 | ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER)); | 
|  | 388 | } | 
|  | 389 |  | 
|  | 390 | static void b43_nphy_bphy_init(struct b43_wldev *dev) | 
|  | 391 | { | 
|  | 392 | unsigned int i; | 
|  | 393 | u16 val; | 
|  | 394 |  | 
|  | 395 | val = 0x1E1F; | 
|  | 396 | for (i = 0; i < 14; i++) { | 
|  | 397 | b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); | 
|  | 398 | val -= 0x202; | 
|  | 399 | } | 
|  | 400 | val = 0x3E3F; | 
|  | 401 | for (i = 0; i < 16; i++) { | 
|  | 402 | b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val); | 
|  | 403 | val -= 0x202; | 
|  | 404 | } | 
|  | 405 | b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); | 
|  | 406 | } | 
|  | 407 |  | 
|  | 408 | /* RSSI Calibration */ | 
|  | 409 | static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type) | 
|  | 410 | { | 
|  | 411 | //TODO | 
|  | 412 | } | 
|  | 413 |  | 
| Michael Buesch | 424047e | 2008-01-09 16:13:56 +0100 | [diff] [blame] | 414 | int b43_phy_initn(struct b43_wldev *dev) | 
|  | 415 | { | 
| Michael Buesch | 95b66ba | 2008-01-18 01:09:25 +0100 | [diff] [blame] | 416 | struct b43_phy *phy = &dev->phy; | 
|  | 417 | u16 tmp; | 
| Michael Buesch | 424047e | 2008-01-09 16:13:56 +0100 | [diff] [blame] | 418 |  | 
| Michael Buesch | 95b66ba | 2008-01-18 01:09:25 +0100 | [diff] [blame] | 419 | //TODO: Spectral management | 
|  | 420 | b43_nphy_tables_init(dev); | 
|  | 421 |  | 
|  | 422 | /* Clear all overrides */ | 
|  | 423 | b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); | 
|  | 424 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); | 
|  | 425 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); | 
|  | 426 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); | 
|  | 427 | b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); | 
|  | 428 | b43_phy_mask(dev, B43_NPHY_RFSEQMODE, | 
|  | 429 | ~(B43_NPHY_RFSEQMODE_CAOVER | | 
|  | 430 | B43_NPHY_RFSEQMODE_TROVER)); | 
|  | 431 | b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); | 
|  | 432 |  | 
|  | 433 | tmp = (phy->rev < 2) ? 64 : 59; | 
|  | 434 | b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, | 
|  | 435 | ~B43_NPHY_BPHY_CTL3_SCALE, | 
|  | 436 | tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); | 
|  | 437 |  | 
|  | 438 | b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); | 
|  | 439 | b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); | 
|  | 440 |  | 
|  | 441 | b43_phy_write(dev, B43_NPHY_TXREALFD, 184); | 
|  | 442 | b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 200); | 
|  | 443 | b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 80); | 
|  | 444 | b43_phy_write(dev, B43_NPHY_C2_BCLIPBKOFF, 511); | 
|  | 445 |  | 
|  | 446 | //TODO MIMO-Config | 
|  | 447 | //TODO Update TX/RX chain | 
|  | 448 |  | 
|  | 449 | if (phy->rev < 2) { | 
|  | 450 | b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); | 
|  | 451 | b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); | 
|  | 452 | } | 
|  | 453 | b43_nphy_workarounds(dev); | 
|  | 454 | b43_nphy_reset_cca(dev); | 
|  | 455 |  | 
|  | 456 | ssb_write32(dev->dev, SSB_TMSLOW, | 
|  | 457 | ssb_read32(dev->dev, SSB_TMSLOW) | B43_TMSLOW_MACPHYCLKEN); | 
|  | 458 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); | 
|  | 459 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | 
|  | 460 |  | 
|  | 461 | b43_phy_read(dev, B43_NPHY_CLASSCTL); /* dummy read */ | 
|  | 462 | //TODO read core1/2 clip1 thres regs | 
|  | 463 |  | 
|  | 464 | if (1 /* FIXME Band is 2.4GHz */) | 
|  | 465 | b43_nphy_bphy_init(dev); | 
|  | 466 | //TODO disable TX power control | 
|  | 467 | //TODO Fix the TX power settings | 
|  | 468 | //TODO Init periodic calibration with reason 3 | 
|  | 469 | b43_nphy_rssi_cal(dev, 2); | 
|  | 470 | b43_nphy_rssi_cal(dev, 0); | 
|  | 471 | b43_nphy_rssi_cal(dev, 1); | 
|  | 472 | //TODO get TX gain | 
|  | 473 | //TODO init superswitch | 
|  | 474 | //TODO calibrate LO | 
|  | 475 | //TODO idle TSSI TX pctl | 
|  | 476 | //TODO TX power control power setup | 
|  | 477 | //TODO table writes | 
|  | 478 | //TODO TX power control coefficients | 
|  | 479 | //TODO enable TX power control | 
|  | 480 | //TODO control antenna selection | 
|  | 481 | //TODO init radar detection | 
|  | 482 | //TODO reset channel if changed | 
|  | 483 |  | 
|  | 484 | b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); | 
| Michael Buesch | 53a6e23 | 2008-01-13 21:23:44 +0100 | [diff] [blame] | 485 | return 0; | 
| Michael Buesch | 424047e | 2008-01-09 16:13:56 +0100 | [diff] [blame] | 486 | } |