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