1 /* 2 3 Broadcom B43 wireless driver 4 IEEE 802.11n HT-PHY support 5 6 Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com> 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; see the file COPYING. If not, write to 20 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 21 Boston, MA 02110-1301, USA. 22 23 */ 24 25 #include <linux/slab.h> 26 27 #include "b43.h" 28 #include "phy_ht.h" 29 #include "tables_phy_ht.h" 30 #include "radio_2059.h" 31 #include "main.h" 32 33 /* Force values to keep compatibility with wl */ 34 enum ht_rssi_type { 35 HT_RSSI_W1 = 0, 36 HT_RSSI_W2 = 1, 37 HT_RSSI_NB = 2, 38 HT_RSSI_IQ = 3, 39 HT_RSSI_TSSI_2G = 4, 40 HT_RSSI_TSSI_5G = 5, 41 HT_RSSI_TBD = 6, 42 }; 43 44 /************************************************** 45 * Radio 2059. 46 **************************************************/ 47 48 static void b43_radio_2059_channel_setup(struct b43_wldev *dev, 49 const struct b43_phy_ht_channeltab_e_radio2059 *e) 50 { 51 static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, }; 52 u16 r; 53 int core; 54 55 b43_radio_write(dev, 0x16, e->radio_syn16); 56 b43_radio_write(dev, 0x17, e->radio_syn17); 57 b43_radio_write(dev, 0x22, e->radio_syn22); 58 b43_radio_write(dev, 0x25, e->radio_syn25); 59 b43_radio_write(dev, 0x27, e->radio_syn27); 60 b43_radio_write(dev, 0x28, e->radio_syn28); 61 b43_radio_write(dev, 0x29, e->radio_syn29); 62 b43_radio_write(dev, 0x2c, e->radio_syn2c); 63 b43_radio_write(dev, 0x2d, e->radio_syn2d); 64 b43_radio_write(dev, 0x37, e->radio_syn37); 65 b43_radio_write(dev, 0x41, e->radio_syn41); 66 b43_radio_write(dev, 0x43, e->radio_syn43); 67 b43_radio_write(dev, 0x47, e->radio_syn47); 68 69 for (core = 0; core < 3; core++) { 70 r = routing[core]; 71 b43_radio_write(dev, r | 0x4a, e->radio_rxtx4a); 72 b43_radio_write(dev, r | 0x58, e->radio_rxtx58); 73 b43_radio_write(dev, r | 0x5a, e->radio_rxtx5a); 74 b43_radio_write(dev, r | 0x6a, e->radio_rxtx6a); 75 b43_radio_write(dev, r | 0x6d, e->radio_rxtx6d); 76 b43_radio_write(dev, r | 0x6e, e->radio_rxtx6e); 77 b43_radio_write(dev, r | 0x92, e->radio_rxtx92); 78 b43_radio_write(dev, r | 0x98, e->radio_rxtx98); 79 } 80 81 udelay(50); 82 83 /* Calibration */ 84 b43_radio_mask(dev, R2059_RFPLL_MISC_EN, ~0x1); 85 b43_radio_mask(dev, R2059_RFPLL_MISC_CAL_RESETN, ~0x4); 86 b43_radio_set(dev, R2059_RFPLL_MISC_CAL_RESETN, 0x4); 87 b43_radio_set(dev, R2059_RFPLL_MISC_EN, 0x1); 88 89 udelay(300); 90 } 91 92 /* Calibrate resistors in LPF of PLL? */ 93 static void b43_radio_2059_rcal(struct b43_wldev *dev) 94 { 95 /* Enable */ 96 b43_radio_set(dev, R2059_C3 | R2059_RCAL_CONFIG, 0x1); 97 usleep_range(10, 20); 98 99 b43_radio_set(dev, R2059_C3 | 0x0BF, 0x1); 100 b43_radio_maskset(dev, R2059_C3 | 0x19B, 0x3, 0x2); 101 102 /* Start */ 103 b43_radio_set(dev, R2059_C3 | R2059_RCAL_CONFIG, 0x2); 104 usleep_range(100, 200); 105 106 /* Stop */ 107 b43_radio_mask(dev, R2059_C3 | R2059_RCAL_CONFIG, ~0x2); 108 109 if (!b43_radio_wait_value(dev, R2059_C3 | R2059_RCAL_STATUS, 1, 1, 100, 110 1000000)) 111 b43err(dev->wl, "Radio 0x2059 rcal timeout\n"); 112 113 /* Disable */ 114 b43_radio_mask(dev, R2059_C3 | R2059_RCAL_CONFIG, ~0x1); 115 116 b43_radio_set(dev, 0xa, 0x60); 117 } 118 119 /* Calibrate the internal RC oscillator? */ 120 static void b43_radio_2057_rccal(struct b43_wldev *dev) 121 { 122 const u16 radio_values[3][2] = { 123 { 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 }, 124 }; 125 int i; 126 127 for (i = 0; i < 3; i++) { 128 b43_radio_write(dev, R2059_RCCAL_MASTER, radio_values[i][0]); 129 b43_radio_write(dev, R2059_RCCAL_X1, 0x6E); 130 b43_radio_write(dev, R2059_RCCAL_TRC0, radio_values[i][1]); 131 132 /* Start */ 133 b43_radio_write(dev, R2059_RCCAL_START_R1_Q1_P1, 0x55); 134 135 /* Wait */ 136 if (!b43_radio_wait_value(dev, R2059_RCCAL_DONE_OSCCAP, 2, 2, 137 500, 5000000)) 138 b43err(dev->wl, "Radio 0x2059 rccal timeout\n"); 139 140 /* Stop */ 141 b43_radio_write(dev, R2059_RCCAL_START_R1_Q1_P1, 0x15); 142 } 143 144 b43_radio_mask(dev, R2059_RCCAL_MASTER, ~0x1); 145 } 146 147 static void b43_radio_2059_init_pre(struct b43_wldev *dev) 148 { 149 b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, ~B43_PHY_HT_RF_CTL_CMD_CHIP0_PU); 150 b43_phy_set(dev, B43_PHY_HT_RF_CTL_CMD, B43_PHY_HT_RF_CTL_CMD_FORCE); 151 b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, ~B43_PHY_HT_RF_CTL_CMD_FORCE); 152 b43_phy_set(dev, B43_PHY_HT_RF_CTL_CMD, B43_PHY_HT_RF_CTL_CMD_CHIP0_PU); 153 } 154 155 static void b43_radio_2059_init(struct b43_wldev *dev) 156 { 157 const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 }; 158 int i; 159 160 /* Prepare (reset?) radio */ 161 b43_radio_2059_init_pre(dev); 162 163 r2059_upload_inittabs(dev); 164 165 for (i = 0; i < ARRAY_SIZE(routing); i++) 166 b43_radio_set(dev, routing[i] | 0x146, 0x3); 167 168 /* Post init starts below */ 169 170 b43_radio_set(dev, R2059_RFPLL_MISC_CAL_RESETN, 0x0078); 171 b43_radio_set(dev, R2059_XTAL_CONFIG2, 0x0080); 172 msleep(2); 173 b43_radio_mask(dev, R2059_RFPLL_MISC_CAL_RESETN, ~0x0078); 174 b43_radio_mask(dev, R2059_XTAL_CONFIG2, ~0x0080); 175 176 if (1) { /* FIXME */ 177 b43_radio_2059_rcal(dev); 178 b43_radio_2057_rccal(dev); 179 } 180 181 b43_radio_mask(dev, R2059_RFPLL_MASTER, ~0x0008); 182 } 183 184 /************************************************** 185 * RF 186 **************************************************/ 187 188 static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) 189 { 190 u8 i; 191 192 u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); 193 b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); 194 195 b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); 196 for (i = 0; i < 200; i++) { 197 if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { 198 i = 0; 199 break; 200 } 201 msleep(1); 202 } 203 if (i) 204 b43err(dev->wl, "Forcing RF sequence timeout\n"); 205 206 b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); 207 } 208 209 static void b43_phy_ht_pa_override(struct b43_wldev *dev, bool enable) 210 { 211 struct b43_phy_ht *htphy = dev->phy.ht; 212 static const u16 regs[3] = { B43_PHY_HT_RF_CTL_INT_C1, 213 B43_PHY_HT_RF_CTL_INT_C2, 214 B43_PHY_HT_RF_CTL_INT_C3 }; 215 int i; 216 217 if (enable) { 218 for (i = 0; i < 3; i++) 219 b43_phy_write(dev, regs[i], htphy->rf_ctl_int_save[i]); 220 } else { 221 for (i = 0; i < 3; i++) 222 htphy->rf_ctl_int_save[i] = b43_phy_read(dev, regs[i]); 223 /* TODO: Does 5GHz band use different value (not 0x0400)? */ 224 for (i = 0; i < 3; i++) 225 b43_phy_write(dev, regs[i], 0x0400); 226 } 227 } 228 229 /************************************************** 230 * Various PHY ops 231 **************************************************/ 232 233 static u16 b43_phy_ht_classifier(struct b43_wldev *dev, u16 mask, u16 val) 234 { 235 u16 tmp; 236 u16 allowed = B43_PHY_HT_CLASS_CTL_CCK_EN | 237 B43_PHY_HT_CLASS_CTL_OFDM_EN | 238 B43_PHY_HT_CLASS_CTL_WAITED_EN; 239 240 tmp = b43_phy_read(dev, B43_PHY_HT_CLASS_CTL); 241 tmp &= allowed; 242 tmp &= ~mask; 243 tmp |= (val & mask); 244 b43_phy_maskset(dev, B43_PHY_HT_CLASS_CTL, ~allowed, tmp); 245 246 return tmp; 247 } 248 249 static void b43_phy_ht_reset_cca(struct b43_wldev *dev) 250 { 251 u16 bbcfg; 252 253 b43_phy_force_clock(dev, true); 254 bbcfg = b43_phy_read(dev, B43_PHY_HT_BBCFG); 255 b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg | B43_PHY_HT_BBCFG_RSTCCA); 256 udelay(1); 257 b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg & ~B43_PHY_HT_BBCFG_RSTCCA); 258 b43_phy_force_clock(dev, false); 259 260 b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); 261 } 262 263 static void b43_phy_ht_zero_extg(struct b43_wldev *dev) 264 { 265 u8 i, j; 266 u16 base[] = { 0x40, 0x60, 0x80 }; 267 268 for (i = 0; i < ARRAY_SIZE(base); i++) { 269 for (j = 0; j < 4; j++) 270 b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0); 271 } 272 273 for (i = 0; i < ARRAY_SIZE(base); i++) 274 b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0); 275 } 276 277 /* Some unknown AFE (Analog Frondned) op */ 278 static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) 279 { 280 u8 i; 281 282 static const u16 ctl_regs[3][2] = { 283 { B43_PHY_HT_AFE_C1_OVER, B43_PHY_HT_AFE_C1 }, 284 { B43_PHY_HT_AFE_C2_OVER, B43_PHY_HT_AFE_C2 }, 285 { B43_PHY_HT_AFE_C3_OVER, B43_PHY_HT_AFE_C3}, 286 }; 287 288 for (i = 0; i < 3; i++) { 289 /* TODO: verify masks&sets */ 290 b43_phy_set(dev, ctl_regs[i][1], 0x4); 291 b43_phy_set(dev, ctl_regs[i][0], 0x4); 292 b43_phy_mask(dev, ctl_regs[i][1], ~0x1); 293 b43_phy_set(dev, ctl_regs[i][0], 0x1); 294 b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0); 295 b43_phy_mask(dev, ctl_regs[i][0], ~0x4); 296 } 297 } 298 299 static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) 300 { 301 clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); 302 clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES); 303 clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES); 304 } 305 306 static void b43_phy_ht_bphy_init(struct b43_wldev *dev) 307 { 308 unsigned int i; 309 u16 val; 310 311 val = 0x1E1F; 312 for (i = 0; i < 16; i++) { 313 b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); 314 val -= 0x202; 315 } 316 val = 0x3E3F; 317 for (i = 0; i < 16; i++) { 318 b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); 319 val -= 0x202; 320 } 321 b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); 322 } 323 324 static void b43_phy_ht_bphy_reset(struct b43_wldev *dev, bool reset) 325 { 326 u16 tmp; 327 328 tmp = b43_read16(dev, B43_MMIO_PSM_PHY_HDR); 329 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, 330 tmp | B43_PSM_HDR_MAC_PHY_FORCE_CLK); 331 332 /* Put BPHY in or take it out of the reset */ 333 if (reset) 334 b43_phy_set(dev, B43_PHY_B_BBCFG, 335 B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX); 336 else 337 b43_phy_mask(dev, B43_PHY_B_BBCFG, 338 (u16)~(B43_PHY_B_BBCFG_RSTCCA | 339 B43_PHY_B_BBCFG_RSTRX)); 340 341 b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp); 342 } 343 344 /************************************************** 345 * Samples 346 **************************************************/ 347 348 static void b43_phy_ht_stop_playback(struct b43_wldev *dev) 349 { 350 struct b43_phy_ht *phy_ht = dev->phy.ht; 351 u16 tmp; 352 int i; 353 354 tmp = b43_phy_read(dev, B43_PHY_HT_SAMP_STAT); 355 if (tmp & 0x1) 356 b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, B43_PHY_HT_SAMP_CMD_STOP); 357 else if (tmp & 0x2) 358 b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, 0x7FFF); 359 360 b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0x0004); 361 362 for (i = 0; i < 3; i++) { 363 if (phy_ht->bb_mult_save[i] >= 0) { 364 b43_httab_write(dev, B43_HTTAB16(13, 0x63 + i * 4), 365 phy_ht->bb_mult_save[i]); 366 b43_httab_write(dev, B43_HTTAB16(13, 0x67 + i * 4), 367 phy_ht->bb_mult_save[i]); 368 } 369 } 370 } 371 372 static u16 b43_phy_ht_load_samples(struct b43_wldev *dev) 373 { 374 int i; 375 u16 len = 20 << 3; 376 377 b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, 0x4400); 378 379 for (i = 0; i < len; i++) { 380 b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, 0); 381 b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, 0); 382 } 383 384 return len; 385 } 386 387 static void b43_phy_ht_run_samples(struct b43_wldev *dev, u16 samps, u16 loops, 388 u16 wait) 389 { 390 struct b43_phy_ht *phy_ht = dev->phy.ht; 391 u16 save_seq_mode; 392 int i; 393 394 for (i = 0; i < 3; i++) { 395 if (phy_ht->bb_mult_save[i] < 0) 396 phy_ht->bb_mult_save[i] = b43_httab_read(dev, B43_HTTAB16(13, 0x63 + i * 4)); 397 } 398 399 b43_phy_write(dev, B43_PHY_HT_SAMP_DEP_CNT, samps - 1); 400 if (loops != 0xFFFF) 401 loops--; 402 b43_phy_write(dev, B43_PHY_HT_SAMP_LOOP_CNT, loops); 403 b43_phy_write(dev, B43_PHY_HT_SAMP_WAIT_CNT, wait); 404 405 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); 406 b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 407 B43_PHY_HT_RF_SEQ_MODE_CA_OVER); 408 409 /* TODO: find out mask bits! Do we need more function arguments? */ 410 b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0); 411 b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0); 412 b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, ~0); 413 b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, 0x1); 414 415 for (i = 0; i < 100; i++) { 416 if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & 1)) { 417 i = 0; 418 break; 419 } 420 udelay(10); 421 } 422 if (i) 423 b43err(dev->wl, "run samples timeout\n"); 424 425 b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); 426 } 427 428 static void b43_phy_ht_tx_tone(struct b43_wldev *dev) 429 { 430 u16 samp; 431 432 samp = b43_phy_ht_load_samples(dev); 433 b43_phy_ht_run_samples(dev, samp, 0xFFFF, 0); 434 } 435 436 /************************************************** 437 * RSSI 438 **************************************************/ 439 440 static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel, 441 enum ht_rssi_type rssi_type) 442 { 443 static const u16 ctl_regs[3][2] = { 444 { B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, }, 445 { B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, }, 446 { B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, }, 447 }; 448 static const u16 radio_r[] = { R2059_C1, R2059_C2, R2059_C3, }; 449 int core; 450 451 if (core_sel == 0) { 452 b43err(dev->wl, "RSSI selection for core off not implemented yet\n"); 453 } else { 454 for (core = 0; core < 3; core++) { 455 /* Check if caller requested a one specific core */ 456 if ((core_sel == 1 && core != 0) || 457 (core_sel == 2 && core != 1) || 458 (core_sel == 3 && core != 2)) 459 continue; 460 461 switch (rssi_type) { 462 case HT_RSSI_TSSI_2G: 463 b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8); 464 b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10); 465 b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9); 466 b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10); 467 468 b43_radio_set(dev, R2059_C3 | 0xbf, 0x1); 469 b43_radio_write(dev, radio_r[core] | 0x159, 470 0x11); 471 break; 472 default: 473 b43err(dev->wl, "RSSI selection for type %d not implemented yet\n", 474 rssi_type); 475 } 476 } 477 } 478 } 479 480 static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, enum ht_rssi_type type, 481 s32 *buf, u8 nsamp) 482 { 483 u16 phy_regs_values[12]; 484 static const u16 phy_regs_to_save[] = { 485 B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, 486 0x848, 0x841, 487 B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, 488 0x868, 0x861, 489 B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, 490 0x888, 0x881, 491 }; 492 u16 tmp[3]; 493 int i; 494 495 for (i = 0; i < 12; i++) 496 phy_regs_values[i] = b43_phy_read(dev, phy_regs_to_save[i]); 497 498 b43_phy_ht_rssi_select(dev, 5, type); 499 500 for (i = 0; i < 6; i++) 501 buf[i] = 0; 502 503 for (i = 0; i < nsamp; i++) { 504 tmp[0] = b43_phy_read(dev, B43_PHY_HT_RSSI_C1); 505 tmp[1] = b43_phy_read(dev, B43_PHY_HT_RSSI_C2); 506 tmp[2] = b43_phy_read(dev, B43_PHY_HT_RSSI_C3); 507 508 buf[0] += ((s8)((tmp[0] & 0x3F) << 2)) >> 2; 509 buf[1] += ((s8)(((tmp[0] >> 8) & 0x3F) << 2)) >> 2; 510 buf[2] += ((s8)((tmp[1] & 0x3F) << 2)) >> 2; 511 buf[3] += ((s8)(((tmp[1] >> 8) & 0x3F) << 2)) >> 2; 512 buf[4] += ((s8)((tmp[2] & 0x3F) << 2)) >> 2; 513 buf[5] += ((s8)(((tmp[2] >> 8) & 0x3F) << 2)) >> 2; 514 } 515 516 for (i = 0; i < 12; i++) 517 b43_phy_write(dev, phy_regs_to_save[i], phy_regs_values[i]); 518 } 519 520 /************************************************** 521 * Tx/Rx 522 **************************************************/ 523 524 static void b43_phy_ht_tx_power_fix(struct b43_wldev *dev) 525 { 526 int i; 527 528 for (i = 0; i < 3; i++) { 529 u16 mask; 530 u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8)); 531 532 if (0) /* FIXME */ 533 mask = 0x2 << (i * 4); 534 else 535 mask = 0; 536 b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask); 537 538 b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16); 539 b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)), 540 tmp & 0xFF); 541 b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)), 542 tmp & 0xFF); 543 } 544 } 545 546 static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable) 547 { 548 struct b43_phy_ht *phy_ht = dev->phy.ht; 549 u16 en_bits = B43_PHY_HT_TXPCTL_CMD_C1_COEFF | 550 B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN | 551 B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN; 552 static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1, 553 B43_PHY_HT_TXPCTL_CMD_C2, 554 B43_PHY_HT_TXPCTL_CMD_C3 }; 555 static const u16 status_regs[3] = { B43_PHY_HT_TX_PCTL_STATUS_C1, 556 B43_PHY_HT_TX_PCTL_STATUS_C2, 557 B43_PHY_HT_TX_PCTL_STATUS_C3 }; 558 int i; 559 560 if (!enable) { 561 if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) { 562 /* We disable enabled TX pwr ctl, save it's state */ 563 for (i = 0; i < 3; i++) 564 phy_ht->tx_pwr_idx[i] = 565 b43_phy_read(dev, status_regs[i]); 566 } 567 b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, ~en_bits); 568 } else { 569 b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits); 570 571 if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) { 572 for (i = 0; i < 3; i++) 573 b43_phy_write(dev, cmd_regs[i], 0x32); 574 } 575 576 for (i = 0; i < 3; i++) 577 if (phy_ht->tx_pwr_idx[i] <= 578 B43_PHY_HT_TXPCTL_CMD_C1_INIT) 579 b43_phy_write(dev, cmd_regs[i], 580 phy_ht->tx_pwr_idx[i]); 581 } 582 583 phy_ht->tx_pwr_ctl = enable; 584 } 585 586 static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev) 587 { 588 struct b43_phy_ht *phy_ht = dev->phy.ht; 589 static const u16 base[] = { 0x840, 0x860, 0x880 }; 590 u16 save_regs[3][3]; 591 s32 rssi_buf[6]; 592 int core; 593 594 for (core = 0; core < 3; core++) { 595 save_regs[core][1] = b43_phy_read(dev, base[core] + 6); 596 save_regs[core][2] = b43_phy_read(dev, base[core] + 7); 597 save_regs[core][0] = b43_phy_read(dev, base[core] + 0); 598 599 b43_phy_write(dev, base[core] + 6, 0); 600 b43_phy_mask(dev, base[core] + 7, ~0xF); /* 0xF? Or just 0x6? */ 601 b43_phy_set(dev, base[core] + 0, 0x0400); 602 b43_phy_set(dev, base[core] + 0, 0x1000); 603 } 604 605 b43_phy_ht_tx_tone(dev); 606 udelay(20); 607 b43_phy_ht_poll_rssi(dev, HT_RSSI_TSSI_2G, rssi_buf, 1); 608 b43_phy_ht_stop_playback(dev); 609 b43_phy_ht_reset_cca(dev); 610 611 phy_ht->idle_tssi[0] = rssi_buf[0] & 0xff; 612 phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff; 613 phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff; 614 615 for (core = 0; core < 3; core++) { 616 b43_phy_write(dev, base[core] + 0, save_regs[core][0]); 617 b43_phy_write(dev, base[core] + 6, save_regs[core][1]); 618 b43_phy_write(dev, base[core] + 7, save_regs[core][2]); 619 } 620 } 621 622 static void b43_phy_ht_tssi_setup(struct b43_wldev *dev) 623 { 624 static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, }; 625 int core; 626 627 /* 0x159 is probably TX_SSI_MUX or TSSIG (by comparing to N-PHY) */ 628 for (core = 0; core < 3; core++) { 629 b43_radio_set(dev, 0x8bf, 0x1); 630 b43_radio_write(dev, routing[core] | 0x0159, 0x0011); 631 } 632 } 633 634 static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev) 635 { 636 struct b43_phy_ht *phy_ht = dev->phy.ht; 637 struct ssb_sprom *sprom = dev->dev->bus_sprom; 638 639 u8 *idle = phy_ht->idle_tssi; 640 u8 target[3]; 641 s16 a1[3], b0[3], b1[3]; 642 643 u16 freq = dev->phy.chandef->chan->center_freq; 644 int i, c; 645 646 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 647 for (c = 0; c < 3; c++) { 648 target[c] = sprom->core_pwr_info[c].maxpwr_2g; 649 a1[c] = sprom->core_pwr_info[c].pa_2g[0]; 650 b0[c] = sprom->core_pwr_info[c].pa_2g[1]; 651 b1[c] = sprom->core_pwr_info[c].pa_2g[2]; 652 } 653 } else if (freq >= 4900 && freq < 5100) { 654 for (c = 0; c < 3; c++) { 655 target[c] = sprom->core_pwr_info[c].maxpwr_5gl; 656 a1[c] = sprom->core_pwr_info[c].pa_5gl[0]; 657 b0[c] = sprom->core_pwr_info[c].pa_5gl[1]; 658 b1[c] = sprom->core_pwr_info[c].pa_5gl[2]; 659 } 660 } else if (freq >= 5100 && freq < 5500) { 661 for (c = 0; c < 3; c++) { 662 target[c] = sprom->core_pwr_info[c].maxpwr_5g; 663 a1[c] = sprom->core_pwr_info[c].pa_5g[0]; 664 b0[c] = sprom->core_pwr_info[c].pa_5g[1]; 665 b1[c] = sprom->core_pwr_info[c].pa_5g[2]; 666 } 667 } else if (freq >= 5500) { 668 for (c = 0; c < 3; c++) { 669 target[c] = sprom->core_pwr_info[c].maxpwr_5gh; 670 a1[c] = sprom->core_pwr_info[c].pa_5gh[0]; 671 b0[c] = sprom->core_pwr_info[c].pa_5gh[1]; 672 b1[c] = sprom->core_pwr_info[c].pa_5gh[2]; 673 } 674 } else { 675 target[0] = target[1] = target[2] = 52; 676 a1[0] = a1[1] = a1[2] = -424; 677 b0[0] = b0[1] = b0[2] = 5612; 678 b1[0] = b1[1] = b1[2] = -1393; 679 } 680 681 b43_phy_set(dev, B43_PHY_HT_TSSIMODE, B43_PHY_HT_TSSIMODE_EN); 682 b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, 683 ~B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN & 0xFFFF); 684 685 /* TODO: Does it depend on sprom->fem.ghz2.tssipos? */ 686 b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 0x4000); 687 688 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 689 ~B43_PHY_HT_TXPCTL_CMD_C1_INIT, 0x19); 690 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C2, 691 ~B43_PHY_HT_TXPCTL_CMD_C2_INIT, 0x19); 692 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C3, 693 ~B43_PHY_HT_TXPCTL_CMD_C3_INIT, 0x19); 694 695 b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 696 B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF); 697 698 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 699 ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C1, 700 idle[0] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT); 701 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 702 ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C2, 703 idle[1] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT); 704 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI2, 705 ~B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3, 706 idle[2] << B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT); 707 708 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_TSSID, 709 0xf0); 710 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_NPTIL2, 711 0x3 << B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT); 712 #if 0 713 /* TODO: what to mask/set? */ 714 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x800, 0) 715 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x400, 0) 716 #endif 717 718 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, 719 ~B43_PHY_HT_TXPCTL_TARG_PWR_C1, 720 target[0] << B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT); 721 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR, 722 ~B43_PHY_HT_TXPCTL_TARG_PWR_C2 & 0xFFFF, 723 target[1] << B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT); 724 b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR2, 725 ~B43_PHY_HT_TXPCTL_TARG_PWR2_C3, 726 target[2] << B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT); 727 728 for (c = 0; c < 3; c++) { 729 s32 num, den, pwr; 730 u32 regval[64]; 731 732 for (i = 0; i < 64; i++) { 733 num = 8 * (16 * b0[c] + b1[c] * i); 734 den = 32768 + a1[c] * i; 735 pwr = max((4 * num + den / 2) / den, -8); 736 regval[i] = pwr; 737 } 738 b43_httab_write_bulk(dev, B43_HTTAB16(26 + c, 0), 64, regval); 739 } 740 } 741 742 /************************************************** 743 * Channel switching ops. 744 **************************************************/ 745 746 static void b43_phy_ht_spur_avoid(struct b43_wldev *dev, 747 struct ieee80211_channel *new_channel) 748 { 749 struct bcma_device *core = dev->dev->bdev; 750 int spuravoid = 0; 751 752 /* Check for 13 and 14 is just a guess, we don't have enough logs. */ 753 if (new_channel->hw_value == 13 || new_channel->hw_value == 14) 754 spuravoid = 1; 755 bcma_core_pll_ctl(core, B43_BCMA_CLKCTLST_PHY_PLL_REQ, 0, false); 756 bcma_pmu_spuravoid_pllupdate(&core->bus->drv_cc, spuravoid); 757 bcma_core_pll_ctl(core, 758 B43_BCMA_CLKCTLST_80211_PLL_REQ | 759 B43_BCMA_CLKCTLST_PHY_PLL_REQ, 760 B43_BCMA_CLKCTLST_80211_PLL_ST | 761 B43_BCMA_CLKCTLST_PHY_PLL_ST, false); 762 763 b43_mac_switch_freq(dev, spuravoid); 764 765 b43_wireless_core_phy_pll_reset(dev); 766 767 if (spuravoid) 768 b43_phy_set(dev, B43_PHY_HT_BBCFG, B43_PHY_HT_BBCFG_RSTRX); 769 else 770 b43_phy_mask(dev, B43_PHY_HT_BBCFG, 771 ~B43_PHY_HT_BBCFG_RSTRX & 0xFFFF); 772 773 b43_phy_ht_reset_cca(dev); 774 } 775 776 static void b43_phy_ht_channel_setup(struct b43_wldev *dev, 777 const struct b43_phy_ht_channeltab_e_phy *e, 778 struct ieee80211_channel *new_channel) 779 { 780 if (new_channel->band == NL80211_BAND_5GHZ) { 781 /* Switch to 2 GHz for a moment to access B-PHY regs */ 782 b43_phy_mask(dev, B43_PHY_HT_BANDCTL, ~B43_PHY_HT_BANDCTL_5GHZ); 783 784 b43_phy_ht_bphy_reset(dev, true); 785 786 /* Switch to 5 GHz */ 787 b43_phy_set(dev, B43_PHY_HT_BANDCTL, B43_PHY_HT_BANDCTL_5GHZ); 788 } else { 789 /* Switch to 2 GHz */ 790 b43_phy_mask(dev, B43_PHY_HT_BANDCTL, ~B43_PHY_HT_BANDCTL_5GHZ); 791 792 b43_phy_ht_bphy_reset(dev, false); 793 } 794 795 b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1); 796 b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2); 797 b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3); 798 b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4); 799 b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5); 800 b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6); 801 802 if (new_channel->hw_value == 14) { 803 b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, 0); 804 b43_phy_set(dev, B43_PHY_HT_TEST, 0x0800); 805 } else { 806 b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, 807 B43_PHY_HT_CLASS_CTL_OFDM_EN); 808 if (new_channel->band == NL80211_BAND_2GHZ) 809 b43_phy_mask(dev, B43_PHY_HT_TEST, ~0x840); 810 } 811 812 if (1) /* TODO: On N it's for early devices only, what about HT? */ 813 b43_phy_ht_tx_power_fix(dev); 814 815 b43_phy_ht_spur_avoid(dev, new_channel); 816 817 b43_phy_write(dev, 0x017e, 0x3830); 818 } 819 820 static int b43_phy_ht_set_channel(struct b43_wldev *dev, 821 struct ieee80211_channel *channel, 822 enum nl80211_channel_type channel_type) 823 { 824 struct b43_phy *phy = &dev->phy; 825 826 const struct b43_phy_ht_channeltab_e_radio2059 *chent_r2059 = NULL; 827 828 if (phy->radio_ver == 0x2059) { 829 chent_r2059 = b43_phy_ht_get_channeltab_e_r2059(dev, 830 channel->center_freq); 831 if (!chent_r2059) 832 return -ESRCH; 833 } else { 834 return -ESRCH; 835 } 836 837 /* TODO: In case of N-PHY some bandwidth switching goes here */ 838 839 if (phy->radio_ver == 0x2059) { 840 b43_radio_2059_channel_setup(dev, chent_r2059); 841 b43_phy_ht_channel_setup(dev, &(chent_r2059->phy_regs), 842 channel); 843 } else { 844 return -ESRCH; 845 } 846 847 return 0; 848 } 849 850 /************************************************** 851 * Basic PHY ops. 852 **************************************************/ 853 854 static int b43_phy_ht_op_allocate(struct b43_wldev *dev) 855 { 856 struct b43_phy_ht *phy_ht; 857 858 phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL); 859 if (!phy_ht) 860 return -ENOMEM; 861 dev->phy.ht = phy_ht; 862 863 return 0; 864 } 865 866 static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev) 867 { 868 struct b43_phy *phy = &dev->phy; 869 struct b43_phy_ht *phy_ht = phy->ht; 870 int i; 871 872 memset(phy_ht, 0, sizeof(*phy_ht)); 873 874 phy_ht->tx_pwr_ctl = true; 875 for (i = 0; i < 3; i++) 876 phy_ht->tx_pwr_idx[i] = B43_PHY_HT_TXPCTL_CMD_C1_INIT + 1; 877 878 for (i = 0; i < 3; i++) 879 phy_ht->bb_mult_save[i] = -1; 880 } 881 882 static int b43_phy_ht_op_init(struct b43_wldev *dev) 883 { 884 struct b43_phy_ht *phy_ht = dev->phy.ht; 885 u16 tmp; 886 u16 clip_state[3]; 887 bool saved_tx_pwr_ctl; 888 889 if (dev->dev->bus_type != B43_BUS_BCMA) { 890 b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n"); 891 return -EOPNOTSUPP; 892 } 893 894 b43_phy_ht_tables_init(dev); 895 896 b43_phy_mask(dev, 0x0be, ~0x2); 897 b43_phy_set(dev, 0x23f, 0x7ff); 898 b43_phy_set(dev, 0x240, 0x7ff); 899 b43_phy_set(dev, 0x241, 0x7ff); 900 901 b43_phy_ht_zero_extg(dev); 902 903 b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); 904 905 b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0); 906 b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0); 907 b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0); 908 909 b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); 910 b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); 911 b43_phy_write(dev, 0x20d, 0xb8); 912 b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8); 913 b43_phy_write(dev, 0x70, 0x50); 914 b43_phy_write(dev, 0x1ff, 0x30); 915 916 if (0) /* TODO: condition */ 917 ; /* TODO: PHY op on reg 0x217 */ 918 919 if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) 920 b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 0); 921 else 922 b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 923 B43_PHY_HT_CLASS_CTL_CCK_EN); 924 925 b43_phy_set(dev, 0xb1, 0x91); 926 b43_phy_write(dev, 0x32f, 0x0003); 927 b43_phy_write(dev, 0x077, 0x0010); 928 b43_phy_write(dev, 0x0b4, 0x0258); 929 b43_phy_mask(dev, 0x17e, ~0x4000); 930 931 b43_phy_write(dev, 0x0b9, 0x0072); 932 933 b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f); 934 b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f); 935 b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f); 936 937 b43_phy_ht_afe_unk1(dev); 938 939 b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111, 940 0x777, 0x111, 0x111, 0x777, 0x111, 0x111); 941 942 b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777); 943 b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777); 944 945 b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02); 946 b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02); 947 b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02); 948 949 b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4, 950 0x8e, 0x96, 0x96, 0x96); 951 b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4, 952 0x8f, 0x9f, 0x9f, 0x9f); 953 b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4, 954 0x8f, 0x9f, 0x9f, 0x9f); 955 956 b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2); 957 b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2); 958 b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2); 959 960 b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); 961 b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); 962 b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); 963 b43_phy_maskset(dev, 0x0283, 0xff00, 0x40); 964 965 b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4, 966 0x09, 0x0e, 0x13, 0x18); 967 b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4, 968 0x09, 0x0e, 0x13, 0x18); 969 /* TODO: Did wl mean 2 instead of 40? */ 970 b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4, 971 0x09, 0x0e, 0x13, 0x18); 972 973 b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd); 974 b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd); 975 b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd); 976 977 b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1); 978 b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1); 979 b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1); 980 b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1); 981 982 /* Copy some tables entries */ 983 tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144)); 984 b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp); 985 tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154)); 986 b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp); 987 tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164)); 988 b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp); 989 990 /* Reset CCA */ 991 b43_phy_force_clock(dev, true); 992 tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG); 993 b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA); 994 b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA); 995 b43_phy_force_clock(dev, false); 996 997 b43_mac_phy_clock_set(dev, true); 998 999 b43_phy_ht_pa_override(dev, false); 1000 b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); 1001 b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); 1002 b43_phy_ht_pa_override(dev, true); 1003 1004 /* TODO: Should we restore it? Or store it in global PHY info? */ 1005 b43_phy_ht_classifier(dev, 0, 0); 1006 b43_phy_ht_read_clip_detection(dev, clip_state); 1007 1008 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 1009 b43_phy_ht_bphy_init(dev); 1010 1011 b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), 1012 B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); 1013 1014 saved_tx_pwr_ctl = phy_ht->tx_pwr_ctl; 1015 b43_phy_ht_tx_power_fix(dev); 1016 b43_phy_ht_tx_power_ctl(dev, false); 1017 b43_phy_ht_tx_power_ctl_idle_tssi(dev); 1018 b43_phy_ht_tx_power_ctl_setup(dev); 1019 b43_phy_ht_tssi_setup(dev); 1020 b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl); 1021 1022 return 0; 1023 } 1024 1025 static void b43_phy_ht_op_free(struct b43_wldev *dev) 1026 { 1027 struct b43_phy *phy = &dev->phy; 1028 struct b43_phy_ht *phy_ht = phy->ht; 1029 1030 kfree(phy_ht); 1031 phy->ht = NULL; 1032 } 1033 1034 /* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ 1035 static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev, 1036 bool blocked) 1037 { 1038 if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) 1039 b43err(dev->wl, "MAC not suspended\n"); 1040 1041 if (blocked) { 1042 b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, 1043 ~B43_PHY_HT_RF_CTL_CMD_CHIP0_PU); 1044 } else { 1045 if (dev->phy.radio_ver == 0x2059) 1046 b43_radio_2059_init(dev); 1047 else 1048 B43_WARN_ON(1); 1049 1050 b43_switch_channel(dev, dev->phy.channel); 1051 } 1052 } 1053 1054 static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on) 1055 { 1056 if (on) { 1057 b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00cd); 1058 b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x0000); 1059 b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00cd); 1060 b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x0000); 1061 b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00cd); 1062 b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x0000); 1063 } else { 1064 b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x07ff); 1065 b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00fd); 1066 b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x07ff); 1067 b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00fd); 1068 b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x07ff); 1069 b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00fd); 1070 } 1071 } 1072 1073 static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev, 1074 unsigned int new_channel) 1075 { 1076 struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan; 1077 enum nl80211_channel_type channel_type = 1078 cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef); 1079 1080 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) { 1081 if ((new_channel < 1) || (new_channel > 14)) 1082 return -EINVAL; 1083 } else { 1084 return -EINVAL; 1085 } 1086 1087 return b43_phy_ht_set_channel(dev, channel, channel_type); 1088 } 1089 1090 static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev) 1091 { 1092 if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) 1093 return 11; 1094 return 36; 1095 } 1096 1097 /************************************************** 1098 * R/W ops. 1099 **************************************************/ 1100 1101 static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, 1102 u16 set) 1103 { 1104 b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 1105 b43_write16(dev, B43_MMIO_PHY_DATA, 1106 (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); 1107 } 1108 1109 static u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg) 1110 { 1111 /* HT-PHY needs 0x200 for read access */ 1112 reg |= 0x200; 1113 1114 b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); 1115 return b43_read16(dev, B43_MMIO_RADIO24_DATA); 1116 } 1117 1118 static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg, 1119 u16 value) 1120 { 1121 b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg); 1122 b43_write16(dev, B43_MMIO_RADIO24_DATA, value); 1123 } 1124 1125 static enum b43_txpwr_result 1126 b43_phy_ht_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi) 1127 { 1128 return B43_TXPWR_RES_DONE; 1129 } 1130 1131 static void b43_phy_ht_op_adjust_txpower(struct b43_wldev *dev) 1132 { 1133 } 1134 1135 /************************************************** 1136 * PHY ops struct. 1137 **************************************************/ 1138 1139 const struct b43_phy_operations b43_phyops_ht = { 1140 .allocate = b43_phy_ht_op_allocate, 1141 .free = b43_phy_ht_op_free, 1142 .prepare_structs = b43_phy_ht_op_prepare_structs, 1143 .init = b43_phy_ht_op_init, 1144 .phy_maskset = b43_phy_ht_op_maskset, 1145 .radio_read = b43_phy_ht_op_radio_read, 1146 .radio_write = b43_phy_ht_op_radio_write, 1147 .software_rfkill = b43_phy_ht_op_software_rfkill, 1148 .switch_analog = b43_phy_ht_op_switch_analog, 1149 .switch_channel = b43_phy_ht_op_switch_channel, 1150 .get_default_chan = b43_phy_ht_op_get_default_chan, 1151 .recalc_txpower = b43_phy_ht_op_recalc_txpower, 1152 .adjust_txpower = b43_phy_ht_op_adjust_txpower, 1153 }; 1154