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