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