root/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wlc_lcnphy_write_table
  2. wlc_lcnphy_read_table
  3. wlc_lcnphy_common_read_table
  4. wlc_lcnphy_common_write_table
  5. wlc_lcnphy_qdiv_roundup
  6. wlc_lcnphy_calc_floor
  7. wlc_lcnphy_get_tx_gain
  8. wlc_lcnphy_set_dac_gain
  9. wlc_lcnphy_set_tx_gain_override
  10. wlc_lcnphy_rx_gain_override_enable
  11. wlc_lcnphy_set_rx_gain_by_distribution
  12. wlc_lcnphy_set_trsw_override
  13. wlc_lcnphy_clear_trsw_override
  14. wlc_lcnphy_set_rx_iq_comp
  15. wlc_lcnphy_rx_iq_est
  16. wlc_lcnphy_calc_rx_iq_comp
  17. wlc_lcnphy_measure_digital_power
  18. wlc_lcnphy_rx_iq_cal_gain
  19. wlc_lcnphy_rx_iq_cal
  20. wlc_lcnphy_get_current_tx_pwr_idx
  21. wlc_lcnphy_crsuprs
  22. wlc_lcnphy_toggle_afe_pwdn
  23. wlc_lcnphy_txrx_spur_avoidance_mode
  24. wlc_lcnphy_set_chanspec_tweaks
  25. wlc_lcnphy_radio_2064_channel_tune_4313
  26. wlc_lcnphy_load_tx_iir_filter
  27. wlc_lcnphy_get_pa_gain
  28. wlc_lcnphy_set_tx_gain
  29. wlc_lcnphy_get_bbmult
  30. wlc_lcnphy_set_bbmult
  31. wlc_lcnphy_clear_tx_power_offsets
  32. wlc_lcnphy_set_tssi_mux
  33. wlc_lcnphy_rfseq_tbl_adc_pwrup
  34. wlc_lcnphy_pwrctrl_rssiparams
  35. wlc_lcnphy_tssi_setup
  36. wlc_lcnphy_tx_pwr_update_npt
  37. wlc_lcnphy_tssi2dbm
  38. wlc_lcnphy_txpower_reset_npt
  39. wlc_lcnphy_txpower_recalc_target
  40. wlc_lcnphy_set_tx_pwr_soft_ctrl
  41. wlc_lcnphy_tempcompensated_txpwrctrl
  42. wlc_lcnphy_set_tx_pwr_ctrl_mode
  43. wlc_lcnphy_set_tx_pwr_ctrl
  44. wlc_lcnphy_tx_iqlo_loopback
  45. wlc_lcnphy_iqcal_wait
  46. wlc_lcnphy_tx_iqlo_loopback_cleanup
  47. wlc_lcnphy_tx_iqlo_cal
  48. wlc_lcnphy_idle_tssi_est
  49. wlc_lcnphy_vbat_temp_sense_setup
  50. wlc_lcnphy_tx_pwr_ctrl_init
  51. wlc_lcnphy_set_pa_gain
  52. wlc_lcnphy_get_radio_loft
  53. wlc_lcnphy_set_tx_iqcc
  54. wlc_lcnphy_set_tx_locc
  55. wlc_lcnphy_set_tx_pwr_by_index
  56. wlc_lcnphy_clear_papd_comptable
  57. wlc_lcnphy_tx_pu
  58. wlc_lcnphy_run_samples
  59. wlc_lcnphy_deaf_mode
  60. wlc_lcnphy_start_tx_tone
  61. wlc_lcnphy_stop_tx_tone
  62. wlc_lcnphy_set_cc
  63. wlc_lcnphy_get_cc
  64. wlc_lcnphy_samp_cap
  65. wlc_lcnphy_a1
  66. wlc_lcnphy_get_tx_iqcc
  67. wlc_lcnphy_tx_iqlo_soft_cal_full
  68. wlc_lcnphy_get_tx_locc
  69. wlc_lcnphy_txpwrtbl_iqlo_cal
  70. wlc_lcnphy_tempsense_new
  71. wlc_lcnphy_tempsense
  72. wlc_lcnphy_tempsense_degree
  73. wlc_lcnphy_vbatsense
  74. wlc_lcnphy_afe_clk_init
  75. wlc_lcnphy_temp_adj
  76. wlc_lcnphy_glacial_timer_based_cal
  77. wlc_lcnphy_periodic_cal
  78. wlc_lcnphy_calib_modes
  79. wlc_lcnphy_get_tssi
  80. wlc_phy_cal_init_lcnphy
  81. wlc_lcnphy_tx_power_adjustment
  82. wlc_lcnphy_load_tx_gain_table
  83. wlc_lcnphy_load_rfpower
  84. wlc_lcnphy_bu_tweaks
  85. wlc_lcnphy_rcal
  86. wlc_lcnphy_rc_cal
  87. wlc_radio_2064_init
  88. wlc_lcnphy_radio_init
  89. wlc_lcnphy_tbl_init
  90. wlc_lcnphy_rev0_baseband_init
  91. wlc_lcnphy_rev2_baseband_init
  92. wlc_lcnphy_agc_temp_init
  93. wlc_lcnphy_baseband_init
  94. wlc_phy_init_lcnphy
  95. wlc_phy_txpwr_srom_read_lcnphy
  96. wlc_2064_vco_cal
  97. wlc_phy_tpc_isenabled_lcnphy
  98. wlc_phy_txpower_recalc_target_lcnphy
  99. wlc_phy_chanspec_set_lcnphy
  100. wlc_phy_detach_lcnphy
  101. wlc_phy_attach_lcnphy
  102. wlc_lcnphy_set_rx_gain
  103. wlc_lcnphy_get_receive_power
  104. wlc_lcnphy_rx_signal_power

   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 }

/* [<][>][^][v][top][bottom][index][help] */