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