phy_n.c revision 755fd183b89bc8a302669b6f35cd98faee473f7a
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/slab.h> 27#include <linux/types.h> 28 29#include "b43.h" 30#include "phy_n.h" 31#include "tables_nphy.h" 32#include "radio_2055.h" 33#include "radio_2056.h" 34#include "main.h" 35 36struct nphy_txgains { 37 u16 txgm[2]; 38 u16 pga[2]; 39 u16 pad[2]; 40 u16 ipa[2]; 41}; 42 43struct nphy_iqcal_params { 44 u16 txgm; 45 u16 pga; 46 u16 pad; 47 u16 ipa; 48 u16 cal_gain; 49 u16 ncorr[5]; 50}; 51 52struct nphy_iq_est { 53 s32 iq0_prod; 54 u32 i0_pwr; 55 u32 q0_pwr; 56 s32 iq1_prod; 57 u32 i1_pwr; 58 u32 q1_pwr; 59}; 60 61enum b43_nphy_rf_sequence { 62 B43_RFSEQ_RX2TX, 63 B43_RFSEQ_TX2RX, 64 B43_RFSEQ_RESET2RX, 65 B43_RFSEQ_UPDATE_GAINH, 66 B43_RFSEQ_UPDATE_GAINL, 67 B43_RFSEQ_UPDATE_GAINU, 68}; 69 70enum b43_nphy_rssi_type { 71 B43_NPHY_RSSI_X = 0, 72 B43_NPHY_RSSI_Y, 73 B43_NPHY_RSSI_Z, 74 B43_NPHY_RSSI_PWRDET, 75 B43_NPHY_RSSI_TSSI_I, 76 B43_NPHY_RSSI_TSSI_Q, 77 B43_NPHY_RSSI_TBD, 78}; 79 80static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, 81 bool enable); 82static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, 83 u8 *events, u8 *delays, u8 length); 84static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, 85 enum b43_nphy_rf_sequence seq); 86static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, 87 u16 value, u8 core, bool off); 88static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, 89 u16 value, u8 core); 90 91static inline bool b43_channel_type_is_40mhz( 92 enum nl80211_channel_type channel_type) 93{ 94 return (channel_type == NL80211_CHAN_HT40MINUS || 95 channel_type == NL80211_CHAN_HT40PLUS); 96} 97 98void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) 99{//TODO 100} 101 102static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev) 103{//TODO 104} 105 106static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, 107 bool ignore_tssi) 108{//TODO 109 return B43_TXPWR_RES_DONE; 110} 111 112static void b43_chantab_radio_upload(struct b43_wldev *dev, 113 const struct b43_nphy_channeltab_entry_rev2 *e) 114{ 115 b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref); 116 b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); 117 b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); 118 b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); 119 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 120 121 b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1); 122 b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2); 123 b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); 124 b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); 125 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 126 127 b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); 128 b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); 129 b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); 130 b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); 131 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 132 133 b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); 134 b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); 135 b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); 136 b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); 137 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 138 139 b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); 140 b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); 141 b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); 142 b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); 143 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 144 145 b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); 146 b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); 147} 148 149static void b43_chantab_phy_upload(struct b43_wldev *dev, 150 const struct b43_phy_n_sfo_cfg *e) 151{ 152 b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); 153 b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); 154 b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3); 155 b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4); 156 b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5); 157 b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); 158} 159 160/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */ 161static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable) 162{ 163 struct b43_phy_n *nphy = dev->phy.n; 164 u8 i; 165 u16 tmp; 166 167 if (nphy->hang_avoid) 168 b43_nphy_stay_in_carrier_search(dev, 1); 169 170 nphy->txpwrctrl = enable; 171 if (!enable) { 172 if (dev->phy.rev >= 3) 173 ; /* TODO */ 174 175 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840); 176 for (i = 0; i < 84; i++) 177 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); 178 179 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40); 180 for (i = 0; i < 84; i++) 181 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0); 182 183 tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN; 184 if (dev->phy.rev >= 3) 185 tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN; 186 b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp); 187 188 if (dev->phy.rev >= 3) { 189 b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100); 190 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100); 191 } else { 192 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000); 193 } 194 195 if (dev->phy.rev == 2) 196 b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, 197 ~B43_NPHY_BPHY_CTL3_SCALE, 0x53); 198 else if (dev->phy.rev < 2) 199 b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, 200 ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A); 201 202 if (dev->phy.rev < 2 && 0) 203 ; /* TODO */ 204 } else { 205 b43err(dev->wl, "enabling tx pwr ctrl not implemented yet\n"); 206 } 207 208 if (nphy->hang_avoid) 209 b43_nphy_stay_in_carrier_search(dev, 0); 210} 211 212/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */ 213static void b43_nphy_tx_power_fix(struct b43_wldev *dev) 214{ 215 struct b43_phy_n *nphy = dev->phy.n; 216 struct ssb_sprom *sprom = &(dev->dev->bus->sprom); 217 218 u8 txpi[2], bbmult, i; 219 u16 tmp, radio_gain, dac_gain; 220 u16 freq = dev->phy.channel_freq; 221 u32 txgain; 222 /* u32 gaintbl; rev3+ */ 223 224 if (nphy->hang_avoid) 225 b43_nphy_stay_in_carrier_search(dev, 1); 226 227 if (dev->phy.rev >= 3) { 228 txpi[0] = 40; 229 txpi[1] = 40; 230 } else if (sprom->revision < 4) { 231 txpi[0] = 72; 232 txpi[1] = 72; 233 } else { 234 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 235 txpi[0] = sprom->txpid2g[0]; 236 txpi[1] = sprom->txpid2g[1]; 237 } else if (freq >= 4900 && freq < 5100) { 238 txpi[0] = sprom->txpid5gl[0]; 239 txpi[1] = sprom->txpid5gl[1]; 240 } else if (freq >= 5100 && freq < 5500) { 241 txpi[0] = sprom->txpid5g[0]; 242 txpi[1] = sprom->txpid5g[1]; 243 } else if (freq >= 5500) { 244 txpi[0] = sprom->txpid5gh[0]; 245 txpi[1] = sprom->txpid5gh[1]; 246 } else { 247 txpi[0] = 91; 248 txpi[1] = 91; 249 } 250 } 251 252 /* 253 for (i = 0; i < 2; i++) { 254 nphy->txpwrindex[i].index_internal = txpi[i]; 255 nphy->txpwrindex[i].index_internal_save = txpi[i]; 256 } 257 */ 258 259 for (i = 0; i < 2; i++) { 260 if (dev->phy.rev >= 3) { 261 /* TODO */ 262 radio_gain = (txgain >> 16) & 0x1FFFF; 263 } else { 264 txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]]; 265 radio_gain = (txgain >> 16) & 0x1FFF; 266 } 267 268 dac_gain = (txgain >> 8) & 0x3F; 269 bbmult = txgain & 0xFF; 270 271 if (dev->phy.rev >= 3) { 272 if (i == 0) 273 b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100); 274 else 275 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100); 276 } else { 277 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000); 278 } 279 280 if (i == 0) 281 b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain); 282 else 283 b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain); 284 285 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D10 + i); 286 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, radio_gain); 287 288 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57); 289 tmp = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); 290 291 if (i == 0) 292 tmp = (tmp & 0x00FF) | (bbmult << 8); 293 else 294 tmp = (tmp & 0xFF00) | bbmult; 295 296 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C57); 297 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, tmp); 298 299 if (0) 300 ; /* TODO */ 301 } 302 303 b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT); 304 305 if (nphy->hang_avoid) 306 b43_nphy_stay_in_carrier_search(dev, 0); 307} 308 309 310/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ 311static void b43_radio_2055_setup(struct b43_wldev *dev, 312 const struct b43_nphy_channeltab_entry_rev2 *e) 313{ 314 B43_WARN_ON(dev->phy.rev >= 3); 315 316 b43_chantab_radio_upload(dev, e); 317 udelay(50); 318 b43_radio_write(dev, B2055_VCO_CAL10, 0x05); 319 b43_radio_write(dev, B2055_VCO_CAL10, 0x45); 320 b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ 321 b43_radio_write(dev, B2055_VCO_CAL10, 0x65); 322 udelay(300); 323} 324 325static void b43_radio_init2055_pre(struct b43_wldev *dev) 326{ 327 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 328 ~B43_NPHY_RFCTL_CMD_PORFORCE); 329 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 330 B43_NPHY_RFCTL_CMD_CHIP0PU | 331 B43_NPHY_RFCTL_CMD_OEPORFORCE); 332 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 333 B43_NPHY_RFCTL_CMD_PORFORCE); 334} 335 336static void b43_radio_init2055_post(struct b43_wldev *dev) 337{ 338 struct b43_phy_n *nphy = dev->phy.n; 339 struct ssb_sprom *sprom = &(dev->dev->bus->sprom); 340 struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); 341 int i; 342 u16 val; 343 bool workaround = false; 344 345 if (sprom->revision < 4) 346 workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM || 347 binfo->type != 0x46D || 348 binfo->rev < 0x41); 349 else 350 workaround = 351 !(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS); 352 353 b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); 354 if (workaround) { 355 b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); 356 b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F); 357 } 358 b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C); 359 b43_radio_write(dev, B2055_CAL_MISC, 0x3C); 360 b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); 361 b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); 362 b43_radio_set(dev, B2055_CAL_MISC, 0x1); 363 msleep(1); 364 b43_radio_set(dev, B2055_CAL_MISC, 0x40); 365 for (i = 0; i < 200; i++) { 366 val = b43_radio_read(dev, B2055_CAL_COUT2); 367 if (val & 0x80) { 368 i = 0; 369 break; 370 } 371 udelay(10); 372 } 373 if (i) 374 b43err(dev->wl, "radio post init timeout\n"); 375 b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); 376 b43_switch_channel(dev, dev->phy.channel); 377 b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9); 378 b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9); 379 b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83); 380 b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83); 381 b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6); 382 b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6); 383 if (!nphy->gain_boost) { 384 b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2); 385 b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2); 386 } else { 387 b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD); 388 b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD); 389 } 390 udelay(2); 391} 392 393/* 394 * Initialize a Broadcom 2055 N-radio 395 * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init 396 */ 397static void b43_radio_init2055(struct b43_wldev *dev) 398{ 399 b43_radio_init2055_pre(dev); 400 if (b43_status(dev) < B43_STAT_INITIALIZED) { 401 /* Follow wl, not specs. Do not force uploading all regs */ 402 b2055_upload_inittab(dev, 0, 0); 403 } else { 404 bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ; 405 b2055_upload_inittab(dev, ghz5, 0); 406 } 407 b43_radio_init2055_post(dev); 408} 409 410/* 411 * Initialize a Broadcom 2056 N-radio 412 * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init 413 */ 414static void b43_radio_init2056(struct b43_wldev *dev) 415{ 416 /* TODO */ 417} 418 419 420/* 421 * Upload the N-PHY tables. 422 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables 423 */ 424static void b43_nphy_tables_init(struct b43_wldev *dev) 425{ 426 if (dev->phy.rev < 3) 427 b43_nphy_rev0_1_2_tables_init(dev); 428 else 429 b43_nphy_rev3plus_tables_init(dev); 430} 431 432/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */ 433static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable) 434{ 435 struct b43_phy_n *nphy = dev->phy.n; 436 enum ieee80211_band band; 437 u16 tmp; 438 439 if (!enable) { 440 nphy->rfctrl_intc1_save = b43_phy_read(dev, 441 B43_NPHY_RFCTL_INTC1); 442 nphy->rfctrl_intc2_save = b43_phy_read(dev, 443 B43_NPHY_RFCTL_INTC2); 444 band = b43_current_band(dev->wl); 445 if (dev->phy.rev >= 3) { 446 if (band == IEEE80211_BAND_5GHZ) 447 tmp = 0x600; 448 else 449 tmp = 0x480; 450 } else { 451 if (band == IEEE80211_BAND_5GHZ) 452 tmp = 0x180; 453 else 454 tmp = 0x120; 455 } 456 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp); 457 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp); 458 } else { 459 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 460 nphy->rfctrl_intc1_save); 461 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 462 nphy->rfctrl_intc2_save); 463 } 464} 465 466/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */ 467static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev) 468{ 469 struct b43_phy_n *nphy = dev->phy.n; 470 u16 tmp; 471 enum ieee80211_band band = b43_current_band(dev->wl); 472 bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) || 473 (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ); 474 475 if (dev->phy.rev >= 3) { 476 if (ipa) { 477 tmp = 4; 478 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2, 479 (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); 480 } 481 482 tmp = 1; 483 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2, 484 (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp); 485 } 486} 487 488/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ 489static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) 490{ 491 u32 tmslow; 492 493 if (dev->phy.type != B43_PHYTYPE_N) 494 return; 495 496 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); 497 if (force) 498 tmslow |= SSB_TMSLOW_FGC; 499 else 500 tmslow &= ~SSB_TMSLOW_FGC; 501 ssb_write32(dev->dev, SSB_TMSLOW, tmslow); 502} 503 504/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ 505static void b43_nphy_reset_cca(struct b43_wldev *dev) 506{ 507 u16 bbcfg; 508 509 b43_nphy_bmac_clock_fgc(dev, 1); 510 bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); 511 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA); 512 udelay(1); 513 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); 514 b43_nphy_bmac_clock_fgc(dev, 0); 515 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 516} 517 518/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */ 519static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble) 520{ 521 u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG); 522 523 mimocfg |= B43_NPHY_MIMOCFG_AUTO; 524 if (preamble == 1) 525 mimocfg |= B43_NPHY_MIMOCFG_GFMIX; 526 else 527 mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX; 528 529 b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg); 530} 531 532/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */ 533static void b43_nphy_update_txrx_chain(struct b43_wldev *dev) 534{ 535 struct b43_phy_n *nphy = dev->phy.n; 536 537 bool override = false; 538 u16 chain = 0x33; 539 540 if (nphy->txrx_chain == 0) { 541 chain = 0x11; 542 override = true; 543 } else if (nphy->txrx_chain == 1) { 544 chain = 0x22; 545 override = true; 546 } 547 548 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, 549 ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN), 550 chain); 551 552 if (override) 553 b43_phy_set(dev, B43_NPHY_RFSEQMODE, 554 B43_NPHY_RFSEQMODE_CAOVER); 555 else 556 b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 557 ~B43_NPHY_RFSEQMODE_CAOVER); 558} 559 560/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */ 561static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est, 562 u16 samps, u8 time, bool wait) 563{ 564 int i; 565 u16 tmp; 566 567 b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps); 568 b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time); 569 if (wait) 570 b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE); 571 else 572 b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE); 573 574 b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START); 575 576 for (i = 1000; i; i--) { 577 tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD); 578 if (!(tmp & B43_NPHY_IQEST_CMD_START)) { 579 est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) | 580 b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0); 581 est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) | 582 b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0); 583 est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) | 584 b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0); 585 586 est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) | 587 b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1); 588 est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) | 589 b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1); 590 est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) | 591 b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1); 592 return; 593 } 594 udelay(10); 595 } 596 memset(est, 0, sizeof(*est)); 597} 598 599/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */ 600static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write, 601 struct b43_phy_n_iq_comp *pcomp) 602{ 603 if (write) { 604 b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0); 605 b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0); 606 b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1); 607 b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1); 608 } else { 609 pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0); 610 pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0); 611 pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1); 612 pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1); 613 } 614} 615 616/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */ 617static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core) 618{ 619 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; 620 621 b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]); 622 if (core == 0) { 623 b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]); 624 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]); 625 } else { 626 b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]); 627 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]); 628 } 629 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]); 630 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]); 631 b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]); 632 b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]); 633 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]); 634 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]); 635 b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]); 636 b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]); 637} 638 639/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */ 640static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core) 641{ 642 u8 rxval, txval; 643 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; 644 645 regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA); 646 if (core == 0) { 647 regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 648 regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); 649 } else { 650 regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 651 regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 652 } 653 regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 654 regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 655 regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); 656 regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); 657 regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1); 658 regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); 659 regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0); 660 regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); 661 662 b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); 663 b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); 664 665 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, 666 ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF, 667 ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); 668 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, 669 ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT)); 670 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, 671 (core << B43_NPHY_RFSEQCA_RXEN_SHIFT)); 672 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS, 673 (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT)); 674 675 if (core == 0) { 676 b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007); 677 b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007); 678 } else { 679 b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007); 680 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007); 681 } 682 683 b43_nphy_rf_control_intc_override(dev, 2, 0, 3); 684 b43_nphy_rf_control_override(dev, 8, 0, 3, false); 685 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); 686 687 if (core == 0) { 688 rxval = 1; 689 txval = 8; 690 } else { 691 rxval = 4; 692 txval = 2; 693 } 694 b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1)); 695 b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core)); 696} 697 698/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */ 699static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask) 700{ 701 int i; 702 s32 iq; 703 u32 ii; 704 u32 qq; 705 int iq_nbits, qq_nbits; 706 int arsh, brsh; 707 u16 tmp, a, b; 708 709 struct nphy_iq_est est; 710 struct b43_phy_n_iq_comp old; 711 struct b43_phy_n_iq_comp new = { }; 712 bool error = false; 713 714 if (mask == 0) 715 return; 716 717 b43_nphy_rx_iq_coeffs(dev, false, &old); 718 b43_nphy_rx_iq_coeffs(dev, true, &new); 719 b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false); 720 new = old; 721 722 for (i = 0; i < 2; i++) { 723 if (i == 0 && (mask & 1)) { 724 iq = est.iq0_prod; 725 ii = est.i0_pwr; 726 qq = est.q0_pwr; 727 } else if (i == 1 && (mask & 2)) { 728 iq = est.iq1_prod; 729 ii = est.i1_pwr; 730 qq = est.q1_pwr; 731 } else { 732 continue; 733 } 734 735 if (ii + qq < 2) { 736 error = true; 737 break; 738 } 739 740 iq_nbits = fls(abs(iq)); 741 qq_nbits = fls(qq); 742 743 arsh = iq_nbits - 20; 744 if (arsh >= 0) { 745 a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); 746 tmp = ii >> arsh; 747 } else { 748 a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); 749 tmp = ii << -arsh; 750 } 751 if (tmp == 0) { 752 error = true; 753 break; 754 } 755 a /= tmp; 756 757 brsh = qq_nbits - 11; 758 if (brsh >= 0) { 759 b = (qq << (31 - qq_nbits)); 760 tmp = ii >> brsh; 761 } else { 762 b = (qq << (31 - qq_nbits)); 763 tmp = ii << -brsh; 764 } 765 if (tmp == 0) { 766 error = true; 767 break; 768 } 769 b = int_sqrt(b / tmp - a * a) - (1 << 10); 770 771 if (i == 0 && (mask & 0x1)) { 772 if (dev->phy.rev >= 3) { 773 new.a0 = a & 0x3FF; 774 new.b0 = b & 0x3FF; 775 } else { 776 new.a0 = b & 0x3FF; 777 new.b0 = a & 0x3FF; 778 } 779 } else if (i == 1 && (mask & 0x2)) { 780 if (dev->phy.rev >= 3) { 781 new.a1 = a & 0x3FF; 782 new.b1 = b & 0x3FF; 783 } else { 784 new.a1 = b & 0x3FF; 785 new.b1 = a & 0x3FF; 786 } 787 } 788 } 789 790 if (error) 791 new = old; 792 793 b43_nphy_rx_iq_coeffs(dev, true, &new); 794} 795 796/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */ 797static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev) 798{ 799 u16 array[4]; 800 int i; 801 802 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50); 803 for (i = 0; i < 4; i++) 804 array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO); 805 806 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]); 807 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]); 808 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]); 809 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]); 810} 811 812/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 813static void b43_nphy_write_clip_detection(struct b43_wldev *dev, 814 const u16 *clip_st) 815{ 816 b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]); 817 b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]); 818} 819 820/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */ 821static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) 822{ 823 clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES); 824 clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); 825} 826 827/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ 828static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) 829{ 830 if (dev->phy.rev >= 3) { 831 if (!init) 832 return; 833 if (0 /* FIXME */) { 834 b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211); 835 b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222); 836 b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144); 837 b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188); 838 } 839 } else { 840 b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0); 841 b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0); 842 843 ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00, 844 0xFC00); 845 b43_write32(dev, B43_MMIO_MACCTL, 846 b43_read32(dev, B43_MMIO_MACCTL) & 847 ~B43_MACCTL_GPOUTSMSK); 848 b43_write16(dev, B43_MMIO_GPIO_MASK, 849 b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00); 850 b43_write16(dev, B43_MMIO_GPIO_CONTROL, 851 b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00); 852 853 if (init) { 854 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 855 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 856 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 857 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 858 } 859 } 860} 861 862/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ 863static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) 864{ 865 u16 tmp; 866 867 if (dev->dev->id.revision == 16) 868 b43_mac_suspend(dev); 869 870 tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL); 871 tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN | 872 B43_NPHY_CLASSCTL_WAITEDEN); 873 tmp &= ~mask; 874 tmp |= (val & mask); 875 b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp); 876 877 if (dev->dev->id.revision == 16) 878 b43_mac_enable(dev); 879 880 return tmp; 881} 882 883/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */ 884static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable) 885{ 886 struct b43_phy *phy = &dev->phy; 887 struct b43_phy_n *nphy = phy->n; 888 889 if (enable) { 890 static const u16 clip[] = { 0xFFFF, 0xFFFF }; 891 if (nphy->deaf_count++ == 0) { 892 nphy->classifier_state = b43_nphy_classifier(dev, 0, 0); 893 b43_nphy_classifier(dev, 0x7, 0); 894 b43_nphy_read_clip_detection(dev, nphy->clip_state); 895 b43_nphy_write_clip_detection(dev, clip); 896 } 897 b43_nphy_reset_cca(dev); 898 } else { 899 if (--nphy->deaf_count == 0) { 900 b43_nphy_classifier(dev, 0x7, nphy->classifier_state); 901 b43_nphy_write_clip_detection(dev, nphy->clip_state); 902 } 903 } 904} 905 906/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */ 907static void b43_nphy_stop_playback(struct b43_wldev *dev) 908{ 909 struct b43_phy_n *nphy = dev->phy.n; 910 u16 tmp; 911 912 if (nphy->hang_avoid) 913 b43_nphy_stay_in_carrier_search(dev, 1); 914 915 tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT); 916 if (tmp & 0x1) 917 b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP); 918 else if (tmp & 0x2) 919 b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 920 921 b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004); 922 923 if (nphy->bb_mult_save & 0x80000000) { 924 tmp = nphy->bb_mult_save & 0xFFFF; 925 b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); 926 nphy->bb_mult_save = 0; 927 } 928 929 if (nphy->hang_avoid) 930 b43_nphy_stay_in_carrier_search(dev, 0); 931} 932 933/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */ 934static void b43_nphy_spur_workaround(struct b43_wldev *dev) 935{ 936 struct b43_phy_n *nphy = dev->phy.n; 937 938 u8 channel = dev->phy.channel; 939 int tone[2] = { 57, 58 }; 940 u32 noise[2] = { 0x3FF, 0x3FF }; 941 942 B43_WARN_ON(dev->phy.rev < 3); 943 944 if (nphy->hang_avoid) 945 b43_nphy_stay_in_carrier_search(dev, 1); 946 947 if (nphy->gband_spurwar_en) { 948 /* TODO: N PHY Adjust Analog Pfbw (7) */ 949 if (channel == 11 && dev->phy.is_40mhz) 950 ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/ 951 else 952 ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 953 /* TODO: N PHY Adjust CRS Min Power (0x1E) */ 954 } 955 956 if (nphy->aband_spurwar_en) { 957 if (channel == 54) { 958 tone[0] = 0x20; 959 noise[0] = 0x25F; 960 } else if (channel == 38 || channel == 102 || channel == 118) { 961 if (0 /* FIXME */) { 962 tone[0] = 0x20; 963 noise[0] = 0x21F; 964 } else { 965 tone[0] = 0; 966 noise[0] = 0; 967 } 968 } else if (channel == 134) { 969 tone[0] = 0x20; 970 noise[0] = 0x21F; 971 } else if (channel == 151) { 972 tone[0] = 0x10; 973 noise[0] = 0x23F; 974 } else if (channel == 153 || channel == 161) { 975 tone[0] = 0x30; 976 noise[0] = 0x23F; 977 } else { 978 tone[0] = 0; 979 noise[0] = 0; 980 } 981 982 if (!tone[0] && !noise[0]) 983 ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/ 984 else 985 ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/ 986 } 987 988 if (nphy->hang_avoid) 989 b43_nphy_stay_in_carrier_search(dev, 0); 990} 991 992/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ 993static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) 994{ 995 struct b43_phy_n *nphy = dev->phy.n; 996 997 u8 i; 998 s16 tmp; 999 u16 data[4]; 1000 s16 gain[2]; 1001 u16 minmax[2]; 1002 static const u16 lna_gain[4] = { -2, 10, 19, 25 }; 1003 1004 if (nphy->hang_avoid) 1005 b43_nphy_stay_in_carrier_search(dev, 1); 1006 1007 if (nphy->gain_boost) { 1008 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 1009 gain[0] = 6; 1010 gain[1] = 6; 1011 } else { 1012 tmp = 40370 - 315 * dev->phy.channel; 1013 gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1)); 1014 tmp = 23242 - 224 * dev->phy.channel; 1015 gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1)); 1016 } 1017 } else { 1018 gain[0] = 0; 1019 gain[1] = 0; 1020 } 1021 1022 for (i = 0; i < 2; i++) { 1023 if (nphy->elna_gain_config) { 1024 data[0] = 19 + gain[i]; 1025 data[1] = 25 + gain[i]; 1026 data[2] = 25 + gain[i]; 1027 data[3] = 25 + gain[i]; 1028 } else { 1029 data[0] = lna_gain[0] + gain[i]; 1030 data[1] = lna_gain[1] + gain[i]; 1031 data[2] = lna_gain[2] + gain[i]; 1032 data[3] = lna_gain[3] + gain[i]; 1033 } 1034 b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data); 1035 1036 minmax[i] = 23 + gain[i]; 1037 } 1038 1039 b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN, 1040 minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT); 1041 b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN, 1042 minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT); 1043 1044 if (nphy->hang_avoid) 1045 b43_nphy_stay_in_carrier_search(dev, 0); 1046} 1047 1048/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ 1049static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) 1050{ 1051 struct b43_phy_n *nphy = dev->phy.n; 1052 u8 i, j; 1053 u8 code; 1054 u16 tmp; 1055 1056 /* TODO: for PHY >= 3 1057 s8 *lna1_gain, *lna2_gain; 1058 u8 *gain_db, *gain_bits; 1059 u16 *rfseq_init; 1060 u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 }; 1061 u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 }; 1062 */ 1063 1064 u8 rfseq_events[3] = { 6, 8, 7 }; 1065 u8 rfseq_delays[3] = { 10, 30, 1 }; 1066 1067 if (dev->phy.rev >= 3) { 1068 /* TODO */ 1069 } else { 1070 /* Set Clip 2 detect */ 1071 b43_phy_set(dev, B43_NPHY_C1_CGAINI, 1072 B43_NPHY_C1_CGAINI_CL2DETECT); 1073 b43_phy_set(dev, B43_NPHY_C2_CGAINI, 1074 B43_NPHY_C2_CGAINI_CL2DETECT); 1075 1076 /* Set narrowband clip threshold */ 1077 b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84); 1078 b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84); 1079 1080 if (!dev->phy.is_40mhz) { 1081 /* Set dwell lengths */ 1082 b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B); 1083 b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B); 1084 b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009); 1085 b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009); 1086 } 1087 1088 /* Set wideband clip 2 threshold */ 1089 b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, 1090 ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 1091 21); 1092 b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, 1093 ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 1094 21); 1095 1096 if (!dev->phy.is_40mhz) { 1097 b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, 1098 ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1); 1099 b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, 1100 ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1); 1101 b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI, 1102 ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1); 1103 b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI, 1104 ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1); 1105 } 1106 1107 b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C); 1108 1109 if (nphy->gain_boost) { 1110 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ && 1111 dev->phy.is_40mhz) 1112 code = 4; 1113 else 1114 code = 5; 1115 } else { 1116 code = dev->phy.is_40mhz ? 6 : 7; 1117 } 1118 1119 /* Set HPVGA2 index */ 1120 b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, 1121 ~B43_NPHY_C1_INITGAIN_HPVGA2, 1122 code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); 1123 b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, 1124 ~B43_NPHY_C2_INITGAIN_HPVGA2, 1125 code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); 1126 1127 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); 1128 /* specs say about 2 loops, but wl does 4 */ 1129 for (i = 0; i < 4; i++) 1130 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 1131 (code << 8 | 0x7C)); 1132 1133 b43_nphy_adjust_lna_gain_table(dev); 1134 1135 if (nphy->elna_gain_config) { 1136 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808); 1137 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0); 1138 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 1139 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 1140 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 1141 1142 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08); 1143 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0); 1144 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 1145 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 1146 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1); 1147 1148 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06); 1149 /* specs say about 2 loops, but wl does 4 */ 1150 for (i = 0; i < 4; i++) 1151 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 1152 (code << 8 | 0x74)); 1153 } 1154 1155 if (dev->phy.rev == 2) { 1156 for (i = 0; i < 4; i++) { 1157 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 1158 (0x0400 * i) + 0x0020); 1159 for (j = 0; j < 21; j++) { 1160 tmp = j * (i < 2 ? 3 : 1); 1161 b43_phy_write(dev, 1162 B43_NPHY_TABLE_DATALO, tmp); 1163 } 1164 } 1165 1166 b43_nphy_set_rf_sequence(dev, 5, 1167 rfseq_events, rfseq_delays, 3); 1168 b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1, 1169 ~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF, 1170 0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT); 1171 1172 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 1173 b43_phy_maskset(dev, B43_PHY_N(0xC5D), 1174 0xFF80, 4); 1175 } 1176 } 1177} 1178 1179/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */ 1180static void b43_nphy_workarounds(struct b43_wldev *dev) 1181{ 1182 struct ssb_bus *bus = dev->dev->bus; 1183 struct b43_phy *phy = &dev->phy; 1184 struct b43_phy_n *nphy = phy->n; 1185 1186 u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 }; 1187 u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 }; 1188 1189 u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 }; 1190 u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 }; 1191 1192 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) 1193 b43_nphy_classifier(dev, 1, 0); 1194 else 1195 b43_nphy_classifier(dev, 1, 1); 1196 1197 if (nphy->hang_avoid) 1198 b43_nphy_stay_in_carrier_search(dev, 1); 1199 1200 b43_phy_set(dev, B43_NPHY_IQFLIP, 1201 B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); 1202 1203 if (dev->phy.rev >= 3) { 1204 /* TODO */ 1205 } else { 1206 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ && 1207 nphy->band5g_pwrgain) { 1208 b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8); 1209 b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8); 1210 } else { 1211 b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); 1212 b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8); 1213 } 1214 1215 /* TODO: convert to b43_ntab_write? */ 1216 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2000); 1217 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A); 1218 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2010); 1219 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A); 1220 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2002); 1221 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA); 1222 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2012); 1223 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA); 1224 1225 if (dev->phy.rev < 2) { 1226 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2008); 1227 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000); 1228 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2018); 1229 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000); 1230 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2007); 1231 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB); 1232 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2017); 1233 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB); 1234 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2006); 1235 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800); 1236 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2016); 1237 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800); 1238 } 1239 1240 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 1241 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 1242 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 1243 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 1244 1245 if (bus->sprom.boardflags2_lo & 0x100 && 1246 bus->boardinfo.type == 0x8B) { 1247 delays1[0] = 0x1; 1248 delays1[5] = 0x14; 1249 } 1250 b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); 1251 b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); 1252 1253 b43_nphy_gain_ctrl_workarounds(dev); 1254 1255 if (dev->phy.rev < 2) { 1256 if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) 1257 b43_hf_write(dev, b43_hf_read(dev) | 1258 B43_HF_MLADVW); 1259 } else if (dev->phy.rev == 2) { 1260 b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); 1261 b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); 1262 } 1263 1264 if (dev->phy.rev < 2) 1265 b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, 1266 ~B43_NPHY_SCRAM_SIGCTL_SCM); 1267 1268 /* Set phase track alpha and beta */ 1269 b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); 1270 b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); 1271 b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); 1272 b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); 1273 b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); 1274 b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); 1275 1276 b43_phy_mask(dev, B43_NPHY_PIL_DW1, 1277 ~B43_NPHY_PIL_DW_64QAM & 0xFFFF); 1278 b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5); 1279 b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4); 1280 b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00); 1281 1282 if (dev->phy.rev == 2) 1283 b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 1284 B43_NPHY_FINERX2_CGC_DECGC); 1285 } 1286 1287 if (nphy->hang_avoid) 1288 b43_nphy_stay_in_carrier_search(dev, 0); 1289} 1290 1291/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */ 1292static int b43_nphy_load_samples(struct b43_wldev *dev, 1293 struct b43_c32 *samples, u16 len) { 1294 struct b43_phy_n *nphy = dev->phy.n; 1295 u16 i; 1296 u32 *data; 1297 1298 data = kzalloc(len * sizeof(u32), GFP_KERNEL); 1299 if (!data) { 1300 b43err(dev->wl, "allocation for samples loading failed\n"); 1301 return -ENOMEM; 1302 } 1303 if (nphy->hang_avoid) 1304 b43_nphy_stay_in_carrier_search(dev, 1); 1305 1306 for (i = 0; i < len; i++) { 1307 data[i] = (samples[i].i & 0x3FF << 10); 1308 data[i] |= samples[i].q & 0x3FF; 1309 } 1310 b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data); 1311 1312 kfree(data); 1313 if (nphy->hang_avoid) 1314 b43_nphy_stay_in_carrier_search(dev, 0); 1315 return 0; 1316} 1317 1318/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */ 1319static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max, 1320 bool test) 1321{ 1322 int i; 1323 u16 bw, len, rot, angle; 1324 struct b43_c32 *samples; 1325 1326 1327 bw = (dev->phy.is_40mhz) ? 40 : 20; 1328 len = bw << 3; 1329 1330 if (test) { 1331 if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX) 1332 bw = 82; 1333 else 1334 bw = 80; 1335 1336 if (dev->phy.is_40mhz) 1337 bw <<= 1; 1338 1339 len = bw << 1; 1340 } 1341 1342 samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL); 1343 if (!samples) { 1344 b43err(dev->wl, "allocation for samples generation failed\n"); 1345 return 0; 1346 } 1347 rot = (((freq * 36) / bw) << 16) / 100; 1348 angle = 0; 1349 1350 for (i = 0; i < len; i++) { 1351 samples[i] = b43_cordic(angle); 1352 angle += rot; 1353 samples[i].q = CORDIC_CONVERT(samples[i].q * max); 1354 samples[i].i = CORDIC_CONVERT(samples[i].i * max); 1355 } 1356 1357 i = b43_nphy_load_samples(dev, samples, len); 1358 kfree(samples); 1359 return (i < 0) ? 0 : len; 1360} 1361 1362/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */ 1363static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, 1364 u16 wait, bool iqmode, bool dac_test) 1365{ 1366 struct b43_phy_n *nphy = dev->phy.n; 1367 int i; 1368 u16 seq_mode; 1369 u32 tmp; 1370 1371 if (nphy->hang_avoid) 1372 b43_nphy_stay_in_carrier_search(dev, true); 1373 1374 if ((nphy->bb_mult_save & 0x80000000) == 0) { 1375 tmp = b43_ntab_read(dev, B43_NTAB16(15, 87)); 1376 nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000; 1377 } 1378 1379 if (!dev->phy.is_40mhz) 1380 tmp = 0x6464; 1381 else 1382 tmp = 0x4747; 1383 b43_ntab_write(dev, B43_NTAB16(15, 87), tmp); 1384 1385 if (nphy->hang_avoid) 1386 b43_nphy_stay_in_carrier_search(dev, false); 1387 1388 b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1)); 1389 1390 if (loops != 0xFFFF) 1391 b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1)); 1392 else 1393 b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops); 1394 1395 b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait); 1396 1397 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE); 1398 1399 b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER); 1400 if (iqmode) { 1401 b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF); 1402 b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000); 1403 } else { 1404 if (dac_test) 1405 b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5); 1406 else 1407 b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1); 1408 } 1409 for (i = 0; i < 100; i++) { 1410 if (b43_phy_read(dev, B43_NPHY_RFSEQST) & 1) { 1411 i = 0; 1412 break; 1413 } 1414 udelay(10); 1415 } 1416 if (i) 1417 b43err(dev->wl, "run samples timeout\n"); 1418 1419 b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); 1420} 1421 1422/* 1423 * Transmits a known value for LO calibration 1424 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone 1425 */ 1426static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val, 1427 bool iqmode, bool dac_test) 1428{ 1429 u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test); 1430 if (samp == 0) 1431 return -1; 1432 b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test); 1433 return 0; 1434} 1435 1436/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */ 1437static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev) 1438{ 1439 struct b43_phy_n *nphy = dev->phy.n; 1440 int i, j; 1441 u32 tmp; 1442 u32 cur_real, cur_imag, real_part, imag_part; 1443 1444 u16 buffer[7]; 1445 1446 if (nphy->hang_avoid) 1447 b43_nphy_stay_in_carrier_search(dev, true); 1448 1449 b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); 1450 1451 for (i = 0; i < 2; i++) { 1452 tmp = ((buffer[i * 2] & 0x3FF) << 10) | 1453 (buffer[i * 2 + 1] & 0x3FF); 1454 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 1455 (((i + 26) << 10) | 320)); 1456 for (j = 0; j < 128; j++) { 1457 b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, 1458 ((tmp >> 16) & 0xFFFF)); 1459 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 1460 (tmp & 0xFFFF)); 1461 } 1462 } 1463 1464 for (i = 0; i < 2; i++) { 1465 tmp = buffer[5 + i]; 1466 real_part = (tmp >> 8) & 0xFF; 1467 imag_part = (tmp & 0xFF); 1468 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 1469 (((i + 26) << 10) | 448)); 1470 1471 if (dev->phy.rev >= 3) { 1472 cur_real = real_part; 1473 cur_imag = imag_part; 1474 tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF); 1475 } 1476 1477 for (j = 0; j < 128; j++) { 1478 if (dev->phy.rev < 3) { 1479 cur_real = (real_part * loscale[j] + 128) >> 8; 1480 cur_imag = (imag_part * loscale[j] + 128) >> 8; 1481 tmp = ((cur_real & 0xFF) << 8) | 1482 (cur_imag & 0xFF); 1483 } 1484 b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, 1485 ((tmp >> 16) & 0xFFFF)); 1486 b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 1487 (tmp & 0xFFFF)); 1488 } 1489 } 1490 1491 if (dev->phy.rev >= 3) { 1492 b43_shm_write16(dev, B43_SHM_SHARED, 1493 B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF); 1494 b43_shm_write16(dev, B43_SHM_SHARED, 1495 B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF); 1496 } 1497 1498 if (nphy->hang_avoid) 1499 b43_nphy_stay_in_carrier_search(dev, false); 1500} 1501 1502/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */ 1503static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd, 1504 u8 *events, u8 *delays, u8 length) 1505{ 1506 struct b43_phy_n *nphy = dev->phy.n; 1507 u8 i; 1508 u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F; 1509 u16 offset1 = cmd << 4; 1510 u16 offset2 = offset1 + 0x80; 1511 1512 if (nphy->hang_avoid) 1513 b43_nphy_stay_in_carrier_search(dev, true); 1514 1515 b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events); 1516 b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays); 1517 1518 for (i = length; i < 16; i++) { 1519 b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end); 1520 b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1); 1521 } 1522 1523 if (nphy->hang_avoid) 1524 b43_nphy_stay_in_carrier_search(dev, false); 1525} 1526 1527/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */ 1528static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, 1529 enum b43_nphy_rf_sequence seq) 1530{ 1531 static const u16 trigger[] = { 1532 [B43_RFSEQ_RX2TX] = B43_NPHY_RFSEQTR_RX2TX, 1533 [B43_RFSEQ_TX2RX] = B43_NPHY_RFSEQTR_TX2RX, 1534 [B43_RFSEQ_RESET2RX] = B43_NPHY_RFSEQTR_RST2RX, 1535 [B43_RFSEQ_UPDATE_GAINH] = B43_NPHY_RFSEQTR_UPGH, 1536 [B43_RFSEQ_UPDATE_GAINL] = B43_NPHY_RFSEQTR_UPGL, 1537 [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU, 1538 }; 1539 int i; 1540 u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE); 1541 1542 B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); 1543 1544 b43_phy_set(dev, B43_NPHY_RFSEQMODE, 1545 B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER); 1546 b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]); 1547 for (i = 0; i < 200; i++) { 1548 if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq])) 1549 goto ok; 1550 msleep(1); 1551 } 1552 b43err(dev->wl, "RF sequence status timeout\n"); 1553ok: 1554 b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode); 1555} 1556 1557/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */ 1558static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, 1559 u16 value, u8 core, bool off) 1560{ 1561 int i; 1562 u8 index = fls(field); 1563 u8 addr, en_addr, val_addr; 1564 /* we expect only one bit set */ 1565 B43_WARN_ON(field & (~(1 << (index - 1)))); 1566 1567 if (dev->phy.rev >= 3) { 1568 const struct nphy_rf_control_override_rev3 *rf_ctrl; 1569 for (i = 0; i < 2; i++) { 1570 if (index == 0 || index == 16) { 1571 b43err(dev->wl, 1572 "Unsupported RF Ctrl Override call\n"); 1573 return; 1574 } 1575 1576 rf_ctrl = &tbl_rf_control_override_rev3[index - 1]; 1577 en_addr = B43_PHY_N((i == 0) ? 1578 rf_ctrl->en_addr0 : rf_ctrl->en_addr1); 1579 val_addr = B43_PHY_N((i == 0) ? 1580 rf_ctrl->val_addr0 : rf_ctrl->val_addr1); 1581 1582 if (off) { 1583 b43_phy_mask(dev, en_addr, ~(field)); 1584 b43_phy_mask(dev, val_addr, 1585 ~(rf_ctrl->val_mask)); 1586 } else { 1587 if (core == 0 || ((1 << core) & i) != 0) { 1588 b43_phy_set(dev, en_addr, field); 1589 b43_phy_maskset(dev, val_addr, 1590 ~(rf_ctrl->val_mask), 1591 (value << rf_ctrl->val_shift)); 1592 } 1593 } 1594 } 1595 } else { 1596 const struct nphy_rf_control_override_rev2 *rf_ctrl; 1597 if (off) { 1598 b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field)); 1599 value = 0; 1600 } else { 1601 b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field); 1602 } 1603 1604 for (i = 0; i < 2; i++) { 1605 if (index <= 1 || index == 16) { 1606 b43err(dev->wl, 1607 "Unsupported RF Ctrl Override call\n"); 1608 return; 1609 } 1610 1611 if (index == 2 || index == 10 || 1612 (index >= 13 && index <= 15)) { 1613 core = 1; 1614 } 1615 1616 rf_ctrl = &tbl_rf_control_override_rev2[index - 2]; 1617 addr = B43_PHY_N((i == 0) ? 1618 rf_ctrl->addr0 : rf_ctrl->addr1); 1619 1620 if ((core & (1 << i)) != 0) 1621 b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask), 1622 (value << rf_ctrl->shift)); 1623 1624 b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1); 1625 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 1626 B43_NPHY_RFCTL_CMD_START); 1627 udelay(1); 1628 b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE); 1629 } 1630 } 1631} 1632 1633/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */ 1634static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, 1635 u16 value, u8 core) 1636{ 1637 u8 i, j; 1638 u16 reg, tmp, val; 1639 1640 B43_WARN_ON(dev->phy.rev < 3); 1641 B43_WARN_ON(field > 4); 1642 1643 for (i = 0; i < 2; i++) { 1644 if ((core == 1 && i == 1) || (core == 2 && !i)) 1645 continue; 1646 1647 reg = (i == 0) ? 1648 B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2; 1649 b43_phy_mask(dev, reg, 0xFBFF); 1650 1651 switch (field) { 1652 case 0: 1653 b43_phy_write(dev, reg, 0); 1654 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 1655 break; 1656 case 1: 1657 if (!i) { 1658 b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1, 1659 0xFC3F, (value << 6)); 1660 b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1, 1661 0xFFFE, 1); 1662 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 1663 B43_NPHY_RFCTL_CMD_START); 1664 for (j = 0; j < 100; j++) { 1665 if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) { 1666 j = 0; 1667 break; 1668 } 1669 udelay(10); 1670 } 1671 if (j) 1672 b43err(dev->wl, 1673 "intc override timeout\n"); 1674 b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1, 1675 0xFFFE); 1676 } else { 1677 b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2, 1678 0xFC3F, (value << 6)); 1679 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER, 1680 0xFFFE, 1); 1681 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 1682 B43_NPHY_RFCTL_CMD_RXTX); 1683 for (j = 0; j < 100; j++) { 1684 if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) { 1685 j = 0; 1686 break; 1687 } 1688 udelay(10); 1689 } 1690 if (j) 1691 b43err(dev->wl, 1692 "intc override timeout\n"); 1693 b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 1694 0xFFFE); 1695 } 1696 break; 1697 case 2: 1698 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { 1699 tmp = 0x0020; 1700 val = value << 5; 1701 } else { 1702 tmp = 0x0010; 1703 val = value << 4; 1704 } 1705 b43_phy_maskset(dev, reg, ~tmp, val); 1706 break; 1707 case 3: 1708 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { 1709 tmp = 0x0001; 1710 val = value; 1711 } else { 1712 tmp = 0x0004; 1713 val = value << 2; 1714 } 1715 b43_phy_maskset(dev, reg, ~tmp, val); 1716 break; 1717 case 4: 1718 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { 1719 tmp = 0x0002; 1720 val = value << 1; 1721 } else { 1722 tmp = 0x0008; 1723 val = value << 3; 1724 } 1725 b43_phy_maskset(dev, reg, ~tmp, val); 1726 break; 1727 } 1728 } 1729} 1730 1731/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */ 1732static void b43_nphy_bphy_init(struct b43_wldev *dev) 1733{ 1734 unsigned int i; 1735 u16 val; 1736 1737 val = 0x1E1F; 1738 for (i = 0; i < 16; i++) { 1739 b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); 1740 val -= 0x202; 1741 } 1742 val = 0x3E3F; 1743 for (i = 0; i < 16; i++) { 1744 b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); 1745 val -= 0x202; 1746 } 1747 b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); 1748} 1749 1750/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */ 1751static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale, 1752 s8 offset, u8 core, u8 rail, 1753 enum b43_nphy_rssi_type type) 1754{ 1755 u16 tmp; 1756 bool core1or5 = (core == 1) || (core == 5); 1757 bool core2or5 = (core == 2) || (core == 5); 1758 1759 offset = clamp_val(offset, -32, 31); 1760 tmp = ((scale & 0x3F) << 8) | (offset & 0x3F); 1761 1762 if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z)) 1763 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp); 1764 if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z)) 1765 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp); 1766 if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z)) 1767 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp); 1768 if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z)) 1769 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp); 1770 1771 if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X)) 1772 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp); 1773 if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X)) 1774 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp); 1775 if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X)) 1776 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp); 1777 if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X)) 1778 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp); 1779 1780 if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y)) 1781 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp); 1782 if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y)) 1783 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp); 1784 if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y)) 1785 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp); 1786 if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y)) 1787 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp); 1788 1789 if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD)) 1790 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp); 1791 if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD)) 1792 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp); 1793 if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD)) 1794 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp); 1795 if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD)) 1796 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp); 1797 1798 if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET)) 1799 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp); 1800 if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET)) 1801 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp); 1802 if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET)) 1803 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp); 1804 if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET)) 1805 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp); 1806 1807 if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I)) 1808 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp); 1809 if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I)) 1810 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp); 1811 1812 if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q)) 1813 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp); 1814 if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q)) 1815 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp); 1816} 1817 1818static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type) 1819{ 1820 u16 val; 1821 1822 if (type < 3) 1823 val = 0; 1824 else if (type == 6) 1825 val = 1; 1826 else if (type == 3) 1827 val = 2; 1828 else 1829 val = 3; 1830 1831 val = (val << 12) | (val << 14); 1832 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val); 1833 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val); 1834 1835 if (type < 3) { 1836 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF, 1837 (type + 1) << 4); 1838 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF, 1839 (type + 1) << 4); 1840 } 1841 1842 if (code == 0) { 1843 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000); 1844 if (type < 3) { 1845 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 1846 ~(B43_NPHY_RFCTL_CMD_RXEN | 1847 B43_NPHY_RFCTL_CMD_CORESEL)); 1848 b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 1849 ~(0x1 << 12 | 1850 0x1 << 5 | 1851 0x1 << 1 | 1852 0x1)); 1853 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 1854 ~B43_NPHY_RFCTL_CMD_START); 1855 udelay(20); 1856 b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1); 1857 } 1858 } else { 1859 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000); 1860 if (type < 3) { 1861 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD, 1862 ~(B43_NPHY_RFCTL_CMD_RXEN | 1863 B43_NPHY_RFCTL_CMD_CORESEL), 1864 (B43_NPHY_RFCTL_CMD_RXEN | 1865 code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT)); 1866 b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 1867 (0x1 << 12 | 1868 0x1 << 5 | 1869 0x1 << 1 | 1870 0x1)); 1871 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 1872 B43_NPHY_RFCTL_CMD_START); 1873 udelay(20); 1874 b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1); 1875 } 1876 } 1877} 1878 1879static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type) 1880{ 1881 struct b43_phy_n *nphy = dev->phy.n; 1882 u8 i; 1883 u16 reg, val; 1884 1885 if (code == 0) { 1886 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF); 1887 b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF); 1888 b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF); 1889 b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF); 1890 b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF); 1891 b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF); 1892 b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3); 1893 b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3); 1894 } else { 1895 for (i = 0; i < 2; i++) { 1896 if ((code == 1 && i == 1) || (code == 2 && !i)) 1897 continue; 1898 1899 reg = (i == 0) ? 1900 B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER; 1901 b43_phy_maskset(dev, reg, 0xFDFF, 0x0200); 1902 1903 if (type < 3) { 1904 reg = (i == 0) ? 1905 B43_NPHY_AFECTL_C1 : 1906 B43_NPHY_AFECTL_C2; 1907 b43_phy_maskset(dev, reg, 0xFCFF, 0); 1908 1909 reg = (i == 0) ? 1910 B43_NPHY_RFCTL_LUT_TRSW_UP1 : 1911 B43_NPHY_RFCTL_LUT_TRSW_UP2; 1912 b43_phy_maskset(dev, reg, 0xFFC3, 0); 1913 1914 if (type == 0) 1915 val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8; 1916 else if (type == 1) 1917 val = 16; 1918 else 1919 val = 32; 1920 b43_phy_set(dev, reg, val); 1921 1922 reg = (i == 0) ? 1923 B43_NPHY_TXF_40CO_B1S0 : 1924 B43_NPHY_TXF_40CO_B32S1; 1925 b43_phy_set(dev, reg, 0x0020); 1926 } else { 1927 if (type == 6) 1928 val = 0x0100; 1929 else if (type == 3) 1930 val = 0x0200; 1931 else 1932 val = 0x0300; 1933 1934 reg = (i == 0) ? 1935 B43_NPHY_AFECTL_C1 : 1936 B43_NPHY_AFECTL_C2; 1937 1938 b43_phy_maskset(dev, reg, 0xFCFF, val); 1939 b43_phy_maskset(dev, reg, 0xF3FF, val << 2); 1940 1941 if (type != 3 && type != 6) { 1942 enum ieee80211_band band = 1943 b43_current_band(dev->wl); 1944 1945 if ((nphy->ipa2g_on && 1946 band == IEEE80211_BAND_2GHZ) || 1947 (nphy->ipa5g_on && 1948 band == IEEE80211_BAND_5GHZ)) 1949 val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE; 1950 else 1951 val = 0x11; 1952 reg = (i == 0) ? 0x2000 : 0x3000; 1953 reg |= B2055_PADDRV; 1954 b43_radio_write16(dev, reg, val); 1955 1956 reg = (i == 0) ? 1957 B43_NPHY_AFECTL_OVER1 : 1958 B43_NPHY_AFECTL_OVER; 1959 b43_phy_set(dev, reg, 0x0200); 1960 } 1961 } 1962 } 1963 } 1964} 1965 1966/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */ 1967static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type) 1968{ 1969 if (dev->phy.rev >= 3) 1970 b43_nphy_rev3_rssi_select(dev, code, type); 1971 else 1972 b43_nphy_rev2_rssi_select(dev, code, type); 1973} 1974 1975/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */ 1976static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf) 1977{ 1978 int i; 1979 for (i = 0; i < 2; i++) { 1980 if (type == 2) { 1981 if (i == 0) { 1982 b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM, 1983 0xFC, buf[0]); 1984 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, 1985 0xFC, buf[1]); 1986 } else { 1987 b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM, 1988 0xFC, buf[2 * i]); 1989 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, 1990 0xFC, buf[2 * i + 1]); 1991 } 1992 } else { 1993 if (i == 0) 1994 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5, 1995 0xF3, buf[0] << 2); 1996 else 1997 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5, 1998 0xF3, buf[2 * i + 1] << 2); 1999 } 2000 } 2001} 2002 2003/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */ 2004static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf, 2005 u8 nsamp) 2006{ 2007 int i; 2008 int out; 2009 u16 save_regs_phy[9]; 2010 u16 s[2]; 2011 2012 if (dev->phy.rev >= 3) { 2013 save_regs_phy[0] = b43_phy_read(dev, 2014 B43_NPHY_RFCTL_LUT_TRSW_UP1); 2015 save_regs_phy[1] = b43_phy_read(dev, 2016 B43_NPHY_RFCTL_LUT_TRSW_UP2); 2017 save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 2018 save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 2019 save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); 2020 save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 2021 save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0); 2022 save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1); 2023 } else if (dev->phy.rev == 2) { 2024 save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 2025 save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 2026 save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 2027 save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD); 2028 save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER); 2029 save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1); 2030 save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2); 2031 } 2032 2033 b43_nphy_rssi_select(dev, 5, type); 2034 2035 if (dev->phy.rev < 2) { 2036 save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL); 2037 b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5); 2038 } 2039 2040 for (i = 0; i < 4; i++) 2041 buf[i] = 0; 2042 2043 for (i = 0; i < nsamp; i++) { 2044 if (dev->phy.rev < 2) { 2045 s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT); 2046 s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT); 2047 } else { 2048 s[0] = b43_phy_read(dev, B43_NPHY_RSSI1); 2049 s[1] = b43_phy_read(dev, B43_NPHY_RSSI2); 2050 } 2051 2052 buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2; 2053 buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2; 2054 buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2; 2055 buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2; 2056 } 2057 out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 | 2058 (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF); 2059 2060 if (dev->phy.rev < 2) 2061 b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]); 2062 2063 if (dev->phy.rev >= 3) { 2064 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 2065 save_regs_phy[0]); 2066 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 2067 save_regs_phy[1]); 2068 b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]); 2069 b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]); 2070 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]); 2071 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]); 2072 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]); 2073 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]); 2074 } else if (dev->phy.rev == 2) { 2075 b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]); 2076 b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]); 2077 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]); 2078 b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]); 2079 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]); 2080 b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]); 2081 b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]); 2082 } 2083 2084 return out; 2085} 2086 2087/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */ 2088static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) 2089{ 2090 int i, j; 2091 u8 state[4]; 2092 u8 code, val; 2093 u16 class, override; 2094 u8 regs_save_radio[2]; 2095 u16 regs_save_phy[2]; 2096 2097 s8 offset[4]; 2098 u8 core; 2099 u8 rail; 2100 2101 u16 clip_state[2]; 2102 u16 clip_off[2] = { 0xFFFF, 0xFFFF }; 2103 s32 results_min[4] = { }; 2104 u8 vcm_final[4] = { }; 2105 s32 results[4][4] = { }; 2106 s32 miniq[4][2] = { }; 2107 2108 if (type == 2) { 2109 code = 0; 2110 val = 6; 2111 } else if (type < 2) { 2112 code = 25; 2113 val = 4; 2114 } else { 2115 B43_WARN_ON(1); 2116 return; 2117 } 2118 2119 class = b43_nphy_classifier(dev, 0, 0); 2120 b43_nphy_classifier(dev, 7, 4); 2121 b43_nphy_read_clip_detection(dev, clip_state); 2122 b43_nphy_write_clip_detection(dev, clip_off); 2123 2124 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) 2125 override = 0x140; 2126 else 2127 override = 0x110; 2128 2129 regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 2130 regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX); 2131 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override); 2132 b43_radio_write16(dev, B2055_C1_PD_RXTX, val); 2133 2134 regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 2135 regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX); 2136 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override); 2137 b43_radio_write16(dev, B2055_C2_PD_RXTX, val); 2138 2139 state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07; 2140 state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07; 2141 b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8); 2142 b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8); 2143 state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07; 2144 state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07; 2145 2146 b43_nphy_rssi_select(dev, 5, type); 2147 b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type); 2148 b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type); 2149 2150 for (i = 0; i < 4; i++) { 2151 u8 tmp[4]; 2152 for (j = 0; j < 4; j++) 2153 tmp[j] = i; 2154 if (type != 1) 2155 b43_nphy_set_rssi_2055_vcm(dev, type, tmp); 2156 b43_nphy_poll_rssi(dev, type, results[i], 8); 2157 if (type < 2) 2158 for (j = 0; j < 2; j++) 2159 miniq[i][j] = min(results[i][2 * j], 2160 results[i][2 * j + 1]); 2161 } 2162 2163 for (i = 0; i < 4; i++) { 2164 s32 mind = 40; 2165 u8 minvcm = 0; 2166 s32 minpoll = 249; 2167 s32 curr; 2168 for (j = 0; j < 4; j++) { 2169 if (type == 2) 2170 curr = abs(results[j][i]); 2171 else 2172 curr = abs(miniq[j][i / 2] - code * 8); 2173 2174 if (curr < mind) { 2175 mind = curr; 2176 minvcm = j; 2177 } 2178 2179 if (results[j][i] < minpoll) 2180 minpoll = results[j][i]; 2181 } 2182 results_min[i] = minpoll; 2183 vcm_final[i] = minvcm; 2184 } 2185 2186 if (type != 1) 2187 b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final); 2188 2189 for (i = 0; i < 4; i++) { 2190 offset[i] = (code * 8) - results[vcm_final[i]][i]; 2191 2192 if (offset[i] < 0) 2193 offset[i] = -((abs(offset[i]) + 4) / 8); 2194 else 2195 offset[i] = (offset[i] + 4) / 8; 2196 2197 if (results_min[i] == 248) 2198 offset[i] = code - 32; 2199 2200 core = (i / 2) ? 2 : 1; 2201 rail = (i % 2) ? 1 : 0; 2202 2203 b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail, 2204 type); 2205 } 2206 2207 b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]); 2208 b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]); 2209 2210 switch (state[2]) { 2211 case 1: 2212 b43_nphy_rssi_select(dev, 1, 2); 2213 break; 2214 case 4: 2215 b43_nphy_rssi_select(dev, 1, 0); 2216 break; 2217 case 2: 2218 b43_nphy_rssi_select(dev, 1, 1); 2219 break; 2220 default: 2221 b43_nphy_rssi_select(dev, 1, 1); 2222 break; 2223 } 2224 2225 switch (state[3]) { 2226 case 1: 2227 b43_nphy_rssi_select(dev, 2, 2); 2228 break; 2229 case 4: 2230 b43_nphy_rssi_select(dev, 2, 0); 2231 break; 2232 default: 2233 b43_nphy_rssi_select(dev, 2, 1); 2234 break; 2235 } 2236 2237 b43_nphy_rssi_select(dev, 0, type); 2238 2239 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]); 2240 b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]); 2241 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]); 2242 b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]); 2243 2244 b43_nphy_classifier(dev, 7, class); 2245 b43_nphy_write_clip_detection(dev, clip_state); 2246 /* Specs don't say about reset here, but it makes wl and b43 dumps 2247 identical, it really seems wl performs this */ 2248 b43_nphy_reset_cca(dev); 2249} 2250 2251/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */ 2252static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) 2253{ 2254 /* TODO */ 2255} 2256 2257/* 2258 * RSSI Calibration 2259 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal 2260 */ 2261static void b43_nphy_rssi_cal(struct b43_wldev *dev) 2262{ 2263 if (dev->phy.rev >= 3) { 2264 b43_nphy_rev3_rssi_cal(dev); 2265 } else { 2266 b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z); 2267 b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X); 2268 b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y); 2269 } 2270} 2271 2272/* 2273 * Restore RSSI Calibration 2274 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal 2275 */ 2276static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) 2277{ 2278 struct b43_phy_n *nphy = dev->phy.n; 2279 2280 u16 *rssical_radio_regs = NULL; 2281 u16 *rssical_phy_regs = NULL; 2282 2283 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 2284 if (!nphy->rssical_chanspec_2G.center_freq) 2285 return; 2286 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 2287 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 2288 } else { 2289 if (!nphy->rssical_chanspec_5G.center_freq) 2290 return; 2291 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 2292 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 2293 } 2294 2295 /* TODO use some definitions */ 2296 b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]); 2297 b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]); 2298 2299 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]); 2300 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]); 2301 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]); 2302 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]); 2303 2304 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]); 2305 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]); 2306 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]); 2307 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]); 2308 2309 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]); 2310 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]); 2311 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]); 2312 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]); 2313} 2314 2315/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */ 2316static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev) 2317{ 2318 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 2319 if (dev->phy.rev >= 6) { 2320 /* TODO If the chip is 47162 2321 return txpwrctrl_tx_gain_ipa_rev5 */ 2322 return txpwrctrl_tx_gain_ipa_rev6; 2323 } else if (dev->phy.rev >= 5) { 2324 return txpwrctrl_tx_gain_ipa_rev5; 2325 } else { 2326 return txpwrctrl_tx_gain_ipa; 2327 } 2328 } else { 2329 return txpwrctrl_tx_gain_ipa_5g; 2330 } 2331} 2332 2333/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */ 2334static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev) 2335{ 2336 struct b43_phy_n *nphy = dev->phy.n; 2337 u16 *save = nphy->tx_rx_cal_radio_saveregs; 2338 u16 tmp; 2339 u8 offset, i; 2340 2341 if (dev->phy.rev >= 3) { 2342 for (i = 0; i < 2; i++) { 2343 tmp = (i == 0) ? 0x2000 : 0x3000; 2344 offset = i * 11; 2345 2346 save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL); 2347 save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL); 2348 save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS); 2349 save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS); 2350 save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS); 2351 save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV); 2352 save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1); 2353 save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2); 2354 save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL); 2355 save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC); 2356 save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1); 2357 2358 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { 2359 b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A); 2360 b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40); 2361 b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55); 2362 b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0); 2363 b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0); 2364 if (nphy->ipa5g_on) { 2365 b43_radio_write16(dev, tmp | B2055_PADDRV, 4); 2366 b43_radio_write16(dev, tmp | B2055_XOCTL1, 1); 2367 } else { 2368 b43_radio_write16(dev, tmp | B2055_PADDRV, 0); 2369 b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F); 2370 } 2371 b43_radio_write16(dev, tmp | B2055_XOCTL2, 0); 2372 } else { 2373 b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06); 2374 b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40); 2375 b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55); 2376 b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0); 2377 b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0); 2378 b43_radio_write16(dev, tmp | B2055_XOCTL1, 0); 2379 if (nphy->ipa2g_on) { 2380 b43_radio_write16(dev, tmp | B2055_PADDRV, 6); 2381 b43_radio_write16(dev, tmp | B2055_XOCTL2, 2382 (dev->phy.rev < 5) ? 0x11 : 0x01); 2383 } else { 2384 b43_radio_write16(dev, tmp | B2055_PADDRV, 0); 2385 b43_radio_write16(dev, tmp | B2055_XOCTL2, 0); 2386 } 2387 } 2388 b43_radio_write16(dev, tmp | B2055_XOREGUL, 0); 2389 b43_radio_write16(dev, tmp | B2055_XOMISC, 0); 2390 b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0); 2391 } 2392 } else { 2393 save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1); 2394 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29); 2395 2396 save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2); 2397 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54); 2398 2399 save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1); 2400 b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29); 2401 2402 save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2); 2403 b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54); 2404 2405 save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX); 2406 save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX); 2407 2408 if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) & 2409 B43_NPHY_BANDCTL_5GHZ)) { 2410 b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04); 2411 b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04); 2412 } else { 2413 b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20); 2414 b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20); 2415 } 2416 2417 if (dev->phy.rev < 2) { 2418 b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20); 2419 b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20); 2420 } else { 2421 b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20); 2422 b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20); 2423 } 2424 } 2425} 2426 2427/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */ 2428static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core, 2429 struct nphy_txgains target, 2430 struct nphy_iqcal_params *params) 2431{ 2432 int i, j, indx; 2433 u16 gain; 2434 2435 if (dev->phy.rev >= 3) { 2436 params->txgm = target.txgm[core]; 2437 params->pga = target.pga[core]; 2438 params->pad = target.pad[core]; 2439 params->ipa = target.ipa[core]; 2440 params->cal_gain = (params->txgm << 12) | (params->pga << 8) | 2441 (params->pad << 4) | (params->ipa); 2442 for (j = 0; j < 5; j++) 2443 params->ncorr[j] = 0x79; 2444 } else { 2445 gain = (target.pad[core]) | (target.pga[core] << 4) | 2446 (target.txgm[core] << 8); 2447 2448 indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 2449 1 : 0; 2450 for (i = 0; i < 9; i++) 2451 if (tbl_iqcal_gainparams[indx][i][0] == gain) 2452 break; 2453 i = min(i, 8); 2454 2455 params->txgm = tbl_iqcal_gainparams[indx][i][1]; 2456 params->pga = tbl_iqcal_gainparams[indx][i][2]; 2457 params->pad = tbl_iqcal_gainparams[indx][i][3]; 2458 params->cal_gain = (params->txgm << 7) | (params->pga << 4) | 2459 (params->pad << 2); 2460 for (j = 0; j < 4; j++) 2461 params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j]; 2462 } 2463} 2464 2465/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */ 2466static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core) 2467{ 2468 struct b43_phy_n *nphy = dev->phy.n; 2469 int i; 2470 u16 scale, entry; 2471 2472 u16 tmp = nphy->txcal_bbmult; 2473 if (core == 0) 2474 tmp >>= 8; 2475 tmp &= 0xff; 2476 2477 for (i = 0; i < 18; i++) { 2478 scale = (ladder_lo[i].percent * tmp) / 100; 2479 entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env; 2480 b43_ntab_write(dev, B43_NTAB16(15, i), entry); 2481 2482 scale = (ladder_iq[i].percent * tmp) / 100; 2483 entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env; 2484 b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry); 2485 } 2486} 2487 2488/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */ 2489static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev) 2490{ 2491 int i; 2492 for (i = 0; i < 15; i++) 2493 b43_phy_write(dev, B43_PHY_N(0x2C5 + i), 2494 tbl_tx_filter_coef_rev4[2][i]); 2495} 2496 2497/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */ 2498static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev) 2499{ 2500 int i, j; 2501 /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */ 2502 static const u16 offset[] = { 0x186, 0x195, 0x2C5 }; 2503 2504 for (i = 0; i < 3; i++) 2505 for (j = 0; j < 15; j++) 2506 b43_phy_write(dev, B43_PHY_N(offset[i] + j), 2507 tbl_tx_filter_coef_rev4[i][j]); 2508 2509 if (dev->phy.is_40mhz) { 2510 for (j = 0; j < 15; j++) 2511 b43_phy_write(dev, B43_PHY_N(offset[0] + j), 2512 tbl_tx_filter_coef_rev4[3][j]); 2513 } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) { 2514 for (j = 0; j < 15; j++) 2515 b43_phy_write(dev, B43_PHY_N(offset[0] + j), 2516 tbl_tx_filter_coef_rev4[5][j]); 2517 } 2518 2519 if (dev->phy.channel == 14) 2520 for (j = 0; j < 15; j++) 2521 b43_phy_write(dev, B43_PHY_N(offset[0] + j), 2522 tbl_tx_filter_coef_rev4[6][j]); 2523} 2524 2525/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */ 2526static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev) 2527{ 2528 struct b43_phy_n *nphy = dev->phy.n; 2529 2530 u16 curr_gain[2]; 2531 struct nphy_txgains target; 2532 const u32 *table = NULL; 2533 2534 if (!nphy->txpwrctrl) { 2535 int i; 2536 2537 if (nphy->hang_avoid) 2538 b43_nphy_stay_in_carrier_search(dev, true); 2539 b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain); 2540 if (nphy->hang_avoid) 2541 b43_nphy_stay_in_carrier_search(dev, false); 2542 2543 for (i = 0; i < 2; ++i) { 2544 if (dev->phy.rev >= 3) { 2545 target.ipa[i] = curr_gain[i] & 0x000F; 2546 target.pad[i] = (curr_gain[i] & 0x00F0) >> 4; 2547 target.pga[i] = (curr_gain[i] & 0x0F00) >> 8; 2548 target.txgm[i] = (curr_gain[i] & 0x7000) >> 12; 2549 } else { 2550 target.ipa[i] = curr_gain[i] & 0x0003; 2551 target.pad[i] = (curr_gain[i] & 0x000C) >> 2; 2552 target.pga[i] = (curr_gain[i] & 0x0070) >> 4; 2553 target.txgm[i] = (curr_gain[i] & 0x0380) >> 7; 2554 } 2555 } 2556 } else { 2557 int i; 2558 u16 index[2]; 2559 index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) & 2560 B43_NPHY_TXPCTL_STAT_BIDX) >> 2561 B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; 2562 index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) & 2563 B43_NPHY_TXPCTL_STAT_BIDX) >> 2564 B43_NPHY_TXPCTL_STAT_BIDX_SHIFT; 2565 2566 for (i = 0; i < 2; ++i) { 2567 if (dev->phy.rev >= 3) { 2568 enum ieee80211_band band = 2569 b43_current_band(dev->wl); 2570 2571 if ((nphy->ipa2g_on && 2572 band == IEEE80211_BAND_2GHZ) || 2573 (nphy->ipa5g_on && 2574 band == IEEE80211_BAND_5GHZ)) { 2575 table = b43_nphy_get_ipa_gain_table(dev); 2576 } else { 2577 if (band == IEEE80211_BAND_5GHZ) { 2578 if (dev->phy.rev == 3) 2579 table = b43_ntab_tx_gain_rev3_5ghz; 2580 else if (dev->phy.rev == 4) 2581 table = b43_ntab_tx_gain_rev4_5ghz; 2582 else 2583 table = b43_ntab_tx_gain_rev5plus_5ghz; 2584 } else { 2585 table = b43_ntab_tx_gain_rev3plus_2ghz; 2586 } 2587 } 2588 2589 target.ipa[i] = (table[index[i]] >> 16) & 0xF; 2590 target.pad[i] = (table[index[i]] >> 20) & 0xF; 2591 target.pga[i] = (table[index[i]] >> 24) & 0xF; 2592 target.txgm[i] = (table[index[i]] >> 28) & 0xF; 2593 } else { 2594 table = b43_ntab_tx_gain_rev0_1_2; 2595 2596 target.ipa[i] = (table[index[i]] >> 16) & 0x3; 2597 target.pad[i] = (table[index[i]] >> 18) & 0x3; 2598 target.pga[i] = (table[index[i]] >> 20) & 0x7; 2599 target.txgm[i] = (table[index[i]] >> 23) & 0x7; 2600 } 2601 } 2602 } 2603 2604 return target; 2605} 2606 2607/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */ 2608static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev) 2609{ 2610 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; 2611 2612 if (dev->phy.rev >= 3) { 2613 b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]); 2614 b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]); 2615 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]); 2616 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]); 2617 b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]); 2618 b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]); 2619 b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]); 2620 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]); 2621 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]); 2622 b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]); 2623 b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]); 2624 b43_nphy_reset_cca(dev); 2625 } else { 2626 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]); 2627 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]); 2628 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]); 2629 b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]); 2630 b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]); 2631 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]); 2632 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]); 2633 } 2634} 2635 2636/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */ 2637static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev) 2638{ 2639 u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs; 2640 u16 tmp; 2641 2642 regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1); 2643 regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2); 2644 if (dev->phy.rev >= 3) { 2645 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00); 2646 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00); 2647 2648 tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1); 2649 regs[2] = tmp; 2650 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600); 2651 2652 tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 2653 regs[3] = tmp; 2654 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600); 2655 2656 regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG); 2657 b43_phy_mask(dev, B43_NPHY_BBCFG, 2658 ~B43_NPHY_BBCFG_RSTRX & 0xFFFF); 2659 2660 tmp = b43_ntab_read(dev, B43_NTAB16(8, 3)); 2661 regs[5] = tmp; 2662 b43_ntab_write(dev, B43_NTAB16(8, 3), 0); 2663 2664 tmp = b43_ntab_read(dev, B43_NTAB16(8, 19)); 2665 regs[6] = tmp; 2666 b43_ntab_write(dev, B43_NTAB16(8, 19), 0); 2667 regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 2668 regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 2669 2670 b43_nphy_rf_control_intc_override(dev, 2, 1, 3); 2671 b43_nphy_rf_control_intc_override(dev, 1, 2, 1); 2672 b43_nphy_rf_control_intc_override(dev, 1, 8, 2); 2673 2674 regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0); 2675 regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1); 2676 b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001); 2677 b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001); 2678 } else { 2679 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000); 2680 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000); 2681 tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 2682 regs[2] = tmp; 2683 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000); 2684 tmp = b43_ntab_read(dev, B43_NTAB16(8, 2)); 2685 regs[3] = tmp; 2686 tmp |= 0x2000; 2687 b43_ntab_write(dev, B43_NTAB16(8, 2), tmp); 2688 tmp = b43_ntab_read(dev, B43_NTAB16(8, 18)); 2689 regs[4] = tmp; 2690 tmp |= 0x2000; 2691 b43_ntab_write(dev, B43_NTAB16(8, 18), tmp); 2692 regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1); 2693 regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2); 2694 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) 2695 tmp = 0x0180; 2696 else 2697 tmp = 0x0120; 2698 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp); 2699 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp); 2700 } 2701} 2702 2703/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */ 2704static void b43_nphy_save_cal(struct b43_wldev *dev) 2705{ 2706 struct b43_phy_n *nphy = dev->phy.n; 2707 2708 struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; 2709 u16 *txcal_radio_regs = NULL; 2710 struct b43_chanspec *iqcal_chanspec; 2711 u16 *table = NULL; 2712 2713 if (nphy->hang_avoid) 2714 b43_nphy_stay_in_carrier_search(dev, 1); 2715 2716 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 2717 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 2718 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 2719 iqcal_chanspec = &nphy->iqcal_chanspec_2G; 2720 table = nphy->cal_cache.txcal_coeffs_2G; 2721 } else { 2722 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 2723 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 2724 iqcal_chanspec = &nphy->iqcal_chanspec_5G; 2725 table = nphy->cal_cache.txcal_coeffs_5G; 2726 } 2727 2728 b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs); 2729 /* TODO use some definitions */ 2730 if (dev->phy.rev >= 3) { 2731 txcal_radio_regs[0] = b43_radio_read(dev, 0x2021); 2732 txcal_radio_regs[1] = b43_radio_read(dev, 0x2022); 2733 txcal_radio_regs[2] = b43_radio_read(dev, 0x3021); 2734 txcal_radio_regs[3] = b43_radio_read(dev, 0x3022); 2735 txcal_radio_regs[4] = b43_radio_read(dev, 0x2023); 2736 txcal_radio_regs[5] = b43_radio_read(dev, 0x2024); 2737 txcal_radio_regs[6] = b43_radio_read(dev, 0x3023); 2738 txcal_radio_regs[7] = b43_radio_read(dev, 0x3024); 2739 } else { 2740 txcal_radio_regs[0] = b43_radio_read(dev, 0x8B); 2741 txcal_radio_regs[1] = b43_radio_read(dev, 0xBA); 2742 txcal_radio_regs[2] = b43_radio_read(dev, 0x8D); 2743 txcal_radio_regs[3] = b43_radio_read(dev, 0xBC); 2744 } 2745 iqcal_chanspec->center_freq = dev->phy.channel_freq; 2746 iqcal_chanspec->channel_type = dev->phy.channel_type; 2747 b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table); 2748 2749 if (nphy->hang_avoid) 2750 b43_nphy_stay_in_carrier_search(dev, 0); 2751} 2752 2753/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */ 2754static void b43_nphy_restore_cal(struct b43_wldev *dev) 2755{ 2756 struct b43_phy_n *nphy = dev->phy.n; 2757 2758 u16 coef[4]; 2759 u16 *loft = NULL; 2760 u16 *table = NULL; 2761 2762 int i; 2763 u16 *txcal_radio_regs = NULL; 2764 struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; 2765 2766 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 2767 if (!nphy->iqcal_chanspec_2G.center_freq) 2768 return; 2769 table = nphy->cal_cache.txcal_coeffs_2G; 2770 loft = &nphy->cal_cache.txcal_coeffs_2G[5]; 2771 } else { 2772 if (!nphy->iqcal_chanspec_5G.center_freq) 2773 return; 2774 table = nphy->cal_cache.txcal_coeffs_5G; 2775 loft = &nphy->cal_cache.txcal_coeffs_5G[5]; 2776 } 2777 2778 b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table); 2779 2780 for (i = 0; i < 4; i++) { 2781 if (dev->phy.rev >= 3) 2782 table[i] = coef[i]; 2783 else 2784 coef[i] = 0; 2785 } 2786 2787 b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef); 2788 b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft); 2789 b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft); 2790 2791 if (dev->phy.rev < 2) 2792 b43_nphy_tx_iq_workaround(dev); 2793 2794 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 2795 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G; 2796 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G; 2797 } else { 2798 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G; 2799 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G; 2800 } 2801 2802 /* TODO use some definitions */ 2803 if (dev->phy.rev >= 3) { 2804 b43_radio_write(dev, 0x2021, txcal_radio_regs[0]); 2805 b43_radio_write(dev, 0x2022, txcal_radio_regs[1]); 2806 b43_radio_write(dev, 0x3021, txcal_radio_regs[2]); 2807 b43_radio_write(dev, 0x3022, txcal_radio_regs[3]); 2808 b43_radio_write(dev, 0x2023, txcal_radio_regs[4]); 2809 b43_radio_write(dev, 0x2024, txcal_radio_regs[5]); 2810 b43_radio_write(dev, 0x3023, txcal_radio_regs[6]); 2811 b43_radio_write(dev, 0x3024, txcal_radio_regs[7]); 2812 } else { 2813 b43_radio_write(dev, 0x8B, txcal_radio_regs[0]); 2814 b43_radio_write(dev, 0xBA, txcal_radio_regs[1]); 2815 b43_radio_write(dev, 0x8D, txcal_radio_regs[2]); 2816 b43_radio_write(dev, 0xBC, txcal_radio_regs[3]); 2817 } 2818 b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs); 2819} 2820 2821/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */ 2822static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, 2823 struct nphy_txgains target, 2824 bool full, bool mphase) 2825{ 2826 struct b43_phy_n *nphy = dev->phy.n; 2827 int i; 2828 int error = 0; 2829 int freq; 2830 bool avoid = false; 2831 u8 length; 2832 u16 tmp, core, type, count, max, numb, last, cmd; 2833 const u16 *table; 2834 bool phy6or5x; 2835 2836 u16 buffer[11]; 2837 u16 diq_start = 0; 2838 u16 save[2]; 2839 u16 gain[2]; 2840 struct nphy_iqcal_params params[2]; 2841 bool updated[2] = { }; 2842 2843 b43_nphy_stay_in_carrier_search(dev, true); 2844 2845 if (dev->phy.rev >= 4) { 2846 avoid = nphy->hang_avoid; 2847 nphy->hang_avoid = 0; 2848 } 2849 2850 b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save); 2851 2852 for (i = 0; i < 2; i++) { 2853 b43_nphy_iq_cal_gain_params(dev, i, target, ¶ms[i]); 2854 gain[i] = params[i].cal_gain; 2855 } 2856 2857 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain); 2858 2859 b43_nphy_tx_cal_radio_setup(dev); 2860 b43_nphy_tx_cal_phy_setup(dev); 2861 2862 phy6or5x = dev->phy.rev >= 6 || 2863 (dev->phy.rev == 5 && nphy->ipa2g_on && 2864 b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ); 2865 if (phy6or5x) { 2866 if (dev->phy.is_40mhz) { 2867 b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18, 2868 tbl_tx_iqlo_cal_loft_ladder_40); 2869 b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18, 2870 tbl_tx_iqlo_cal_iqimb_ladder_40); 2871 } else { 2872 b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18, 2873 tbl_tx_iqlo_cal_loft_ladder_20); 2874 b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18, 2875 tbl_tx_iqlo_cal_iqimb_ladder_20); 2876 } 2877 } 2878 2879 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9); 2880 2881 if (!dev->phy.is_40mhz) 2882 freq = 2500; 2883 else 2884 freq = 5000; 2885 2886 if (nphy->mphase_cal_phase_id > 2) 2887 b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8, 2888 0xFFFF, 0, true, false); 2889 else 2890 error = b43_nphy_tx_tone(dev, freq, 250, true, false); 2891 2892 if (error == 0) { 2893 if (nphy->mphase_cal_phase_id > 2) { 2894 table = nphy->mphase_txcal_bestcoeffs; 2895 length = 11; 2896 if (dev->phy.rev < 3) 2897 length -= 2; 2898 } else { 2899 if (!full && nphy->txiqlocal_coeffsvalid) { 2900 table = nphy->txiqlocal_bestc; 2901 length = 11; 2902 if (dev->phy.rev < 3) 2903 length -= 2; 2904 } else { 2905 full = true; 2906 if (dev->phy.rev >= 3) { 2907 table = tbl_tx_iqlo_cal_startcoefs_nphyrev3; 2908 length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3; 2909 } else { 2910 table = tbl_tx_iqlo_cal_startcoefs; 2911 length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS; 2912 } 2913 } 2914 } 2915 2916 b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table); 2917 2918 if (full) { 2919 if (dev->phy.rev >= 3) 2920 max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3; 2921 else 2922 max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL; 2923 } else { 2924 if (dev->phy.rev >= 3) 2925 max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3; 2926 else 2927 max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL; 2928 } 2929 2930 if (mphase) { 2931 count = nphy->mphase_txcal_cmdidx; 2932 numb = min(max, 2933 (u16)(count + nphy->mphase_txcal_numcmds)); 2934 } else { 2935 count = 0; 2936 numb = max; 2937 } 2938 2939 for (; count < numb; count++) { 2940 if (full) { 2941 if (dev->phy.rev >= 3) 2942 cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count]; 2943 else 2944 cmd = tbl_tx_iqlo_cal_cmds_fullcal[count]; 2945 } else { 2946 if (dev->phy.rev >= 3) 2947 cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count]; 2948 else 2949 cmd = tbl_tx_iqlo_cal_cmds_recal[count]; 2950 } 2951 2952 core = (cmd & 0x3000) >> 12; 2953 type = (cmd & 0x0F00) >> 8; 2954 2955 if (phy6or5x && updated[core] == 0) { 2956 b43_nphy_update_tx_cal_ladder(dev, core); 2957 updated[core] = 1; 2958 } 2959 2960 tmp = (params[core].ncorr[type] << 8) | 0x66; 2961 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp); 2962 2963 if (type == 1 || type == 3 || type == 4) { 2964 buffer[0] = b43_ntab_read(dev, 2965 B43_NTAB16(15, 69 + core)); 2966 diq_start = buffer[0]; 2967 buffer[0] = 0; 2968 b43_ntab_write(dev, B43_NTAB16(15, 69 + core), 2969 0); 2970 } 2971 2972 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd); 2973 for (i = 0; i < 2000; i++) { 2974 tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD); 2975 if (tmp & 0xC000) 2976 break; 2977 udelay(10); 2978 } 2979 2980 b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, 2981 buffer); 2982 b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, 2983 buffer); 2984 2985 if (type == 1 || type == 3 || type == 4) 2986 buffer[0] = diq_start; 2987 } 2988 2989 if (mphase) 2990 nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb; 2991 2992 last = (dev->phy.rev < 3) ? 6 : 7; 2993 2994 if (!mphase || nphy->mphase_cal_phase_id == last) { 2995 b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer); 2996 b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer); 2997 if (dev->phy.rev < 3) { 2998 buffer[0] = 0; 2999 buffer[1] = 0; 3000 buffer[2] = 0; 3001 buffer[3] = 0; 3002 } 3003 b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, 3004 buffer); 3005 b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2, 3006 buffer); 3007 b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, 3008 buffer); 3009 b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, 3010 buffer); 3011 length = 11; 3012 if (dev->phy.rev < 3) 3013 length -= 2; 3014 b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, 3015 nphy->txiqlocal_bestc); 3016 nphy->txiqlocal_coeffsvalid = true; 3017 nphy->txiqlocal_chanspec.center_freq = 3018 dev->phy.channel_freq; 3019 nphy->txiqlocal_chanspec.channel_type = 3020 dev->phy.channel_type; 3021 } else { 3022 length = 11; 3023 if (dev->phy.rev < 3) 3024 length -= 2; 3025 b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, 3026 nphy->mphase_txcal_bestcoeffs); 3027 } 3028 3029 b43_nphy_stop_playback(dev); 3030 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0); 3031 } 3032 3033 b43_nphy_tx_cal_phy_cleanup(dev); 3034 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save); 3035 3036 if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last)) 3037 b43_nphy_tx_iq_workaround(dev); 3038 3039 if (dev->phy.rev >= 4) 3040 nphy->hang_avoid = avoid; 3041 3042 b43_nphy_stay_in_carrier_search(dev, false); 3043 3044 return error; 3045} 3046 3047/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */ 3048static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev) 3049{ 3050 struct b43_phy_n *nphy = dev->phy.n; 3051 u8 i; 3052 u16 buffer[7]; 3053 bool equal = true; 3054 3055 if (!nphy->txiqlocal_coeffsvalid || 3056 nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq || 3057 nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type) 3058 return; 3059 3060 b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); 3061 for (i = 0; i < 4; i++) { 3062 if (buffer[i] != nphy->txiqlocal_bestc[i]) { 3063 equal = false; 3064 break; 3065 } 3066 } 3067 3068 if (!equal) { 3069 b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, 3070 nphy->txiqlocal_bestc); 3071 for (i = 0; i < 4; i++) 3072 buffer[i] = 0; 3073 b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, 3074 buffer); 3075 b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, 3076 &nphy->txiqlocal_bestc[5]); 3077 b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, 3078 &nphy->txiqlocal_bestc[5]); 3079 } 3080} 3081 3082/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */ 3083static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev, 3084 struct nphy_txgains target, u8 type, bool debug) 3085{ 3086 struct b43_phy_n *nphy = dev->phy.n; 3087 int i, j, index; 3088 u8 rfctl[2]; 3089 u8 afectl_core; 3090 u16 tmp[6]; 3091 u16 cur_hpf1, cur_hpf2, cur_lna; 3092 u32 real, imag; 3093 enum ieee80211_band band; 3094 3095 u8 use; 3096 u16 cur_hpf; 3097 u16 lna[3] = { 3, 3, 1 }; 3098 u16 hpf1[3] = { 7, 2, 0 }; 3099 u16 hpf2[3] = { 2, 0, 0 }; 3100 u32 power[3] = { }; 3101 u16 gain_save[2]; 3102 u16 cal_gain[2]; 3103 struct nphy_iqcal_params cal_params[2]; 3104 struct nphy_iq_est est; 3105 int ret = 0; 3106 bool playtone = true; 3107 int desired = 13; 3108 3109 b43_nphy_stay_in_carrier_search(dev, 1); 3110 3111 if (dev->phy.rev < 2) 3112 b43_nphy_reapply_tx_cal_coeffs(dev); 3113 b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); 3114 for (i = 0; i < 2; i++) { 3115 b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]); 3116 cal_gain[i] = cal_params[i].cal_gain; 3117 } 3118 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain); 3119 3120 for (i = 0; i < 2; i++) { 3121 if (i == 0) { 3122 rfctl[0] = B43_NPHY_RFCTL_INTC1; 3123 rfctl[1] = B43_NPHY_RFCTL_INTC2; 3124 afectl_core = B43_NPHY_AFECTL_C1; 3125 } else { 3126 rfctl[0] = B43_NPHY_RFCTL_INTC2; 3127 rfctl[1] = B43_NPHY_RFCTL_INTC1; 3128 afectl_core = B43_NPHY_AFECTL_C2; 3129 } 3130 3131 tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA); 3132 tmp[2] = b43_phy_read(dev, afectl_core); 3133 tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER); 3134 tmp[4] = b43_phy_read(dev, rfctl[0]); 3135 tmp[5] = b43_phy_read(dev, rfctl[1]); 3136 3137 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, 3138 ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF, 3139 ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT)); 3140 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN, 3141 (1 - i)); 3142 b43_phy_set(dev, afectl_core, 0x0006); 3143 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006); 3144 3145 band = b43_current_band(dev->wl); 3146 3147 if (nphy->rxcalparams & 0xFF000000) { 3148 if (band == IEEE80211_BAND_5GHZ) 3149 b43_phy_write(dev, rfctl[0], 0x140); 3150 else 3151 b43_phy_write(dev, rfctl[0], 0x110); 3152 } else { 3153 if (band == IEEE80211_BAND_5GHZ) 3154 b43_phy_write(dev, rfctl[0], 0x180); 3155 else 3156 b43_phy_write(dev, rfctl[0], 0x120); 3157 } 3158 3159 if (band == IEEE80211_BAND_5GHZ) 3160 b43_phy_write(dev, rfctl[1], 0x148); 3161 else 3162 b43_phy_write(dev, rfctl[1], 0x114); 3163 3164 if (nphy->rxcalparams & 0x10000) { 3165 b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC, 3166 (i + 1)); 3167 b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC, 3168 (2 - i)); 3169 } 3170 3171 for (j = 0; j < 4; j++) { 3172 if (j < 3) { 3173 cur_lna = lna[j]; 3174 cur_hpf1 = hpf1[j]; 3175 cur_hpf2 = hpf2[j]; 3176 } else { 3177 if (power[1] > 10000) { 3178 use = 1; 3179 cur_hpf = cur_hpf1; 3180 index = 2; 3181 } else { 3182 if (power[0] > 10000) { 3183 use = 1; 3184 cur_hpf = cur_hpf1; 3185 index = 1; 3186 } else { 3187 index = 0; 3188 use = 2; 3189 cur_hpf = cur_hpf2; 3190 } 3191 } 3192 cur_lna = lna[index]; 3193 cur_hpf1 = hpf1[index]; 3194 cur_hpf2 = hpf2[index]; 3195 cur_hpf += desired - hweight32(power[index]); 3196 cur_hpf = clamp_val(cur_hpf, 0, 10); 3197 if (use == 1) 3198 cur_hpf1 = cur_hpf; 3199 else 3200 cur_hpf2 = cur_hpf; 3201 } 3202 3203 tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) | 3204 (cur_lna << 2)); 3205 b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3, 3206 false); 3207 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 3208 b43_nphy_stop_playback(dev); 3209 3210 if (playtone) { 3211 ret = b43_nphy_tx_tone(dev, 4000, 3212 (nphy->rxcalparams & 0xFFFF), 3213 false, false); 3214 playtone = false; 3215 } else { 3216 b43_nphy_run_samples(dev, 160, 0xFFFF, 0, 3217 false, false); 3218 } 3219 3220 if (ret == 0) { 3221 if (j < 3) { 3222 b43_nphy_rx_iq_est(dev, &est, 1024, 32, 3223 false); 3224 if (i == 0) { 3225 real = est.i0_pwr; 3226 imag = est.q0_pwr; 3227 } else { 3228 real = est.i1_pwr; 3229 imag = est.q1_pwr; 3230 } 3231 power[i] = ((real + imag) / 1024) + 1; 3232 } else { 3233 b43_nphy_calc_rx_iq_comp(dev, 1 << i); 3234 } 3235 b43_nphy_stop_playback(dev); 3236 } 3237 3238 if (ret != 0) 3239 break; 3240 } 3241 3242 b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC); 3243 b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC); 3244 b43_phy_write(dev, rfctl[1], tmp[5]); 3245 b43_phy_write(dev, rfctl[0], tmp[4]); 3246 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]); 3247 b43_phy_write(dev, afectl_core, tmp[2]); 3248 b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]); 3249 3250 if (ret != 0) 3251 break; 3252 } 3253 3254 b43_nphy_rf_control_override(dev, 0x400, 0, 3, true); 3255 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 3256 b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save); 3257 3258 b43_nphy_stay_in_carrier_search(dev, 0); 3259 3260 return ret; 3261} 3262 3263static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev, 3264 struct nphy_txgains target, u8 type, bool debug) 3265{ 3266 return -1; 3267} 3268 3269/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */ 3270static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, 3271 struct nphy_txgains target, u8 type, bool debug) 3272{ 3273 if (dev->phy.rev >= 3) 3274 return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug); 3275 else 3276 return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); 3277} 3278 3279/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ 3280static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on) 3281{ 3282 u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); 3283 if (on) 3284 tmslow |= SSB_TMSLOW_PHYCLK; 3285 else 3286 tmslow &= ~SSB_TMSLOW_PHYCLK; 3287 ssb_write32(dev->dev, SSB_TMSLOW, tmslow); 3288} 3289 3290/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ 3291static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) 3292{ 3293 struct b43_phy *phy = &dev->phy; 3294 struct b43_phy_n *nphy = phy->n; 3295 /* u16 buf[16]; it's rev3+ */ 3296 3297 nphy->phyrxchain = mask; 3298 3299 if (0 /* FIXME clk */) 3300 return; 3301 3302 b43_mac_suspend(dev); 3303 3304 if (nphy->hang_avoid) 3305 b43_nphy_stay_in_carrier_search(dev, true); 3306 3307 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, 3308 (mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT); 3309 3310 if ((mask & 0x3) != 0x3) { 3311 b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1); 3312 if (dev->phy.rev >= 3) { 3313 /* TODO */ 3314 } 3315 } else { 3316 b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E); 3317 if (dev->phy.rev >= 3) { 3318 /* TODO */ 3319 } 3320 } 3321 3322 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 3323 3324 if (nphy->hang_avoid) 3325 b43_nphy_stay_in_carrier_search(dev, false); 3326 3327 b43_mac_enable(dev); 3328} 3329 3330/* 3331 * Init N-PHY 3332 * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N 3333 */ 3334int b43_phy_initn(struct b43_wldev *dev) 3335{ 3336 struct ssb_bus *bus = dev->dev->bus; 3337 struct b43_phy *phy = &dev->phy; 3338 struct b43_phy_n *nphy = phy->n; 3339 u8 tx_pwr_state; 3340 struct nphy_txgains target; 3341 u16 tmp; 3342 enum ieee80211_band tmp2; 3343 bool do_rssi_cal; 3344 3345 u16 clip[2]; 3346 bool do_cal = false; 3347 3348 if ((dev->phy.rev >= 3) && 3349 (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && 3350 (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) { 3351 chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40); 3352 } 3353 nphy->deaf_count = 0; 3354 b43_nphy_tables_init(dev); 3355 nphy->crsminpwr_adjusted = false; 3356 nphy->noisevars_adjusted = false; 3357 3358 /* Clear all overrides */ 3359 if (dev->phy.rev >= 3) { 3360 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0); 3361 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); 3362 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0); 3363 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0); 3364 } else { 3365 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); 3366 } 3367 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); 3368 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); 3369 if (dev->phy.rev < 6) { 3370 b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); 3371 b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); 3372 } 3373 b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 3374 ~(B43_NPHY_RFSEQMODE_CAOVER | 3375 B43_NPHY_RFSEQMODE_TROVER)); 3376 if (dev->phy.rev >= 3) 3377 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0); 3378 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); 3379 3380 if (dev->phy.rev <= 2) { 3381 tmp = (dev->phy.rev == 2) ? 0x3B : 0x40; 3382 b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, 3383 ~B43_NPHY_BPHY_CTL3_SCALE, 3384 tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); 3385 } 3386 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); 3387 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); 3388 3389 if (bus->sprom.boardflags2_lo & 0x100 || 3390 (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && 3391 bus->boardinfo.type == 0x8B)) 3392 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0); 3393 else 3394 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8); 3395 b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8); 3396 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50); 3397 b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30); 3398 3399 b43_nphy_update_mimo_config(dev, nphy->preamble_override); 3400 b43_nphy_update_txrx_chain(dev); 3401 3402 if (phy->rev < 2) { 3403 b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); 3404 b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); 3405 } 3406 3407 tmp2 = b43_current_band(dev->wl); 3408 if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) || 3409 (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) { 3410 b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1); 3411 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F, 3412 nphy->papd_epsilon_offset[0] << 7); 3413 b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1); 3414 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F, 3415 nphy->papd_epsilon_offset[1] << 7); 3416 b43_nphy_int_pa_set_tx_dig_filters(dev); 3417 } else if (phy->rev >= 5) { 3418 b43_nphy_ext_pa_set_tx_dig_filters(dev); 3419 } 3420 3421 b43_nphy_workarounds(dev); 3422 3423 /* Reset CCA, in init code it differs a little from standard way */ 3424 b43_nphy_bmac_clock_fgc(dev, 1); 3425 tmp = b43_phy_read(dev, B43_NPHY_BBCFG); 3426 b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA); 3427 b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); 3428 b43_nphy_bmac_clock_fgc(dev, 0); 3429 3430 b43_nphy_mac_phy_clock_set(dev, true); 3431 3432 b43_nphy_pa_override(dev, false); 3433 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); 3434 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 3435 b43_nphy_pa_override(dev, true); 3436 3437 b43_nphy_classifier(dev, 0, 0); 3438 b43_nphy_read_clip_detection(dev, clip); 3439 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 3440 b43_nphy_bphy_init(dev); 3441 3442 tx_pwr_state = nphy->txpwrctrl; 3443 b43_nphy_tx_power_ctrl(dev, false); 3444 b43_nphy_tx_power_fix(dev); 3445 /* TODO N PHY TX Power Control Idle TSSI */ 3446 /* TODO N PHY TX Power Control Setup */ 3447 3448 if (phy->rev >= 3) { 3449 /* TODO */ 3450 } else { 3451 b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, 3452 b43_ntab_tx_gain_rev0_1_2); 3453 b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, 3454 b43_ntab_tx_gain_rev0_1_2); 3455 } 3456 3457 if (nphy->phyrxchain != 3) 3458 b43_nphy_set_rx_core_state(dev, nphy->phyrxchain); 3459 if (nphy->mphase_cal_phase_id > 0) 3460 ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ 3461 3462 do_rssi_cal = false; 3463 if (phy->rev >= 3) { 3464 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 3465 do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq; 3466 else 3467 do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq; 3468 3469 if (do_rssi_cal) 3470 b43_nphy_rssi_cal(dev); 3471 else 3472 b43_nphy_restore_rssi_cal(dev); 3473 } else { 3474 b43_nphy_rssi_cal(dev); 3475 } 3476 3477 if (!((nphy->measure_hold & 0x6) != 0)) { 3478 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 3479 do_cal = !nphy->iqcal_chanspec_2G.center_freq; 3480 else 3481 do_cal = !nphy->iqcal_chanspec_5G.center_freq; 3482 3483 if (nphy->mute) 3484 do_cal = false; 3485 3486 if (do_cal) { 3487 target = b43_nphy_get_tx_gains(dev); 3488 3489 if (nphy->antsel_type == 2) 3490 b43_nphy_superswitch_init(dev, true); 3491 if (nphy->perical != 2) { 3492 b43_nphy_rssi_cal(dev); 3493 if (phy->rev >= 3) { 3494 nphy->cal_orig_pwr_idx[0] = 3495 nphy->txpwrindex[0].index_internal; 3496 nphy->cal_orig_pwr_idx[1] = 3497 nphy->txpwrindex[1].index_internal; 3498 /* TODO N PHY Pre Calibrate TX Gain */ 3499 target = b43_nphy_get_tx_gains(dev); 3500 } 3501 if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) 3502 if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0) 3503 b43_nphy_save_cal(dev); 3504 } else if (nphy->mphase_cal_phase_id == 0) 3505 ;/* N PHY Periodic Calibration with arg 3 */ 3506 } else { 3507 b43_nphy_restore_cal(dev); 3508 } 3509 } 3510 3511 b43_nphy_tx_pwr_ctrl_coef_setup(dev); 3512 b43_nphy_tx_power_ctrl(dev, tx_pwr_state); 3513 b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015); 3514 b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320); 3515 if (phy->rev >= 3 && phy->rev <= 6) 3516 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014); 3517 b43_nphy_tx_lp_fbw(dev); 3518 if (phy->rev >= 3) 3519 b43_nphy_spur_workaround(dev); 3520 3521 b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); 3522 return 0; 3523} 3524 3525/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ 3526static void b43_nphy_channel_setup(struct b43_wldev *dev, 3527 const struct b43_phy_n_sfo_cfg *e, 3528 struct ieee80211_channel *new_channel) 3529{ 3530 struct b43_phy *phy = &dev->phy; 3531 struct b43_phy_n *nphy = dev->phy.n; 3532 3533 u16 old_band_5ghz; 3534 u32 tmp32; 3535 3536 old_band_5ghz = 3537 b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; 3538 if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) { 3539 tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); 3540 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); 3541 b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); 3542 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); 3543 b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); 3544 } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) { 3545 b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); 3546 tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); 3547 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); 3548 b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF); 3549 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); 3550 } 3551 3552 b43_chantab_phy_upload(dev, e); 3553 3554 if (new_channel->hw_value == 14) { 3555 b43_nphy_classifier(dev, 2, 0); 3556 b43_phy_set(dev, B43_PHY_B_TEST, 0x0800); 3557 } else { 3558 b43_nphy_classifier(dev, 2, 2); 3559 if (new_channel->band == IEEE80211_BAND_2GHZ) 3560 b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); 3561 } 3562 3563 if (!nphy->txpwrctrl) 3564 b43_nphy_tx_power_fix(dev); 3565 3566 if (dev->phy.rev < 3) 3567 b43_nphy_adjust_lna_gain_table(dev); 3568 3569 b43_nphy_tx_lp_fbw(dev); 3570 3571 if (dev->phy.rev >= 3 && 0) { 3572 /* TODO */ 3573 } 3574 3575 b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830); 3576 3577 if (phy->rev >= 3) 3578 b43_nphy_spur_workaround(dev); 3579} 3580 3581/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ 3582static int b43_nphy_set_channel(struct b43_wldev *dev, 3583 struct ieee80211_channel *channel, 3584 enum nl80211_channel_type channel_type) 3585{ 3586 struct b43_phy *phy = &dev->phy; 3587 3588 const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; 3589 const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; 3590 3591 u8 tmp; 3592 3593 if (dev->phy.rev >= 3) { 3594 tabent_r3 = b43_nphy_get_chantabent_rev3(dev, 3595 channel->center_freq); 3596 tabent_r3 = NULL; 3597 if (!tabent_r3) 3598 return -ESRCH; 3599 } else { 3600 tabent_r2 = b43_nphy_get_chantabent_rev2(dev, 3601 channel->hw_value); 3602 if (!tabent_r2) 3603 return -ESRCH; 3604 } 3605 3606 /* Channel is set later in common code, but we need to set it on our 3607 own to let this function's subcalls work properly. */ 3608 phy->channel = channel->hw_value; 3609 phy->channel_freq = channel->center_freq; 3610 3611 if (b43_channel_type_is_40mhz(phy->channel_type) != 3612 b43_channel_type_is_40mhz(channel_type)) 3613 ; /* TODO: BMAC BW Set (channel_type) */ 3614 3615 if (channel_type == NL80211_CHAN_HT40PLUS) 3616 b43_phy_set(dev, B43_NPHY_RXCTL, 3617 B43_NPHY_RXCTL_BSELU20); 3618 else if (channel_type == NL80211_CHAN_HT40MINUS) 3619 b43_phy_mask(dev, B43_NPHY_RXCTL, 3620 ~B43_NPHY_RXCTL_BSELU20); 3621 3622 if (dev->phy.rev >= 3) { 3623 tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0; 3624 b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); 3625 /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */ 3626 b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel); 3627 } else { 3628 tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050; 3629 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); 3630 b43_radio_2055_setup(dev, tabent_r2); 3631 b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel); 3632 } 3633 3634 return 0; 3635} 3636 3637static int b43_nphy_op_allocate(struct b43_wldev *dev) 3638{ 3639 struct b43_phy_n *nphy; 3640 3641 nphy = kzalloc(sizeof(*nphy), GFP_KERNEL); 3642 if (!nphy) 3643 return -ENOMEM; 3644 dev->phy.n = nphy; 3645 3646 return 0; 3647} 3648 3649static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) 3650{ 3651 struct b43_phy *phy = &dev->phy; 3652 struct b43_phy_n *nphy = phy->n; 3653 3654 memset(nphy, 0, sizeof(*nphy)); 3655 3656 nphy->gain_boost = true; /* this way we follow wl, assume it is true */ 3657 nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */ 3658 nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */ 3659 nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */ 3660} 3661 3662static void b43_nphy_op_free(struct b43_wldev *dev) 3663{ 3664 struct b43_phy *phy = &dev->phy; 3665 struct b43_phy_n *nphy = phy->n; 3666 3667 kfree(nphy); 3668 phy->n = NULL; 3669} 3670 3671static int b43_nphy_op_init(struct b43_wldev *dev) 3672{ 3673 return b43_phy_initn(dev); 3674} 3675 3676static inline void check_phyreg(struct b43_wldev *dev, u16 offset) 3677{ 3678#if B43_DEBUG 3679 if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { 3680 /* OFDM registers are onnly available on A/G-PHYs */ 3681 b43err(dev->wl, "Invalid OFDM PHY access at " 3682 "0x%04X on N-PHY\n", offset); 3683 dump_stack(); 3684 } 3685 if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { 3686 /* Ext-G registers are only available on G-PHYs */ 3687 b43err(dev->wl, "Invalid EXT-G PHY access at " 3688 "0x%04X on N-PHY\n", offset); 3689 dump_stack(); 3690 } 3691#endif /* B43_DEBUG */ 3692} 3693 3694static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg) 3695{ 3696 check_phyreg(dev, reg); 3697 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 3698 return b43_read16(dev, B43_MMIO_PHY_DATA); 3699} 3700 3701static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) 3702{ 3703 check_phyreg(dev, reg); 3704 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 3705 b43_write16(dev, B43_MMIO_PHY_DATA, value); 3706} 3707 3708static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, 3709 u16 set) 3710{ 3711 check_phyreg(dev, reg); 3712 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 3713 b43_write16(dev, B43_MMIO_PHY_DATA, 3714 (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); 3715} 3716 3717static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) 3718{ 3719 /* Register 1 is a 32-bit register. */ 3720 B43_WARN_ON(reg == 1); 3721 /* N-PHY needs 0x100 for read access */ 3722 reg |= 0x100; 3723 3724 b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 3725 return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); 3726} 3727 3728static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) 3729{ 3730 /* Register 1 is a 32-bit register. */ 3731 B43_WARN_ON(reg == 1); 3732 3733 b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 3734 b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); 3735} 3736 3737/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ 3738static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, 3739 bool blocked) 3740{ 3741 if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) 3742 b43err(dev->wl, "MAC not suspended\n"); 3743 3744 if (blocked) { 3745 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 3746 ~B43_NPHY_RFCTL_CMD_CHIP0PU); 3747 if (dev->phy.rev >= 3) { 3748 b43_radio_mask(dev, 0x09, ~0x2); 3749 3750 b43_radio_write(dev, 0x204D, 0); 3751 b43_radio_write(dev, 0x2053, 0); 3752 b43_radio_write(dev, 0x2058, 0); 3753 b43_radio_write(dev, 0x205E, 0); 3754 b43_radio_mask(dev, 0x2062, ~0xF0); 3755 b43_radio_write(dev, 0x2064, 0); 3756 3757 b43_radio_write(dev, 0x304D, 0); 3758 b43_radio_write(dev, 0x3053, 0); 3759 b43_radio_write(dev, 0x3058, 0); 3760 b43_radio_write(dev, 0x305E, 0); 3761 b43_radio_mask(dev, 0x3062, ~0xF0); 3762 b43_radio_write(dev, 0x3064, 0); 3763 } 3764 } else { 3765 if (dev->phy.rev >= 3) { 3766 b43_radio_init2056(dev); 3767 b43_switch_channel(dev, dev->phy.channel); 3768 } else { 3769 b43_radio_init2055(dev); 3770 } 3771 } 3772} 3773 3774static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) 3775{ 3776 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 3777 on ? 0 : 0x7FFF); 3778} 3779 3780static int b43_nphy_op_switch_channel(struct b43_wldev *dev, 3781 unsigned int new_channel) 3782{ 3783 struct ieee80211_channel *channel = dev->wl->hw->conf.channel; 3784 enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type; 3785 3786 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 3787 if ((new_channel < 1) || (new_channel > 14)) 3788 return -EINVAL; 3789 } else { 3790 if (new_channel > 200) 3791 return -EINVAL; 3792 } 3793 3794 return b43_nphy_set_channel(dev, channel, channel_type); 3795} 3796 3797static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) 3798{ 3799 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 3800 return 1; 3801 return 36; 3802} 3803 3804const struct b43_phy_operations b43_phyops_n = { 3805 .allocate = b43_nphy_op_allocate, 3806 .free = b43_nphy_op_free, 3807 .prepare_structs = b43_nphy_op_prepare_structs, 3808 .init = b43_nphy_op_init, 3809 .phy_read = b43_nphy_op_read, 3810 .phy_write = b43_nphy_op_write, 3811 .phy_maskset = b43_nphy_op_maskset, 3812 .radio_read = b43_nphy_op_radio_read, 3813 .radio_write = b43_nphy_op_radio_write, 3814 .software_rfkill = b43_nphy_op_software_rfkill, 3815 .switch_analog = b43_nphy_op_switch_analog, 3816 .switch_channel = b43_nphy_op_switch_channel, 3817 .get_default_chan = b43_nphy_op_get_default_chan, 3818 .recalc_txpower = b43_nphy_op_recalc_txpower, 3819 .adjust_txpower = b43_nphy_op_adjust_txpower, 3820}; 3821