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