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