phy_n.c revision 15931e318b27e85ea06f44d53abc3d3e6a3fc9ff
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 25#include <linux/delay.h> 26#include <linux/types.h> 27 28#include "b43.h" 29#include "phy_n.h" 30#include "tables_nphy.h" 31#include "main.h" 32 33struct nphy_txgains { 34 u16 txgm[2]; 35 u16 pga[2]; 36 u16 pad[2]; 37 u16 ipa[2]; 38}; 39 40struct nphy_iqcal_params { 41 u16 txgm; 42 u16 pga; 43 u16 pad; 44 u16 ipa; 45 u16 cal_gain; 46 u16 ncorr[5]; 47}; 48 49struct nphy_iq_est { 50 s32 iq0_prod; 51 u32 i0_pwr; 52 u32 q0_pwr; 53 s32 iq1_prod; 54 u32 i1_pwr; 55 u32 q1_pwr; 56}; 57 58void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) 59{//TODO 60} 61 62static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev) 63{//TODO 64} 65 66static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, 67 bool ignore_tssi) 68{//TODO 69 return B43_TXPWR_RES_DONE; 70} 71 72static void b43_chantab_radio_upload(struct b43_wldev *dev, 73 const struct b43_nphy_channeltab_entry *e) 74{ 75 b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref); 76 b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); 77 b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); 78 b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); 79 b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1); 80 b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2); 81 b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); 82 b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); 83 b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); 84 b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); 85 b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); 86 b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); 87 b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); 88 b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); 89 b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); 90 b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); 91 b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); 92 b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); 93 b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); 94 b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); 95 b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); 96 b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); 97} 98 99static void b43_chantab_phy_upload(struct b43_wldev *dev, 100 const struct b43_nphy_channeltab_entry *e) 101{ 102 b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); 103 b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); 104 b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3); 105 b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4); 106 b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5); 107 b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); 108} 109 110static void b43_nphy_tx_power_fix(struct b43_wldev *dev) 111{ 112 //TODO 113} 114 115/* Tune the hardware to a new channel. */ 116static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) 117{ 118 const struct b43_nphy_channeltab_entry *tabent; 119 120 tabent = b43_nphy_get_chantabent(dev, channel); 121 if (!tabent) 122 return -ESRCH; 123 124 //FIXME enable/disable band select upper20 in RXCTL 125 if (0 /*FIXME 5Ghz*/) 126 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20); 127 else 128 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50); 129 b43_chantab_radio_upload(dev, tabent); 130 udelay(50); 131 b43_radio_write16(dev, B2055_VCO_CAL10, 5); 132 b43_radio_write16(dev, B2055_VCO_CAL10, 45); 133 b43_radio_write16(dev, B2055_VCO_CAL10, 65); 134 udelay(300); 135 if (0 /*FIXME 5Ghz*/) 136 b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); 137 else 138 b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); 139 b43_chantab_phy_upload(dev, tabent); 140 b43_nphy_tx_power_fix(dev); 141 142 return 0; 143} 144 145static void b43_radio_init2055_pre(struct b43_wldev *dev) 146{ 147 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 148 ~B43_NPHY_RFCTL_CMD_PORFORCE); 149 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 150 B43_NPHY_RFCTL_CMD_CHIP0PU | 151 B43_NPHY_RFCTL_CMD_OEPORFORCE); 152 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 153 B43_NPHY_RFCTL_CMD_PORFORCE); 154} 155 156static void b43_radio_init2055_post(struct b43_wldev *dev) 157{ 158 struct ssb_sprom *sprom = &(dev->dev->bus->sprom); 159 struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); 160 int i; 161 u16 val; 162 163 b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); 164 msleep(1); 165 if ((sprom->revision != 4) || 166 !(sprom->boardflags_hi & B43_BFH_RSSIINV)) { 167 if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || 168 (binfo->type != 0x46D) || 169 (binfo->rev < 0x41)) { 170 b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); 171 b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); 172 msleep(1); 173 } 174 } 175 b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C); 176 msleep(1); 177 b43_radio_write16(dev, B2055_CAL_MISC, 0x3C); 178 msleep(1); 179 b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); 180 msleep(1); 181 b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); 182 msleep(1); 183 b43_radio_set(dev, B2055_CAL_MISC, 0x1); 184 msleep(1); 185 b43_radio_set(dev, B2055_CAL_MISC, 0x40); 186 msleep(1); 187 for (i = 0; i < 100; i++) { 188 val = b43_radio_read16(dev, B2055_CAL_COUT2); 189 if (val & 0x80) 190 break; 191 udelay(10); 192 } 193 msleep(1); 194 b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); 195 msleep(1); 196 nphy_channel_switch(dev, dev->phy.channel); 197 b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); 198 b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); 199 b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); 200 b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83); 201} 202 203/* Initialize a Broadcom 2055 N-radio */ 204static void b43_radio_init2055(struct b43_wldev *dev) 205{ 206 b43_radio_init2055_pre(dev); 207 if (b43_status(dev) < B43_STAT_INITIALIZED) 208 b2055_upload_inittab(dev, 0, 1); 209 else 210 b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0); 211 b43_radio_init2055_post(dev); 212} 213 214void b43_nphy_radio_turn_on(struct b43_wldev *dev) 215{ 216 b43_radio_init2055(dev); 217} 218 219void b43_nphy_radio_turn_off(struct b43_wldev *dev) 220{ 221 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 222 ~B43_NPHY_RFCTL_CMD_EN); 223} 224 225#define ntab_upload(dev, offset, data) do { \ 226 unsigned int i; \ 227 for (i = 0; i < (offset##_SIZE); i++) \ 228 b43_ntab_write(dev, (offset) + i, (data)[i]); \ 229 } while (0) 230 231/* 232 * Upload the N-PHY tables. 233 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables 234 */ 235static void b43_nphy_tables_init(struct b43_wldev *dev) 236{ 237 if (dev->phy.rev < 3) 238 b43_nphy_rev0_1_2_tables_init(dev); 239 else 240 b43_nphy_rev3plus_tables_init(dev); 241} 242 243static void b43_nphy_workarounds(struct b43_wldev *dev) 244{ 245 struct b43_phy *phy = &dev->phy; 246 unsigned int i; 247 248 b43_phy_set(dev, B43_NPHY_IQFLIP, 249 B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); 250 if (1 /* FIXME band is 2.4GHz */) { 251 b43_phy_set(dev, B43_NPHY_CLASSCTL, 252 B43_NPHY_CLASSCTL_CCKEN); 253 } else { 254 b43_phy_mask(dev, B43_NPHY_CLASSCTL, 255 ~B43_NPHY_CLASSCTL_CCKEN); 256 } 257 b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); 258 b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8); 259 260 /* Fixup some tables */ 261 b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA); 262 b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA); 263 b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); 264 b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); 265 b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0); 266 b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0); 267 b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); 268 b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); 269 b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800); 270 b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800); 271 272 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 273 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 274 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 275 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 276 277 //TODO set RF sequence 278 279 /* Set narrowband clip threshold */ 280 b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66); 281 b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66); 282 283 /* Set wideband clip 2 threshold */ 284 b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, 285 ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 286 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT); 287 b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, 288 ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 289 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT); 290 291 /* Set Clip 2 detect */ 292 b43_phy_set(dev, B43_NPHY_C1_CGAINI, 293 B43_NPHY_C1_CGAINI_CL2DETECT); 294 b43_phy_set(dev, B43_NPHY_C2_CGAINI, 295 B43_NPHY_C2_CGAINI_CL2DETECT); 296 297 if (0 /*FIXME*/) { 298 /* Set dwell lengths */ 299 b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43); 300 b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43); 301 b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9); 302 b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9); 303 304 /* Set gain backoff */ 305 b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, 306 ~B43_NPHY_C1_CGAINI_GAINBKOFF, 307 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT); 308 b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, 309 ~B43_NPHY_C2_CGAINI_GAINBKOFF, 310 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT); 311 312 /* Set HPVGA2 index */ 313 b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, 314 ~B43_NPHY_C1_INITGAIN_HPVGA2, 315 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); 316 b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, 317 ~B43_NPHY_C2_INITGAIN_HPVGA2, 318 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); 319 320 //FIXME verify that the specs really mean to use autoinc here. 321 for (i = 0; i < 3; i++) 322 b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673); 323 } 324 325 /* Set minimum gain value */ 326 b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, 327 ~B43_NPHY_C1_MINGAIN, 328 23 << B43_NPHY_C1_MINGAIN_SHIFT); 329 b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, 330 ~B43_NPHY_C2_MINGAIN, 331 23 << B43_NPHY_C2_MINGAIN_SHIFT); 332 333 if (phy->rev < 2) { 334 b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, 335 ~B43_NPHY_SCRAM_SIGCTL_SCM); 336 } 337 338 /* Set phase track alpha and beta */ 339 b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); 340 b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); 341 b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); 342 b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); 343 b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); 344 b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); 345} 346 347/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ 348static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) 349{ 350 struct b43_phy_n *nphy = dev->phy.n; 351 enum ieee80211_band band; 352 u16 tmp; 353 354 if (!enable) { 355 nphy->rfctrl_intc1_save = b43_phy_read(dev, 356 B43_NPHY_RFCTL_INTC1); 357 nphy->rfctrl_intc2_save = b43_phy_read(dev, 358 B43_NPHY_RFCTL_INTC2); 359 band = b43_current_band(dev->wl); 360 if (dev->phy.rev >= 3) { 361 if (band == IEEE80211_BAND_5GHZ) 362 tmp = 0x600; 363 else 364 tmp = 0x480; 365 } else { 366 if (band == IEEE80211_BAND_5GHZ) 367 tmp = 0x180; 368 else 369 tmp = 0x120; 370 } 371 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp); 372 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp); 373 } else { 374 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 375 nphy->rfctrl_intc1_save); 376 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 377 nphy->rfctrl_intc2_save); 378 } 379} 380 381/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */ 382static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev) 383{ 384 struct b43_phy_n *nphy = dev->phy.n; 385 u16 tmp; 386 enum ieee80211_band band = b43_current_band(dev->wl); 387 bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) || 388 (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ); 389 390 if (dev->phy.rev >= 3) { 391 if (ipa) { 392 tmp = 4; 393 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2, 394 (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); 395 } 396 397 tmp = 1; 398 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2, 399 (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); 400 } 401} 402 403/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ 404static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) 405{ 406 u32 tmslow; 407 408 if (dev->phy.type != B43_PHYTYPE_N) 409 return; 410 411 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); 412 if (force) 413 tmslow |= SSB_TMSLOW_FGC; 414 else 415 tmslow &= ~SSB_TMSLOW_FGC; 416 ssb_write32(dev->dev, SSB_TMSLOW, tmslow); 417} 418 419/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ 420static void b43_nphy_reset_cca(struct b43_wldev *dev) 421{ 422 u16 bbcfg; 423 424 b43_nphy_bmac_clock_fgc(dev, 1); 425 bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); 426 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA); 427 udelay(1); 428 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); 429 b43_nphy_bmac_clock_fgc(dev, 0); 430 /* TODO: N PHY Force RF Seq with argument 2 */ 431} 432 433/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ 434static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est, 435 u16 samps, u8 time, bool wait) 436{ 437 int i; 438 u16 tmp; 439 440 b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps); 441 b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time); 442 if (wait) 443 b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE); 444 else 445 b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE); 446 447 b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START); 448 449 for (i = 1000; i; i--) { 450 tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD); 451 if (!(tmp & B43_NPHY_IQEST_CMD_START)) { 452 est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) | 453 b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0); 454 est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) | 455 b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0); 456 est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) | 457 b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0); 458 459 est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) | 460 b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1); 461 est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) | 462 b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1); 463 est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) | 464 b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1); 465 return; 466 } 467 udelay(10); 468 } 469 memset(est, 0, sizeof(*est)); 470} 471 472/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */ 473static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, 474 struct b43_phy_n_iq_comp *pcomp) 475{ 476 if (write) { 477 b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0); 478 b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0); 479 b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1); 480 b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1); 481 } else { 482 pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0); 483 pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0); 484 pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1); 485 pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1); 486 } 487} 488 489/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ 490static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) 491{ 492 int i; 493 s32 iq; 494 u32 ii; 495 u32 qq; 496 int iq_nbits, qq_nbits; 497 int arsh, brsh; 498 u16 tmp, a, b; 499 500 struct nphy_iq_est est; 501 struct b43_phy_n_iq_comp old; 502 struct b43_phy_n_iq_comp new = { }; 503 bool error = false; 504 505 if (mask == 0) 506 return; 507 508 b43_nphy_rx_iq_coeffs(dev, false, &old); 509 b43_nphy_rx_iq_coeffs(dev, true, &new); 510 b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false); 511 new = old; 512 513 for (i = 0; i < 2; i++) { 514 if (i == 0 && (mask & 1)) { 515 iq = est.iq0_prod; 516 ii = est.i0_pwr; 517 qq = est.q0_pwr; 518 } else if (i == 1 && (mask & 2)) { 519 iq = est.iq1_prod; 520 ii = est.i1_pwr; 521 qq = est.q1_pwr; 522 } else { 523 B43_WARN_ON(1); 524 continue; 525 } 526 527 if (ii + qq < 2) { 528 error = true; 529 break; 530 } 531 532 iq_nbits = fls(abs(iq)); 533 qq_nbits = fls(qq); 534 535 arsh = iq_nbits - 20; 536 if (arsh >= 0) { 537 a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); 538 tmp = ii >> arsh; 539 } else { 540 a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); 541 tmp = ii << -arsh; 542 } 543 if (tmp == 0) { 544 error = true; 545 break; 546 } 547 a /= tmp; 548 549 brsh = qq_nbits - 11; 550 if (brsh >= 0) { 551 b = (qq << (31 - qq_nbits)); 552 tmp = ii >> brsh; 553 } else { 554 b = (qq << (31 - qq_nbits)); 555 tmp = ii << -brsh; 556 } 557 if (tmp == 0) { 558 error = true; 559 break; 560 } 561 b = int_sqrt(b / tmp - a * a) - (1 << 10); 562 563 if (i == 0 && (mask & 0x1)) { 564 if (dev->phy.rev >= 3) { 565 new.a0 = a & 0x3FF; 566 new.b0 = b & 0x3FF; 567 } else { 568 new.a0 = b & 0x3FF; 569 new.b0 = a & 0x3FF; 570 } 571 } else if (i == 1 && (mask & 0x2)) { 572 if (dev->phy.rev >= 3) { 573 new.a1 = a & 0x3FF; 574 new.b1 = b & 0x3FF; 575 } else { 576 new.a1 = b & 0x3FF; 577 new.b1 = a & 0x3FF; 578 } 579 } 580 } 581 582 if (error) 583 new = old; 584 585 b43_nphy_rx_iq_coeffs(dev, true, &new); 586} 587 588/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ 589static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) 590{ 591 u16 array[4]; 592 int i; 593 594 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50); 595 for (i = 0; i < 4; i++) 596 array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); 597 598 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]); 599 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]); 600 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]); 601 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]); 602} 603 604/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 605static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st) 606{ 607 b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]); 608 b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]); 609} 610 611/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 612static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) 613{ 614 clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES); 615 clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); 616} 617 618/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ 619static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) 620{ 621 u16 tmp; 622 623 if (dev->dev->id.revision == 16) 624 b43_mac_suspend(dev); 625 626 tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL); 627 tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN | 628 B43_NPHY_CLASSCTL_WAITEDEN); 629 tmp &= ~mask; 630 tmp |= (val & mask); 631 b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp); 632 633 if (dev->dev->id.revision == 16) 634 b43_mac_enable(dev); 635 636 return tmp; 637} 638 639/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */ 640static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) 641{ 642 struct b43_phy *phy = &dev->phy; 643 struct b43_phy_n *nphy = phy->n; 644 645 if (enable) { 646 u16 clip[] = { 0xFFFF, 0xFFFF }; 647 if (nphy->deaf_count++ == 0) { 648 nphy->classifier_state = b43_nphy_classifier(dev, 0, 0); 649 b43_nphy_classifier(dev, 0x7, 0); 650 b43_nphy_read_clip_detection(dev, nphy->clip_state); 651 b43_nphy_write_clip_detection(dev, clip); 652 } 653 b43_nphy_reset_cca(dev); 654 } else { 655 if (--nphy->deaf_count == 0) { 656 b43_nphy_classifier(dev, 0x7, nphy->classifier_state); 657 b43_nphy_write_clip_detection(dev, nphy->clip_state); 658 } 659 } 660} 661 662enum b43_nphy_rf_sequence { 663 B43_RFSEQ_RX2TX, 664 B43_RFSEQ_TX2RX, 665 B43_RFSEQ_RESET2RX, 666 B43_RFSEQ_UPDATE_GAINH, 667 B43_RFSEQ_UPDATE_GAINL, 668 B43_RFSEQ_UPDATE_GAINU, 669}; 670 671static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, 672 enum b43_nphy_rf_sequence seq) 673{ 674 static const u16 trigger[] = { 675 [B43_RFSEQ_RX2TX] = B43_NPHY_RFSEQTR_RX2TX, 676 [B43_RFSEQ_TX2RX] = B43_NPHY_RFSEQTR_TX2RX, 677 [B43_RFSEQ_RESET2RX] = B43_NPHY_RFSEQTR_RST2RX, 678 [B43_RFSEQ_UPDATE_GAINH] = B43_NPHY_RFSEQTR_UPGH, 679 [B43_RFSEQ_UPDATE_GAINL] = B43_NPHY_RFSEQTR_UPGL, 680 [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU, 681 }; 682 int i; 683 684 B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); 685 686 b43_phy_set(dev, B43_NPHY_RFSEQMODE, 687 B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER); 688 b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]); 689 for (i = 0; i < 200; i++) { 690 if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq])) 691 goto ok; 692 msleep(1); 693 } 694 b43err(dev->wl, "RF sequence status timeout\n"); 695ok: 696 b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 697 ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER)); 698} 699 700static void b43_nphy_bphy_init(struct b43_wldev *dev) 701{ 702 unsigned int i; 703 u16 val; 704 705 val = 0x1E1F; 706 for (i = 0; i < 14; i++) { 707 b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); 708 val -= 0x202; 709 } 710 val = 0x3E3F; 711 for (i = 0; i < 16; i++) { 712 b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val); 713 val -= 0x202; 714 } 715 b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); 716} 717 718/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ 719static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, 720 s8 offset, u8 core, u8 rail, u8 type) 721{ 722 u16 tmp; 723 bool core1or5 = (core == 1) || (core == 5); 724 bool core2or5 = (core == 2) || (core == 5); 725 726 offset = clamp_val(offset, -32, 31); 727 tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); 728 729 if (core1or5 && (rail == 0) && (type == 2)) 730 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp); 731 if (core1or5 && (rail == 1) && (type == 2)) 732 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp); 733 if (core2or5 && (rail == 0) && (type == 2)) 734 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp); 735 if (core2or5 && (rail == 1) && (type == 2)) 736 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp); 737 if (core1or5 && (rail == 0) && (type == 0)) 738 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp); 739 if (core1or5 && (rail == 1) && (type == 0)) 740 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp); 741 if (core2or5 && (rail == 0) && (type == 0)) 742 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp); 743 if (core2or5 && (rail == 1) && (type == 0)) 744 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp); 745 if (core1or5 && (rail == 0) && (type == 1)) 746 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp); 747 if (core1or5 && (rail == 1) && (type == 1)) 748 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp); 749 if (core2or5 && (rail == 0) && (type == 1)) 750 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp); 751 if (core2or5 && (rail == 1) && (type == 1)) 752 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp); 753 if (core1or5 && (rail == 0) && (type == 6)) 754 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp); 755 if (core1or5 && (rail == 1) && (type == 6)) 756 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp); 757 if (core2or5 && (rail == 0) && (type == 6)) 758 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp); 759 if (core2or5 && (rail == 1) && (type == 6)) 760 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp); 761 if (core1or5 && (rail == 0) && (type == 3)) 762 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp); 763 if (core1or5 && (rail == 1) && (type == 3)) 764 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp); 765 if (core2or5 && (rail == 0) && (type == 3)) 766 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp); 767 if (core2or5 && (rail == 1) && (type == 3)) 768 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp); 769 if (core1or5 && (type == 4)) 770 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp); 771 if (core2or5 && (type == 4)) 772 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp); 773 if (core1or5 && (type == 5)) 774 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp); 775 if (core2or5 && (type == 5)) 776 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp); 777} 778 779/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ 780static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type) 781{ 782 u16 val; 783 784 if (dev->phy.rev >= 3) { 785 /* TODO */ 786 } else { 787 if (type < 3) 788 val = 0; 789 else if (type == 6) 790 val = 1; 791 else if (type == 3) 792 val = 2; 793 else 794 val = 3; 795 796 val = (val << 12) | (val << 14); 797 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val); 798 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val); 799 800 if (type < 3) { 801 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF, 802 (type + 1) << 4); 803 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF, 804 (type + 1) << 4); 805 } 806 807 /* TODO use some definitions */ 808 if (code == 0) { 809 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0); 810 if (type < 3) { 811 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 812 0xFEC7, 0); 813 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 814 0xEFDC, 0); 815 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 816 0xFFFE, 0); 817 udelay(20); 818 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 819 0xFFFE, 0); 820 } 821 } else { 822 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 823 0x3000); 824 if (type < 3) { 825 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 826 0xFEC7, 0x0180); 827 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 828 0xEFDC, (code << 1 | 0x1021)); 829 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 830 0xFFFE, 0x0001); 831 udelay(20); 832 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 833 0xFFFE, 0); 834 } 835 } 836 } 837} 838 839/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ 840static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf) 841{ 842 int i; 843 for (i = 0; i < 2; i++) { 844 if (type == 2) { 845 if (i == 0) { 846 b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM, 847 0xFC, buf[0]); 848 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, 849 0xFC, buf[1]); 850 } else { 851 b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM, 852 0xFC, buf[2 * i]); 853 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, 854 0xFC, buf[2 * i + 1]); 855 } 856 } else { 857 if (i == 0) 858 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, 859 0xF3, buf[0] << 2); 860 else 861 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, 862 0xF3, buf[2 * i + 1] << 2); 863 } 864 } 865} 866 867/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ 868static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, 869 u8 nsamp) 870{ 871 int i; 872 int out; 873 u16 save_regs_phy[9]; 874 u16 s[2]; 875 876 if (dev->phy.rev >= 3) { 877 save_regs_phy[0] = b43_phy_read(dev, 878 B43_NPHY_RFCTL_LUT_TRSW_UP1); 879 save_regs_phy[1] = b43_phy_read(dev, 880 B43_NPHY_RFCTL_LUT_TRSW_UP2); 881 save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 882 save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 883 save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); 884 save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 885 save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); 886 save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); 887 } 888 889 b43_nphy_rssi_select(dev, 5, type); 890 891 if (dev->phy.rev < 2) { 892 save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL); 893 b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5); 894 } 895 896 for (i = 0; i < 4; i++) 897 buf[i] = 0; 898 899 for (i = 0; i < nsamp; i++) { 900 if (dev->phy.rev < 2) { 901 s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT); 902 s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT); 903 } else { 904 s[0] = b43_phy_read(dev, B43_NPHY_RSSI1); 905 s[1] = b43_phy_read(dev, B43_NPHY_RSSI2); 906 } 907 908 buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2; 909 buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2; 910 buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2; 911 buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2; 912 } 913 out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | 914 (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); 915 916 if (dev->phy.rev < 2) 917 b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); 918 919 if (dev->phy.rev >= 3) { 920 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 921 save_regs_phy[0]); 922 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 923 save_regs_phy[1]); 924 b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]); 925 b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]); 926 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]); 927 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); 928 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); 929 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); 930 } 931 932 return out; 933} 934 935/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ 936static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) 937{ 938 int i, j; 939 u8 state[4]; 940 u8 code, val; 941 u16 class, override; 942 u8 regs_save_radio[2]; 943 u16 regs_save_phy[2]; 944 s8 offset[4]; 945 946 u16 clip_state[2]; 947 u16 clip_off[2] = { 0xFFFF, 0xFFFF }; 948 s32 results_min[4] = { }; 949 u8 vcm_final[4] = { }; 950 s32 results[4][4] = { }; 951 s32 miniq[4][2] = { }; 952 953 if (type == 2) { 954 code = 0; 955 val = 6; 956 } else if (type < 2) { 957 code = 25; 958 val = 4; 959 } else { 960 B43_WARN_ON(1); 961 return; 962 } 963 964 class = b43_nphy_classifier(dev, 0, 0); 965 b43_nphy_classifier(dev, 7, 4); 966 b43_nphy_read_clip_detection(dev, clip_state); 967 b43_nphy_write_clip_detection(dev, clip_off); 968 969 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) 970 override = 0x140; 971 else 972 override = 0x110; 973 974 regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 975 regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX); 976 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override); 977 b43_radio_write16(dev, B2055_C1_PD_RXTX, val); 978 979 regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 980 regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX); 981 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override); 982 b43_radio_write16(dev, B2055_C2_PD_RXTX, val); 983 984 state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07; 985 state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07; 986 b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8); 987 b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8); 988 state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07; 989 state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07; 990 991 b43_nphy_rssi_select(dev, 5, type); 992 b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type); 993 b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type); 994 995 for (i = 0; i < 4; i++) { 996 u8 tmp[4]; 997 for (j = 0; j < 4; j++) 998 tmp[j] = i; 999 if (type != 1) 1000 b43_nphy_set_rssi_2055_vcm(dev, type, tmp); 1001 b43_nphy_poll_rssi(dev, type, results[i], 8); 1002 if (type < 2) 1003 for (j = 0; j < 2; j++) 1004 miniq[i][j] = min(results[i][2 * j], 1005 results[i][2 * j + 1]); 1006 } 1007 1008 for (i = 0; i < 4; i++) { 1009 s32 mind = 40; 1010 u8 minvcm = 0; 1011 s32 minpoll = 249; 1012 s32 curr; 1013 for (j = 0; j < 4; j++) { 1014 if (type == 2) 1015 curr = abs(results[j][i]); 1016 else 1017 curr = abs(miniq[j][i / 2] - code * 8); 1018 1019 if (curr < mind) { 1020 mind = curr; 1021 minvcm = j; 1022 } 1023 1024 if (results[j][i] < minpoll) 1025 minpoll = results[j][i]; 1026 } 1027 results_min[i] = minpoll; 1028 vcm_final[i] = minvcm; 1029 } 1030 1031 if (type != 1) 1032 b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final); 1033 1034 for (i = 0; i < 4; i++) { 1035 offset[i] = (code * 8) - results[vcm_final[i]][i]; 1036 1037 if (offset[i] < 0) 1038 offset[i] = -((abs(offset[i]) + 4) / 8); 1039 else 1040 offset[i] = (offset[i] + 4) / 8; 1041 1042 if (results_min[i] == 248) 1043 offset[i] = code - 32; 1044 1045 if (i % 2 == 0) 1046 b43_nphy_scale_offset_rssi(dev, 0, offset[i], 1, 0, 1047 type); 1048 else 1049 b43_nphy_scale_offset_rssi(dev, 0, offset[i], 2, 1, 1050 type); 1051 } 1052 1053 b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); 1054 b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[1]); 1055 1056 switch (state[2]) { 1057 case 1: 1058 b43_nphy_rssi_select(dev, 1, 2); 1059 break; 1060 case 4: 1061 b43_nphy_rssi_select(dev, 1, 0); 1062 break; 1063 case 2: 1064 b43_nphy_rssi_select(dev, 1, 1); 1065 break; 1066 default: 1067 b43_nphy_rssi_select(dev, 1, 1); 1068 break; 1069 } 1070 1071 switch (state[3]) { 1072 case 1: 1073 b43_nphy_rssi_select(dev, 2, 2); 1074 break; 1075 case 4: 1076 b43_nphy_rssi_select(dev, 2, 0); 1077 break; 1078 default: 1079 b43_nphy_rssi_select(dev, 2, 1); 1080 break; 1081 } 1082 1083 b43_nphy_rssi_select(dev, 0, type); 1084 1085 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]); 1086 b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]); 1087 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]); 1088 b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]); 1089 1090 b43_nphy_classifier(dev, 7, class); 1091 b43_nphy_write_clip_detection(dev, clip_state); 1092} 1093 1094/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ 1095static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) 1096{ 1097 /* TODO */ 1098} 1099 1100/* 1101 * RSSI Calibration 1102 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal 1103 */ 1104static void b43_nphy_rssi_cal(struct b43_wldev *dev) 1105{ 1106 if (dev->phy.rev >= 3) { 1107 b43_nphy_rev3_rssi_cal(dev); 1108 } else { 1109 b43_nphy_rev2_rssi_cal(dev, 2); 1110 b43_nphy_rev2_rssi_cal(dev, 0); 1111 b43_nphy_rev2_rssi_cal(dev, 1); 1112 } 1113} 1114 1115/* 1116 * Restore RSSI Calibration 1117 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal 1118 */ 1119static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) 1120{ 1121 struct b43_phy_n *nphy = dev->phy.n; 1122 1123 u16 *rssical_radio_regs = NULL; 1124 u16 *rssical_phy_regs = NULL; 1125 1126 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 1127 if (!nphy->rssical_chanspec_2G) 1128 return; 1129 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 1130 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 1131 } else { 1132 if (!nphy->rssical_chanspec_5G) 1133 return; 1134 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 1135 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 1136 } 1137 1138 /* TODO use some definitions */ 1139 b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]); 1140 b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]); 1141 1142 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]); 1143 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]); 1144 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]); 1145 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]); 1146 1147 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]); 1148 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]); 1149 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]); 1150 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]); 1151 1152 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]); 1153 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]); 1154 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]); 1155 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); 1156} 1157 1158/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */ 1159static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) 1160{ 1161 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 1162 if (dev->phy.rev >= 6) { 1163 /* TODO If the chip is 47162 1164 return txpwrctrl_tx_gain_ipa_rev5 */ 1165 return txpwrctrl_tx_gain_ipa_rev6; 1166 } else if (dev->phy.rev >= 5) { 1167 return txpwrctrl_tx_gain_ipa_rev5; 1168 } else { 1169 return txpwrctrl_tx_gain_ipa; 1170 } 1171 } else { 1172 return txpwrctrl_tx_gain_ipa_5g; 1173 } 1174} 1175 1176/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ 1177static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) 1178{ 1179 struct b43_phy_n *nphy = dev->phy.n; 1180 u16 *save = nphy->tx_rx_cal_radio_saveregs; 1181 1182 if (dev->phy.rev >= 3) { 1183 /* TODO */ 1184 } else { 1185 save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1); 1186 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29); 1187 1188 save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2); 1189 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54); 1190 1191 save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1); 1192 b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29); 1193 1194 save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2); 1195 b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54); 1196 1197 save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX); 1198 save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX); 1199 1200 if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) & 1201 B43_NPHY_BANDCTL_5GHZ)) { 1202 b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04); 1203 b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04); 1204 } else { 1205 b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20); 1206 b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20); 1207 } 1208 1209 if (dev->phy.rev < 2) { 1210 b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20); 1211 b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20); 1212 } else { 1213 b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20); 1214 b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20); 1215 } 1216 } 1217} 1218 1219/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ 1220static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, 1221 struct nphy_txgains target, 1222 struct nphy_iqcal_params *params) 1223{ 1224 int i, j, indx; 1225 u16 gain; 1226 1227 if (dev->phy.rev >= 3) { 1228 params->txgm = target.txgm[core]; 1229 params->pga = target.pga[core]; 1230 params->pad = target.pad[core]; 1231 params->ipa = target.ipa[core]; 1232 params->cal_gain = (params->txgm << 12) | (params->pga << 8) | 1233 (params->pad << 4) | (params->ipa); 1234 for (j = 0; j < 5; j++) 1235 params->ncorr[j] = 0x79; 1236 } else { 1237 gain = (target.pad[core]) | (target.pga[core] << 4) | 1238 (target.txgm[core] << 8); 1239 1240 indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 1241 1 : 0; 1242 for (i = 0; i < 9; i++) 1243 if (tbl_iqcal_gainparams[indx][i][0] == gain) 1244 break; 1245 i = min(i, 8); 1246 1247 params->txgm = tbl_iqcal_gainparams[indx][i][1]; 1248 params->pga = tbl_iqcal_gainparams[indx][i][2]; 1249 params->pad = tbl_iqcal_gainparams[indx][i][3]; 1250 params->cal_gain = (params->txgm << 7) | (params->pga << 4) | 1251 (params->pad << 2); 1252 for (j = 0; j < 4; j++) 1253 params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; 1254 } 1255} 1256 1257/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ 1258static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) 1259{ 1260 struct b43_phy_n *nphy = dev->phy.n; 1261 int i; 1262 u16 scale, entry; 1263 1264 u16 tmp = nphy->txcal_bbmult; 1265 if (core == 0) 1266 tmp >>= 8; 1267 tmp &= 0xff; 1268 1269 for (i = 0; i < 18; i++) { 1270 scale = (ladder_lo[i].percent * tmp) / 100; 1271 entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; 1272 /* TODO: Write an N PHY Table with ID 15, length 1, 1273 offset i, width 16, and data entry */ 1274 1275 scale = (ladder_iq[i].percent * tmp) / 100; 1276 entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; 1277 /* TODO: Write an N PHY Table with ID 15, length 1, 1278 offset i + 32, width 16, and data entry */ 1279 } 1280} 1281 1282/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ 1283static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) 1284{ 1285 struct b43_phy_n *nphy = dev->phy.n; 1286 1287 u16 curr_gain[2]; 1288 struct nphy_txgains target; 1289 const u32 *table = NULL; 1290 1291 if (nphy->txpwrctrl == 0) { 1292 int i; 1293 1294 if (nphy->hang_avoid) 1295 b43_nphy_stay_in_carrier_search(dev, true); 1296 /* TODO: Read an N PHY Table with ID 7, length 2, 1297 offset 0x110, width 16, and curr_gain */ 1298 if (nphy->hang_avoid) 1299 b43_nphy_stay_in_carrier_search(dev, false); 1300 1301 for (i = 0; i < 2; ++i) { 1302 if (dev->phy.rev >= 3) { 1303 target.ipa[i] = curr_gain[i] & 0x000F; 1304 target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; 1305 target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 1306 target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 1307 } else { 1308 target.ipa[i] = curr_gain[i] & 0x0003; 1309 target.pad[i] = (curr_gain[i] & 0x000C) >> 2; 1310 target.pga[i] = (curr_gain[i] & 0x0070) >> 4; 1311 target.txgm[i] = (curr_gain[i] & 0x0380) >> 7; 1312 } 1313 } 1314 } else { 1315 int i; 1316 u16 index[2]; 1317 index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) & 1318 B43_NPHY_TXPCTL_STAT_BIDX) >> 1319 B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; 1320 index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) & 1321 B43_NPHY_TXPCTL_STAT_BIDX) >> 1322 B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; 1323 1324 for (i = 0; i < 2; ++i) { 1325 if (dev->phy.rev >= 3) { 1326 enum ieee80211_band band = 1327 b43_current_band(dev->wl); 1328 1329 if ((nphy->ipa2g_on && 1330 band == IEEE80211_BAND_2GHZ) || 1331 (nphy->ipa5g_on && 1332 band == IEEE80211_BAND_5GHZ)) { 1333 table = b43_nphy_get_ipa_gain_table(dev); 1334 } else { 1335 if (band == IEEE80211_BAND_5GHZ) { 1336 if (dev->phy.rev == 3) 1337 table = b43_ntab_tx_gain_rev3_5ghz; 1338 else if (dev->phy.rev == 4) 1339 table = b43_ntab_tx_gain_rev4_5ghz; 1340 else 1341 table = b43_ntab_tx_gain_rev5plus_5ghz; 1342 } else { 1343 table = b43_ntab_tx_gain_rev3plus_2ghz; 1344 } 1345 } 1346 1347 target.ipa[i] = (table[index[i]] >> 16) & 0xF; 1348 target.pad[i] = (table[index[i]] >> 20) & 0xF; 1349 target.pga[i] = (table[index[i]] >> 24) & 0xF; 1350 target.txgm[i] = (table[index[i]] >> 28) & 0xF; 1351 } else { 1352 table = b43_ntab_tx_gain_rev0_1_2; 1353 1354 target.ipa[i] = (table[index[i]] >> 16) & 0x3; 1355 target.pad[i] = (table[index[i]] >> 18) & 0x3; 1356 target.pga[i] = (table[index[i]] >> 20) & 0x7; 1357 target.txgm[i] = (table[index[i]] >> 23) & 0x7; 1358 } 1359 } 1360 } 1361 1362 return target; 1363} 1364 1365/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ 1366static void b43_nphy_restore_cal(struct b43_wldev *dev) 1367{ 1368 struct b43_phy_n *nphy = dev->phy.n; 1369 1370 u16 coef[4]; 1371 u16 *loft = NULL; 1372 u16 *table = NULL; 1373 1374 int i; 1375 u16 *txcal_radio_regs = NULL; 1376 struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; 1377 1378 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 1379 if (nphy->iqcal_chanspec_2G == 0) 1380 return; 1381 table = nphy->cal_cache.txcal_coeffs_2G; 1382 loft = &nphy->cal_cache.txcal_coeffs_2G[5]; 1383 } else { 1384 if (nphy->iqcal_chanspec_5G == 0) 1385 return; 1386 table = nphy->cal_cache.txcal_coeffs_5G; 1387 loft = &nphy->cal_cache.txcal_coeffs_5G[5]; 1388 } 1389 1390 /* TODO: Write an N PHY table with ID 15, length 4, offset 80, 1391 width 16, and data from table */ 1392 1393 for (i = 0; i < 4; i++) { 1394 if (dev->phy.rev >= 3) 1395 table[i] = coef[i]; 1396 else 1397 coef[i] = 0; 1398 } 1399 1400 /* TODO: Write an N PHY table with ID 15, length 4, offset 88, 1401 width 16, and data from coef */ 1402 /* TODO: Write an N PHY table with ID 15, length 2, offset 85, 1403 width 16 and data from loft */ 1404 /* TODO: Write an N PHY table with ID 15, length 2, offset 93, 1405 width 16 and data from loft */ 1406 1407 if (dev->phy.rev < 2) 1408 b43_nphy_tx_iq_workaround(dev); 1409 1410 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 1411 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 1412 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 1413 } else { 1414 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 1415 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 1416 } 1417 1418 /* TODO use some definitions */ 1419 if (dev->phy.rev >= 3) { 1420 b43_radio_write(dev, 0x2021, txcal_radio_regs[0]); 1421 b43_radio_write(dev, 0x2022, txcal_radio_regs[1]); 1422 b43_radio_write(dev, 0x3021, txcal_radio_regs[2]); 1423 b43_radio_write(dev, 0x3022, txcal_radio_regs[3]); 1424 b43_radio_write(dev, 0x2023, txcal_radio_regs[4]); 1425 b43_radio_write(dev, 0x2024, txcal_radio_regs[5]); 1426 b43_radio_write(dev, 0x3023, txcal_radio_regs[6]); 1427 b43_radio_write(dev, 0x3024, txcal_radio_regs[7]); 1428 } else { 1429 b43_radio_write(dev, 0x8B, txcal_radio_regs[0]); 1430 b43_radio_write(dev, 0xBA, txcal_radio_regs[1]); 1431 b43_radio_write(dev, 0x8D, txcal_radio_regs[2]); 1432 b43_radio_write(dev, 0xBC, txcal_radio_regs[3]); 1433 } 1434 b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs); 1435} 1436 1437/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */ 1438static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, 1439 struct nphy_txgains target, 1440 bool full, bool mphase) 1441{ 1442 struct b43_phy_n *nphy = dev->phy.n; 1443 int i; 1444 int error = 0; 1445 int freq; 1446 bool avoid = false; 1447 u8 length; 1448 u16 tmp, core, type, count, max, numb, last, cmd; 1449 const u16 *table; 1450 bool phy6or5x; 1451 1452 u16 buffer[11]; 1453 u16 diq_start = 0; 1454 u16 save[2]; 1455 u16 gain[2]; 1456 struct nphy_iqcal_params params[2]; 1457 bool updated[2] = { }; 1458 1459 b43_nphy_stay_in_carrier_search(dev, true); 1460 1461 if (dev->phy.rev >= 4) { 1462 avoid = nphy->hang_avoid; 1463 nphy->hang_avoid = 0; 1464 } 1465 1466 /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110, 1467 width 16, and data pointer save */ 1468 1469 for (i = 0; i < 2; i++) { 1470 b43_nphy_iq_cal_gain_params(dev, i, target, ¶ms[i]); 1471 gain[i] = params[i].cal_gain; 1472 } 1473 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, 1474 width 16, and data pointer gain */ 1475 1476 b43_nphy_tx_cal_radio_setup(dev); 1477 /* TODO: Call N PHY TX Cal PHY Setup */ 1478 1479 phy6or5x = dev->phy.rev >= 6 || 1480 (dev->phy.rev == 5 && nphy->ipa2g_on && 1481 b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ); 1482 if (phy6or5x) { 1483 /* TODO */ 1484 } 1485 1486 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); 1487 1488 if (1 /* FIXME: the band width is 20 MHz */) 1489 freq = 2500; 1490 else 1491 freq = 5000; 1492 1493 if (nphy->mphase_cal_phase_id > 2) 1494 ;/* TODO: Call N PHY Run Samples with (band width * 8), 1495 0xFFFF, 0, 1, 0 as arguments */ 1496 else 1497 ;/* TODO: Call N PHY TX Tone with freq, 250, 1, 0 as arguments 1498 and save result as error */ 1499 1500 if (error == 0) { 1501 if (nphy->mphase_cal_phase_id > 2) { 1502 table = nphy->mphase_txcal_bestcoeffs; 1503 length = 11; 1504 if (dev->phy.rev < 3) 1505 length -= 2; 1506 } else { 1507 if (!full && nphy->txiqlocal_coeffsvalid) { 1508 table = nphy->txiqlocal_bestc; 1509 length = 11; 1510 if (dev->phy.rev < 3) 1511 length -= 2; 1512 } else { 1513 full = true; 1514 if (dev->phy.rev >= 3) { 1515 table = tbl_tx_iqlo_cal_startcoefs_nphyrev3; 1516 length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3; 1517 } else { 1518 table = tbl_tx_iqlo_cal_startcoefs; 1519 length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS; 1520 } 1521 } 1522 } 1523 1524 /* TODO: Write an N PHY Table with ID 15, length from above, 1525 offset 64, width 16, and the data pointer from above */ 1526 1527 if (full) { 1528 if (dev->phy.rev >= 3) 1529 max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3; 1530 else 1531 max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL; 1532 } else { 1533 if (dev->phy.rev >= 3) 1534 max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3; 1535 else 1536 max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL; 1537 } 1538 1539 if (mphase) { 1540 count = nphy->mphase_txcal_cmdidx; 1541 numb = min(max, 1542 (u16)(count + nphy->mphase_txcal_numcmds)); 1543 } else { 1544 count = 0; 1545 numb = max; 1546 } 1547 1548 for (; count < numb; count++) { 1549 if (full) { 1550 if (dev->phy.rev >= 3) 1551 cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count]; 1552 else 1553 cmd = tbl_tx_iqlo_cal_cmds_fullcal[count]; 1554 } else { 1555 if (dev->phy.rev >= 3) 1556 cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count]; 1557 else 1558 cmd = tbl_tx_iqlo_cal_cmds_recal[count]; 1559 } 1560 1561 core = (cmd & 0x3000) >> 12; 1562 type = (cmd & 0x0F00) >> 8; 1563 1564 if (phy6or5x && updated[core] == 0) { 1565 b43_nphy_update_tx_cal_ladder(dev, core); 1566 updated[core] = 1; 1567 } 1568 1569 tmp = (params[core].ncorr[type] << 8) | 0x66; 1570 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp); 1571 1572 if (type == 1 || type == 3 || type == 4) { 1573 /* TODO: Read an N PHY Table with ID 15, 1574 length 1, offset 69 + core, 1575 width 16, and data pointer buffer */ 1576 diq_start = buffer[0]; 1577 buffer[0] = 0; 1578 /* TODO: Write an N PHY Table with ID 15, 1579 length 1, offset 69 + core, width 16, 1580 and data of 0 */ 1581 } 1582 1583 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd); 1584 for (i = 0; i < 2000; i++) { 1585 tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD); 1586 if (tmp & 0xC000) 1587 break; 1588 udelay(10); 1589 } 1590 1591 /* TODO: Read an N PHY Table with ID 15, 1592 length table_length, offset 96, width 16, 1593 and data pointer buffer */ 1594 /* TODO: Write an N PHY Table with ID 15, 1595 length table_length, offset 64, width 16, 1596 and data pointer buffer */ 1597 1598 if (type == 1 || type == 3 || type == 4) 1599 buffer[0] = diq_start; 1600 } 1601 1602 if (mphase) 1603 nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb; 1604 1605 last = (dev->phy.rev < 3) ? 6 : 7; 1606 1607 if (!mphase || nphy->mphase_cal_phase_id == last) { 1608 /* TODO: Write an N PHY Table with ID 15, length 4, 1609 offset 96, width 16, and data pointer buffer */ 1610 /* TODO: Read an N PHY Table with ID 15, length 4, 1611 offset 80, width 16, and data pointer buffer */ 1612 if (dev->phy.rev < 3) { 1613 buffer[0] = 0; 1614 buffer[1] = 0; 1615 buffer[2] = 0; 1616 buffer[3] = 0; 1617 } 1618 /* TODO: Write an N PHY Table with ID 15, length 4, 1619 offset 88, width 16, and data pointer buffer */ 1620 /* TODO: Read an N PHY Table with ID 15, length 2, 1621 offset 101, width 16, and data pointer buffer*/ 1622 /* TODO: Write an N PHY Table with ID 15, length 2, 1623 offset 85, width 16, and data pointer buffer */ 1624 /* TODO: Write an N PHY Table with ID 15, length 2, 1625 offset 93, width 16, and data pointer buffer */ 1626 length = 11; 1627 if (dev->phy.rev < 3) 1628 length -= 2; 1629 /* TODO: Read an N PHY Table with ID 15, length length, 1630 offset 96, width 16, and data pointer 1631 nphy->txiqlocal_bestc */ 1632 nphy->txiqlocal_coeffsvalid = true; 1633 /* TODO: Set nphy->txiqlocal_chanspec to 1634 the current channel */ 1635 } else { 1636 length = 11; 1637 if (dev->phy.rev < 3) 1638 length -= 2; 1639 /* TODO: Read an N PHY Table with ID 5, length length, 1640 offset 96, width 16, and data pointer 1641 nphy->mphase_txcal_bestcoeffs */ 1642 } 1643 1644 /* TODO: Call N PHY Stop Playback */ 1645 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0); 1646 } 1647 1648 /* TODO: Call N PHY TX Cal PHY Cleanup */ 1649 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, 1650 width 16, and data from save */ 1651 1652 if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) 1653 b43_nphy_tx_iq_workaround(dev); 1654 1655 if (dev->phy.rev >= 4) 1656 nphy->hang_avoid = avoid; 1657 1658 b43_nphy_stay_in_carrier_search(dev, false); 1659 1660 return error; 1661} 1662 1663/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */ 1664static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, 1665 struct nphy_txgains target, u8 type, bool debug) 1666{ 1667 struct b43_phy_n *nphy = dev->phy.n; 1668 int i, j, index; 1669 u8 rfctl[2]; 1670 u8 afectl_core; 1671 u16 tmp[6]; 1672 u16 cur_hpf1, cur_hpf2, cur_lna; 1673 u32 real, imag; 1674 enum ieee80211_band band; 1675 1676 u8 use; 1677 u16 cur_hpf; 1678 u16 lna[3] = { 3, 3, 1 }; 1679 u16 hpf1[3] = { 7, 2, 0 }; 1680 u16 hpf2[3] = { 2, 0, 0 }; 1681 u32 power[3]; 1682 u16 gain_save[2]; 1683 u16 cal_gain[2]; 1684 struct nphy_iqcal_params cal_params[2]; 1685 struct nphy_iq_est est; 1686 int ret = 0; 1687 bool playtone = true; 1688 int desired = 13; 1689 1690 b43_nphy_stay_in_carrier_search(dev, 1); 1691 1692 if (dev->phy.rev < 2) 1693 ;/* TODO: Call N PHY Reapply TX Cal Coeffs */ 1694 /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110, 1695 width 16, and data gain_save */ 1696 for (i = 0; i < 2; i++) { 1697 b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]); 1698 cal_gain[i] = cal_params[i].cal_gain; 1699 } 1700 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, 1701 width 16, and data from cal_gain */ 1702 1703 for (i = 0; i < 2; i++) { 1704 if (i == 0) { 1705 rfctl[0] = B43_NPHY_RFCTL_INTC1; 1706 rfctl[1] = B43_NPHY_RFCTL_INTC2; 1707 afectl_core = B43_NPHY_AFECTL_C1; 1708 } else { 1709 rfctl[0] = B43_NPHY_RFCTL_INTC2; 1710 rfctl[1] = B43_NPHY_RFCTL_INTC1; 1711 afectl_core = B43_NPHY_AFECTL_C2; 1712 } 1713 1714 tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA); 1715 tmp[2] = b43_phy_read(dev, afectl_core); 1716 tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 1717 tmp[4] = b43_phy_read(dev, rfctl[0]); 1718 tmp[5] = b43_phy_read(dev, rfctl[1]); 1719 1720 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, 1721 (u16)~B43_NPHY_RFSEQCA_RXDIS, 1722 ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); 1723 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, 1724 (1 - i)); 1725 b43_phy_set(dev, afectl_core, 0x0006); 1726 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006); 1727 1728 band = b43_current_band(dev->wl); 1729 1730 if (nphy->rxcalparams & 0xFF000000) { 1731 if (band == IEEE80211_BAND_5GHZ) 1732 b43_phy_write(dev, rfctl[0], 0x140); 1733 else 1734 b43_phy_write(dev, rfctl[0], 0x110); 1735 } else { 1736 if (band == IEEE80211_BAND_5GHZ) 1737 b43_phy_write(dev, rfctl[0], 0x180); 1738 else 1739 b43_phy_write(dev, rfctl[0], 0x120); 1740 } 1741 1742 if (band == IEEE80211_BAND_5GHZ) 1743 b43_phy_write(dev, rfctl[1], 0x148); 1744 else 1745 b43_phy_write(dev, rfctl[1], 0x114); 1746 1747 if (nphy->rxcalparams & 0x10000) { 1748 b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC, 1749 (i + 1)); 1750 b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC, 1751 (2 - i)); 1752 } 1753 1754 for (j = 0; i < 4; j++) { 1755 if (j < 3) { 1756 cur_lna = lna[j]; 1757 cur_hpf1 = hpf1[j]; 1758 cur_hpf2 = hpf2[j]; 1759 } else { 1760 if (power[1] > 10000) { 1761 use = 1; 1762 cur_hpf = cur_hpf1; 1763 index = 2; 1764 } else { 1765 if (power[0] > 10000) { 1766 use = 1; 1767 cur_hpf = cur_hpf1; 1768 index = 1; 1769 } else { 1770 index = 0; 1771 use = 2; 1772 cur_hpf = cur_hpf2; 1773 } 1774 } 1775 cur_lna = lna[index]; 1776 cur_hpf1 = hpf1[index]; 1777 cur_hpf2 = hpf2[index]; 1778 cur_hpf += desired - hweight32(power[index]); 1779 cur_hpf = clamp_val(cur_hpf, 0, 10); 1780 if (use == 1) 1781 cur_hpf1 = cur_hpf; 1782 else 1783 cur_hpf2 = cur_hpf; 1784 } 1785 1786 tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | 1787 (cur_lna << 2)); 1788 /* TODO:Call N PHY RF Ctrl Override with 0x400, tmp[0], 1789 3, 0 as arguments */ 1790 /* TODO: Call N PHY Force RF Seq with 2 as argument */ 1791 /* TODO: Call N PHT Stop Playback */ 1792 1793 if (playtone) { 1794 /* TODO: Call N PHY TX Tone with 4000, 1795 (nphy_rxcalparams & 0xffff), 0, 0 1796 as arguments and save result as ret */ 1797 playtone = false; 1798 } else { 1799 /* TODO: Call N PHY Run Samples with 160, 1800 0xFFFF, 0, 0, 0 as arguments */ 1801 } 1802 1803 if (ret == 0) { 1804 if (j < 3) { 1805 b43_nphy_rx_iq_est(dev, &est, 1024, 32, 1806 false); 1807 if (i == 0) { 1808 real = est.i0_pwr; 1809 imag = est.q0_pwr; 1810 } else { 1811 real = est.i1_pwr; 1812 imag = est.q1_pwr; 1813 } 1814 power[i] = ((real + imag) / 1024) + 1; 1815 } else { 1816 b43_nphy_calc_rx_iq_comp(dev, 1 << i); 1817 } 1818 /* TODO: Call N PHY Stop Playback */ 1819 } 1820 1821 if (ret != 0) 1822 break; 1823 } 1824 1825 b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC); 1826 b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC); 1827 b43_phy_write(dev, rfctl[1], tmp[5]); 1828 b43_phy_write(dev, rfctl[0], tmp[4]); 1829 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]); 1830 b43_phy_write(dev, afectl_core, tmp[2]); 1831 b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]); 1832 1833 if (ret != 0) 1834 break; 1835 } 1836 1837 /* TODO: Call N PHY RF Ctrl Override with 0x400, 0, 3, 1 as arguments*/ 1838 /* TODO: Call N PHY Force RF Seq with 2 as argument */ 1839 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110, 1840 width 16, and data from gain_save */ 1841 1842 b43_nphy_stay_in_carrier_search(dev, 0); 1843 1844 return ret; 1845} 1846 1847static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev, 1848 struct nphy_txgains target, u8 type, bool debug) 1849{ 1850 return -1; 1851} 1852 1853/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */ 1854static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, 1855 struct nphy_txgains target, u8 type, bool debug) 1856{ 1857 if (dev->phy.rev >= 3) 1858 return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug); 1859 else 1860 return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); 1861} 1862 1863/* 1864 * Init N-PHY 1865 * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N 1866 */ 1867int b43_phy_initn(struct b43_wldev *dev) 1868{ 1869 struct ssb_bus *bus = dev->dev->bus; 1870 struct b43_phy *phy = &dev->phy; 1871 struct b43_phy_n *nphy = phy->n; 1872 u8 tx_pwr_state; 1873 struct nphy_txgains target; 1874 u16 tmp; 1875 enum ieee80211_band tmp2; 1876 bool do_rssi_cal; 1877 1878 u16 clip[2]; 1879 bool do_cal = false; 1880 1881 if ((dev->phy.rev >= 3) && 1882 (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && 1883 (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) { 1884 chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40); 1885 } 1886 nphy->deaf_count = 0; 1887 b43_nphy_tables_init(dev); 1888 nphy->crsminpwr_adjusted = false; 1889 nphy->noisevars_adjusted = false; 1890 1891 /* Clear all overrides */ 1892 if (dev->phy.rev >= 3) { 1893 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0); 1894 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); 1895 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0); 1896 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0); 1897 } else { 1898 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); 1899 } 1900 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); 1901 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); 1902 if (dev->phy.rev < 6) { 1903 b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); 1904 b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); 1905 } 1906 b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 1907 ~(B43_NPHY_RFSEQMODE_CAOVER | 1908 B43_NPHY_RFSEQMODE_TROVER)); 1909 if (dev->phy.rev >= 3) 1910 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0); 1911 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); 1912 1913 if (dev->phy.rev <= 2) { 1914 tmp = (dev->phy.rev == 2) ? 0x3B : 0x40; 1915 b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, 1916 ~B43_NPHY_BPHY_CTL3_SCALE, 1917 tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); 1918 } 1919 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); 1920 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); 1921 1922 if (bus->sprom.boardflags2_lo & 0x100 || 1923 (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && 1924 bus->boardinfo.type == 0x8B)) 1925 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0); 1926 else 1927 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8); 1928 b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8); 1929 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); 1930 b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); 1931 1932 /* TODO MIMO-Config */ 1933 /* TODO Update TX/RX chain */ 1934 1935 if (phy->rev < 2) { 1936 b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); 1937 b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); 1938 } 1939 1940 tmp2 = b43_current_band(dev->wl); 1941 if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) || 1942 (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) { 1943 b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1); 1944 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F, 1945 nphy->papd_epsilon_offset[0] << 7); 1946 b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1); 1947 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F, 1948 nphy->papd_epsilon_offset[1] << 7); 1949 /* TODO N PHY IPA Set TX Dig Filters */ 1950 } else if (phy->rev >= 5) { 1951 /* TODO N PHY Ext PA Set TX Dig Filters */ 1952 } 1953 1954 b43_nphy_workarounds(dev); 1955 1956 /* Reset CCA, in init code it differs a little from standard way */ 1957 /* b43_nphy_bmac_clock_fgc(dev, 1); */ 1958 tmp = b43_phy_read(dev, B43_NPHY_BBCFG); 1959 b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA); 1960 b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); 1961 /* b43_nphy_bmac_clock_fgc(dev, 0); */ 1962 1963 /* TODO N PHY MAC PHY Clock Set with argument 1 */ 1964 1965 b43_nphy_pa_override(dev, false); 1966 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); 1967 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 1968 b43_nphy_pa_override(dev, true); 1969 1970 b43_nphy_classifier(dev, 0, 0); 1971 b43_nphy_read_clip_detection(dev, clip); 1972 tx_pwr_state = nphy->txpwrctrl; 1973 /* TODO N PHY TX power control with argument 0 1974 (turning off power control) */ 1975 /* TODO Fix the TX Power Settings */ 1976 /* TODO N PHY TX Power Control Idle TSSI */ 1977 /* TODO N PHY TX Power Control Setup */ 1978 1979 if (phy->rev >= 3) { 1980 /* TODO */ 1981 } else { 1982 /* TODO Write an N PHY table with ID 26, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */ 1983 /* TODO Write an N PHY table with ID 27, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */ 1984 } 1985 1986 if (nphy->phyrxchain != 3) 1987 ;/* TODO N PHY RX Core Set State with phyrxchain as argument */ 1988 if (nphy->mphase_cal_phase_id > 0) 1989 ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ 1990 1991 do_rssi_cal = false; 1992 if (phy->rev >= 3) { 1993 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 1994 do_rssi_cal = (nphy->rssical_chanspec_2G == 0); 1995 else 1996 do_rssi_cal = (nphy->rssical_chanspec_5G == 0); 1997 1998 if (do_rssi_cal) 1999 b43_nphy_rssi_cal(dev); 2000 else 2001 b43_nphy_restore_rssi_cal(dev); 2002 } else { 2003 b43_nphy_rssi_cal(dev); 2004 } 2005 2006 if (!((nphy->measure_hold & 0x6) != 0)) { 2007 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 2008 do_cal = (nphy->iqcal_chanspec_2G == 0); 2009 else 2010 do_cal = (nphy->iqcal_chanspec_5G == 0); 2011 2012 if (nphy->mute) 2013 do_cal = false; 2014 2015 if (do_cal) { 2016 target = b43_nphy_get_tx_gains(dev); 2017 2018 if (nphy->antsel_type == 2) 2019 ;/*TODO NPHY Superswitch Init with argument 1*/ 2020 if (nphy->perical != 2) { 2021 b43_nphy_rssi_cal(dev); 2022 if (phy->rev >= 3) { 2023 nphy->cal_orig_pwr_idx[0] = 2024 nphy->txpwrindex[0].index_internal; 2025 nphy->cal_orig_pwr_idx[1] = 2026 nphy->txpwrindex[1].index_internal; 2027 /* TODO N PHY Pre Calibrate TX Gain */ 2028 target = b43_nphy_get_tx_gains(dev); 2029 } 2030 } 2031 } 2032 } 2033 2034 if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) { 2035 if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) 2036 ;/* Call N PHY Save Cal */ 2037 else if (nphy->mphase_cal_phase_id == 0) 2038 ;/* N PHY Periodic Calibration with argument 3 */ 2039 } else { 2040 b43_nphy_restore_cal(dev); 2041 } 2042 2043 /* b43_nphy_tx_pwr_ctrl_coef_setup(dev); */ 2044 /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */ 2045 b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015); 2046 b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320); 2047 if (phy->rev >= 3 && phy->rev <= 6) 2048 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014); 2049 b43_nphy_tx_lp_fbw(dev); 2050 /* TODO N PHY Spur Workaround */ 2051 2052 b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); 2053 return 0; 2054} 2055 2056static int b43_nphy_op_allocate(struct b43_wldev *dev) 2057{ 2058 struct b43_phy_n *nphy; 2059 2060 nphy = kzalloc(sizeof(*nphy), GFP_KERNEL); 2061 if (!nphy) 2062 return -ENOMEM; 2063 dev->phy.n = nphy; 2064 2065 return 0; 2066} 2067 2068static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) 2069{ 2070 struct b43_phy *phy = &dev->phy; 2071 struct b43_phy_n *nphy = phy->n; 2072 2073 memset(nphy, 0, sizeof(*nphy)); 2074 2075 //TODO init struct b43_phy_n 2076} 2077 2078static void b43_nphy_op_free(struct b43_wldev *dev) 2079{ 2080 struct b43_phy *phy = &dev->phy; 2081 struct b43_phy_n *nphy = phy->n; 2082 2083 kfree(nphy); 2084 phy->n = NULL; 2085} 2086 2087static int b43_nphy_op_init(struct b43_wldev *dev) 2088{ 2089 return b43_phy_initn(dev); 2090} 2091 2092static inline void check_phyreg(struct b43_wldev *dev, u16 offset) 2093{ 2094#if B43_DEBUG 2095 if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { 2096 /* OFDM registers are onnly available on A/G-PHYs */ 2097 b43err(dev->wl, "Invalid OFDM PHY access at " 2098 "0x%04X on N-PHY\n", offset); 2099 dump_stack(); 2100 } 2101 if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { 2102 /* Ext-G registers are only available on G-PHYs */ 2103 b43err(dev->wl, "Invalid EXT-G PHY access at " 2104 "0x%04X on N-PHY\n", offset); 2105 dump_stack(); 2106 } 2107#endif /* B43_DEBUG */ 2108} 2109 2110static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg) 2111{ 2112 check_phyreg(dev, reg); 2113 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 2114 return b43_read16(dev, B43_MMIO_PHY_DATA); 2115} 2116 2117static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) 2118{ 2119 check_phyreg(dev, reg); 2120 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 2121 b43_write16(dev, B43_MMIO_PHY_DATA, value); 2122} 2123 2124static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) 2125{ 2126 /* Register 1 is a 32-bit register. */ 2127 B43_WARN_ON(reg == 1); 2128 /* N-PHY needs 0x100 for read access */ 2129 reg |= 0x100; 2130 2131 b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 2132 return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); 2133} 2134 2135static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) 2136{ 2137 /* Register 1 is a 32-bit register. */ 2138 B43_WARN_ON(reg == 1); 2139 2140 b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 2141 b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); 2142} 2143 2144static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, 2145 bool blocked) 2146{//TODO 2147} 2148 2149static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) 2150{ 2151 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 2152 on ? 0 : 0x7FFF); 2153} 2154 2155static int b43_nphy_op_switch_channel(struct b43_wldev *dev, 2156 unsigned int new_channel) 2157{ 2158 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 2159 if ((new_channel < 1) || (new_channel > 14)) 2160 return -EINVAL; 2161 } else { 2162 if (new_channel > 200) 2163 return -EINVAL; 2164 } 2165 2166 return nphy_channel_switch(dev, new_channel); 2167} 2168 2169static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) 2170{ 2171 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 2172 return 1; 2173 return 36; 2174} 2175 2176const struct b43_phy_operations b43_phyops_n = { 2177 .allocate = b43_nphy_op_allocate, 2178 .free = b43_nphy_op_free, 2179 .prepare_structs = b43_nphy_op_prepare_structs, 2180 .init = b43_nphy_op_init, 2181 .phy_read = b43_nphy_op_read, 2182 .phy_write = b43_nphy_op_write, 2183 .radio_read = b43_nphy_op_radio_read, 2184 .radio_write = b43_nphy_op_radio_write, 2185 .software_rfkill = b43_nphy_op_software_rfkill, 2186 .switch_analog = b43_nphy_op_switch_analog, 2187 .switch_channel = b43_nphy_op_switch_channel, 2188 .get_default_chan = b43_nphy_op_get_default_chan, 2189 .recalc_txpower = b43_nphy_op_recalc_txpower, 2190 .adjust_txpower = b43_nphy_op_adjust_txpower, 2191}; 2192