1 // SPDX-License-Identifier: ISC 2 /* 3 * Copyright (c) 2010 Broadcom Corporation 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/delay.h> 8 #include <linux/cordic.h> 9 10 #include <pmu.h> 11 #include <d11.h> 12 #include <phy_shim.h> 13 #include "phy_qmath.h" 14 #include "phy_hal.h" 15 #include "phy_radio.h" 16 #include "phytbl_lcn.h" 17 #include "phy_lcn.h" 18 19 #define PLL_2064_NDIV 90 20 #define PLL_2064_LOW_END_VCO 3000 21 #define PLL_2064_LOW_END_KVCO 27 22 #define PLL_2064_HIGH_END_VCO 4200 23 #define PLL_2064_HIGH_END_KVCO 68 24 #define PLL_2064_LOOP_BW_DOUBLER 200 25 #define PLL_2064_D30_DOUBLER 10500 26 #define PLL_2064_LOOP_BW 260 27 #define PLL_2064_D30 8000 28 #define PLL_2064_CAL_REF_TO 8 29 #define PLL_2064_MHZ 1000000 30 #define PLL_2064_OPEN_LOOP_DELAY 5 31 32 #define TEMPSENSE 1 33 #define VBATSENSE 2 34 35 #define NOISE_IF_UPD_CHK_INTERVAL 1 36 #define NOISE_IF_UPD_RST_INTERVAL 60 37 #define NOISE_IF_UPD_THRESHOLD_CNT 1 38 #define NOISE_IF_UPD_TRHRESHOLD 50 39 #define NOISE_IF_UPD_TIMEOUT 1000 40 #define NOISE_IF_OFF 0 41 #define NOISE_IF_CHK 1 42 #define NOISE_IF_ON 2 43 44 #define PAPD_BLANKING_PROFILE 3 45 #define PAPD2LUT 0 46 #define PAPD_CORR_NORM 0 47 #define PAPD_BLANKING_THRESHOLD 0 48 #define PAPD_STOP_AFTER_LAST_UPDATE 0 49 50 #define LCN_TARGET_PWR 60 51 52 #define LCN_VBAT_OFFSET_433X 34649679 53 #define LCN_VBAT_SLOPE_433X 8258032 54 55 #define LCN_VBAT_SCALE_NOM 53 56 #define LCN_VBAT_SCALE_DEN 432 57 58 #define LCN_TEMPSENSE_OFFSET 80812 59 #define LCN_TEMPSENSE_DEN 2647 60 61 #define LCN_BW_LMT 200 62 #define LCN_CUR_LMT 1250 63 #define LCN_MULT 1 64 #define LCN_VCO_DIV 30 65 #define LCN_OFFSET 680 66 #define LCN_FACT 490 67 #define LCN_CUR_DIV 2640 68 69 #define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \ 70 (0 + 8) 71 #define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \ 72 (0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT) 73 74 #define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \ 75 (0 + 8) 76 #define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \ 77 (0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT) 78 79 #define wlc_lcnphy_enable_tx_gain_override(pi) \ 80 wlc_lcnphy_set_tx_gain_override(pi, true) 81 #define wlc_lcnphy_disable_tx_gain_override(pi) \ 82 wlc_lcnphy_set_tx_gain_override(pi, false) 83 84 #define wlc_lcnphy_iqcal_active(pi) \ 85 (read_phy_reg((pi), 0x451) & \ 86 ((0x1 << 15) | (0x1 << 14))) 87 88 #define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13)) 89 #define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \ 90 (pi->temppwrctrl_capable) 91 #define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \ 92 (pi->hwpwrctrl_capable) 93 94 #define SWCTRL_BT_TX 0x18 95 #define SWCTRL_OVR_DISABLE 0x40 96 97 #define AFE_CLK_INIT_MODE_TXRX2X 1 98 #define AFE_CLK_INIT_MODE_PAPD 0 99 100 #define LCNPHY_TBL_ID_IQLOCAL 0x00 101 102 #define LCNPHY_TBL_ID_RFSEQ 0x08 103 #define LCNPHY_TBL_ID_GAIN_IDX 0x0d 104 #define LCNPHY_TBL_ID_SW_CTRL 0x0f 105 #define LCNPHY_TBL_ID_GAIN_TBL 0x12 106 #define LCNPHY_TBL_ID_SPUR 0x14 107 #define LCNPHY_TBL_ID_SAMPLEPLAY 0x15 108 #define LCNPHY_TBL_ID_SAMPLEPLAY1 0x16 109 110 #define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 832 111 #define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 128 112 #define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 192 113 #define LCNPHY_TX_PWR_CTRL_IQ_OFFSET 320 114 #define LCNPHY_TX_PWR_CTRL_LO_OFFSET 448 115 #define LCNPHY_TX_PWR_CTRL_PWR_OFFSET 576 116 117 #define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313 140 118 119 #define LCNPHY_TX_PWR_CTRL_START_NPT 1 120 #define LCNPHY_TX_PWR_CTRL_MAX_NPT 7 121 122 #define LCNPHY_NOISE_SAMPLES_DEFAULT 5000 123 124 #define LCNPHY_ACI_DETECT_START 1 125 #define LCNPHY_ACI_DETECT_PROGRESS 2 126 #define LCNPHY_ACI_DETECT_STOP 3 127 128 #define LCNPHY_ACI_CRSHIFRMLO_TRSH 100 129 #define LCNPHY_ACI_GLITCH_TRSH 2000 130 #define LCNPHY_ACI_TMOUT 250 131 #define LCNPHY_ACI_DETECT_TIMEOUT 2 132 #define LCNPHY_ACI_START_DELAY 0 133 134 #define wlc_lcnphy_tx_gain_override_enabled(pi) \ 135 (0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6))) 136 137 #define wlc_lcnphy_total_tx_frames(pi) \ 138 wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \ 139 offsetof(struct macstat, txallfrm)) 140 141 struct lcnphy_txgains { 142 u16 gm_gain; 143 u16 pga_gain; 144 u16 pad_gain; 145 u16 dac_gain; 146 }; 147 148 enum lcnphy_cal_mode { 149 LCNPHY_CAL_FULL, 150 LCNPHY_CAL_RECAL, 151 LCNPHY_CAL_CURRECAL, 152 LCNPHY_CAL_DIGCAL, 153 LCNPHY_CAL_GCTRL 154 }; 155 156 struct lcnphy_rx_iqcomp { 157 u8 chan; 158 s16 a; 159 s16 b; 160 }; 161 162 struct lcnphy_spb_tone { 163 s16 re; 164 s16 im; 165 }; 166 167 struct lcnphy_unsign16_struct { 168 u16 re; 169 u16 im; 170 }; 171 172 struct lcnphy_iq_est { 173 u32 iq_prod; 174 u32 i_pwr; 175 u32 q_pwr; 176 }; 177 178 struct lcnphy_sfo_cfg { 179 u16 ptcentreTs20; 180 u16 ptcentreFactor; 181 }; 182 183 enum lcnphy_papd_cal_type { 184 LCNPHY_PAPD_CAL_CW, 185 LCNPHY_PAPD_CAL_OFDM 186 }; 187 188 typedef u16 iqcal_gain_params_lcnphy[9]; 189 190 static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = { 191 {0, 0, 0, 0, 0, 0, 0, 0, 0}, 192 }; 193 194 static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = { 195 tbl_iqcal_gainparams_lcnphy_2G, 196 }; 197 198 static const u16 iqcal_gainparams_numgains_lcnphy[1] = { 199 ARRAY_SIZE(tbl_iqcal_gainparams_lcnphy_2G), 200 }; 201 202 static const struct lcnphy_sfo_cfg lcnphy_sfo_cfg[] = { 203 {965, 1087}, 204 {967, 1085}, 205 {969, 1082}, 206 {971, 1080}, 207 {973, 1078}, 208 {975, 1076}, 209 {977, 1073}, 210 {979, 1071}, 211 {981, 1069}, 212 {983, 1067}, 213 {985, 1065}, 214 {987, 1063}, 215 {989, 1060}, 216 {994, 1055} 217 }; 218 219 static const 220 u16 lcnphy_iqcal_loft_gainladder[] = { 221 ((2 << 8) | 0), 222 ((3 << 8) | 0), 223 ((4 << 8) | 0), 224 ((6 << 8) | 0), 225 ((8 << 8) | 0), 226 ((11 << 8) | 0), 227 ((16 << 8) | 0), 228 ((16 << 8) | 1), 229 ((16 << 8) | 2), 230 ((16 << 8) | 3), 231 ((16 << 8) | 4), 232 ((16 << 8) | 5), 233 ((16 << 8) | 6), 234 ((16 << 8) | 7), 235 ((23 << 8) | 7), 236 ((32 << 8) | 7), 237 ((45 << 8) | 7), 238 ((64 << 8) | 7), 239 ((91 << 8) | 7), 240 ((128 << 8) | 7) 241 }; 242 243 static const 244 u16 lcnphy_iqcal_ir_gainladder[] = { 245 ((1 << 8) | 0), 246 ((2 << 8) | 0), 247 ((4 << 8) | 0), 248 ((6 << 8) | 0), 249 ((8 << 8) | 0), 250 ((11 << 8) | 0), 251 ((16 << 8) | 0), 252 ((23 << 8) | 0), 253 ((32 << 8) | 0), 254 ((45 << 8) | 0), 255 ((64 << 8) | 0), 256 ((64 << 8) | 1), 257 ((64 << 8) | 2), 258 ((64 << 8) | 3), 259 ((64 << 8) | 4), 260 ((64 << 8) | 5), 261 ((64 << 8) | 6), 262 ((64 << 8) | 7), 263 ((91 << 8) | 7), 264 ((128 << 8) | 7) 265 }; 266 267 static const 268 struct lcnphy_spb_tone lcnphy_spb_tone_3750[] = { 269 {88, 0}, 270 {73, 49}, 271 {34, 81}, 272 {-17, 86}, 273 {-62, 62}, 274 {-86, 17}, 275 {-81, -34}, 276 {-49, -73}, 277 {0, -88}, 278 {49, -73}, 279 {81, -34}, 280 {86, 17}, 281 {62, 62}, 282 {17, 86}, 283 {-34, 81}, 284 {-73, 49}, 285 {-88, 0}, 286 {-73, -49}, 287 {-34, -81}, 288 {17, -86}, 289 {62, -62}, 290 {86, -17}, 291 {81, 34}, 292 {49, 73}, 293 {0, 88}, 294 {-49, 73}, 295 {-81, 34}, 296 {-86, -17}, 297 {-62, -62}, 298 {-17, -86}, 299 {34, -81}, 300 {73, -49}, 301 }; 302 303 static const 304 u16 iqlo_loopback_rf_regs[20] = { 305 RADIO_2064_REG036, 306 RADIO_2064_REG11A, 307 RADIO_2064_REG03A, 308 RADIO_2064_REG025, 309 RADIO_2064_REG028, 310 RADIO_2064_REG005, 311 RADIO_2064_REG112, 312 RADIO_2064_REG0FF, 313 RADIO_2064_REG11F, 314 RADIO_2064_REG00B, 315 RADIO_2064_REG113, 316 RADIO_2064_REG007, 317 RADIO_2064_REG0FC, 318 RADIO_2064_REG0FD, 319 RADIO_2064_REG012, 320 RADIO_2064_REG057, 321 RADIO_2064_REG059, 322 RADIO_2064_REG05C, 323 RADIO_2064_REG078, 324 RADIO_2064_REG092, 325 }; 326 327 static const 328 u16 tempsense_phy_regs[14] = { 329 0x503, 330 0x4a4, 331 0x4d0, 332 0x4d9, 333 0x4da, 334 0x4a6, 335 0x938, 336 0x939, 337 0x4d8, 338 0x4d0, 339 0x4d7, 340 0x4a5, 341 0x40d, 342 0x4a2, 343 }; 344 345 static const 346 u16 rxiq_cal_rf_reg[11] = { 347 RADIO_2064_REG098, 348 RADIO_2064_REG116, 349 RADIO_2064_REG12C, 350 RADIO_2064_REG06A, 351 RADIO_2064_REG00B, 352 RADIO_2064_REG01B, 353 RADIO_2064_REG113, 354 RADIO_2064_REG01D, 355 RADIO_2064_REG114, 356 RADIO_2064_REG02E, 357 RADIO_2064_REG12A, 358 }; 359 360 static const 361 struct lcnphy_rx_iqcomp lcnphy_rx_iqcomp_table_rev0[] = { 362 {1, 0, 0}, 363 {2, 0, 0}, 364 {3, 0, 0}, 365 {4, 0, 0}, 366 {5, 0, 0}, 367 {6, 0, 0}, 368 {7, 0, 0}, 369 {8, 0, 0}, 370 {9, 0, 0}, 371 {10, 0, 0}, 372 {11, 0, 0}, 373 {12, 0, 0}, 374 {13, 0, 0}, 375 {14, 0, 0}, 376 {34, 0, 0}, 377 {38, 0, 0}, 378 {42, 0, 0}, 379 {46, 0, 0}, 380 {36, 0, 0}, 381 {40, 0, 0}, 382 {44, 0, 0}, 383 {48, 0, 0}, 384 {52, 0, 0}, 385 {56, 0, 0}, 386 {60, 0, 0}, 387 {64, 0, 0}, 388 {100, 0, 0}, 389 {104, 0, 0}, 390 {108, 0, 0}, 391 {112, 0, 0}, 392 {116, 0, 0}, 393 {120, 0, 0}, 394 {124, 0, 0}, 395 {128, 0, 0}, 396 {132, 0, 0}, 397 {136, 0, 0}, 398 {140, 0, 0}, 399 {149, 0, 0}, 400 {153, 0, 0}, 401 {157, 0, 0}, 402 {161, 0, 0}, 403 {165, 0, 0}, 404 {184, 0, 0}, 405 {188, 0, 0}, 406 {192, 0, 0}, 407 {196, 0, 0}, 408 {200, 0, 0}, 409 {204, 0, 0}, 410 {208, 0, 0}, 411 {212, 0, 0}, 412 {216, 0, 0}, 413 }; 414 415 static const u32 lcnphy_23bitgaincode_table[] = { 416 0x200100, 417 0x200200, 418 0x200004, 419 0x200014, 420 0x200024, 421 0x200034, 422 0x200134, 423 0x200234, 424 0x200334, 425 0x200434, 426 0x200037, 427 0x200137, 428 0x200237, 429 0x200337, 430 0x200437, 431 0x000035, 432 0x000135, 433 0x000235, 434 0x000037, 435 0x000137, 436 0x000237, 437 0x000337, 438 0x00013f, 439 0x00023f, 440 0x00033f, 441 0x00034f, 442 0x00044f, 443 0x00144f, 444 0x00244f, 445 0x00254f, 446 0x00354f, 447 0x00454f, 448 0x00464f, 449 0x01464f, 450 0x02464f, 451 0x03464f, 452 0x04464f, 453 }; 454 455 static const s8 lcnphy_gain_table[] = { 456 -16, 457 -13, 458 10, 459 7, 460 4, 461 0, 462 3, 463 6, 464 9, 465 12, 466 15, 467 18, 468 21, 469 24, 470 27, 471 30, 472 33, 473 36, 474 39, 475 42, 476 45, 477 48, 478 50, 479 53, 480 56, 481 59, 482 62, 483 65, 484 68, 485 71, 486 74, 487 77, 488 80, 489 83, 490 86, 491 89, 492 92, 493 }; 494 495 static const s8 lcnphy_gain_index_offset_for_rssi[] = { 496 7, 497 7, 498 7, 499 7, 500 7, 501 7, 502 7, 503 8, 504 7, 505 7, 506 6, 507 7, 508 7, 509 4, 510 4, 511 4, 512 4, 513 4, 514 4, 515 4, 516 4, 517 3, 518 3, 519 3, 520 3, 521 3, 522 3, 523 4, 524 2, 525 2, 526 2, 527 2, 528 2, 529 2, 530 -1, 531 -2, 532 -2, 533 -2 534 }; 535 536 struct chan_info_2064_lcnphy { 537 uint chan; 538 uint freq; 539 u8 logen_buftune; 540 u8 logen_rccr_tx; 541 u8 txrf_mix_tune_ctrl; 542 u8 pa_input_tune_g; 543 u8 logen_rccr_rx; 544 u8 pa_rxrf_lna1_freq_tune; 545 u8 pa_rxrf_lna2_freq_tune; 546 u8 rxrf_rxrf_spare1; 547 }; 548 549 static const struct chan_info_2064_lcnphy chan_info_2064_lcnphy[] = { 550 {1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 551 {2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 552 {3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 553 {4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 554 {5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 555 {6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 556 {7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 557 {8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 558 {9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 559 {10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 560 {11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 561 {12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 562 {13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 563 {14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80}, 564 }; 565 566 static const struct lcnphy_radio_regs lcnphy_radio_regs_2064[] = { 567 {0x00, 0, 0, 0, 0}, 568 {0x01, 0x64, 0x64, 0, 0}, 569 {0x02, 0x20, 0x20, 0, 0}, 570 {0x03, 0x66, 0x66, 0, 0}, 571 {0x04, 0xf8, 0xf8, 0, 0}, 572 {0x05, 0, 0, 0, 0}, 573 {0x06, 0x10, 0x10, 0, 0}, 574 {0x07, 0, 0, 0, 0}, 575 {0x08, 0, 0, 0, 0}, 576 {0x09, 0, 0, 0, 0}, 577 {0x0A, 0x37, 0x37, 0, 0}, 578 {0x0B, 0x6, 0x6, 0, 0}, 579 {0x0C, 0x55, 0x55, 0, 0}, 580 {0x0D, 0x8b, 0x8b, 0, 0}, 581 {0x0E, 0, 0, 0, 0}, 582 {0x0F, 0x5, 0x5, 0, 0}, 583 {0x10, 0, 0, 0, 0}, 584 {0x11, 0xe, 0xe, 0, 0}, 585 {0x12, 0, 0, 0, 0}, 586 {0x13, 0xb, 0xb, 0, 0}, 587 {0x14, 0x2, 0x2, 0, 0}, 588 {0x15, 0x12, 0x12, 0, 0}, 589 {0x16, 0x12, 0x12, 0, 0}, 590 {0x17, 0xc, 0xc, 0, 0}, 591 {0x18, 0xc, 0xc, 0, 0}, 592 {0x19, 0xc, 0xc, 0, 0}, 593 {0x1A, 0x8, 0x8, 0, 0}, 594 {0x1B, 0x2, 0x2, 0, 0}, 595 {0x1C, 0, 0, 0, 0}, 596 {0x1D, 0x1, 0x1, 0, 0}, 597 {0x1E, 0x12, 0x12, 0, 0}, 598 {0x1F, 0x6e, 0x6e, 0, 0}, 599 {0x20, 0x2, 0x2, 0, 0}, 600 {0x21, 0x23, 0x23, 0, 0}, 601 {0x22, 0x8, 0x8, 0, 0}, 602 {0x23, 0, 0, 0, 0}, 603 {0x24, 0, 0, 0, 0}, 604 {0x25, 0xc, 0xc, 0, 0}, 605 {0x26, 0x33, 0x33, 0, 0}, 606 {0x27, 0x55, 0x55, 0, 0}, 607 {0x28, 0, 0, 0, 0}, 608 {0x29, 0x30, 0x30, 0, 0}, 609 {0x2A, 0xb, 0xb, 0, 0}, 610 {0x2B, 0x1b, 0x1b, 0, 0}, 611 {0x2C, 0x3, 0x3, 0, 0}, 612 {0x2D, 0x1b, 0x1b, 0, 0}, 613 {0x2E, 0, 0, 0, 0}, 614 {0x2F, 0x20, 0x20, 0, 0}, 615 {0x30, 0xa, 0xa, 0, 0}, 616 {0x31, 0, 0, 0, 0}, 617 {0x32, 0x62, 0x62, 0, 0}, 618 {0x33, 0x19, 0x19, 0, 0}, 619 {0x34, 0x33, 0x33, 0, 0}, 620 {0x35, 0x77, 0x77, 0, 0}, 621 {0x36, 0, 0, 0, 0}, 622 {0x37, 0x70, 0x70, 0, 0}, 623 {0x38, 0x3, 0x3, 0, 0}, 624 {0x39, 0xf, 0xf, 0, 0}, 625 {0x3A, 0x6, 0x6, 0, 0}, 626 {0x3B, 0xcf, 0xcf, 0, 0}, 627 {0x3C, 0x1a, 0x1a, 0, 0}, 628 {0x3D, 0x6, 0x6, 0, 0}, 629 {0x3E, 0x42, 0x42, 0, 0}, 630 {0x3F, 0, 0, 0, 0}, 631 {0x40, 0xfb, 0xfb, 0, 0}, 632 {0x41, 0x9a, 0x9a, 0, 0}, 633 {0x42, 0x7a, 0x7a, 0, 0}, 634 {0x43, 0x29, 0x29, 0, 0}, 635 {0x44, 0, 0, 0, 0}, 636 {0x45, 0x8, 0x8, 0, 0}, 637 {0x46, 0xce, 0xce, 0, 0}, 638 {0x47, 0x27, 0x27, 0, 0}, 639 {0x48, 0x62, 0x62, 0, 0}, 640 {0x49, 0x6, 0x6, 0, 0}, 641 {0x4A, 0x58, 0x58, 0, 0}, 642 {0x4B, 0xf7, 0xf7, 0, 0}, 643 {0x4C, 0, 0, 0, 0}, 644 {0x4D, 0xb3, 0xb3, 0, 0}, 645 {0x4E, 0, 0, 0, 0}, 646 {0x4F, 0x2, 0x2, 0, 0}, 647 {0x50, 0, 0, 0, 0}, 648 {0x51, 0x9, 0x9, 0, 0}, 649 {0x52, 0x5, 0x5, 0, 0}, 650 {0x53, 0x17, 0x17, 0, 0}, 651 {0x54, 0x38, 0x38, 0, 0}, 652 {0x55, 0, 0, 0, 0}, 653 {0x56, 0, 0, 0, 0}, 654 {0x57, 0xb, 0xb, 0, 0}, 655 {0x58, 0, 0, 0, 0}, 656 {0x59, 0, 0, 0, 0}, 657 {0x5A, 0, 0, 0, 0}, 658 {0x5B, 0, 0, 0, 0}, 659 {0x5C, 0, 0, 0, 0}, 660 {0x5D, 0, 0, 0, 0}, 661 {0x5E, 0x88, 0x88, 0, 0}, 662 {0x5F, 0xcc, 0xcc, 0, 0}, 663 {0x60, 0x74, 0x74, 0, 0}, 664 {0x61, 0x74, 0x74, 0, 0}, 665 {0x62, 0x74, 0x74, 0, 0}, 666 {0x63, 0x44, 0x44, 0, 0}, 667 {0x64, 0x77, 0x77, 0, 0}, 668 {0x65, 0x44, 0x44, 0, 0}, 669 {0x66, 0x77, 0x77, 0, 0}, 670 {0x67, 0x55, 0x55, 0, 0}, 671 {0x68, 0x77, 0x77, 0, 0}, 672 {0x69, 0x77, 0x77, 0, 0}, 673 {0x6A, 0, 0, 0, 0}, 674 {0x6B, 0x7f, 0x7f, 0, 0}, 675 {0x6C, 0x8, 0x8, 0, 0}, 676 {0x6D, 0, 0, 0, 0}, 677 {0x6E, 0x88, 0x88, 0, 0}, 678 {0x6F, 0x66, 0x66, 0, 0}, 679 {0x70, 0x66, 0x66, 0, 0}, 680 {0x71, 0x28, 0x28, 0, 0}, 681 {0x72, 0x55, 0x55, 0, 0}, 682 {0x73, 0x4, 0x4, 0, 0}, 683 {0x74, 0, 0, 0, 0}, 684 {0x75, 0, 0, 0, 0}, 685 {0x76, 0, 0, 0, 0}, 686 {0x77, 0x1, 0x1, 0, 0}, 687 {0x78, 0xd6, 0xd6, 0, 0}, 688 {0x79, 0, 0, 0, 0}, 689 {0x7A, 0, 0, 0, 0}, 690 {0x7B, 0, 0, 0, 0}, 691 {0x7C, 0, 0, 0, 0}, 692 {0x7D, 0, 0, 0, 0}, 693 {0x7E, 0, 0, 0, 0}, 694 {0x7F, 0, 0, 0, 0}, 695 {0x80, 0, 0, 0, 0}, 696 {0x81, 0, 0, 0, 0}, 697 {0x82, 0, 0, 0, 0}, 698 {0x83, 0xb4, 0xb4, 0, 0}, 699 {0x84, 0x1, 0x1, 0, 0}, 700 {0x85, 0x20, 0x20, 0, 0}, 701 {0x86, 0x5, 0x5, 0, 0}, 702 {0x87, 0xff, 0xff, 0, 0}, 703 {0x88, 0x7, 0x7, 0, 0}, 704 {0x89, 0x77, 0x77, 0, 0}, 705 {0x8A, 0x77, 0x77, 0, 0}, 706 {0x8B, 0x77, 0x77, 0, 0}, 707 {0x8C, 0x77, 0x77, 0, 0}, 708 {0x8D, 0x8, 0x8, 0, 0}, 709 {0x8E, 0xa, 0xa, 0, 0}, 710 {0x8F, 0x8, 0x8, 0, 0}, 711 {0x90, 0x18, 0x18, 0, 0}, 712 {0x91, 0x5, 0x5, 0, 0}, 713 {0x92, 0x1f, 0x1f, 0, 0}, 714 {0x93, 0x10, 0x10, 0, 0}, 715 {0x94, 0x3, 0x3, 0, 0}, 716 {0x95, 0, 0, 0, 0}, 717 {0x96, 0, 0, 0, 0}, 718 {0x97, 0xaa, 0xaa, 0, 0}, 719 {0x98, 0, 0, 0, 0}, 720 {0x99, 0x23, 0x23, 0, 0}, 721 {0x9A, 0x7, 0x7, 0, 0}, 722 {0x9B, 0xf, 0xf, 0, 0}, 723 {0x9C, 0x10, 0x10, 0, 0}, 724 {0x9D, 0x3, 0x3, 0, 0}, 725 {0x9E, 0x4, 0x4, 0, 0}, 726 {0x9F, 0x20, 0x20, 0, 0}, 727 {0xA0, 0, 0, 0, 0}, 728 {0xA1, 0, 0, 0, 0}, 729 {0xA2, 0, 0, 0, 0}, 730 {0xA3, 0, 0, 0, 0}, 731 {0xA4, 0x1, 0x1, 0, 0}, 732 {0xA5, 0x77, 0x77, 0, 0}, 733 {0xA6, 0x77, 0x77, 0, 0}, 734 {0xA7, 0x77, 0x77, 0, 0}, 735 {0xA8, 0x77, 0x77, 0, 0}, 736 {0xA9, 0x8c, 0x8c, 0, 0}, 737 {0xAA, 0x88, 0x88, 0, 0}, 738 {0xAB, 0x78, 0x78, 0, 0}, 739 {0xAC, 0x57, 0x57, 0, 0}, 740 {0xAD, 0x88, 0x88, 0, 0}, 741 {0xAE, 0, 0, 0, 0}, 742 {0xAF, 0x8, 0x8, 0, 0}, 743 {0xB0, 0x88, 0x88, 0, 0}, 744 {0xB1, 0, 0, 0, 0}, 745 {0xB2, 0x1b, 0x1b, 0, 0}, 746 {0xB3, 0x3, 0x3, 0, 0}, 747 {0xB4, 0x24, 0x24, 0, 0}, 748 {0xB5, 0x3, 0x3, 0, 0}, 749 {0xB6, 0x1b, 0x1b, 0, 0}, 750 {0xB7, 0x24, 0x24, 0, 0}, 751 {0xB8, 0x3, 0x3, 0, 0}, 752 {0xB9, 0, 0, 0, 0}, 753 {0xBA, 0xaa, 0xaa, 0, 0}, 754 {0xBB, 0, 0, 0, 0}, 755 {0xBC, 0x4, 0x4, 0, 0}, 756 {0xBD, 0, 0, 0, 0}, 757 {0xBE, 0x8, 0x8, 0, 0}, 758 {0xBF, 0x11, 0x11, 0, 0}, 759 {0xC0, 0, 0, 0, 0}, 760 {0xC1, 0, 0, 0, 0}, 761 {0xC2, 0x62, 0x62, 0, 0}, 762 {0xC3, 0x1e, 0x1e, 0, 0}, 763 {0xC4, 0x33, 0x33, 0, 0}, 764 {0xC5, 0x37, 0x37, 0, 0}, 765 {0xC6, 0, 0, 0, 0}, 766 {0xC7, 0x70, 0x70, 0, 0}, 767 {0xC8, 0x1e, 0x1e, 0, 0}, 768 {0xC9, 0x6, 0x6, 0, 0}, 769 {0xCA, 0x4, 0x4, 0, 0}, 770 {0xCB, 0x2f, 0x2f, 0, 0}, 771 {0xCC, 0xf, 0xf, 0, 0}, 772 {0xCD, 0, 0, 0, 0}, 773 {0xCE, 0xff, 0xff, 0, 0}, 774 {0xCF, 0x8, 0x8, 0, 0}, 775 {0xD0, 0x3f, 0x3f, 0, 0}, 776 {0xD1, 0x3f, 0x3f, 0, 0}, 777 {0xD2, 0x3f, 0x3f, 0, 0}, 778 {0xD3, 0, 0, 0, 0}, 779 {0xD4, 0, 0, 0, 0}, 780 {0xD5, 0, 0, 0, 0}, 781 {0xD6, 0xcc, 0xcc, 0, 0}, 782 {0xD7, 0, 0, 0, 0}, 783 {0xD8, 0x8, 0x8, 0, 0}, 784 {0xD9, 0x8, 0x8, 0, 0}, 785 {0xDA, 0x8, 0x8, 0, 0}, 786 {0xDB, 0x11, 0x11, 0, 0}, 787 {0xDC, 0, 0, 0, 0}, 788 {0xDD, 0x87, 0x87, 0, 0}, 789 {0xDE, 0x88, 0x88, 0, 0}, 790 {0xDF, 0x8, 0x8, 0, 0}, 791 {0xE0, 0x8, 0x8, 0, 0}, 792 {0xE1, 0x8, 0x8, 0, 0}, 793 {0xE2, 0, 0, 0, 0}, 794 {0xE3, 0, 0, 0, 0}, 795 {0xE4, 0, 0, 0, 0}, 796 {0xE5, 0xf5, 0xf5, 0, 0}, 797 {0xE6, 0x30, 0x30, 0, 0}, 798 {0xE7, 0x1, 0x1, 0, 0}, 799 {0xE8, 0, 0, 0, 0}, 800 {0xE9, 0xff, 0xff, 0, 0}, 801 {0xEA, 0, 0, 0, 0}, 802 {0xEB, 0, 0, 0, 0}, 803 {0xEC, 0x22, 0x22, 0, 0}, 804 {0xED, 0, 0, 0, 0}, 805 {0xEE, 0, 0, 0, 0}, 806 {0xEF, 0, 0, 0, 0}, 807 {0xF0, 0x3, 0x3, 0, 0}, 808 {0xF1, 0x1, 0x1, 0, 0}, 809 {0xF2, 0, 0, 0, 0}, 810 {0xF3, 0, 0, 0, 0}, 811 {0xF4, 0, 0, 0, 0}, 812 {0xF5, 0, 0, 0, 0}, 813 {0xF6, 0, 0, 0, 0}, 814 {0xF7, 0x6, 0x6, 0, 0}, 815 {0xF8, 0, 0, 0, 0}, 816 {0xF9, 0, 0, 0, 0}, 817 {0xFA, 0x40, 0x40, 0, 0}, 818 {0xFB, 0, 0, 0, 0}, 819 {0xFC, 0x1, 0x1, 0, 0}, 820 {0xFD, 0x80, 0x80, 0, 0}, 821 {0xFE, 0x2, 0x2, 0, 0}, 822 {0xFF, 0x10, 0x10, 0, 0}, 823 {0x100, 0x2, 0x2, 0, 0}, 824 {0x101, 0x1e, 0x1e, 0, 0}, 825 {0x102, 0x1e, 0x1e, 0, 0}, 826 {0x103, 0, 0, 0, 0}, 827 {0x104, 0x1f, 0x1f, 0, 0}, 828 {0x105, 0, 0x8, 0, 1}, 829 {0x106, 0x2a, 0x2a, 0, 0}, 830 {0x107, 0xf, 0xf, 0, 0}, 831 {0x108, 0, 0, 0, 0}, 832 {0x109, 0, 0, 0, 0}, 833 {0x10A, 0, 0, 0, 0}, 834 {0x10B, 0, 0, 0, 0}, 835 {0x10C, 0, 0, 0, 0}, 836 {0x10D, 0, 0, 0, 0}, 837 {0x10E, 0, 0, 0, 0}, 838 {0x10F, 0, 0, 0, 0}, 839 {0x110, 0, 0, 0, 0}, 840 {0x111, 0, 0, 0, 0}, 841 {0x112, 0, 0, 0, 0}, 842 {0x113, 0, 0, 0, 0}, 843 {0x114, 0, 0, 0, 0}, 844 {0x115, 0, 0, 0, 0}, 845 {0x116, 0, 0, 0, 0}, 846 {0x117, 0, 0, 0, 0}, 847 {0x118, 0, 0, 0, 0}, 848 {0x119, 0, 0, 0, 0}, 849 {0x11A, 0, 0, 0, 0}, 850 {0x11B, 0, 0, 0, 0}, 851 {0x11C, 0x1, 0x1, 0, 0}, 852 {0x11D, 0, 0, 0, 0}, 853 {0x11E, 0, 0, 0, 0}, 854 {0x11F, 0, 0, 0, 0}, 855 {0x120, 0, 0, 0, 0}, 856 {0x121, 0, 0, 0, 0}, 857 {0x122, 0x80, 0x80, 0, 0}, 858 {0x123, 0, 0, 0, 0}, 859 {0x124, 0xf8, 0xf8, 0, 0}, 860 {0x125, 0, 0, 0, 0}, 861 {0x126, 0, 0, 0, 0}, 862 {0x127, 0, 0, 0, 0}, 863 {0x128, 0, 0, 0, 0}, 864 {0x129, 0, 0, 0, 0}, 865 {0x12A, 0, 0, 0, 0}, 866 {0x12B, 0, 0, 0, 0}, 867 {0x12C, 0, 0, 0, 0}, 868 {0x12D, 0, 0, 0, 0}, 869 {0x12E, 0, 0, 0, 0}, 870 {0x12F, 0, 0, 0, 0}, 871 {0x130, 0, 0, 0, 0}, 872 {0xFFFF, 0, 0, 0, 0} 873 }; 874 875 #define LCNPHY_NUM_DIG_FILT_COEFFS 16 876 #define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13 877 878 static const u16 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK] 879 [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = { 880 {0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64, 881 128, 64,}, 882 {1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93, 883 167, 93,}, 884 {2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64, 885 128, 64,}, 886 {3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760, 887 170, 340, 170,}, 888 {20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760, 889 256, 185, 256,}, 890 {21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760, 891 256, 273, 256,}, 892 {22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760, 893 256, 352, 256,}, 894 {23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760, 895 128, 233, 128,}, 896 {24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256, 897 1881, 256,}, 898 {25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256, 899 1881, 256,}, 900 {26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128, 901 384, 288,}, 902 {27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864, 903 128, 384, 288,}, 904 {30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760, 905 170, 340, 170,}, 906 }; 907 908 #define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3 909 static const u16 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM] 910 [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = { 911 {0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0, 912 0x278, 0xfea0, 0x80, 0x100, 0x80,}, 913 {1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, 914 750, 0xFE2B, 212, 0xFFCE, 212,}, 915 {2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748, 916 0xFEF2, 128, 0xFFE2, 128} 917 }; 918 919 #define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \ 920 mod_phy_reg(pi, 0x4a4, \ 921 (0x1ff << 0), \ 922 (u16)(idx) << 0) 923 924 #define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \ 925 mod_phy_reg(pi, 0x4a5, \ 926 (0x7 << 8), \ 927 (u16)(npt) << 8) 928 929 #define wlc_lcnphy_get_tx_pwr_ctrl(pi) \ 930 (read_phy_reg((pi), 0x4a4) & \ 931 ((0x1 << 15) | \ 932 (0x1 << 14) | \ 933 (0x1 << 13))) 934 935 #define wlc_lcnphy_get_tx_pwr_npt(pi) \ 936 ((read_phy_reg(pi, 0x4a5) & \ 937 (0x7 << 8)) >> \ 938 8) 939 940 #define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \ 941 (read_phy_reg(pi, 0x473) & 0x1ff) 942 943 #define wlc_lcnphy_get_target_tx_pwr(pi) \ 944 ((read_phy_reg(pi, 0x4a7) & \ 945 (0xff << 0)) >> \ 946 0) 947 948 #define wlc_lcnphy_set_target_tx_pwr(pi, target) \ 949 mod_phy_reg(pi, 0x4a7, \ 950 (0xff << 0), \ 951 (u16)(target) << 0) 952 953 #define wlc_radio_2064_rcal_done(pi) \ 954 (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20)) 955 956 #define tempsense_done(pi) \ 957 (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000)) 958 959 #define LCNPHY_IQLOCC_READ(val) \ 960 ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f))) 961 962 #define FIXED_TXPWR 78 963 #define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val)) 964 965 void wlc_lcnphy_write_table(struct brcms_phy *pi, const struct phytbl_info *pti) 966 { 967 wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456); 968 } 969 970 void wlc_lcnphy_read_table(struct brcms_phy *pi, struct phytbl_info *pti) 971 { 972 wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456); 973 } 974 975 static void 976 wlc_lcnphy_common_read_table(struct brcms_phy *pi, u32 tbl_id, 977 const u16 *tbl_ptr, u32 tbl_len, 978 u32 tbl_width, u32 tbl_offset) 979 { 980 struct phytbl_info tab; 981 tab.tbl_id = tbl_id; 982 tab.tbl_ptr = tbl_ptr; 983 tab.tbl_len = tbl_len; 984 tab.tbl_width = tbl_width; 985 tab.tbl_offset = tbl_offset; 986 wlc_lcnphy_read_table(pi, &tab); 987 } 988 989 static void 990 wlc_lcnphy_common_write_table(struct brcms_phy *pi, u32 tbl_id, 991 const u16 *tbl_ptr, u32 tbl_len, 992 u32 tbl_width, u32 tbl_offset) 993 { 994 995 struct phytbl_info tab; 996 tab.tbl_id = tbl_id; 997 tab.tbl_ptr = tbl_ptr; 998 tab.tbl_len = tbl_len; 999 tab.tbl_width = tbl_width; 1000 tab.tbl_offset = tbl_offset; 1001 wlc_lcnphy_write_table(pi, &tab); 1002 } 1003 1004 static u32 1005 wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) 1006 { 1007 u32 quotient, remainder, roundup, rbit; 1008 1009 quotient = dividend / divisor; 1010 remainder = dividend % divisor; 1011 rbit = divisor & 1; 1012 roundup = (divisor >> 1) + rbit; 1013 1014 while (precision--) { 1015 quotient <<= 1; 1016 if (remainder >= roundup) { 1017 quotient++; 1018 remainder = ((remainder - roundup) << 1) + rbit; 1019 } else { 1020 remainder <<= 1; 1021 } 1022 } 1023 1024 if (remainder >= roundup) 1025 quotient++; 1026 1027 return quotient; 1028 } 1029 1030 static int wlc_lcnphy_calc_floor(s16 coeff_x, int type) 1031 { 1032 int k; 1033 k = 0; 1034 if (type == 0) { 1035 if (coeff_x < 0) 1036 k = (coeff_x - 1) / 2; 1037 else 1038 k = coeff_x / 2; 1039 } 1040 1041 if (type == 1) { 1042 if ((coeff_x + 1) < 0) 1043 k = (coeff_x) / 2; 1044 else 1045 k = (coeff_x + 1) / 2; 1046 } 1047 return k; 1048 } 1049 1050 static void 1051 wlc_lcnphy_get_tx_gain(struct brcms_phy *pi, struct lcnphy_txgains *gains) 1052 { 1053 u16 dac_gain, rfgain0, rfgain1; 1054 1055 dac_gain = read_phy_reg(pi, 0x439) >> 0; 1056 gains->dac_gain = (dac_gain & 0x380) >> 7; 1057 1058 rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0; 1059 rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0; 1060 1061 gains->gm_gain = rfgain0 & 0xff; 1062 gains->pga_gain = (rfgain0 >> 8) & 0xff; 1063 gains->pad_gain = rfgain1 & 0xff; 1064 } 1065 1066 1067 static void wlc_lcnphy_set_dac_gain(struct brcms_phy *pi, u16 dac_gain) 1068 { 1069 u16 dac_ctrl; 1070 1071 dac_ctrl = (read_phy_reg(pi, 0x439) >> 0); 1072 dac_ctrl = dac_ctrl & 0xc7f; 1073 dac_ctrl = dac_ctrl | (dac_gain << 7); 1074 mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0); 1075 1076 } 1077 1078 static void wlc_lcnphy_set_tx_gain_override(struct brcms_phy *pi, bool bEnable) 1079 { 1080 u16 bit = bEnable ? 1 : 0; 1081 1082 mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7); 1083 1084 mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14); 1085 1086 mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6); 1087 } 1088 1089 static void 1090 wlc_lcnphy_rx_gain_override_enable(struct brcms_phy *pi, bool enable) 1091 { 1092 u16 ebit = enable ? 1 : 0; 1093 1094 mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8); 1095 1096 mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0); 1097 1098 if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { 1099 mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4); 1100 mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6); 1101 mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5); 1102 mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6); 1103 } else { 1104 mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12); 1105 mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13); 1106 mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5); 1107 } 1108 1109 if (CHSPEC_IS2G(pi->radio_chanspec)) { 1110 mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10); 1111 mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3); 1112 } 1113 } 1114 1115 static void 1116 wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, 1117 u16 trsw, 1118 u16 ext_lna, 1119 u16 biq2, 1120 u16 biq1, 1121 u16 tia, u16 lna2, u16 lna1) 1122 { 1123 u16 gain0_15, gain16_19; 1124 1125 gain16_19 = biq2 & 0xf; 1126 gain0_15 = ((biq1 & 0xf) << 12) | 1127 ((tia & 0xf) << 8) | 1128 ((lna2 & 0x3) << 6) | 1129 ((lna2 & 0x3) << 4) | 1130 ((lna1 & 0x3) << 2) | 1131 ((lna1 & 0x3) << 0); 1132 1133 mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); 1134 mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); 1135 mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); 1136 1137 if (LCNREV_LT(pi->pubpi.phy_rev, 2)) { 1138 mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); 1139 mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10); 1140 } else { 1141 mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10); 1142 1143 mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15); 1144 1145 mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); 1146 } 1147 1148 mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); 1149 1150 } 1151 1152 static void wlc_lcnphy_set_trsw_override(struct brcms_phy *pi, bool tx, bool rx) 1153 { 1154 1155 mod_phy_reg(pi, 0x44d, 1156 (0x1 << 1) | 1157 (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0)); 1158 1159 or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0)); 1160 } 1161 1162 static void wlc_lcnphy_clear_trsw_override(struct brcms_phy *pi) 1163 { 1164 1165 and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0))); 1166 } 1167 1168 static void wlc_lcnphy_set_rx_iq_comp(struct brcms_phy *pi, u16 a, u16 b) 1169 { 1170 mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0); 1171 1172 mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0); 1173 1174 mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0); 1175 1176 mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0); 1177 1178 mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0); 1179 1180 mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0); 1181 1182 } 1183 1184 static bool 1185 wlc_lcnphy_rx_iq_est(struct brcms_phy *pi, 1186 u16 num_samps, 1187 u8 wait_time, struct lcnphy_iq_est *iq_est) 1188 { 1189 int wait_count = 0; 1190 bool result = true; 1191 1192 mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5); 1193 1194 mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3); 1195 1196 mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0); 1197 1198 mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0); 1199 1200 mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8); 1201 1202 mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9); 1203 1204 while (read_phy_reg(pi, 0x481) & (0x1 << 9)) { 1205 1206 if (wait_count > (10 * 500)) { 1207 result = false; 1208 goto cleanup; 1209 } 1210 udelay(100); 1211 wait_count++; 1212 } 1213 1214 iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) | 1215 (u32) read_phy_reg(pi, 0x484); 1216 iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) | 1217 (u32) read_phy_reg(pi, 0x486); 1218 iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) | 1219 (u32) read_phy_reg(pi, 0x488); 1220 1221 cleanup: 1222 mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3); 1223 1224 mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5); 1225 1226 return result; 1227 } 1228 1229 static bool wlc_lcnphy_calc_rx_iq_comp(struct brcms_phy *pi, u16 num_samps) 1230 { 1231 #define LCNPHY_MIN_RXIQ_PWR 2 1232 bool result; 1233 u16 a0_new, b0_new; 1234 struct lcnphy_iq_est iq_est = { 0, 0, 0 }; 1235 s32 a, b, temp; 1236 s16 iq_nbits, qq_nbits, arsh, brsh; 1237 s32 iq; 1238 u32 ii, qq; 1239 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 1240 1241 a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0); 1242 b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0); 1243 mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2); 1244 1245 mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6); 1246 1247 wlc_lcnphy_set_rx_iq_comp(pi, 0, 0); 1248 1249 result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est); 1250 if (!result) 1251 goto cleanup; 1252 1253 iq = (s32) iq_est.iq_prod; 1254 ii = iq_est.i_pwr; 1255 qq = iq_est.q_pwr; 1256 1257 if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) { 1258 result = false; 1259 goto cleanup; 1260 } 1261 1262 iq_nbits = wlc_phy_nbits(iq); 1263 qq_nbits = wlc_phy_nbits(qq); 1264 1265 arsh = 10 - (30 - iq_nbits); 1266 if (arsh >= 0) { 1267 a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh))); 1268 temp = (s32) (ii >> arsh); 1269 if (temp == 0) 1270 return false; 1271 } else { 1272 a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh))); 1273 temp = (s32) (ii << -arsh); 1274 if (temp == 0) 1275 return false; 1276 } 1277 a /= temp; 1278 brsh = qq_nbits - 31 + 20; 1279 if (brsh >= 0) { 1280 b = (qq << (31 - qq_nbits)); 1281 temp = (s32) (ii >> brsh); 1282 if (temp == 0) 1283 return false; 1284 } else { 1285 b = (qq << (31 - qq_nbits)); 1286 temp = (s32) (ii << -brsh); 1287 if (temp == 0) 1288 return false; 1289 } 1290 b /= temp; 1291 b -= a * a; 1292 b = (s32) int_sqrt((unsigned long) b); 1293 b -= (1 << 10); 1294 a0_new = (u16) (a & 0x3ff); 1295 b0_new = (u16) (b & 0x3ff); 1296 cleanup: 1297 1298 wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new); 1299 1300 mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0); 1301 1302 mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3); 1303 1304 pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new; 1305 pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new; 1306 1307 return result; 1308 } 1309 1310 static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples) 1311 { 1312 struct lcnphy_iq_est iq_est = { 0, 0, 0 }; 1313 1314 if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est)) 1315 return 0; 1316 return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; 1317 } 1318 1319 static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain, 1320 u16 tia_gain, u16 lna2_gain) 1321 { 1322 u32 i_thresh_l, q_thresh_l; 1323 u32 i_thresh_h, q_thresh_h; 1324 struct lcnphy_iq_est iq_est_h, iq_est_l; 1325 1326 wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain, 1327 lna2_gain, 0); 1328 1329 wlc_lcnphy_rx_gain_override_enable(pi, true); 1330 wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0); 1331 udelay(500); 1332 write_radio_reg(pi, RADIO_2064_REG112, 0); 1333 if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l)) 1334 return false; 1335 1336 wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0); 1337 udelay(500); 1338 write_radio_reg(pi, RADIO_2064_REG112, 0); 1339 if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h)) 1340 return false; 1341 1342 i_thresh_l = (iq_est_l.i_pwr << 1); 1343 i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr; 1344 1345 q_thresh_l = (iq_est_l.q_pwr << 1); 1346 q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr; 1347 if ((iq_est_h.i_pwr > i_thresh_l) && 1348 (iq_est_h.i_pwr < i_thresh_h) && 1349 (iq_est_h.q_pwr > q_thresh_l) && 1350 (iq_est_h.q_pwr < q_thresh_h)) 1351 return true; 1352 1353 return false; 1354 } 1355 1356 static bool 1357 wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, 1358 const struct lcnphy_rx_iqcomp *iqcomp, 1359 int iqcomp_sz, bool tx_switch, bool rx_switch, int module, 1360 int tx_gain_idx) 1361 { 1362 struct lcnphy_txgains old_gains; 1363 u16 tx_pwr_ctrl; 1364 u8 tx_gain_index_old = 0; 1365 bool result = false, tx_gain_override_old = false; 1366 u16 i, Core1TxControl_old, RFOverride0_old, 1367 RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, 1368 rfoverride3_old, rfoverride3val_old, rfoverride4_old, 1369 rfoverride4val_old, afectrlovr_old, afectrlovrval_old; 1370 int tia_gain, lna2_gain, biq1_gain; 1371 bool set_gain; 1372 u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; 1373 u16 values_to_save[11]; 1374 s16 *ptr; 1375 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 1376 1377 ptr = kmalloc_array(131, sizeof(s16), GFP_ATOMIC); 1378 if (NULL == ptr) 1379 return false; 1380 if (module == 2) { 1381 while (iqcomp_sz--) { 1382 if (iqcomp[iqcomp_sz].chan == 1383 CHSPEC_CHANNEL(pi->radio_chanspec)) { 1384 wlc_lcnphy_set_rx_iq_comp(pi, 1385 (u16) 1386 iqcomp[iqcomp_sz].a, 1387 (u16) 1388 iqcomp[iqcomp_sz].b); 1389 result = true; 1390 break; 1391 } 1392 } 1393 goto cal_done; 1394 } 1395 1396 WARN_ON(module != 1); 1397 tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); 1398 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); 1399 1400 for (i = 0; i < 11; i++) 1401 values_to_save[i] = 1402 read_radio_reg(pi, rxiq_cal_rf_reg[i]); 1403 Core1TxControl_old = read_phy_reg(pi, 0x631); 1404 1405 or_phy_reg(pi, 0x631, 0x0015); 1406 1407 RFOverride0_old = read_phy_reg(pi, 0x44c); 1408 RFOverrideVal0_old = read_phy_reg(pi, 0x44d); 1409 rfoverride2_old = read_phy_reg(pi, 0x4b0); 1410 rfoverride2val_old = read_phy_reg(pi, 0x4b1); 1411 rfoverride3_old = read_phy_reg(pi, 0x4f9); 1412 rfoverride3val_old = read_phy_reg(pi, 0x4fa); 1413 rfoverride4_old = read_phy_reg(pi, 0x938); 1414 rfoverride4val_old = read_phy_reg(pi, 0x939); 1415 afectrlovr_old = read_phy_reg(pi, 0x43b); 1416 afectrlovrval_old = read_phy_reg(pi, 0x43c); 1417 old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); 1418 old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); 1419 1420 tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); 1421 if (tx_gain_override_old) { 1422 wlc_lcnphy_get_tx_gain(pi, &old_gains); 1423 tx_gain_index_old = pi_lcn->lcnphy_current_index; 1424 } 1425 1426 wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); 1427 1428 mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); 1429 mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); 1430 1431 mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); 1432 mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); 1433 1434 write_radio_reg(pi, RADIO_2064_REG116, 0x06); 1435 write_radio_reg(pi, RADIO_2064_REG12C, 0x07); 1436 write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); 1437 write_radio_reg(pi, RADIO_2064_REG098, 0x03); 1438 write_radio_reg(pi, RADIO_2064_REG00B, 0x7); 1439 mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); 1440 write_radio_reg(pi, RADIO_2064_REG01D, 0x01); 1441 write_radio_reg(pi, RADIO_2064_REG114, 0x01); 1442 write_radio_reg(pi, RADIO_2064_REG02E, 0x10); 1443 write_radio_reg(pi, RADIO_2064_REG12A, 0x08); 1444 1445 mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); 1446 mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); 1447 mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); 1448 mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); 1449 mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); 1450 mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); 1451 mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); 1452 mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); 1453 mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); 1454 mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); 1455 1456 mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); 1457 mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); 1458 1459 write_phy_reg(pi, 0x6da, 0xffff); 1460 or_phy_reg(pi, 0x6db, 0x3); 1461 1462 wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); 1463 for (lna2_gain = 3; lna2_gain >= 0; lna2_gain--) { 1464 for (tia_gain = 4; tia_gain >= 0; tia_gain--) { 1465 for (biq1_gain = 6; biq1_gain >= 0; biq1_gain--) { 1466 set_gain = wlc_lcnphy_rx_iq_cal_gain(pi, 1467 (u16) 1468 biq1_gain, 1469 (u16) 1470 tia_gain, 1471 (u16) 1472 lna2_gain); 1473 if (!set_gain) 1474 continue; 1475 1476 result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024); 1477 goto stop_tone; 1478 } 1479 } 1480 } 1481 1482 stop_tone: 1483 wlc_lcnphy_stop_tx_tone(pi); 1484 1485 write_phy_reg(pi, 0x631, Core1TxControl_old); 1486 1487 write_phy_reg(pi, 0x44c, RFOverrideVal0_old); 1488 write_phy_reg(pi, 0x44d, RFOverrideVal0_old); 1489 write_phy_reg(pi, 0x4b0, rfoverride2_old); 1490 write_phy_reg(pi, 0x4b1, rfoverride2val_old); 1491 write_phy_reg(pi, 0x4f9, rfoverride3_old); 1492 write_phy_reg(pi, 0x4fa, rfoverride3val_old); 1493 write_phy_reg(pi, 0x938, rfoverride4_old); 1494 write_phy_reg(pi, 0x939, rfoverride4val_old); 1495 write_phy_reg(pi, 0x43b, afectrlovr_old); 1496 write_phy_reg(pi, 0x43c, afectrlovrval_old); 1497 write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); 1498 write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); 1499 1500 wlc_lcnphy_clear_trsw_override(pi); 1501 1502 mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); 1503 1504 for (i = 0; i < 11; i++) 1505 write_radio_reg(pi, rxiq_cal_rf_reg[i], 1506 values_to_save[i]); 1507 1508 if (tx_gain_override_old) 1509 wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); 1510 else 1511 wlc_lcnphy_disable_tx_gain_override(pi); 1512 1513 wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); 1514 wlc_lcnphy_rx_gain_override_enable(pi, false); 1515 1516 cal_done: 1517 kfree(ptr); 1518 return result; 1519 } 1520 1521 s8 wlc_lcnphy_get_current_tx_pwr_idx(struct brcms_phy *pi) 1522 { 1523 s8 index; 1524 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 1525 1526 if (txpwrctrl_off(pi)) 1527 index = pi_lcn->lcnphy_current_index; 1528 else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) 1529 index = (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on( 1530 pi) / 2); 1531 else 1532 index = pi_lcn->lcnphy_current_index; 1533 return index; 1534 } 1535 1536 void wlc_lcnphy_crsuprs(struct brcms_phy *pi, int channel) 1537 { 1538 u16 afectrlovr, afectrlovrval; 1539 afectrlovr = read_phy_reg(pi, 0x43b); 1540 afectrlovrval = read_phy_reg(pi, 0x43c); 1541 if (channel != 0) { 1542 mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1); 1543 1544 mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1); 1545 1546 mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4); 1547 1548 mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6); 1549 1550 write_phy_reg(pi, 0x44b, 0xffff); 1551 wlc_lcnphy_tx_pu(pi, 1); 1552 1553 mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8); 1554 1555 or_phy_reg(pi, 0x6da, 0x0080); 1556 1557 or_phy_reg(pi, 0x00a, 0x228); 1558 } else { 1559 and_phy_reg(pi, 0x00a, ~(0x228)); 1560 1561 and_phy_reg(pi, 0x6da, 0xFF7F); 1562 write_phy_reg(pi, 0x43b, afectrlovr); 1563 write_phy_reg(pi, 0x43c, afectrlovrval); 1564 } 1565 } 1566 1567 static void wlc_lcnphy_toggle_afe_pwdn(struct brcms_phy *pi) 1568 { 1569 u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr; 1570 1571 save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c); 1572 save_AfeCtrlOvr = read_phy_reg(pi, 0x43b); 1573 1574 write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1); 1575 write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1); 1576 1577 write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe); 1578 write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe); 1579 1580 write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal); 1581 write_phy_reg(pi, 0x43b, save_AfeCtrlOvr); 1582 } 1583 1584 static void 1585 wlc_lcnphy_txrx_spur_avoidance_mode(struct brcms_phy *pi, bool enable) 1586 { 1587 if (enable) { 1588 write_phy_reg(pi, 0x942, 0x7); 1589 write_phy_reg(pi, 0x93b, ((1 << 13) + 23)); 1590 write_phy_reg(pi, 0x93c, ((1 << 13) + 1989)); 1591 1592 write_phy_reg(pi, 0x44a, 0x084); 1593 write_phy_reg(pi, 0x44a, 0x080); 1594 write_phy_reg(pi, 0x6d3, 0x2222); 1595 write_phy_reg(pi, 0x6d3, 0x2220); 1596 } else { 1597 write_phy_reg(pi, 0x942, 0x0); 1598 write_phy_reg(pi, 0x93b, ((0 << 13) + 23)); 1599 write_phy_reg(pi, 0x93c, ((0 << 13) + 1989)); 1600 } 1601 wlapi_switch_macfreq(pi->sh->physhim, enable); 1602 } 1603 1604 static void 1605 wlc_lcnphy_set_chanspec_tweaks(struct brcms_phy *pi, u16 chanspec) 1606 { 1607 u8 channel = CHSPEC_CHANNEL(chanspec); 1608 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 1609 1610 if (channel == 14) 1611 mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); 1612 else 1613 mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); 1614 1615 pi_lcn->lcnphy_bandedge_corr = 2; 1616 if (channel == 1) 1617 pi_lcn->lcnphy_bandedge_corr = 4; 1618 1619 if (channel == 1 || channel == 2 || channel == 3 || 1620 channel == 4 || channel == 9 || 1621 channel == 10 || channel == 11 || channel == 12) { 1622 bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2, 1623 0x03000c04); 1624 bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3, 1625 ~0x00ffffff, 0x0); 1626 bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4, 1627 0x200005c0); 1628 1629 bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL, 1630 BCMA_CC_PMU_CTL_PLL_UPD); 1631 write_phy_reg(pi, 0x942, 0); 1632 wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); 1633 pi_lcn->lcnphy_spurmod = false; 1634 mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8); 1635 1636 write_phy_reg(pi, 0x425, 0x5907); 1637 } else { 1638 bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2, 1639 0x03140c04); 1640 bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3, 1641 ~0x00ffffff, 0x333333); 1642 bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4, 1643 0x202c2820); 1644 1645 bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL, 1646 BCMA_CC_PMU_CTL_PLL_UPD); 1647 write_phy_reg(pi, 0x942, 0); 1648 wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); 1649 1650 pi_lcn->lcnphy_spurmod = false; 1651 mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8); 1652 1653 write_phy_reg(pi, 0x425, 0x590a); 1654 } 1655 1656 or_phy_reg(pi, 0x44a, 0x44); 1657 write_phy_reg(pi, 0x44a, 0x80); 1658 } 1659 1660 static void 1661 wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) 1662 { 1663 uint i; 1664 const struct chan_info_2064_lcnphy *ci; 1665 u8 rfpll_doubler = 0; 1666 u8 pll_pwrup, pll_pwrup_ovr; 1667 s32 qFxtal, qFref, qFvco, qFcal; 1668 u8 d15, d16, f16, e44, e45; 1669 u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div; 1670 u16 loop_bw, d30, setCount; 1671 1672 u8 h29, h28_ten, e30, h30_ten, cp_current; 1673 u16 g30, d28; 1674 1675 ci = &chan_info_2064_lcnphy[0]; 1676 rfpll_doubler = 1; 1677 1678 mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2); 1679 1680 write_radio_reg(pi, RADIO_2064_REG09E, 0xf); 1681 if (!rfpll_doubler) { 1682 loop_bw = PLL_2064_LOOP_BW; 1683 d30 = PLL_2064_D30; 1684 } else { 1685 loop_bw = PLL_2064_LOOP_BW_DOUBLER; 1686 d30 = PLL_2064_D30_DOUBLER; 1687 } 1688 1689 if (CHSPEC_IS2G(pi->radio_chanspec)) { 1690 for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++) 1691 if (chan_info_2064_lcnphy[i].chan == channel) 1692 break; 1693 1694 if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) 1695 return; 1696 1697 ci = &chan_info_2064_lcnphy[i]; 1698 } 1699 1700 write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune); 1701 1702 mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx); 1703 1704 mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl); 1705 1706 mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g); 1707 1708 mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2, 1709 (ci->logen_rccr_rx) << 2); 1710 1711 mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune); 1712 1713 mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4, 1714 (ci->pa_rxrf_lna2_freq_tune) << 4); 1715 1716 write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1); 1717 1718 pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044); 1719 pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B); 1720 1721 or_radio_reg(pi, RADIO_2064_REG044, 0x07); 1722 1723 or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1); 1724 e44 = 0; 1725 e45 = 0; 1726 1727 fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq); 1728 if (pi->xtalfreq > 26000000) 1729 e44 = 1; 1730 if (pi->xtalfreq > 52000000) 1731 e45 = 1; 1732 if (e44 == 0) 1733 fcal_div = 1; 1734 else if (e45 == 0) 1735 fcal_div = 2; 1736 else 1737 fcal_div = 4; 1738 fvco3 = (ci->freq * 3); 1739 fref3 = 2 * fpfd; 1740 1741 qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16); 1742 qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16); 1743 qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ; 1744 qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16); 1745 1746 write_radio_reg(pi, RADIO_2064_REG04F, 0x02); 1747 1748 d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1; 1749 write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2))); 1750 write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5); 1751 1752 d16 = (qFcal * 8 / (d15 + 1)) - 1; 1753 write_radio_reg(pi, RADIO_2064_REG051, d16); 1754 1755 f16 = ((d16 + 1) * (d15 + 1)) / qFcal; 1756 setCount = f16 * 3 * (ci->freq) / 32 - 1; 1757 mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0), 1758 (u8) (setCount >> 8)); 1759 1760 or_radio_reg(pi, RADIO_2064_REG053, 0x10); 1761 write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff)); 1762 1763 div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4; 1764 1765 div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4; 1766 while (div_frac >= fref3) { 1767 div_int++; 1768 div_frac -= fref3; 1769 } 1770 div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20); 1771 1772 mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0), 1773 (u8) (div_int >> 4)); 1774 mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4), 1775 (u8) (div_int << 4)); 1776 mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0), 1777 (u8) (div_frac >> 16)); 1778 write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff); 1779 write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff); 1780 1781 write_radio_reg(pi, RADIO_2064_REG040, 0xfb); 1782 1783 write_radio_reg(pi, RADIO_2064_REG041, 0x9A); 1784 write_radio_reg(pi, RADIO_2064_REG042, 0xA3); 1785 write_radio_reg(pi, RADIO_2064_REG043, 0x0C); 1786 1787 h29 = LCN_BW_LMT / loop_bw; 1788 d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) * 1789 (fvco3 / 2 - PLL_2064_LOW_END_VCO)) / 1790 (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO)) 1791 + PLL_2064_LOW_END_KVCO; 1792 h28_ten = (d28 * 10) / LCN_VCO_DIV; 1793 e30 = (d30 - LCN_OFFSET) / LCN_FACT; 1794 g30 = LCN_OFFSET + (e30 * LCN_FACT); 1795 h30_ten = (g30 * 10) / LCN_CUR_DIV; 1796 cp_current = ((LCN_CUR_LMT * h29 * LCN_MULT * 100) / h28_ten) / h30_ten; 1797 mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current); 1798 1799 if (channel >= 1 && channel <= 5) 1800 write_radio_reg(pi, RADIO_2064_REG03C, 0x8); 1801 else 1802 write_radio_reg(pi, RADIO_2064_REG03C, 0x7); 1803 write_radio_reg(pi, RADIO_2064_REG03D, 0x3); 1804 1805 mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c); 1806 udelay(1); 1807 1808 wlc_2064_vco_cal(pi); 1809 1810 write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup); 1811 write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr); 1812 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { 1813 write_radio_reg(pi, RADIO_2064_REG038, 3); 1814 write_radio_reg(pi, RADIO_2064_REG091, 7); 1815 } 1816 1817 if (!(pi->sh->boardflags & BFL_FEM)) { 1818 static const u8 reg038[14] = { 1819 0xd, 0xe, 0xd, 0xd, 0xd, 0xc, 0xa, 1820 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0 1821 }; 1822 1823 write_radio_reg(pi, RADIO_2064_REG02A, 0xf); 1824 write_radio_reg(pi, RADIO_2064_REG091, 0x3); 1825 write_radio_reg(pi, RADIO_2064_REG038, 0x3); 1826 1827 write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]); 1828 } 1829 } 1830 1831 static int 1832 wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type) 1833 { 1834 s16 filt_index = -1; 1835 int j; 1836 1837 u16 addr[] = { 1838 0x910, 1839 0x91e, 1840 0x91f, 1841 0x924, 1842 0x925, 1843 0x926, 1844 0x920, 1845 0x921, 1846 0x927, 1847 0x928, 1848 0x929, 1849 0x922, 1850 0x923, 1851 0x930, 1852 0x931, 1853 0x932 1854 }; 1855 1856 u16 addr_ofdm[] = { 1857 0x90f, 1858 0x900, 1859 0x901, 1860 0x906, 1861 0x907, 1862 0x908, 1863 0x902, 1864 0x903, 1865 0x909, 1866 0x90a, 1867 0x90b, 1868 0x904, 1869 0x905, 1870 0x90c, 1871 0x90d, 1872 0x90e 1873 }; 1874 1875 if (!is_ofdm) { 1876 for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) { 1877 if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) { 1878 filt_index = (s16) j; 1879 break; 1880 } 1881 } 1882 1883 if (filt_index != -1) { 1884 for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) 1885 write_phy_reg(pi, addr[j], 1886 LCNPHY_txdigfiltcoeffs_cck 1887 [filt_index][j + 1]); 1888 } 1889 } else { 1890 for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) { 1891 if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) { 1892 filt_index = (s16) j; 1893 break; 1894 } 1895 } 1896 1897 if (filt_index != -1) { 1898 for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) 1899 write_phy_reg(pi, addr_ofdm[j], 1900 LCNPHY_txdigfiltcoeffs_ofdm 1901 [filt_index][j + 1]); 1902 } 1903 } 1904 1905 return (filt_index != -1) ? 0 : -1; 1906 } 1907 1908 static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi) 1909 { 1910 u16 pa_gain; 1911 1912 pa_gain = (read_phy_reg(pi, 0x4fb) & 1913 LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >> 1914 LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT; 1915 1916 return pa_gain; 1917 } 1918 1919 static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi, 1920 struct lcnphy_txgains *target_gains) 1921 { 1922 u16 pa_gain = wlc_lcnphy_get_pa_gain(pi); 1923 1924 mod_phy_reg( 1925 pi, 0x4b5, 1926 (0xffff << 0), 1927 ((target_gains->gm_gain) | 1928 (target_gains->pga_gain << 8)) << 1929 0); 1930 mod_phy_reg(pi, 0x4fb, 1931 (0x7fff << 0), 1932 ((target_gains->pad_gain) | (pa_gain << 8)) << 0); 1933 1934 mod_phy_reg( 1935 pi, 0x4fc, 1936 (0xffff << 0), 1937 ((target_gains->gm_gain) | 1938 (target_gains->pga_gain << 8)) << 1939 0); 1940 mod_phy_reg(pi, 0x4fd, 1941 (0x7fff << 0), 1942 ((target_gains->pad_gain) | (pa_gain << 8)) << 0); 1943 1944 wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain); 1945 1946 wlc_lcnphy_enable_tx_gain_override(pi); 1947 } 1948 1949 static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi) 1950 { 1951 u16 m0m1; 1952 struct phytbl_info tab; 1953 1954 tab.tbl_ptr = &m0m1; 1955 tab.tbl_len = 1; 1956 tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; 1957 tab.tbl_offset = 87; 1958 tab.tbl_width = 16; 1959 wlc_lcnphy_read_table(pi, &tab); 1960 1961 return (u8) ((m0m1 & 0xff00) >> 8); 1962 } 1963 1964 static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0) 1965 { 1966 u16 m0m1 = (u16) m0 << 8; 1967 struct phytbl_info tab; 1968 1969 tab.tbl_ptr = &m0m1; 1970 tab.tbl_len = 1; 1971 tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; 1972 tab.tbl_offset = 87; 1973 tab.tbl_width = 16; 1974 wlc_lcnphy_write_table(pi, &tab); 1975 } 1976 1977 static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi) 1978 { 1979 u32 data_buf[64]; 1980 struct phytbl_info tab; 1981 1982 memset(data_buf, 0, sizeof(data_buf)); 1983 1984 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 1985 tab.tbl_width = 32; 1986 tab.tbl_ptr = data_buf; 1987 1988 if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { 1989 1990 tab.tbl_len = 30; 1991 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; 1992 wlc_lcnphy_write_table(pi, &tab); 1993 } 1994 1995 tab.tbl_len = 64; 1996 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET; 1997 wlc_lcnphy_write_table(pi, &tab); 1998 } 1999 2000 enum lcnphy_tssi_mode { 2001 LCNPHY_TSSI_PRE_PA, 2002 LCNPHY_TSSI_POST_PA, 2003 LCNPHY_TSSI_EXT 2004 }; 2005 2006 static void 2007 wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos) 2008 { 2009 mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0); 2010 2011 mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6); 2012 2013 if (LCNPHY_TSSI_POST_PA == pos) { 2014 mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2); 2015 2016 mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3); 2017 2018 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { 2019 mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); 2020 } else { 2021 mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); 2022 mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); 2023 mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0); 2024 mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2); 2025 mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0); 2026 mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4); 2027 mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); 2028 mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77); 2029 mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1); 2030 mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7); 2031 mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1); 2032 mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4); 2033 } 2034 } else { 2035 mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); 2036 2037 mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3); 2038 2039 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { 2040 mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); 2041 } else { 2042 mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0); 2043 mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); 2044 } 2045 } 2046 mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14); 2047 2048 if (LCNPHY_TSSI_EXT == pos) { 2049 write_radio_reg(pi, RADIO_2064_REG07F, 1); 2050 mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2); 2051 mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7); 2052 mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3); 2053 } 2054 } 2055 2056 static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(struct brcms_phy *pi) 2057 { 2058 u16 N1, N2, N3, N4, N5, N6, N; 2059 N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0)) 2060 >> 0); 2061 N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12)) 2062 >> 12); 2063 N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0)) 2064 >> 0); 2065 N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8)) 2066 >> 8); 2067 N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0)) 2068 >> 0); 2069 N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8)) 2070 >> 8); 2071 N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80; 2072 if (N < 1600) 2073 N = 1600; 2074 return N; 2075 } 2076 2077 static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi) 2078 { 2079 u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp; 2080 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 2081 2082 auxpga_vmid = (2 << 8) | 2083 (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf; 2084 auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4; 2085 auxpga_gain_temp = 2; 2086 2087 mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0); 2088 2089 mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1); 2090 2091 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3); 2092 2093 mod_phy_reg(pi, 0x4db, 2094 (0x3ff << 0) | 2095 (0x7 << 12), 2096 (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); 2097 2098 mod_phy_reg(pi, 0x4dc, 2099 (0x3ff << 0) | 2100 (0x7 << 12), 2101 (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); 2102 2103 mod_phy_reg(pi, 0x40a, 2104 (0x3ff << 0) | 2105 (0x7 << 12), 2106 (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12)); 2107 2108 mod_phy_reg(pi, 0x40b, 2109 (0x3ff << 0) | 2110 (0x7 << 12), 2111 (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); 2112 2113 mod_phy_reg(pi, 0x40c, 2114 (0x3ff << 0) | 2115 (0x7 << 12), 2116 (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); 2117 2118 mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); 2119 mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0)); 2120 } 2121 2122 static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) 2123 { 2124 struct phytbl_info tab; 2125 u32 rfseq, ind; 2126 enum lcnphy_tssi_mode mode; 2127 u8 tssi_sel; 2128 2129 if (pi->sh->boardflags & BFL_FEM) { 2130 tssi_sel = 0x1; 2131 mode = LCNPHY_TSSI_EXT; 2132 } else { 2133 tssi_sel = 0xe; 2134 mode = LCNPHY_TSSI_POST_PA; 2135 } 2136 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 2137 tab.tbl_width = 32; 2138 tab.tbl_ptr = &ind; 2139 tab.tbl_len = 1; 2140 tab.tbl_offset = 0; 2141 for (ind = 0; ind < 128; ind++) { 2142 wlc_lcnphy_write_table(pi, &tab); 2143 tab.tbl_offset++; 2144 } 2145 tab.tbl_offset = 704; 2146 for (ind = 0; ind < 128; ind++) { 2147 wlc_lcnphy_write_table(pi, &tab); 2148 tab.tbl_offset++; 2149 } 2150 mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0); 2151 2152 mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2); 2153 2154 mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); 2155 2156 wlc_lcnphy_set_tssi_mux(pi, mode); 2157 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); 2158 2159 mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); 2160 2161 mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5); 2162 2163 mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0); 2164 2165 mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0); 2166 2167 mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12); 2168 2169 mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8); 2170 2171 mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0); 2172 2173 mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8); 2174 2175 mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0); 2176 2177 mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8); 2178 2179 mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6); 2180 2181 mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0); 2182 2183 wlc_lcnphy_clear_tx_power_offsets(pi); 2184 2185 mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15); 2186 2187 mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0); 2188 2189 mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); 2190 2191 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { 2192 mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel); 2193 mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); 2194 } else { 2195 mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1); 2196 mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); 2197 mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); 2198 } 2199 2200 write_radio_reg(pi, RADIO_2064_REG025, 0xc); 2201 2202 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { 2203 mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); 2204 } else { 2205 if (CHSPEC_IS2G(pi->radio_chanspec)) 2206 mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1); 2207 else 2208 mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1); 2209 } 2210 2211 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) 2212 mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1); 2213 else 2214 mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2); 2215 2216 mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0); 2217 2218 mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3); 2219 2220 if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) 2221 mod_phy_reg(pi, 0x4d7, 2222 (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12); 2223 2224 rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi); 2225 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; 2226 tab.tbl_width = 16; 2227 tab.tbl_ptr = &rfseq; 2228 tab.tbl_len = 1; 2229 tab.tbl_offset = 6; 2230 wlc_lcnphy_write_table(pi, &tab); 2231 2232 mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2); 2233 2234 mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2); 2235 2236 mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); 2237 2238 mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2); 2239 2240 mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); 2241 2242 mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0); 2243 mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); 2244 mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); 2245 2246 wlc_lcnphy_pwrctrl_rssiparams(pi); 2247 } 2248 2249 void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi) 2250 { 2251 u16 tx_cnt, tx_total, npt; 2252 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 2253 2254 tx_total = wlc_lcnphy_total_tx_frames(pi); 2255 tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt; 2256 npt = wlc_lcnphy_get_tx_pwr_npt(pi); 2257 2258 if (tx_cnt > (1 << npt)) { 2259 2260 pi_lcn->lcnphy_tssi_tx_cnt = tx_total; 2261 2262 pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi); 2263 pi_lcn->lcnphy_tssi_npt = npt; 2264 2265 } 2266 } 2267 2268 s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1) 2269 { 2270 s32 a, b, p; 2271 2272 a = 32768 + (a1 * tssi); 2273 b = (1024 * b0) + (64 * b1 * tssi); 2274 p = ((2 * b) + a) / (2 * a); 2275 2276 return p; 2277 } 2278 2279 static void wlc_lcnphy_txpower_reset_npt(struct brcms_phy *pi) 2280 { 2281 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 2282 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) 2283 return; 2284 2285 pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313; 2286 pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT; 2287 } 2288 2289 void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi) 2290 { 2291 struct phytbl_info tab; 2292 u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM + 2293 BRCMS_NUM_RATES_MCS_1_STREAM]; 2294 uint i, j; 2295 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) 2296 return; 2297 2298 for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) { 2299 2300 if (i == BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM) 2301 j = TXP_FIRST_MCS_20_SISO; 2302 2303 rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j])); 2304 } 2305 2306 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 2307 tab.tbl_width = 32; 2308 tab.tbl_len = ARRAY_SIZE(rate_table); 2309 tab.tbl_ptr = rate_table; 2310 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; 2311 wlc_lcnphy_write_table(pi, &tab); 2312 2313 if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) { 2314 wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min); 2315 2316 wlc_lcnphy_txpower_reset_npt(pi); 2317 } 2318 } 2319 2320 static void wlc_lcnphy_set_tx_pwr_soft_ctrl(struct brcms_phy *pi, s8 index) 2321 { 2322 u32 cck_offset[4] = { 22, 22, 22, 22 }; 2323 u32 ofdm_offset, reg_offset_cck; 2324 int i; 2325 u16 index2; 2326 struct phytbl_info tab; 2327 2328 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) 2329 return; 2330 2331 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14); 2332 2333 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14); 2334 2335 or_phy_reg(pi, 0x6da, 0x0040); 2336 2337 reg_offset_cck = 0; 2338 for (i = 0; i < 4; i++) 2339 cck_offset[i] -= reg_offset_cck; 2340 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 2341 tab.tbl_width = 32; 2342 tab.tbl_len = 4; 2343 tab.tbl_ptr = cck_offset; 2344 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; 2345 wlc_lcnphy_write_table(pi, &tab); 2346 ofdm_offset = 0; 2347 tab.tbl_len = 1; 2348 tab.tbl_ptr = &ofdm_offset; 2349 for (i = 836; i < 862; i++) { 2350 tab.tbl_offset = i; 2351 wlc_lcnphy_write_table(pi, &tab); 2352 } 2353 2354 mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15); 2355 2356 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14); 2357 2358 mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13); 2359 2360 mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7); 2361 2362 mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6); 2363 2364 mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15); 2365 2366 index2 = (u16) (index * 2); 2367 mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0); 2368 2369 mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4); 2370 2371 } 2372 2373 static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi) 2374 { 2375 s8 index, delta_brd, delta_temp, new_index, tempcorrx; 2376 s16 manp, meas_temp, temp_diff; 2377 bool neg = false; 2378 u16 temp; 2379 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 2380 2381 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) 2382 return pi_lcn->lcnphy_current_index; 2383 2384 index = FIXED_TXPWR; 2385 2386 if (pi_lcn->lcnphy_tempsense_slope == 0) 2387 return index; 2388 2389 temp = (u16) wlc_lcnphy_tempsense(pi, 0); 2390 meas_temp = LCNPHY_TEMPSENSE(temp); 2391 2392 if (pi->tx_power_min != 0) 2393 delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min); 2394 else 2395 delta_brd = 0; 2396 2397 manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense); 2398 temp_diff = manp - meas_temp; 2399 if (temp_diff < 0) { 2400 neg = true; 2401 temp_diff = -temp_diff; 2402 } 2403 2404 delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192), 2405 (u32) (pi_lcn-> 2406 lcnphy_tempsense_slope 2407 * 10), 0); 2408 if (neg) 2409 delta_temp = -delta_temp; 2410 2411 if (pi_lcn->lcnphy_tempsense_option == 3 2412 && LCNREV_IS(pi->pubpi.phy_rev, 0)) 2413 delta_temp = 0; 2414 if (pi_lcn->lcnphy_tempcorrx > 31) 2415 tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64); 2416 else 2417 tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx; 2418 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) 2419 tempcorrx = 4; 2420 new_index = 2421 index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr; 2422 new_index += tempcorrx; 2423 2424 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) 2425 index = 127; 2426 2427 if (new_index < 0 || new_index > 126) 2428 return index; 2429 2430 return new_index; 2431 } 2432 2433 static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(struct brcms_phy *pi, u16 mode) 2434 { 2435 2436 u16 current_mode = mode; 2437 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && 2438 mode == LCNPHY_TX_PWR_CTRL_HW) 2439 current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED; 2440 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) && 2441 mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) 2442 current_mode = LCNPHY_TX_PWR_CTRL_HW; 2443 return current_mode; 2444 } 2445 2446 void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode) 2447 { 2448 u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi); 2449 s8 index; 2450 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 2451 2452 mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode); 2453 old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode); 2454 2455 mod_phy_reg(pi, 0x6da, (0x1 << 6), 2456 ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6); 2457 2458 mod_phy_reg(pi, 0x6a3, (0x1 << 4), 2459 ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4); 2460 2461 if (old_mode != mode) { 2462 if (LCNPHY_TX_PWR_CTRL_HW == old_mode) { 2463 2464 wlc_lcnphy_tx_pwr_update_npt(pi); 2465 2466 wlc_lcnphy_clear_tx_power_offsets(pi); 2467 } 2468 if (LCNPHY_TX_PWR_CTRL_HW == mode) { 2469 2470 wlc_lcnphy_txpower_recalc_target(pi); 2471 2472 wlc_lcnphy_set_start_tx_pwr_idx(pi, 2473 pi_lcn-> 2474 lcnphy_tssi_idx); 2475 wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt); 2476 mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0); 2477 2478 pi_lcn->lcnphy_tssi_tx_cnt = 2479 wlc_lcnphy_total_tx_frames(pi); 2480 2481 wlc_lcnphy_disable_tx_gain_override(pi); 2482 pi_lcn->lcnphy_tx_power_idx_override = -1; 2483 } else 2484 wlc_lcnphy_enable_tx_gain_override(pi); 2485 2486 mod_phy_reg(pi, 0x4a4, 2487 ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode); 2488 if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) { 2489 index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); 2490 wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index); 2491 pi_lcn->lcnphy_current_index = (s8) 2492 ((read_phy_reg(pi, 2493 0x4a9) & 2494 0xFF) / 2); 2495 } 2496 } 2497 } 2498 2499 static void 2500 wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save) 2501 { 2502 u16 vmid; 2503 int i; 2504 for (i = 0; i < 20; i++) 2505 values_to_save[i] = 2506 read_radio_reg(pi, iqlo_loopback_rf_regs[i]); 2507 2508 mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12); 2509 mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14); 2510 2511 mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11); 2512 mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13); 2513 2514 mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); 2515 mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); 2516 2517 mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); 2518 mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); 2519 2520 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) 2521 and_radio_reg(pi, RADIO_2064_REG03A, 0xFD); 2522 else 2523 and_radio_reg(pi, RADIO_2064_REG03A, 0xF9); 2524 or_radio_reg(pi, RADIO_2064_REG11A, 0x1); 2525 2526 or_radio_reg(pi, RADIO_2064_REG036, 0x01); 2527 or_radio_reg(pi, RADIO_2064_REG11A, 0x18); 2528 udelay(20); 2529 2530 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { 2531 if (CHSPEC_IS5G(pi->radio_chanspec)) 2532 mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0); 2533 else 2534 or_radio_reg(pi, RADIO_2064_REG03A, 1); 2535 } else { 2536 if (CHSPEC_IS5G(pi->radio_chanspec)) 2537 mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1); 2538 else 2539 or_radio_reg(pi, RADIO_2064_REG03A, 0x3); 2540 } 2541 2542 udelay(20); 2543 2544 write_radio_reg(pi, RADIO_2064_REG025, 0xF); 2545 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { 2546 if (CHSPEC_IS5G(pi->radio_chanspec)) 2547 mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4); 2548 else 2549 mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6); 2550 } else { 2551 if (CHSPEC_IS5G(pi->radio_chanspec)) 2552 mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1); 2553 else 2554 mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1); 2555 } 2556 2557 udelay(20); 2558 2559 write_radio_reg(pi, RADIO_2064_REG005, 0x8); 2560 or_radio_reg(pi, RADIO_2064_REG112, 0x80); 2561 udelay(20); 2562 2563 or_radio_reg(pi, RADIO_2064_REG0FF, 0x10); 2564 or_radio_reg(pi, RADIO_2064_REG11F, 0x44); 2565 udelay(20); 2566 2567 or_radio_reg(pi, RADIO_2064_REG00B, 0x7); 2568 or_radio_reg(pi, RADIO_2064_REG113, 0x10); 2569 udelay(20); 2570 2571 write_radio_reg(pi, RADIO_2064_REG007, 0x1); 2572 udelay(20); 2573 2574 vmid = 0x2A6; 2575 mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3); 2576 write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff)); 2577 or_radio_reg(pi, RADIO_2064_REG11F, 0x44); 2578 udelay(20); 2579 2580 or_radio_reg(pi, RADIO_2064_REG0FF, 0x10); 2581 udelay(20); 2582 write_radio_reg(pi, RADIO_2064_REG012, 0x02); 2583 or_radio_reg(pi, RADIO_2064_REG112, 0x06); 2584 write_radio_reg(pi, RADIO_2064_REG036, 0x11); 2585 write_radio_reg(pi, RADIO_2064_REG059, 0xcc); 2586 write_radio_reg(pi, RADIO_2064_REG05C, 0x2e); 2587 write_radio_reg(pi, RADIO_2064_REG078, 0xd7); 2588 write_radio_reg(pi, RADIO_2064_REG092, 0x15); 2589 } 2590 2591 static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi) 2592 { 2593 uint delay_count = 0; 2594 2595 while (wlc_lcnphy_iqcal_active(pi)) { 2596 udelay(100); 2597 delay_count++; 2598 2599 if (delay_count > (10 * 500)) 2600 break; 2601 } 2602 2603 return (0 == wlc_lcnphy_iqcal_active(pi)); 2604 } 2605 2606 static void 2607 wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save) 2608 { 2609 int i; 2610 2611 and_phy_reg(pi, 0x44c, 0x0 >> 11); 2612 2613 and_phy_reg(pi, 0x43b, 0xC); 2614 2615 for (i = 0; i < 20; i++) 2616 write_radio_reg(pi, iqlo_loopback_rf_regs[i], 2617 values_to_save[i]); 2618 } 2619 2620 static void 2621 wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi, 2622 struct lcnphy_txgains *target_gains, 2623 enum lcnphy_cal_mode cal_mode, bool keep_tone) 2624 { 2625 2626 struct lcnphy_txgains cal_gains, temp_gains; 2627 u16 hash; 2628 u8 band_idx; 2629 int j; 2630 u16 ncorr_override[5]; 2631 u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 2632 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; 2633 2634 u16 commands_fullcal[] = { 2635 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 2636 }; 2637 2638 u16 commands_recal[] = { 2639 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 2640 }; 2641 2642 u16 command_nums_fullcal[] = { 2643 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 2644 }; 2645 2646 u16 command_nums_recal[] = { 2647 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 2648 }; 2649 u16 *command_nums = command_nums_fullcal; 2650 2651 u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start; 2652 u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2; 2653 u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl; 2654 bool tx_gain_override_old; 2655 struct lcnphy_txgains old_gains; 2656 uint i, n_cal_cmds = 0, n_cal_start = 0; 2657 u16 *values_to_save; 2658 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 2659 2660 values_to_save = kmalloc_array(20, sizeof(u16), GFP_ATOMIC); 2661 if (NULL == values_to_save) 2662 return; 2663 2664 save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); 2665 save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); 2666 2667 or_phy_reg(pi, 0x6da, 0x40); 2668 or_phy_reg(pi, 0x6db, 0x3); 2669 2670 switch (cal_mode) { 2671 case LCNPHY_CAL_FULL: 2672 start_coeffs = syst_coeffs; 2673 cal_cmds = commands_fullcal; 2674 n_cal_cmds = ARRAY_SIZE(commands_fullcal); 2675 break; 2676 2677 case LCNPHY_CAL_RECAL: 2678 start_coeffs = syst_coeffs; 2679 cal_cmds = commands_recal; 2680 n_cal_cmds = ARRAY_SIZE(commands_recal); 2681 command_nums = command_nums_recal; 2682 break; 2683 2684 default: 2685 break; 2686 } 2687 2688 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2689 start_coeffs, 11, 16, 64); 2690 2691 write_phy_reg(pi, 0x6da, 0xffff); 2692 mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3); 2693 2694 tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi); 2695 2696 mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); 2697 2698 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); 2699 2700 save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db); 2701 2702 mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0); 2703 2704 mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12); 2705 2706 wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save); 2707 2708 tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); 2709 if (tx_gain_override_old) 2710 wlc_lcnphy_get_tx_gain(pi, &old_gains); 2711 2712 if (!target_gains) { 2713 if (!tx_gain_override_old) 2714 wlc_lcnphy_set_tx_pwr_by_index(pi, 2715 pi_lcn->lcnphy_tssi_idx); 2716 wlc_lcnphy_get_tx_gain(pi, &temp_gains); 2717 target_gains = &temp_gains; 2718 } 2719 2720 hash = (target_gains->gm_gain << 8) | 2721 (target_gains->pga_gain << 4) | (target_gains->pad_gain); 2722 2723 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0); 2724 2725 cal_gains = *target_gains; 2726 memset(ncorr_override, 0, sizeof(ncorr_override)); 2727 for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) { 2728 if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) { 2729 cal_gains.gm_gain = 2730 tbl_iqcal_gainparams_lcnphy[band_idx][j][1]; 2731 cal_gains.pga_gain = 2732 tbl_iqcal_gainparams_lcnphy[band_idx][j][2]; 2733 cal_gains.pad_gain = 2734 tbl_iqcal_gainparams_lcnphy[band_idx][j][3]; 2735 memcpy(ncorr_override, 2736 &tbl_iqcal_gainparams_lcnphy[band_idx][j][3], 2737 sizeof(ncorr_override)); 2738 break; 2739 } 2740 } 2741 2742 wlc_lcnphy_set_tx_gain(pi, &cal_gains); 2743 2744 write_phy_reg(pi, 0x453, 0xaa9); 2745 write_phy_reg(pi, 0x93d, 0xc0); 2746 2747 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2748 lcnphy_iqcal_loft_gainladder, 2749 ARRAY_SIZE(lcnphy_iqcal_loft_gainladder), 2750 16, 0); 2751 2752 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2753 lcnphy_iqcal_ir_gainladder, 2754 ARRAY_SIZE( 2755 lcnphy_iqcal_ir_gainladder), 16, 2756 32); 2757 2758 if (pi->phy_tx_tone_freq) { 2759 2760 wlc_lcnphy_stop_tx_tone(pi); 2761 udelay(5); 2762 wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1); 2763 } else { 2764 wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1); 2765 } 2766 2767 write_phy_reg(pi, 0x6da, 0xffff); 2768 2769 for (i = n_cal_start; i < n_cal_cmds; i++) { 2770 u16 zero_diq = 0; 2771 u16 best_coeffs[11]; 2772 u16 command_num; 2773 2774 cal_type = (cal_cmds[i] & 0x0f00) >> 8; 2775 2776 command_num = command_nums[i]; 2777 if (ncorr_override[cal_type]) 2778 command_num = 2779 ncorr_override[cal_type] << 8 | (command_num & 2780 0xff); 2781 2782 write_phy_reg(pi, 0x452, command_num); 2783 2784 if ((cal_type == 3) || (cal_type == 4)) { 2785 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2786 &diq_start, 1, 16, 69); 2787 2788 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2789 &zero_diq, 1, 16, 69); 2790 } 2791 2792 write_phy_reg(pi, 0x451, cal_cmds[i]); 2793 2794 if (!wlc_lcnphy_iqcal_wait(pi)) 2795 goto cleanup; 2796 2797 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2798 best_coeffs, 2799 ARRAY_SIZE(best_coeffs), 16, 96); 2800 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2801 best_coeffs, 2802 ARRAY_SIZE(best_coeffs), 16, 64); 2803 2804 if ((cal_type == 3) || (cal_type == 4)) 2805 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2806 &diq_start, 1, 16, 69); 2807 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2808 pi_lcn->lcnphy_cal_results. 2809 txiqlocal_bestcoeffs, 2810 ARRAY_SIZE(pi_lcn-> 2811 lcnphy_cal_results. 2812 txiqlocal_bestcoeffs), 2813 16, 96); 2814 } 2815 2816 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2817 pi_lcn->lcnphy_cal_results. 2818 txiqlocal_bestcoeffs, 2819 ARRAY_SIZE(pi_lcn->lcnphy_cal_results. 2820 txiqlocal_bestcoeffs), 16, 96); 2821 pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true; 2822 2823 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2824 &pi_lcn->lcnphy_cal_results. 2825 txiqlocal_bestcoeffs[0], 4, 16, 80); 2826 2827 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL, 2828 &pi_lcn->lcnphy_cal_results. 2829 txiqlocal_bestcoeffs[5], 2, 16, 85); 2830 2831 cleanup: 2832 wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save); 2833 kfree(values_to_save); 2834 2835 if (!keep_tone) 2836 wlc_lcnphy_stop_tx_tone(pi); 2837 2838 write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2); 2839 2840 write_phy_reg(pi, 0x453, 0); 2841 2842 if (tx_gain_override_old) 2843 wlc_lcnphy_set_tx_gain(pi, &old_gains); 2844 wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old); 2845 2846 write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl); 2847 write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl); 2848 2849 } 2850 2851 static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) 2852 { 2853 bool suspend, tx_gain_override_old; 2854 struct lcnphy_txgains old_gains; 2855 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 2856 u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB, 2857 idleTssi0_regvalue_2C; 2858 u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); 2859 u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112); 2860 u16 SAVE_jtag_bb_afe_switch = 2861 read_radio_reg(pi, RADIO_2064_REG007) & 1; 2862 u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; 2863 u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; 2864 u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi); 2865 2866 idleTssi = read_phy_reg(pi, 0x4ab); 2867 suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & 2868 MCTL_EN_MAC)); 2869 if (!suspend) 2870 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2871 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); 2872 2873 tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); 2874 wlc_lcnphy_get_tx_gain(pi, &old_gains); 2875 2876 wlc_lcnphy_enable_tx_gain_override(pi); 2877 wlc_lcnphy_set_tx_pwr_by_index(pi, 127); 2878 write_radio_reg(pi, RADIO_2064_REG112, 0x6); 2879 mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1); 2880 mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); 2881 mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); 2882 wlc_lcnphy_tssi_setup(pi); 2883 2884 mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0)); 2885 mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6)); 2886 2887 wlc_lcnphy_set_bbmult(pi, 0x0); 2888 2889 wlc_phy_do_dummy_tx(pi, true, OFF); 2890 idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) 2891 >> 0); 2892 2893 idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0)) 2894 >> 0); 2895 2896 if (idleTssi0_2C >= 256) 2897 idleTssi0_OB = idleTssi0_2C - 256; 2898 else 2899 idleTssi0_OB = idleTssi0_2C + 256; 2900 2901 idleTssi0_regvalue_OB = idleTssi0_OB; 2902 if (idleTssi0_regvalue_OB >= 256) 2903 idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256; 2904 else 2905 idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256; 2906 mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0); 2907 2908 mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); 2909 2910 wlc_lcnphy_set_bbmult(pi, SAVE_bbmult); 2911 wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); 2912 wlc_lcnphy_set_tx_gain(pi, &old_gains); 2913 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); 2914 2915 write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain); 2916 mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch); 2917 mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga); 2918 mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en); 2919 mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7); 2920 if (!suspend) 2921 wlapi_enable_mac(pi->sh->physhim); 2922 } 2923 2924 static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode) 2925 { 2926 bool suspend; 2927 u16 save_txpwrCtrlEn; 2928 u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain; 2929 u16 auxpga_vmid; 2930 struct phytbl_info tab; 2931 u32 val; 2932 u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025, 2933 save_reg112; 2934 u16 values_to_save[14]; 2935 s8 index; 2936 int i; 2937 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 2938 udelay(999); 2939 2940 save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007); 2941 save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF); 2942 save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F); 2943 save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005); 2944 save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025); 2945 save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112); 2946 2947 for (i = 0; i < 14; i++) 2948 values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]); 2949 suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & 2950 MCTL_EN_MAC)); 2951 if (!suspend) 2952 wlapi_suspend_mac_and_wait(pi->sh->physhim); 2953 save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4); 2954 2955 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); 2956 index = pi_lcn->lcnphy_current_index; 2957 wlc_lcnphy_set_tx_pwr_by_index(pi, 127); 2958 mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1); 2959 mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4); 2960 mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2); 2961 mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0); 2962 2963 mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2); 2964 2965 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); 2966 2967 mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15); 2968 2969 mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5); 2970 2971 mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0); 2972 2973 mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12); 2974 2975 mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8); 2976 2977 mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0); 2978 2979 mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8); 2980 2981 mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0); 2982 2983 mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8); 2984 2985 mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4); 2986 2987 mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8); 2988 2989 mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12); 2990 2991 mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12); 2992 2993 mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13); 2994 2995 mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15); 2996 2997 write_radio_reg(pi, RADIO_2064_REG025, 0xC); 2998 2999 mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3); 3000 3001 mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2); 3002 3003 mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2); 3004 3005 mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12); 3006 3007 val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi); 3008 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; 3009 tab.tbl_width = 16; 3010 tab.tbl_len = 1; 3011 tab.tbl_ptr = &val; 3012 tab.tbl_offset = 6; 3013 wlc_lcnphy_write_table(pi, &tab); 3014 if (mode == TEMPSENSE) { 3015 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3); 3016 3017 mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12); 3018 3019 auxpga_vmidcourse = 8; 3020 auxpga_vmidfine = 0x4; 3021 auxpga_gain = 2; 3022 mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5); 3023 } else { 3024 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3); 3025 3026 mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12); 3027 3028 auxpga_vmidcourse = 7; 3029 auxpga_vmidfine = 0xa; 3030 auxpga_gain = 2; 3031 } 3032 auxpga_vmid = 3033 (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine); 3034 mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0); 3035 3036 mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2); 3037 3038 mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1); 3039 3040 mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12); 3041 3042 mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5); 3043 3044 write_radio_reg(pi, RADIO_2064_REG112, 0x6); 3045 3046 wlc_phy_do_dummy_tx(pi, true, OFF); 3047 if (!tempsense_done(pi)) 3048 udelay(10); 3049 3050 write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007); 3051 write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF); 3052 write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F); 3053 write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005); 3054 write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025); 3055 write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112); 3056 for (i = 0; i < 14; i++) 3057 write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]); 3058 wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index); 3059 3060 write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn); 3061 if (!suspend) 3062 wlapi_enable_mac(pi->sh->physhim); 3063 udelay(999); 3064 } 3065 3066 static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) 3067 { 3068 struct lcnphy_txgains tx_gains; 3069 u8 bbmult; 3070 struct phytbl_info tab; 3071 s32 a1, b0, b1; 3072 s32 tssi, pwr, mintargetpwr; 3073 bool suspend; 3074 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 3075 3076 suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & 3077 MCTL_EN_MAC)); 3078 if (!suspend) 3079 wlapi_suspend_mac_and_wait(pi->sh->physhim); 3080 3081 if (!pi->hwpwrctrl_capable) { 3082 if (CHSPEC_IS2G(pi->radio_chanspec)) { 3083 tx_gains.gm_gain = 4; 3084 tx_gains.pga_gain = 12; 3085 tx_gains.pad_gain = 12; 3086 tx_gains.dac_gain = 0; 3087 3088 bbmult = 150; 3089 } else { 3090 tx_gains.gm_gain = 7; 3091 tx_gains.pga_gain = 15; 3092 tx_gains.pad_gain = 14; 3093 tx_gains.dac_gain = 0; 3094 3095 bbmult = 150; 3096 } 3097 wlc_lcnphy_set_tx_gain(pi, &tx_gains); 3098 wlc_lcnphy_set_bbmult(pi, bbmult); 3099 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); 3100 } else { 3101 3102 wlc_lcnphy_idle_tssi_est(ppi); 3103 3104 wlc_lcnphy_clear_tx_power_offsets(pi); 3105 3106 b0 = pi->txpa_2g[0]; 3107 b1 = pi->txpa_2g[1]; 3108 a1 = pi->txpa_2g[2]; 3109 mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); 3110 3111 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 3112 tab.tbl_width = 32; 3113 tab.tbl_ptr = &pwr; 3114 tab.tbl_len = 1; 3115 tab.tbl_offset = 0; 3116 for (tssi = 0; tssi < 128; tssi++) { 3117 pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1); 3118 3119 pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr; 3120 wlc_lcnphy_write_table(pi, &tab); 3121 tab.tbl_offset++; 3122 } 3123 mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0); 3124 mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0); 3125 mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8); 3126 mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4); 3127 mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2); 3128 3129 mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); 3130 3131 write_phy_reg(pi, 0x4a8, 10); 3132 3133 wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR); 3134 3135 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW); 3136 } 3137 if (!suspend) 3138 wlapi_enable_mac(pi->sh->physhim); 3139 } 3140 3141 static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain) 3142 { 3143 mod_phy_reg(pi, 0x4fb, 3144 LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK, 3145 gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT); 3146 mod_phy_reg(pi, 0x4fd, 3147 LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK, 3148 gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT); 3149 } 3150 3151 void 3152 wlc_lcnphy_get_radio_loft(struct brcms_phy *pi, 3153 u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0) 3154 { 3155 *ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089)); 3156 *eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A)); 3157 *fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B)); 3158 *fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C)); 3159 } 3160 3161 void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b) 3162 { 3163 struct phytbl_info tab; 3164 u16 iqcc[2]; 3165 3166 iqcc[0] = a; 3167 iqcc[1] = b; 3168 3169 tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; 3170 tab.tbl_width = 16; 3171 tab.tbl_ptr = iqcc; 3172 tab.tbl_len = 2; 3173 tab.tbl_offset = 80; 3174 wlc_lcnphy_write_table(pi, &tab); 3175 } 3176 3177 void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq) 3178 { 3179 struct phytbl_info tab; 3180 3181 tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL; 3182 tab.tbl_width = 16; 3183 tab.tbl_ptr = &didq; 3184 tab.tbl_len = 1; 3185 tab.tbl_offset = 85; 3186 wlc_lcnphy_write_table(pi, &tab); 3187 } 3188 3189 void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index) 3190 { 3191 struct phytbl_info tab; 3192 u16 a, b; 3193 u8 bb_mult; 3194 u32 bbmultiqcomp, txgain, locoeffs, rfpower; 3195 struct lcnphy_txgains gains; 3196 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 3197 3198 pi_lcn->lcnphy_tx_power_idx_override = (s8) index; 3199 pi_lcn->lcnphy_current_index = (u8) index; 3200 3201 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 3202 tab.tbl_width = 32; 3203 tab.tbl_len = 1; 3204 3205 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); 3206 3207 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index; 3208 tab.tbl_ptr = &bbmultiqcomp; 3209 wlc_lcnphy_read_table(pi, &tab); 3210 3211 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index; 3212 tab.tbl_width = 32; 3213 tab.tbl_ptr = &txgain; 3214 wlc_lcnphy_read_table(pi, &tab); 3215 3216 gains.gm_gain = (u16) (txgain & 0xff); 3217 gains.pga_gain = (u16) (txgain >> 8) & 0xff; 3218 gains.pad_gain = (u16) (txgain >> 16) & 0xff; 3219 gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07; 3220 wlc_lcnphy_set_tx_gain(pi, &gains); 3221 wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f); 3222 3223 bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff); 3224 wlc_lcnphy_set_bbmult(pi, bb_mult); 3225 3226 wlc_lcnphy_enable_tx_gain_override(pi); 3227 3228 if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { 3229 3230 a = (u16) ((bbmultiqcomp >> 10) & 0x3ff); 3231 b = (u16) (bbmultiqcomp & 0x3ff); 3232 wlc_lcnphy_set_tx_iqcc(pi, a, b); 3233 3234 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index; 3235 tab.tbl_ptr = &locoeffs; 3236 wlc_lcnphy_read_table(pi, &tab); 3237 3238 wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs); 3239 3240 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index; 3241 tab.tbl_ptr = &rfpower; 3242 wlc_lcnphy_read_table(pi, &tab); 3243 mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0); 3244 3245 } 3246 } 3247 3248 static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi) 3249 { 3250 u32 j; 3251 struct phytbl_info tab; 3252 u32 temp_offset[128]; 3253 tab.tbl_ptr = temp_offset; 3254 tab.tbl_len = 128; 3255 tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL; 3256 tab.tbl_width = 32; 3257 tab.tbl_offset = 0; 3258 3259 memset(temp_offset, 0, sizeof(temp_offset)); 3260 for (j = 1; j < 128; j += 2) 3261 temp_offset[j] = 0x80000; 3262 3263 wlc_lcnphy_write_table(pi, &tab); 3264 return; 3265 } 3266 3267 void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable) 3268 { 3269 if (!bEnable) { 3270 3271 and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4))); 3272 3273 mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1); 3274 3275 and_phy_reg(pi, 0x44c, 3276 ~(u16) ((0x1 << 3) | 3277 (0x1 << 5) | 3278 (0x1 << 12) | 3279 (0x1 << 0) | (0x1 << 1) | (0x1 << 2))); 3280 3281 and_phy_reg(pi, 0x44d, 3282 ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14))); 3283 mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2); 3284 3285 mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0)); 3286 3287 and_phy_reg(pi, 0x4f9, 3288 ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); 3289 3290 and_phy_reg(pi, 0x4fa, 3291 ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2))); 3292 } else { 3293 3294 mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); 3295 mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); 3296 3297 mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4); 3298 mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6); 3299 3300 mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12); 3301 mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14); 3302 3303 wlc_lcnphy_set_trsw_override(pi, true, false); 3304 3305 mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2); 3306 mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2); 3307 3308 if (CHSPEC_IS2G(pi->radio_chanspec)) { 3309 3310 mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3); 3311 mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3); 3312 3313 mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5); 3314 mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5); 3315 3316 mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1); 3317 mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1); 3318 3319 mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2); 3320 mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2); 3321 3322 mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); 3323 mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0); 3324 } else { 3325 3326 mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3); 3327 mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3); 3328 3329 mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5); 3330 mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5); 3331 3332 mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1); 3333 mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1); 3334 3335 mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2); 3336 mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2); 3337 3338 mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); 3339 mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); 3340 } 3341 } 3342 } 3343 3344 static void 3345 wlc_lcnphy_run_samples(struct brcms_phy *pi, 3346 u16 num_samps, 3347 u16 num_loops, u16 wait, bool iqcalmode) 3348 { 3349 3350 or_phy_reg(pi, 0x6da, 0x8080); 3351 3352 mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0); 3353 if (num_loops != 0xffff) 3354 num_loops--; 3355 mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0); 3356 3357 mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0); 3358 3359 if (iqcalmode) { 3360 3361 and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15)); 3362 or_phy_reg(pi, 0x453, (0x1 << 15)); 3363 } else { 3364 write_phy_reg(pi, 0x63f, 1); 3365 wlc_lcnphy_tx_pu(pi, 1); 3366 } 3367 3368 or_radio_reg(pi, RADIO_2064_REG112, 0x6); 3369 } 3370 3371 void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode) 3372 { 3373 3374 u8 phybw40; 3375 phybw40 = CHSPEC_IS40(pi->radio_chanspec); 3376 3377 mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5); 3378 mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9); 3379 3380 if (phybw40 == 0) { 3381 mod_phy_reg((pi), 0x410, 3382 (0x1 << 6) | 3383 (0x1 << 5), 3384 ((CHSPEC_IS2G( 3385 pi->radio_chanspec)) ? (!mode) : 0) << 3386 6 | (!mode) << 5); 3387 mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7); 3388 } 3389 } 3390 3391 void 3392 wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val, 3393 bool iqcalmode) 3394 { 3395 u8 phy_bw; 3396 u16 num_samps, t, k; 3397 u32 bw; 3398 s32 theta = 0, rot = 0; 3399 struct cordic_iq tone_samp; 3400 u32 data_buf[64]; 3401 u16 i_samp, q_samp; 3402 struct phytbl_info tab; 3403 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 3404 3405 pi->phy_tx_tone_freq = f_kHz; 3406 3407 wlc_lcnphy_deaf_mode(pi, true); 3408 3409 phy_bw = 40; 3410 if (pi_lcn->lcnphy_spurmod) { 3411 write_phy_reg(pi, 0x942, 0x2); 3412 write_phy_reg(pi, 0x93b, 0x0); 3413 write_phy_reg(pi, 0x93c, 0x0); 3414 wlc_lcnphy_txrx_spur_avoidance_mode(pi, false); 3415 } 3416 3417 if (f_kHz) { 3418 k = 1; 3419 do { 3420 bw = phy_bw * 1000 * k; 3421 num_samps = bw / abs(f_kHz); 3422 k++; 3423 } while ((num_samps * (u32) (abs(f_kHz))) != bw); 3424 } else 3425 num_samps = 2; 3426 3427 rot = ((f_kHz * 36) / phy_bw) / 100; 3428 theta = 0; 3429 3430 for (t = 0; t < num_samps; t++) { 3431 3432 tone_samp = cordic_calc_iq(theta); 3433 3434 theta += rot; 3435 3436 i_samp = (u16)(CORDIC_FLOAT(tone_samp.i * max_val) & 0x3ff); 3437 q_samp = (u16)(CORDIC_FLOAT(tone_samp.q * max_val) & 0x3ff); 3438 data_buf[t] = (i_samp << 10) | q_samp; 3439 } 3440 3441 mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0); 3442 3443 mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3); 3444 3445 tab.tbl_ptr = data_buf; 3446 tab.tbl_len = num_samps; 3447 tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY; 3448 tab.tbl_offset = 0; 3449 tab.tbl_width = 32; 3450 wlc_lcnphy_write_table(pi, &tab); 3451 3452 wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode); 3453 } 3454 3455 void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi) 3456 { 3457 s16 playback_status; 3458 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 3459 3460 pi->phy_tx_tone_freq = 0; 3461 if (pi_lcn->lcnphy_spurmod) { 3462 write_phy_reg(pi, 0x942, 0x7); 3463 write_phy_reg(pi, 0x93b, 0x2017); 3464 write_phy_reg(pi, 0x93c, 0x27c5); 3465 wlc_lcnphy_txrx_spur_avoidance_mode(pi, true); 3466 } 3467 3468 playback_status = read_phy_reg(pi, 0x644); 3469 if (playback_status & (0x1 << 0)) { 3470 wlc_lcnphy_tx_pu(pi, 0); 3471 mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1); 3472 } else if (playback_status & (0x1 << 1)) 3473 mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15); 3474 3475 mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0); 3476 3477 mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3); 3478 3479 mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7); 3480 3481 and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9); 3482 3483 wlc_lcnphy_deaf_mode(pi, false); 3484 } 3485 3486 static void 3487 wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y) 3488 { 3489 u16 di0dq0; 3490 u16 x, y, data_rf; 3491 int k; 3492 switch (cal_type) { 3493 case 0: 3494 wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y); 3495 break; 3496 case 2: 3497 di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff); 3498 wlc_lcnphy_set_tx_locc(pi, di0dq0); 3499 break; 3500 case 3: 3501 k = wlc_lcnphy_calc_floor(coeff_x, 0); 3502 y = 8 + k; 3503 k = wlc_lcnphy_calc_floor(coeff_x, 1); 3504 x = 8 - k; 3505 data_rf = (x * 16 + y); 3506 write_radio_reg(pi, RADIO_2064_REG089, data_rf); 3507 k = wlc_lcnphy_calc_floor(coeff_y, 0); 3508 y = 8 + k; 3509 k = wlc_lcnphy_calc_floor(coeff_y, 1); 3510 x = 8 - k; 3511 data_rf = (x * 16 + y); 3512 write_radio_reg(pi, RADIO_2064_REG08A, data_rf); 3513 break; 3514 case 4: 3515 k = wlc_lcnphy_calc_floor(coeff_x, 0); 3516 y = 8 + k; 3517 k = wlc_lcnphy_calc_floor(coeff_x, 1); 3518 x = 8 - k; 3519 data_rf = (x * 16 + y); 3520 write_radio_reg(pi, RADIO_2064_REG08B, data_rf); 3521 k = wlc_lcnphy_calc_floor(coeff_y, 0); 3522 y = 8 + k; 3523 k = wlc_lcnphy_calc_floor(coeff_y, 1); 3524 x = 8 - k; 3525 data_rf = (x * 16 + y); 3526 write_radio_reg(pi, RADIO_2064_REG08C, data_rf); 3527 break; 3528 } 3529 } 3530 3531 static struct lcnphy_unsign16_struct 3532 wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type) 3533 { 3534 u16 a, b, didq; 3535 u8 di0, dq0, ei, eq, fi, fq; 3536 struct lcnphy_unsign16_struct cc; 3537 cc.re = 0; 3538 cc.im = 0; 3539 switch (cal_type) { 3540 case 0: 3541 wlc_lcnphy_get_tx_iqcc(pi, &a, &b); 3542 cc.re = a; 3543 cc.im = b; 3544 break; 3545 case 2: 3546 didq = wlc_lcnphy_get_tx_locc(pi); 3547 di0 = (((didq & 0xff00) << 16) >> 24); 3548 dq0 = (((didq & 0x00ff) << 24) >> 24); 3549 cc.re = (u16) di0; 3550 cc.im = (u16) dq0; 3551 break; 3552 case 3: 3553 wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq); 3554 cc.re = (u16) ei; 3555 cc.im = (u16) eq; 3556 break; 3557 case 4: 3558 wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq); 3559 cc.re = (u16) fi; 3560 cc.im = (u16) fq; 3561 break; 3562 } 3563 return cc; 3564 } 3565 3566 static void 3567 wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh, 3568 s16 *ptr, int mode) 3569 { 3570 u32 curval1, curval2, stpptr, curptr, strptr, val; 3571 u16 sslpnCalibClkEnCtrl, timer; 3572 u16 old_sslpnCalibClkEnCtrl; 3573 s16 imag, real; 3574 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 3575 3576 timer = 0; 3577 old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); 3578 3579 curval1 = bcma_read16(pi->d11core, D11REGOFFS(psm_corectlsts)); 3580 ptr[130] = 0; 3581 bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts), 3582 ((1 << 6) | curval1)); 3583 3584 bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_strptr), 0x7E00); 3585 bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_stpptr), 0x8000); 3586 udelay(20); 3587 curval2 = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param)); 3588 bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), 3589 curval2 | 0x30); 3590 3591 write_phy_reg(pi, 0x555, 0x0); 3592 write_phy_reg(pi, 0x5a6, 0x5); 3593 3594 write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6)); 3595 write_phy_reg(pi, 0x5cf, 3); 3596 write_phy_reg(pi, 0x5a5, 0x3); 3597 write_phy_reg(pi, 0x583, 0x0); 3598 write_phy_reg(pi, 0x584, 0x0); 3599 write_phy_reg(pi, 0x585, 0x0fff); 3600 write_phy_reg(pi, 0x586, 0x0000); 3601 3602 write_phy_reg(pi, 0x580, 0x4501); 3603 3604 sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); 3605 write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008)); 3606 stpptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_stpptr)); 3607 curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr)); 3608 do { 3609 udelay(10); 3610 curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr)); 3611 timer++; 3612 } while ((curptr != stpptr) && (timer < 500)); 3613 3614 bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), 0x2); 3615 strptr = 0x7E00; 3616 bcma_write32(pi->d11core, D11REGOFFS(tplatewrptr), strptr); 3617 while (strptr < 0x8000) { 3618 val = bcma_read32(pi->d11core, D11REGOFFS(tplatewrdata)); 3619 imag = ((val >> 16) & 0x3ff); 3620 real = ((val) & 0x3ff); 3621 if (imag > 511) 3622 imag -= 1024; 3623 3624 if (real > 511) 3625 real -= 1024; 3626 3627 if (pi_lcn->lcnphy_iqcal_swp_dis) 3628 ptr[(strptr - 0x7E00) / 4] = real; 3629 else 3630 ptr[(strptr - 0x7E00) / 4] = imag; 3631 3632 if (clip_detect_algo) { 3633 if (imag > thresh || imag < -thresh) { 3634 strptr = 0x8000; 3635 ptr[130] = 1; 3636 } 3637 } 3638 3639 strptr += 4; 3640 } 3641 3642 write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); 3643 bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), curval2); 3644 bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts), curval1); 3645 } 3646 3647 static void 3648 wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels, 3649 int step_size_lg2) 3650 { 3651 const struct lcnphy_spb_tone *phy_c1; 3652 struct lcnphy_spb_tone phy_c2; 3653 struct lcnphy_unsign16_struct phy_c3; 3654 int phy_c4, phy_c5, k, l, j, phy_c6; 3655 u16 phy_c7, phy_c8, phy_c9; 3656 s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16; 3657 s16 *ptr, phy_c17; 3658 s32 phy_c18, phy_c19; 3659 u32 phy_c20, phy_c21; 3660 bool phy_c22, phy_c23, phy_c24, phy_c25; 3661 u16 phy_c26, phy_c27; 3662 u16 phy_c28, phy_c29, phy_c30; 3663 u16 phy_c31; 3664 u16 *phy_c32; 3665 phy_c21 = 0; 3666 phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0; 3667 ptr = kmalloc_array(131, sizeof(s16), GFP_ATOMIC); 3668 if (NULL == ptr) 3669 return; 3670 3671 phy_c32 = kmalloc_array(20, sizeof(u16), GFP_ATOMIC); 3672 if (NULL == phy_c32) { 3673 kfree(ptr); 3674 return; 3675 } 3676 phy_c26 = read_phy_reg(pi, 0x6da); 3677 phy_c27 = read_phy_reg(pi, 0x6db); 3678 phy_c31 = read_radio_reg(pi, RADIO_2064_REG026); 3679 write_phy_reg(pi, 0x93d, 0xC0); 3680 3681 wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0); 3682 write_phy_reg(pi, 0x6da, 0xffff); 3683 or_phy_reg(pi, 0x6db, 0x3); 3684 3685 wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32); 3686 udelay(500); 3687 phy_c28 = read_phy_reg(pi, 0x938); 3688 phy_c29 = read_phy_reg(pi, 0x4d7); 3689 phy_c30 = read_phy_reg(pi, 0x4d8); 3690 or_phy_reg(pi, 0x938, 0x1 << 2); 3691 or_phy_reg(pi, 0x4d7, 0x1 << 2); 3692 or_phy_reg(pi, 0x4d7, 0x1 << 3); 3693 mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12); 3694 or_phy_reg(pi, 0x4d8, 1 << 0); 3695 or_phy_reg(pi, 0x4d8, 1 << 1); 3696 mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2); 3697 mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12); 3698 phy_c1 = &lcnphy_spb_tone_3750[0]; 3699 phy_c4 = 32; 3700 3701 if (num_levels == 0) { 3702 if (cal_type != 0) 3703 num_levels = 4; 3704 else 3705 num_levels = 9; 3706 } 3707 if (step_size_lg2 == 0) { 3708 if (cal_type != 0) 3709 step_size_lg2 = 3; 3710 else 3711 step_size_lg2 = 8; 3712 } 3713 3714 phy_c7 = (1 << step_size_lg2); 3715 phy_c3 = wlc_lcnphy_get_cc(pi, cal_type); 3716 phy_c15 = (s16) phy_c3.re; 3717 phy_c16 = (s16) phy_c3.im; 3718 if (cal_type == 2) { 3719 if (phy_c3.re > 127) 3720 phy_c15 = phy_c3.re - 256; 3721 if (phy_c3.im > 127) 3722 phy_c16 = phy_c3.im - 256; 3723 } 3724 wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16); 3725 udelay(20); 3726 for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) { 3727 phy_c23 = true; 3728 phy_c22 = false; 3729 switch (cal_type) { 3730 case 0: 3731 phy_c10 = 511; 3732 break; 3733 case 2: 3734 phy_c10 = 127; 3735 break; 3736 case 3: 3737 phy_c10 = 15; 3738 break; 3739 case 4: 3740 phy_c10 = 15; 3741 break; 3742 } 3743 3744 phy_c9 = read_phy_reg(pi, 0x93d); 3745 phy_c9 = 2 * phy_c9; 3746 phy_c24 = false; 3747 phy_c5 = 7; 3748 phy_c25 = true; 3749 while (1) { 3750 write_radio_reg(pi, RADIO_2064_REG026, 3751 (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4)); 3752 udelay(50); 3753 phy_c22 = false; 3754 ptr[130] = 0; 3755 wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2); 3756 if (ptr[130] == 1) 3757 phy_c22 = true; 3758 if (phy_c22) 3759 phy_c5 -= 1; 3760 if ((phy_c22 != phy_c24) && (!phy_c25)) 3761 break; 3762 if (!phy_c22) 3763 phy_c5 += 1; 3764 if (phy_c5 <= 0 || phy_c5 >= 7) 3765 break; 3766 phy_c24 = phy_c22; 3767 phy_c25 = false; 3768 } 3769 3770 if (phy_c5 < 0) 3771 phy_c5 = 0; 3772 else if (phy_c5 > 7) 3773 phy_c5 = 7; 3774 3775 for (k = -phy_c7; k <= phy_c7; k += phy_c7) { 3776 for (l = -phy_c7; l <= phy_c7; l += phy_c7) { 3777 phy_c11 = phy_c15 + k; 3778 phy_c12 = phy_c16 + l; 3779 3780 if (phy_c11 < -phy_c10) 3781 phy_c11 = -phy_c10; 3782 else if (phy_c11 > phy_c10) 3783 phy_c11 = phy_c10; 3784 if (phy_c12 < -phy_c10) 3785 phy_c12 = -phy_c10; 3786 else if (phy_c12 > phy_c10) 3787 phy_c12 = phy_c10; 3788 wlc_lcnphy_set_cc(pi, cal_type, phy_c11, 3789 phy_c12); 3790 udelay(20); 3791 wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2); 3792 3793 phy_c18 = 0; 3794 phy_c19 = 0; 3795 for (j = 0; j < 128; j++) { 3796 if (cal_type != 0) 3797 phy_c6 = j % phy_c4; 3798 else 3799 phy_c6 = (2 * j) % phy_c4; 3800 3801 phy_c2.re = phy_c1[phy_c6].re; 3802 phy_c2.im = phy_c1[phy_c6].im; 3803 phy_c17 = ptr[j]; 3804 phy_c18 = phy_c18 + phy_c17 * phy_c2.re; 3805 phy_c19 = phy_c19 + phy_c17 * phy_c2.im; 3806 } 3807 3808 phy_c18 = phy_c18 >> 10; 3809 phy_c19 = phy_c19 >> 10; 3810 phy_c20 = ((phy_c18 * phy_c18) + 3811 (phy_c19 * phy_c19)); 3812 3813 if (phy_c23 || phy_c20 < phy_c21) { 3814 phy_c21 = phy_c20; 3815 phy_c13 = phy_c11; 3816 phy_c14 = phy_c12; 3817 } 3818 phy_c23 = false; 3819 } 3820 } 3821 phy_c23 = true; 3822 phy_c15 = phy_c13; 3823 phy_c16 = phy_c14; 3824 phy_c7 = phy_c7 >> 1; 3825 wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16); 3826 udelay(20); 3827 } 3828 goto cleanup; 3829 cleanup: 3830 wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32); 3831 wlc_lcnphy_stop_tx_tone(pi); 3832 write_phy_reg(pi, 0x6da, phy_c26); 3833 write_phy_reg(pi, 0x6db, phy_c27); 3834 write_phy_reg(pi, 0x938, phy_c28); 3835 write_phy_reg(pi, 0x4d7, phy_c29); 3836 write_phy_reg(pi, 0x4d8, phy_c30); 3837 write_radio_reg(pi, RADIO_2064_REG026, phy_c31); 3838 3839 kfree(phy_c32); 3840 kfree(ptr); 3841 } 3842 3843 void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b) 3844 { 3845 u16 iqcc[2]; 3846 struct phytbl_info tab; 3847 3848 tab.tbl_ptr = iqcc; 3849 tab.tbl_len = 2; 3850 tab.tbl_id = 0; 3851 tab.tbl_offset = 80; 3852 tab.tbl_width = 16; 3853 wlc_lcnphy_read_table(pi, &tab); 3854 3855 *a = iqcc[0]; 3856 *b = iqcc[1]; 3857 } 3858 3859 static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi) 3860 { 3861 struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4; 3862 3863 wlc_lcnphy_set_cc(pi, 0, 0, 0); 3864 wlc_lcnphy_set_cc(pi, 2, 0, 0); 3865 wlc_lcnphy_set_cc(pi, 3, 0, 0); 3866 wlc_lcnphy_set_cc(pi, 4, 0, 0); 3867 3868 wlc_lcnphy_a1(pi, 4, 0, 0); 3869 wlc_lcnphy_a1(pi, 3, 0, 0); 3870 wlc_lcnphy_a1(pi, 2, 3, 2); 3871 wlc_lcnphy_a1(pi, 0, 5, 8); 3872 wlc_lcnphy_a1(pi, 2, 2, 1); 3873 wlc_lcnphy_a1(pi, 0, 4, 3); 3874 3875 iqcc0 = wlc_lcnphy_get_cc(pi, 0); 3876 locc2 = wlc_lcnphy_get_cc(pi, 2); 3877 locc3 = wlc_lcnphy_get_cc(pi, 3); 3878 locc4 = wlc_lcnphy_get_cc(pi, 4); 3879 } 3880 3881 u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi) 3882 { 3883 struct phytbl_info tab; 3884 u16 didq; 3885 3886 tab.tbl_id = 0; 3887 tab.tbl_width = 16; 3888 tab.tbl_ptr = &didq; 3889 tab.tbl_len = 1; 3890 tab.tbl_offset = 85; 3891 wlc_lcnphy_read_table(pi, &tab); 3892 3893 return didq; 3894 } 3895 3896 static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) 3897 { 3898 3899 struct lcnphy_txgains target_gains, old_gains; 3900 u8 save_bb_mult; 3901 u16 a, b, didq, save_pa_gain = 0; 3902 uint idx, SAVE_txpwrindex = 0xFF; 3903 u32 val; 3904 u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); 3905 struct phytbl_info tab; 3906 u8 ei0, eq0, fi0, fq0; 3907 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 3908 3909 wlc_lcnphy_get_tx_gain(pi, &old_gains); 3910 save_pa_gain = wlc_lcnphy_get_pa_gain(pi); 3911 3912 save_bb_mult = wlc_lcnphy_get_bbmult(pi); 3913 3914 if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF) 3915 SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi); 3916 3917 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); 3918 3919 target_gains.gm_gain = 7; 3920 target_gains.pga_gain = 0; 3921 target_gains.pad_gain = 21; 3922 target_gains.dac_gain = 0; 3923 wlc_lcnphy_set_tx_gain(pi, &target_gains); 3924 3925 if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { 3926 3927 wlc_lcnphy_set_tx_pwr_by_index(pi, 30); 3928 3929 wlc_lcnphy_tx_iqlo_cal(pi, &target_gains, 3930 (pi_lcn-> 3931 lcnphy_recal ? LCNPHY_CAL_RECAL : 3932 LCNPHY_CAL_FULL), false); 3933 } else { 3934 wlc_lcnphy_set_tx_pwr_by_index(pi, 16); 3935 wlc_lcnphy_tx_iqlo_soft_cal_full(pi); 3936 } 3937 3938 wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0); 3939 if ((abs((s8) fi0) == 15) && (abs((s8) fq0) == 15)) { 3940 if (CHSPEC_IS5G(pi->radio_chanspec)) { 3941 target_gains.gm_gain = 255; 3942 target_gains.pga_gain = 255; 3943 target_gains.pad_gain = 0xf0; 3944 target_gains.dac_gain = 0; 3945 } else { 3946 target_gains.gm_gain = 7; 3947 target_gains.pga_gain = 45; 3948 target_gains.pad_gain = 186; 3949 target_gains.dac_gain = 0; 3950 } 3951 3952 if (LCNREV_IS(pi->pubpi.phy_rev, 1) 3953 || pi_lcn->lcnphy_hw_iqcal_en) { 3954 3955 target_gains.pga_gain = 0; 3956 target_gains.pad_gain = 30; 3957 wlc_lcnphy_set_tx_pwr_by_index(pi, 16); 3958 wlc_lcnphy_tx_iqlo_cal(pi, &target_gains, 3959 LCNPHY_CAL_FULL, false); 3960 } else { 3961 wlc_lcnphy_tx_iqlo_soft_cal_full(pi); 3962 } 3963 } 3964 3965 wlc_lcnphy_get_tx_iqcc(pi, &a, &b); 3966 3967 didq = wlc_lcnphy_get_tx_locc(pi); 3968 3969 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 3970 tab.tbl_width = 32; 3971 tab.tbl_ptr = &val; 3972 3973 tab.tbl_len = 1; 3974 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET; 3975 3976 for (idx = 0; idx < 128; idx++) { 3977 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx; 3978 3979 wlc_lcnphy_read_table(pi, &tab); 3980 val = (val & 0xfff00000) | 3981 ((u32) (a & 0x3FF) << 10) | (b & 0x3ff); 3982 wlc_lcnphy_write_table(pi, &tab); 3983 3984 val = didq; 3985 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx; 3986 wlc_lcnphy_write_table(pi, &tab); 3987 } 3988 3989 pi_lcn->lcnphy_cal_results.txiqlocal_a = a; 3990 pi_lcn->lcnphy_cal_results.txiqlocal_b = b; 3991 pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq; 3992 pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0; 3993 pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0; 3994 pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0; 3995 pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0; 3996 3997 wlc_lcnphy_set_bbmult(pi, save_bb_mult); 3998 wlc_lcnphy_set_pa_gain(pi, save_pa_gain); 3999 wlc_lcnphy_set_tx_gain(pi, &old_gains); 4000 4001 if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF) 4002 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); 4003 else 4004 wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex); 4005 } 4006 4007 s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode) 4008 { 4009 u16 tempsenseval1, tempsenseval2; 4010 s16 avg = 0; 4011 bool suspend = false; 4012 4013 if (mode == 1) { 4014 suspend = (0 == (bcma_read32(pi->d11core, 4015 D11REGOFFS(maccontrol)) & 4016 MCTL_EN_MAC)); 4017 if (!suspend) 4018 wlapi_suspend_mac_and_wait(pi->sh->physhim); 4019 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); 4020 } 4021 tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF; 4022 tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF; 4023 4024 if (tempsenseval1 > 255) 4025 avg = (s16) (tempsenseval1 - 512); 4026 else 4027 avg = (s16) tempsenseval1; 4028 4029 if (tempsenseval2 > 255) 4030 avg += (s16) (tempsenseval2 - 512); 4031 else 4032 avg += (s16) tempsenseval2; 4033 4034 avg /= 2; 4035 4036 if (mode == 1) { 4037 4038 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); 4039 4040 udelay(100); 4041 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); 4042 4043 if (!suspend) 4044 wlapi_enable_mac(pi->sh->physhim); 4045 } 4046 return avg; 4047 } 4048 4049 u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode) 4050 { 4051 u16 tempsenseval1, tempsenseval2; 4052 s32 avg = 0; 4053 bool suspend = false; 4054 u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); 4055 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 4056 4057 if (mode == 1) { 4058 suspend = (0 == (bcma_read32(pi->d11core, 4059 D11REGOFFS(maccontrol)) & 4060 MCTL_EN_MAC)); 4061 if (!suspend) 4062 wlapi_suspend_mac_and_wait(pi->sh->physhim); 4063 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE); 4064 } 4065 tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF; 4066 tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF; 4067 4068 if (tempsenseval1 > 255) 4069 avg = (int)(tempsenseval1 - 512); 4070 else 4071 avg = (int)tempsenseval1; 4072 4073 if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) { 4074 if (tempsenseval2 > 255) 4075 avg = (int)(avg - tempsenseval2 + 512); 4076 else 4077 avg = (int)(avg - tempsenseval2); 4078 } else { 4079 if (tempsenseval2 > 255) 4080 avg = (int)(avg + tempsenseval2 - 512); 4081 else 4082 avg = (int)(avg + tempsenseval2); 4083 avg = avg / 2; 4084 } 4085 if (avg < 0) 4086 avg = avg + 512; 4087 4088 if (pi_lcn->lcnphy_tempsense_option == 2) 4089 avg = tempsenseval1; 4090 4091 if (mode) 4092 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); 4093 4094 if (mode == 1) { 4095 4096 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); 4097 4098 udelay(100); 4099 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); 4100 4101 if (!suspend) 4102 wlapi_enable_mac(pi->sh->physhim); 4103 } 4104 return (u16) avg; 4105 } 4106 4107 s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode) 4108 { 4109 s32 degree = wlc_lcnphy_tempsense_new(pi, mode); 4110 degree = 4111 ((degree << 4112 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1)) 4113 / LCN_TEMPSENSE_DEN; 4114 return (s8) degree; 4115 } 4116 4117 s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode) 4118 { 4119 u16 vbatsenseval; 4120 s32 avg = 0; 4121 bool suspend = false; 4122 4123 if (mode == 1) { 4124 suspend = (0 == (bcma_read32(pi->d11core, 4125 D11REGOFFS(maccontrol)) & 4126 MCTL_EN_MAC)); 4127 if (!suspend) 4128 wlapi_suspend_mac_and_wait(pi->sh->physhim); 4129 wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE); 4130 } 4131 4132 vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF; 4133 4134 if (vbatsenseval > 255) 4135 avg = (s32) (vbatsenseval - 512); 4136 else 4137 avg = (s32) vbatsenseval; 4138 4139 avg = (avg * LCN_VBAT_SCALE_NOM + 4140 (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN; 4141 4142 if (mode == 1) { 4143 if (!suspend) 4144 wlapi_enable_mac(pi->sh->physhim); 4145 } 4146 return (s8) avg; 4147 } 4148 4149 static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode) 4150 { 4151 u8 phybw40; 4152 phybw40 = CHSPEC_IS40(pi->radio_chanspec); 4153 4154 mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7); 4155 4156 if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) || 4157 (mode == AFE_CLK_INIT_MODE_TXRX2X)) 4158 write_phy_reg(pi, 0x6d0, 0x7); 4159 4160 wlc_lcnphy_toggle_afe_pwdn(pi); 4161 } 4162 4163 static void wlc_lcnphy_temp_adj(struct brcms_phy *pi) 4164 { 4165 } 4166 4167 static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi) 4168 { 4169 bool suspend; 4170 s8 index; 4171 u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); 4172 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 4173 suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & 4174 MCTL_EN_MAC)); 4175 if (!suspend) 4176 wlapi_suspend_mac_and_wait(pi->sh->physhim); 4177 wlc_lcnphy_deaf_mode(pi, true); 4178 pi->phy_lastcal = pi->sh->now; 4179 pi->phy_forcecal = false; 4180 index = pi_lcn->lcnphy_current_index; 4181 4182 wlc_lcnphy_txpwrtbl_iqlo_cal(pi); 4183 4184 wlc_lcnphy_set_tx_pwr_by_index(pi, index); 4185 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl); 4186 wlc_lcnphy_deaf_mode(pi, false); 4187 if (!suspend) 4188 wlapi_enable_mac(pi->sh->physhim); 4189 4190 } 4191 4192 static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi) 4193 { 4194 bool suspend, full_cal; 4195 const struct lcnphy_rx_iqcomp *rx_iqcomp; 4196 int rx_iqcomp_sz; 4197 u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); 4198 s8 index; 4199 struct phytbl_info tab; 4200 s32 a1, b0, b1; 4201 s32 tssi, pwr, mintargetpwr; 4202 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 4203 4204 pi->phy_lastcal = pi->sh->now; 4205 pi->phy_forcecal = false; 4206 full_cal = 4207 (pi_lcn->lcnphy_full_cal_channel != 4208 CHSPEC_CHANNEL(pi->radio_chanspec)); 4209 pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec); 4210 index = pi_lcn->lcnphy_current_index; 4211 4212 suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & 4213 MCTL_EN_MAC)); 4214 if (!suspend) { 4215 wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000); 4216 wlapi_suspend_mac_and_wait(pi->sh->physhim); 4217 } 4218 4219 wlc_lcnphy_deaf_mode(pi, true); 4220 4221 wlc_lcnphy_txpwrtbl_iqlo_cal(pi); 4222 4223 rx_iqcomp = lcnphy_rx_iqcomp_table_rev0; 4224 rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0); 4225 4226 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) 4227 wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40); 4228 else 4229 wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127); 4230 4231 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) { 4232 4233 wlc_lcnphy_idle_tssi_est((struct brcms_phy_pub *) pi); 4234 4235 b0 = pi->txpa_2g[0]; 4236 b1 = pi->txpa_2g[1]; 4237 a1 = pi->txpa_2g[2]; 4238 mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1); 4239 4240 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 4241 tab.tbl_width = 32; 4242 tab.tbl_ptr = &pwr; 4243 tab.tbl_len = 1; 4244 tab.tbl_offset = 0; 4245 for (tssi = 0; tssi < 128; tssi++) { 4246 pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1); 4247 pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr; 4248 wlc_lcnphy_write_table(pi, &tab); 4249 tab.tbl_offset++; 4250 } 4251 } 4252 4253 wlc_lcnphy_set_tx_pwr_by_index(pi, index); 4254 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl); 4255 wlc_lcnphy_deaf_mode(pi, false); 4256 if (!suspend) 4257 wlapi_enable_mac(pi->sh->physhim); 4258 } 4259 4260 void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode) 4261 { 4262 u16 temp_new; 4263 int temp1, temp2, temp_diff; 4264 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 4265 4266 switch (mode) { 4267 case PHY_PERICAL_CHAN: 4268 break; 4269 case PHY_FULLCAL: 4270 wlc_lcnphy_periodic_cal(pi); 4271 break; 4272 case PHY_PERICAL_PHYINIT: 4273 wlc_lcnphy_periodic_cal(pi); 4274 break; 4275 case PHY_PERICAL_WATCHDOG: 4276 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { 4277 temp_new = wlc_lcnphy_tempsense(pi, 0); 4278 temp1 = LCNPHY_TEMPSENSE(temp_new); 4279 temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper); 4280 temp_diff = temp1 - temp2; 4281 if ((pi_lcn->lcnphy_cal_counter > 90) || 4282 (temp_diff > 60) || (temp_diff < -60)) { 4283 wlc_lcnphy_glacial_timer_based_cal(pi); 4284 wlc_2064_vco_cal(pi); 4285 pi_lcn->lcnphy_cal_temper = temp_new; 4286 pi_lcn->lcnphy_cal_counter = 0; 4287 } else 4288 pi_lcn->lcnphy_cal_counter++; 4289 } 4290 break; 4291 case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL: 4292 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) 4293 wlc_lcnphy_tx_power_adjustment( 4294 (struct brcms_phy_pub *) pi); 4295 break; 4296 } 4297 } 4298 4299 void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr) 4300 { 4301 s8 cck_offset; 4302 u16 status; 4303 status = (read_phy_reg(pi, 0x4ab)); 4304 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) && 4305 (status & (0x1 << 15))) { 4306 *ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) 4307 >> 0) >> 1); 4308 4309 if (wlc_phy_tpc_isenabled_lcnphy(pi)) 4310 cck_offset = pi->tx_power_offset[TXP_FIRST_CCK]; 4311 else 4312 cck_offset = 0; 4313 4314 *cck_pwr = *ofdm_pwr + cck_offset; 4315 } else { 4316 *cck_pwr = 0; 4317 *ofdm_pwr = 0; 4318 } 4319 } 4320 4321 void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi) 4322 { 4323 return; 4324 4325 } 4326 4327 void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi) 4328 { 4329 s8 index; 4330 u16 index2; 4331 struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro); 4332 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 4333 u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); 4334 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && 4335 SAVE_txpwrctrl) { 4336 index = wlc_lcnphy_tempcompensated_txpwrctrl(pi); 4337 index2 = (u16) (index * 2); 4338 mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0); 4339 4340 pi_lcn->lcnphy_current_index = 4341 (s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2); 4342 } 4343 } 4344 4345 static void 4346 wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, 4347 const struct lcnphy_tx_gain_tbl_entry *gain_table) 4348 { 4349 u32 j; 4350 struct phytbl_info tab; 4351 u32 val; 4352 u16 pa_gain; 4353 u16 gm_gain; 4354 4355 if (pi->sh->boardflags & BFL_FEM) 4356 pa_gain = 0x10; 4357 else 4358 pa_gain = 0x60; 4359 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 4360 tab.tbl_width = 32; 4361 tab.tbl_len = 1; 4362 tab.tbl_ptr = &val; 4363 4364 /* fixed gm_gain value for iPA */ 4365 gm_gain = 15; 4366 for (j = 0; j < 128; j++) { 4367 if (pi->sh->boardflags & BFL_FEM) 4368 gm_gain = gain_table[j].gm; 4369 val = (((u32) pa_gain << 24) | 4370 (gain_table[j].pad << 16) | 4371 (gain_table[j].pga << 8) | gm_gain); 4372 4373 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j; 4374 wlc_lcnphy_write_table(pi, &tab); 4375 4376 val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20); 4377 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j; 4378 wlc_lcnphy_write_table(pi, &tab); 4379 } 4380 } 4381 4382 static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi) 4383 { 4384 struct phytbl_info tab; 4385 u32 val, bbmult, rfgain; 4386 u8 index; 4387 u8 scale_factor = 1; 4388 s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift; 4389 4390 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; 4391 tab.tbl_width = 32; 4392 tab.tbl_len = 1; 4393 4394 for (index = 0; index < 128; index++) { 4395 tab.tbl_ptr = &bbmult; 4396 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index; 4397 wlc_lcnphy_read_table(pi, &tab); 4398 bbmult = bbmult >> 20; 4399 4400 tab.tbl_ptr = &rfgain; 4401 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index; 4402 wlc_lcnphy_read_table(pi, &tab); 4403 4404 qm_log10((s32) (bbmult), 0, &temp1, &qQ1); 4405 qm_log10((s32) (1 << 6), 0, &temp2, &qQ2); 4406 4407 if (qQ1 < qQ2) { 4408 temp2 = qm_shr16(temp2, qQ2 - qQ1); 4409 qQ = qQ1; 4410 } else { 4411 temp1 = qm_shr16(temp1, qQ1 - qQ2); 4412 qQ = qQ2; 4413 } 4414 temp = qm_sub16(temp1, temp2); 4415 4416 if (qQ >= 4) 4417 shift = qQ - 4; 4418 else 4419 shift = 4 - qQ; 4420 4421 val = (((index << shift) + (5 * temp) + 4422 (1 << (scale_factor + shift - 3))) >> (scale_factor + 4423 shift - 2)); 4424 4425 tab.tbl_ptr = &val; 4426 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index; 4427 wlc_lcnphy_write_table(pi, &tab); 4428 } 4429 } 4430 4431 static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi) 4432 { 4433 or_phy_reg(pi, 0x805, 0x1); 4434 4435 mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0); 4436 4437 mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0); 4438 4439 write_phy_reg(pi, 0x414, 0x1e10); 4440 write_phy_reg(pi, 0x415, 0x0640); 4441 4442 mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8); 4443 4444 or_phy_reg(pi, 0x44a, 0x44); 4445 write_phy_reg(pi, 0x44a, 0x80); 4446 mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0); 4447 4448 mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0); 4449 4450 if (!(pi->sh->boardrev < 0x1204)) 4451 mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0); 4452 4453 write_phy_reg(pi, 0x7d6, 0x0902); 4454 mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0); 4455 4456 mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4); 4457 4458 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { 4459 mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0); 4460 4461 mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0); 4462 4463 mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0); 4464 4465 mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0); 4466 4467 mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2); 4468 4469 mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4); 4470 mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0); 4471 mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90); 4472 mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2); 4473 mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0); 4474 4475 mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2); 4476 4477 wlc_lcnphy_clear_tx_power_offsets(pi); 4478 mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6); 4479 4480 } 4481 } 4482 4483 static void wlc_lcnphy_rcal(struct brcms_phy *pi) 4484 { 4485 u8 rcal_value; 4486 4487 and_radio_reg(pi, RADIO_2064_REG05B, 0xfD); 4488 4489 or_radio_reg(pi, RADIO_2064_REG004, 0x40); 4490 or_radio_reg(pi, RADIO_2064_REG120, 0x10); 4491 4492 or_radio_reg(pi, RADIO_2064_REG078, 0x80); 4493 or_radio_reg(pi, RADIO_2064_REG129, 0x02); 4494 4495 or_radio_reg(pi, RADIO_2064_REG057, 0x01); 4496 4497 or_radio_reg(pi, RADIO_2064_REG05B, 0x02); 4498 mdelay(5); 4499 SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000); 4500 4501 if (wlc_radio_2064_rcal_done(pi)) { 4502 rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C); 4503 rcal_value = rcal_value & 0x1f; 4504 } 4505 4506 and_radio_reg(pi, RADIO_2064_REG05B, 0xfD); 4507 4508 and_radio_reg(pi, RADIO_2064_REG057, 0xFE); 4509 } 4510 4511 static void wlc_lcnphy_rc_cal(struct brcms_phy *pi) 4512 { 4513 u8 dflt_rc_cal_val; 4514 u16 flt_val; 4515 4516 dflt_rc_cal_val = 7; 4517 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) 4518 dflt_rc_cal_val = 11; 4519 flt_val = 4520 (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) | 4521 (dflt_rc_cal_val); 4522 write_phy_reg(pi, 0x933, flt_val); 4523 write_phy_reg(pi, 0x934, flt_val); 4524 write_phy_reg(pi, 0x935, flt_val); 4525 write_phy_reg(pi, 0x936, flt_val); 4526 write_phy_reg(pi, 0x937, (flt_val & 0x1FF)); 4527 4528 return; 4529 } 4530 4531 static void wlc_radio_2064_init(struct brcms_phy *pi) 4532 { 4533 u32 i; 4534 const struct lcnphy_radio_regs *lcnphyregs = NULL; 4535 4536 lcnphyregs = lcnphy_radio_regs_2064; 4537 4538 for (i = 0; lcnphyregs[i].address != 0xffff; i++) 4539 if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a) 4540 write_radio_reg(pi, 4541 ((lcnphyregs[i].address & 0x3fff) | 4542 RADIO_DEFAULT_CORE), 4543 (u16) lcnphyregs[i].init_a); 4544 else if (lcnphyregs[i].do_init_g) 4545 write_radio_reg(pi, 4546 ((lcnphyregs[i].address & 0x3fff) | 4547 RADIO_DEFAULT_CORE), 4548 (u16) lcnphyregs[i].init_g); 4549 4550 write_radio_reg(pi, RADIO_2064_REG032, 0x62); 4551 write_radio_reg(pi, RADIO_2064_REG033, 0x19); 4552 4553 write_radio_reg(pi, RADIO_2064_REG090, 0x10); 4554 4555 write_radio_reg(pi, RADIO_2064_REG010, 0x00); 4556 4557 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { 4558 4559 write_radio_reg(pi, RADIO_2064_REG060, 0x7f); 4560 write_radio_reg(pi, RADIO_2064_REG061, 0x72); 4561 write_radio_reg(pi, RADIO_2064_REG062, 0x7f); 4562 } 4563 4564 write_radio_reg(pi, RADIO_2064_REG01D, 0x02); 4565 write_radio_reg(pi, RADIO_2064_REG01E, 0x06); 4566 4567 mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0); 4568 4569 mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3); 4570 4571 mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6); 4572 4573 mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9); 4574 4575 mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12); 4576 4577 write_phy_reg(pi, 0x4ea, 0x4688); 4578 4579 if (pi->sh->boardflags & BFL_FEM) 4580 mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); 4581 else 4582 mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0); 4583 4584 mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); 4585 4586 mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0); 4587 4588 wlc_lcnphy_set_tx_locc(pi, 0); 4589 4590 wlc_lcnphy_rcal(pi); 4591 4592 wlc_lcnphy_rc_cal(pi); 4593 4594 if (!(pi->sh->boardflags & BFL_FEM)) { 4595 write_radio_reg(pi, RADIO_2064_REG032, 0x6f); 4596 write_radio_reg(pi, RADIO_2064_REG033, 0x19); 4597 write_radio_reg(pi, RADIO_2064_REG039, 0xe); 4598 } 4599 4600 } 4601 4602 static void wlc_lcnphy_radio_init(struct brcms_phy *pi) 4603 { 4604 wlc_radio_2064_init(pi); 4605 } 4606 4607 static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) 4608 { 4609 uint idx; 4610 struct phytbl_info tab; 4611 const struct phytbl_info *tb; 4612 u32 val; 4613 4614 for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) 4615 wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]); 4616 4617 if (pi->sh->boardflags & BFL_FEM_BT) { 4618 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; 4619 tab.tbl_width = 16; 4620 tab.tbl_ptr = &val; 4621 tab.tbl_len = 1; 4622 val = 100; 4623 tab.tbl_offset = 4; 4624 wlc_lcnphy_write_table(pi, &tab); 4625 } 4626 4627 if (!(pi->sh->boardflags & BFL_FEM)) { 4628 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; 4629 tab.tbl_width = 16; 4630 tab.tbl_ptr = &val; 4631 tab.tbl_len = 1; 4632 4633 val = 150; 4634 tab.tbl_offset = 0; 4635 wlc_lcnphy_write_table(pi, &tab); 4636 4637 val = 220; 4638 tab.tbl_offset = 1; 4639 wlc_lcnphy_write_table(pi, &tab); 4640 } 4641 4642 if (CHSPEC_IS2G(pi->radio_chanspec)) { 4643 if (pi->sh->boardflags & BFL_FEM) 4644 wlc_lcnphy_load_tx_gain_table( 4645 pi, 4646 dot11lcnphy_2GHz_extPA_gaintable_rev0); 4647 else 4648 wlc_lcnphy_load_tx_gain_table( 4649 pi, 4650 dot11lcnphy_2GHz_gaintable_rev0); 4651 } 4652 4653 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { 4654 int l; 4655 4656 if (CHSPEC_IS2G(pi->radio_chanspec)) { 4657 l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz; 4658 if (pi->sh->boardflags & BFL_EXTLNA) 4659 tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2; 4660 else 4661 tb = dot11lcnphytbl_rx_gain_info_2G_rev2; 4662 } else { 4663 l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz; 4664 if (pi->sh->boardflags & BFL_EXTLNA_5GHz) 4665 tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2; 4666 else 4667 tb = dot11lcnphytbl_rx_gain_info_5G_rev2; 4668 } 4669 4670 for (idx = 0; idx < l; idx++) 4671 wlc_lcnphy_write_table(pi, &tb[idx]); 4672 } 4673 4674 if (pi->sh->boardflags & BFL_FEM) { 4675 if (pi->sh->boardflags & BFL_FEM_BT) { 4676 if (pi->sh->boardrev < 0x1250) 4677 tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa; 4678 else 4679 tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250; 4680 } else { 4681 tb = &dot11lcn_sw_ctrl_tbl_info_4313_epa; 4682 } 4683 } else { 4684 if (pi->sh->boardflags & BFL_FEM_BT) 4685 tb = &dot11lcn_sw_ctrl_tbl_info_4313_bt_ipa; 4686 else 4687 tb = &dot11lcn_sw_ctrl_tbl_info_4313; 4688 } 4689 wlc_lcnphy_write_table(pi, tb); 4690 wlc_lcnphy_load_rfpower(pi); 4691 4692 wlc_lcnphy_clear_papd_comptable(pi); 4693 } 4694 4695 static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi) 4696 { 4697 u16 afectrl1; 4698 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 4699 4700 write_radio_reg(pi, RADIO_2064_REG11C, 0x0); 4701 4702 write_phy_reg(pi, 0x43b, 0x0); 4703 write_phy_reg(pi, 0x43c, 0x0); 4704 write_phy_reg(pi, 0x44c, 0x0); 4705 write_phy_reg(pi, 0x4e6, 0x0); 4706 write_phy_reg(pi, 0x4f9, 0x0); 4707 write_phy_reg(pi, 0x4b0, 0x0); 4708 write_phy_reg(pi, 0x938, 0x0); 4709 write_phy_reg(pi, 0x4b0, 0x0); 4710 write_phy_reg(pi, 0x44e, 0); 4711 4712 or_phy_reg(pi, 0x567, 0x03); 4713 4714 or_phy_reg(pi, 0x44a, 0x44); 4715 write_phy_reg(pi, 0x44a, 0x80); 4716 4717 if (!(pi->sh->boardflags & BFL_FEM)) 4718 wlc_lcnphy_set_tx_pwr_by_index(pi, 52); 4719 4720 if (0) { 4721 afectrl1 = 0; 4722 afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) | 4723 (pi_lcn->lcnphy_rssi_vc << 4) | 4724 (pi_lcn->lcnphy_rssi_gs << 10)); 4725 write_phy_reg(pi, 0x43e, afectrl1); 4726 } 4727 4728 mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0); 4729 if (pi->sh->boardflags & BFL_FEM) { 4730 mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0); 4731 4732 write_phy_reg(pi, 0x910, 0x1); 4733 } 4734 4735 mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8); 4736 mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0); 4737 mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0); 4738 4739 } 4740 4741 static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi) 4742 { 4743 if (CHSPEC_IS5G(pi->radio_chanspec)) { 4744 mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0); 4745 mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8); 4746 } 4747 } 4748 4749 static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi) 4750 { 4751 s16 temp; 4752 struct phytbl_info tab; 4753 u32 tableBuffer[2]; 4754 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 4755 4756 temp = (s16) read_phy_reg(pi, 0x4df); 4757 pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0; 4758 4759 if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127) 4760 pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256; 4761 4762 pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8; 4763 4764 if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127) 4765 pi_lcn->lcnphy_dsssgainidxtableoffset -= 256; 4766 4767 tab.tbl_ptr = tableBuffer; 4768 tab.tbl_len = 2; 4769 tab.tbl_id = 17; 4770 tab.tbl_offset = 59; 4771 tab.tbl_width = 32; 4772 wlc_lcnphy_read_table(pi, &tab); 4773 4774 if (tableBuffer[0] > 63) 4775 tableBuffer[0] -= 128; 4776 pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0]; 4777 4778 if (tableBuffer[1] > 63) 4779 tableBuffer[1] -= 128; 4780 pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1]; 4781 4782 temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0)); 4783 if (temp > 127) 4784 temp -= 256; 4785 pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp; 4786 4787 pi_lcn->lcnphy_Med_Low_Gain_db = 4788 (read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8; 4789 pi_lcn->lcnphy_Very_Low_Gain_db = 4790 (read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0; 4791 4792 tab.tbl_ptr = tableBuffer; 4793 tab.tbl_len = 2; 4794 tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX; 4795 tab.tbl_offset = 28; 4796 tab.tbl_width = 32; 4797 wlc_lcnphy_read_table(pi, &tab); 4798 4799 pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0]; 4800 pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1]; 4801 4802 } 4803 4804 static void wlc_lcnphy_baseband_init(struct brcms_phy *pi) 4805 { 4806 4807 wlc_lcnphy_tbl_init(pi); 4808 wlc_lcnphy_rev0_baseband_init(pi); 4809 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) 4810 wlc_lcnphy_rev2_baseband_init(pi); 4811 wlc_lcnphy_bu_tweaks(pi); 4812 } 4813 4814 void wlc_phy_init_lcnphy(struct brcms_phy *pi) 4815 { 4816 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 4817 4818 pi_lcn->lcnphy_cal_counter = 0; 4819 pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense; 4820 4821 or_phy_reg(pi, 0x44a, 0x80); 4822 and_phy_reg(pi, 0x44a, 0x7f); 4823 4824 wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X); 4825 4826 write_phy_reg(pi, 0x60a, 160); 4827 4828 write_phy_reg(pi, 0x46a, 25); 4829 4830 wlc_lcnphy_baseband_init(pi); 4831 4832 wlc_lcnphy_radio_init(pi); 4833 4834 if (CHSPEC_IS2G(pi->radio_chanspec)) 4835 wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi); 4836 4837 wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec); 4838 4839 bcma_chipco_regctl_maskset(&pi->d11core->bus->drv_cc, 0, ~0xf, 0x9); 4840 4841 bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 0, 0x0, 4842 0x03CDDDDD); 4843 4844 if ((pi->sh->boardflags & BFL_FEM) 4845 && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) 4846 wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR); 4847 4848 wlc_lcnphy_agc_temp_init(pi); 4849 4850 wlc_lcnphy_temp_adj(pi); 4851 4852 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14); 4853 4854 udelay(100); 4855 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14); 4856 4857 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW); 4858 pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT; 4859 wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT); 4860 } 4861 4862 static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) 4863 { 4864 s8 txpwr = 0; 4865 int i; 4866 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 4867 struct ssb_sprom *sprom = &pi->d11core->bus->sprom; 4868 4869 if (CHSPEC_IS2G(pi->radio_chanspec)) { 4870 u16 cckpo = 0; 4871 u32 offset_ofdm, offset_mcs; 4872 4873 pi_lcn->lcnphy_tr_isolation_mid = sprom->fem.ghz2.tr_iso; 4874 4875 pi_lcn->lcnphy_rx_power_offset = sprom->rxpo2g; 4876 4877 pi->txpa_2g[0] = sprom->pa0b0; 4878 pi->txpa_2g[1] = sprom->pa0b1; 4879 pi->txpa_2g[2] = sprom->pa0b2; 4880 4881 pi_lcn->lcnphy_rssi_vf = sprom->rssismf2g; 4882 pi_lcn->lcnphy_rssi_vc = sprom->rssismc2g; 4883 pi_lcn->lcnphy_rssi_gs = sprom->rssisav2g; 4884 4885 pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf; 4886 pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc; 4887 pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs; 4888 4889 pi_lcn->lcnphy_rssi_vf_hightemp = pi_lcn->lcnphy_rssi_vf; 4890 pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc; 4891 pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs; 4892 4893 txpwr = sprom->core_pwr_info[0].maxpwr_2g; 4894 pi->tx_srom_max_2g = txpwr; 4895 4896 for (i = 0; i < PWRTBL_NUM_COEFF; i++) { 4897 pi->txpa_2g_low_temp[i] = pi->txpa_2g[i]; 4898 pi->txpa_2g_high_temp[i] = pi->txpa_2g[i]; 4899 } 4900 4901 cckpo = sprom->cck2gpo; 4902 offset_ofdm = sprom->ofdm2gpo; 4903 if (cckpo) { 4904 uint max_pwr_chan = txpwr; 4905 4906 for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) { 4907 pi->tx_srom_max_rate_2g[i] = 4908 max_pwr_chan - ((cckpo & 0xf) * 2); 4909 cckpo >>= 4; 4910 } 4911 4912 for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { 4913 pi->tx_srom_max_rate_2g[i] = 4914 max_pwr_chan - 4915 ((offset_ofdm & 0xf) * 2); 4916 offset_ofdm >>= 4; 4917 } 4918 } else { 4919 u8 opo = 0; 4920 4921 opo = sprom->opo; 4922 4923 for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) 4924 pi->tx_srom_max_rate_2g[i] = txpwr; 4925 4926 for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) { 4927 pi->tx_srom_max_rate_2g[i] = txpwr - 4928 ((offset_ofdm & 0xf) * 2); 4929 offset_ofdm >>= 4; 4930 } 4931 offset_mcs = sprom->mcs2gpo[1] << 16; 4932 offset_mcs |= sprom->mcs2gpo[0]; 4933 pi_lcn->lcnphy_mcs20_po = offset_mcs; 4934 for (i = TXP_FIRST_SISO_MCS_20; 4935 i <= TXP_LAST_SISO_MCS_20; i++) { 4936 pi->tx_srom_max_rate_2g[i] = 4937 txpwr - ((offset_mcs & 0xf) * 2); 4938 offset_mcs >>= 4; 4939 } 4940 } 4941 4942 pi_lcn->lcnphy_rawtempsense = sprom->rawtempsense; 4943 pi_lcn->lcnphy_measPower = sprom->measpower; 4944 pi_lcn->lcnphy_tempsense_slope = sprom->tempsense_slope; 4945 pi_lcn->lcnphy_hw_iqcal_en = sprom->hw_iqcal_en; 4946 pi_lcn->lcnphy_iqcal_swp_dis = sprom->iqcal_swp_dis; 4947 pi_lcn->lcnphy_tempcorrx = sprom->tempcorrx; 4948 pi_lcn->lcnphy_tempsense_option = sprom->tempsense_option; 4949 pi_lcn->lcnphy_freqoffset_corr = sprom->freqoffset_corr; 4950 if (sprom->ant_available_bg > 1) 4951 wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, 4952 sprom->ant_available_bg); 4953 } 4954 pi_lcn->lcnphy_cck_dig_filt_type = -1; 4955 4956 return true; 4957 } 4958 4959 void wlc_2064_vco_cal(struct brcms_phy *pi) 4960 { 4961 u8 calnrst; 4962 4963 mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3); 4964 calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8; 4965 write_radio_reg(pi, RADIO_2064_REG056, calnrst); 4966 udelay(1); 4967 write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03); 4968 udelay(1); 4969 write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07); 4970 udelay(300); 4971 mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0); 4972 } 4973 4974 bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi) 4975 { 4976 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) 4977 return false; 4978 else 4979 return (LCNPHY_TX_PWR_CTRL_HW == 4980 wlc_lcnphy_get_tx_pwr_ctrl((pi))); 4981 } 4982 4983 void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi) 4984 { 4985 u16 pwr_ctrl; 4986 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) { 4987 wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL); 4988 } else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) { 4989 pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); 4990 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); 4991 wlc_lcnphy_txpower_recalc_target(pi); 4992 wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl); 4993 } 4994 } 4995 4996 void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) 4997 { 4998 u8 channel = CHSPEC_CHANNEL(chanspec); 4999 5000 wlc_phy_chanspec_radio_set((struct brcms_phy_pub *)pi, chanspec); 5001 5002 wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec); 5003 5004 or_phy_reg(pi, 0x44a, 0x44); 5005 write_phy_reg(pi, 0x44a, 0x80); 5006 5007 wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel); 5008 udelay(1000); 5009 5010 wlc_lcnphy_toggle_afe_pwdn(pi); 5011 5012 write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20); 5013 write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor); 5014 5015 if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) { 5016 mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8); 5017 5018 wlc_lcnphy_load_tx_iir_filter(pi, false, 3); 5019 } else { 5020 mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8); 5021 5022 wlc_lcnphy_load_tx_iir_filter(pi, false, 2); 5023 } 5024 5025 if (pi->sh->boardflags & BFL_FEM) 5026 wlc_lcnphy_load_tx_iir_filter(pi, true, 0); 5027 else 5028 wlc_lcnphy_load_tx_iir_filter(pi, true, 3); 5029 5030 mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); 5031 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) 5032 wlc_lcnphy_tssi_setup(pi); 5033 } 5034 5035 void wlc_phy_detach_lcnphy(struct brcms_phy *pi) 5036 { 5037 kfree(pi->u.pi_lcnphy); 5038 } 5039 5040 bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) 5041 { 5042 struct brcms_phy_lcnphy *pi_lcn; 5043 5044 pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC); 5045 if (pi->u.pi_lcnphy == NULL) 5046 return false; 5047 5048 pi_lcn = pi->u.pi_lcnphy; 5049 5050 if (0 == (pi->sh->boardflags & BFL_NOPA)) { 5051 pi->hwpwrctrl = true; 5052 pi->hwpwrctrl_capable = true; 5053 } 5054 5055 pi->xtalfreq = bcma_chipco_get_alp_clock(&pi->d11core->bus->drv_cc); 5056 pi_lcn->lcnphy_papd_rxGnCtrl_init = 0; 5057 5058 pi->pi_fptr.init = wlc_phy_init_lcnphy; 5059 pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy; 5060 pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy; 5061 pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy; 5062 pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc; 5063 pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc; 5064 pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc; 5065 pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft; 5066 pi->pi_fptr.detach = wlc_phy_detach_lcnphy; 5067 5068 if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) 5069 return false; 5070 5071 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { 5072 if (pi_lcn->lcnphy_tempsense_option == 3) { 5073 pi->hwpwrctrl = true; 5074 pi->hwpwrctrl_capable = true; 5075 pi->temppwrctrl_capable = false; 5076 } else { 5077 pi->hwpwrctrl = false; 5078 pi->hwpwrctrl_capable = false; 5079 pi->temppwrctrl_capable = true; 5080 } 5081 } 5082 5083 return true; 5084 } 5085 5086 static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain) 5087 { 5088 u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19; 5089 5090 trsw = (gain & ((u32) 1 << 28)) ? 0 : 1; 5091 ext_lna = (u16) (gain >> 29) & 0x01; 5092 lna1 = (u16) (gain >> 0) & 0x0f; 5093 lna2 = (u16) (gain >> 4) & 0x0f; 5094 tia = (u16) (gain >> 8) & 0xf; 5095 biq0 = (u16) (gain >> 12) & 0xf; 5096 biq1 = (u16) (gain >> 16) & 0xf; 5097 5098 gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) | 5099 ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) | 5100 ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12)); 5101 gain16_19 = biq1; 5102 5103 mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0); 5104 mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9); 5105 mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10); 5106 mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); 5107 mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); 5108 5109 if (CHSPEC_IS2G(pi->radio_chanspec)) { 5110 mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); 5111 mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3); 5112 } 5113 wlc_lcnphy_rx_gain_override_enable(pi, true); 5114 } 5115 5116 static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index) 5117 { 5118 u32 received_power = 0; 5119 s32 max_index = 0; 5120 u32 gain_code = 0; 5121 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 5122 5123 max_index = 36; 5124 if (*gain_index >= 0) 5125 gain_code = lcnphy_23bitgaincode_table[*gain_index]; 5126 5127 if (-1 == *gain_index) { 5128 *gain_index = 0; 5129 while ((*gain_index <= (s32) max_index) 5130 && (received_power < 700)) { 5131 wlc_lcnphy_set_rx_gain(pi, 5132 lcnphy_23bitgaincode_table 5133 [*gain_index]); 5134 received_power = 5135 wlc_lcnphy_measure_digital_power( 5136 pi, 5137 pi_lcn-> 5138 lcnphy_noise_samples); 5139 (*gain_index)++; 5140 } 5141 (*gain_index)--; 5142 } else { 5143 wlc_lcnphy_set_rx_gain(pi, gain_code); 5144 received_power = 5145 wlc_lcnphy_measure_digital_power(pi, 5146 pi_lcn-> 5147 lcnphy_noise_samples); 5148 } 5149 5150 return received_power; 5151 } 5152 5153 s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index) 5154 { 5155 s32 gain = 0; 5156 s32 nominal_power_db; 5157 s32 log_val, gain_mismatch, desired_gain, input_power_offset_db, 5158 input_power_db; 5159 s32 received_power, temperature; 5160 u32 power; 5161 u32 msb1, msb2, val1, val2, diff1, diff2; 5162 uint freq; 5163 struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; 5164 5165 received_power = wlc_lcnphy_get_receive_power(pi, &gain_index); 5166 5167 gain = lcnphy_gain_table[gain_index]; 5168 5169 nominal_power_db = read_phy_reg(pi, 0x425) >> 8; 5170 5171 power = (received_power * 16); 5172 msb1 = ffs(power) - 1; 5173 msb2 = msb1 + 1; 5174 val1 = 1 << msb1; 5175 val2 = 1 << msb2; 5176 diff1 = (power - val1); 5177 diff2 = (val2 - power); 5178 if (diff1 < diff2) 5179 log_val = msb1; 5180 else 5181 log_val = msb2; 5182 5183 log_val = log_val * 3; 5184 5185 gain_mismatch = (nominal_power_db / 2) - (log_val); 5186 5187 desired_gain = gain + gain_mismatch; 5188 5189 input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF; 5190 5191 if (input_power_offset_db > 127) 5192 input_power_offset_db -= 256; 5193 5194 input_power_db = input_power_offset_db - desired_gain; 5195 5196 input_power_db = 5197 input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index]; 5198 5199 freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec)); 5200 if ((freq > 2427) && (freq <= 2467)) 5201 input_power_db = input_power_db - 1; 5202 5203 temperature = pi_lcn->lcnphy_lastsensed_temperature; 5204 5205 if ((temperature - 15) < -30) 5206 input_power_db = 5207 input_power_db + 5208 (((temperature - 10 - 25) * 286) >> 12) - 5209 7; 5210 else if ((temperature - 15) < 4) 5211 input_power_db = 5212 input_power_db + 5213 (((temperature - 10 - 25) * 286) >> 12) - 5214 3; 5215 else 5216 input_power_db = input_power_db + 5217 (((temperature - 10 - 25) * 286) >> 12); 5218 5219 wlc_lcnphy_rx_gain_override_enable(pi, 0); 5220 5221 return input_power_db; 5222 } 5223