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