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