Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / brcm80211 / brcmsmac / phy / phy_lcn.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/delay.h>
19 #include <linux/cordic.h>
20
21 #include <pmu.h>
22 #include <d11.h>
23 #include <phy_shim.h>
24 #include "phy_qmath.h"
25 #include "phy_hal.h"
26 #include "phy_radio.h"
27 #include "phytbl_lcn.h"
28 #include "phy_lcn.h"
29
30 #define PLL_2064_NDIV           90
31 #define PLL_2064_LOW_END_VCO    3000
32 #define PLL_2064_LOW_END_KVCO   27
33 #define PLL_2064_HIGH_END_VCO   4200
34 #define PLL_2064_HIGH_END_KVCO  68
35 #define PLL_2064_LOOP_BW_DOUBLER        200
36 #define PLL_2064_D30_DOUBLER            10500
37 #define PLL_2064_LOOP_BW        260
38 #define PLL_2064_D30            8000
39 #define PLL_2064_CAL_REF_TO     8
40 #define PLL_2064_MHZ            1000000
41 #define PLL_2064_OPEN_LOOP_DELAY        5
42
43 #define TEMPSENSE                       1
44 #define VBATSENSE           2
45
46 #define NOISE_IF_UPD_CHK_INTERVAL       1
47 #define NOISE_IF_UPD_RST_INTERVAL       60
48 #define NOISE_IF_UPD_THRESHOLD_CNT      1
49 #define NOISE_IF_UPD_TRHRESHOLD 50
50 #define NOISE_IF_UPD_TIMEOUT            1000
51 #define NOISE_IF_OFF                    0
52 #define NOISE_IF_CHK                    1
53 #define NOISE_IF_ON                     2
54
55 #define PAPD_BLANKING_PROFILE           3
56 #define PAPD2LUT                        0
57 #define PAPD_CORR_NORM                  0
58 #define PAPD_BLANKING_THRESHOLD         0
59 #define PAPD_STOP_AFTER_LAST_UPDATE     0
60
61 #define LCN_TARGET_PWR  60
62
63 #define LCN_VBAT_OFFSET_433X 34649679
64 #define LCN_VBAT_SLOPE_433X  8258032
65
66 #define LCN_VBAT_SCALE_NOM  53
67 #define LCN_VBAT_SCALE_DEN  432
68
69 #define LCN_TEMPSENSE_OFFSET  80812
70 #define LCN_TEMPSENSE_DEN  2647
71
72 #define LCN_BW_LMT      200
73 #define LCN_CUR_LMT     1250
74 #define LCN_MULT        1
75 #define LCN_VCO_DIV     30
76 #define LCN_OFFSET      680
77 #define LCN_FACT        490
78 #define LCN_CUR_DIV     2640
79
80 #define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
81         (0 + 8)
82 #define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
83         (0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
84
85 #define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
86         (0 + 8)
87 #define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
88         (0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
89
90 #define wlc_lcnphy_enable_tx_gain_override(pi) \
91         wlc_lcnphy_set_tx_gain_override(pi, true)
92 #define wlc_lcnphy_disable_tx_gain_override(pi) \
93         wlc_lcnphy_set_tx_gain_override(pi, false)
94
95 #define wlc_lcnphy_iqcal_active(pi)     \
96         (read_phy_reg((pi), 0x451) & \
97          ((0x1 << 15) | (0x1 << 14)))
98
99 #define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
100 #define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
101         (pi->temppwrctrl_capable)
102 #define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
103         (pi->hwpwrctrl_capable)
104
105 #define SWCTRL_BT_TX            0x18
106 #define SWCTRL_OVR_DISABLE      0x40
107
108 #define AFE_CLK_INIT_MODE_TXRX2X        1
109 #define AFE_CLK_INIT_MODE_PAPD          0
110
111 #define LCNPHY_TBL_ID_IQLOCAL                   0x00
112
113 #define LCNPHY_TBL_ID_RFSEQ         0x08
114 #define LCNPHY_TBL_ID_GAIN_IDX          0x0d
115 #define LCNPHY_TBL_ID_SW_CTRL                   0x0f
116 #define LCNPHY_TBL_ID_GAIN_TBL          0x12
117 #define LCNPHY_TBL_ID_SPUR                      0x14
118 #define LCNPHY_TBL_ID_SAMPLEPLAY                0x15
119 #define LCNPHY_TBL_ID_SAMPLEPLAY1               0x16
120
121 #define LCNPHY_TX_PWR_CTRL_RATE_OFFSET  832
122 #define LCNPHY_TX_PWR_CTRL_MAC_OFFSET   128
123 #define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET  192
124 #define LCNPHY_TX_PWR_CTRL_IQ_OFFSET            320
125 #define LCNPHY_TX_PWR_CTRL_LO_OFFSET            448
126 #define LCNPHY_TX_PWR_CTRL_PWR_OFFSET           576
127
128 #define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313  140
129
130 #define LCNPHY_TX_PWR_CTRL_START_NPT            1
131 #define LCNPHY_TX_PWR_CTRL_MAX_NPT                      7
132
133 #define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
134
135 #define LCNPHY_ACI_DETECT_START      1
136 #define LCNPHY_ACI_DETECT_PROGRESS   2
137 #define LCNPHY_ACI_DETECT_STOP       3
138
139 #define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
140 #define LCNPHY_ACI_GLITCH_TRSH 2000
141 #define LCNPHY_ACI_TMOUT 250
142 #define LCNPHY_ACI_DETECT_TIMEOUT  2
143 #define LCNPHY_ACI_START_DELAY 0
144
145 #define wlc_lcnphy_tx_gain_override_enabled(pi) \
146         (0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
147
148 #define wlc_lcnphy_total_tx_frames(pi) \
149         wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + \
150                             offsetof(struct macstat, txallfrm))
151
152 struct lcnphy_txgains {
153         u16 gm_gain;
154         u16 pga_gain;
155         u16 pad_gain;
156         u16 dac_gain;
157 };
158
159 enum lcnphy_cal_mode {
160         LCNPHY_CAL_FULL,
161         LCNPHY_CAL_RECAL,
162         LCNPHY_CAL_CURRECAL,
163         LCNPHY_CAL_DIGCAL,
164         LCNPHY_CAL_GCTRL
165 };
166
167 struct lcnphy_rx_iqcomp {
168         u8 chan;
169         s16 a;
170         s16 b;
171 };
172
173 struct lcnphy_spb_tone {
174         s16 re;
175         s16 im;
176 };
177
178 struct lcnphy_unsign16_struct {
179         u16 re;
180         u16 im;
181 };
182
183 struct lcnphy_iq_est {
184         u32 iq_prod;
185         u32 i_pwr;
186         u32 q_pwr;
187 };
188
189 struct lcnphy_sfo_cfg {
190         u16 ptcentreTs20;
191         u16 ptcentreFactor;
192 };
193
194 enum lcnphy_papd_cal_type {
195         LCNPHY_PAPD_CAL_CW,
196         LCNPHY_PAPD_CAL_OFDM
197 };
198
199 typedef u16 iqcal_gain_params_lcnphy[9];
200
201 static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
202         {0, 0, 0, 0, 0, 0, 0, 0, 0},
203 };
204
205 static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
206         tbl_iqcal_gainparams_lcnphy_2G,
207 };
208
209 static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
210         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 = false;
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 = false;
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 = false;
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 = true;
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 = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
2817                          MCTL_EN_MAC));
2818         if (!suspend)
2819                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2820         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2821
2822         tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
2823         wlc_lcnphy_get_tx_gain(pi, &old_gains);
2824
2825         wlc_lcnphy_enable_tx_gain_override(pi);
2826         wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
2827         write_radio_reg(pi, RADIO_2064_REG112, 0x6);
2828         mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
2829         mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
2830         mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
2831         wlc_lcnphy_tssi_setup(pi);
2832         wlc_phy_do_dummy_tx(pi, true, OFF);
2833         idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
2834                     >> 0);
2835
2836         idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
2837                         >> 0);
2838
2839         if (idleTssi0_2C >= 256)
2840                 idleTssi0_OB = idleTssi0_2C - 256;
2841         else
2842                 idleTssi0_OB = idleTssi0_2C + 256;
2843
2844         idleTssi0_regvalue_OB = idleTssi0_OB;
2845         if (idleTssi0_regvalue_OB >= 256)
2846                 idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
2847         else
2848                 idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
2849         mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
2850
2851         mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
2852
2853         wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
2854         wlc_lcnphy_set_tx_gain(pi, &old_gains);
2855         wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
2856
2857         write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
2858         mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
2859         mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
2860         mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
2861         mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
2862         if (!suspend)
2863                 wlapi_enable_mac(pi->sh->physhim);
2864 }
2865
2866 static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
2867 {
2868         bool suspend;
2869         u16 save_txpwrCtrlEn;
2870         u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
2871         u16 auxpga_vmid;
2872         struct phytbl_info tab;
2873         u32 val;
2874         u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
2875            save_reg112;
2876         u16 values_to_save[14];
2877         s8 index;
2878         int i;
2879         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2880         udelay(999);
2881
2882         save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
2883         save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
2884         save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
2885         save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
2886         save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
2887         save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
2888
2889         for (i = 0; i < 14; i++)
2890                 values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
2891         suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
2892                          MCTL_EN_MAC));
2893         if (!suspend)
2894                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2895         save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
2896
2897         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2898         index = pi_lcn->lcnphy_current_index;
2899         wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
2900         mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
2901         mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
2902         mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
2903         mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
2904
2905         mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
2906
2907         mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
2908
2909         mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
2910
2911         mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
2912
2913         mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
2914
2915         mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
2916
2917         mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
2918
2919         mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
2920
2921         mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
2922
2923         mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
2924
2925         mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
2926
2927         mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
2928
2929         mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
2930
2931         mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
2932
2933         mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
2934
2935         mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
2936
2937         mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
2938
2939         write_radio_reg(pi, RADIO_2064_REG025, 0xC);
2940
2941         mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
2942
2943         mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
2944
2945         mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
2946
2947         mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
2948
2949         val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
2950         tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
2951         tab.tbl_width = 16;
2952         tab.tbl_len = 1;
2953         tab.tbl_ptr = &val;
2954         tab.tbl_offset = 6;
2955         wlc_lcnphy_write_table(pi, &tab);
2956         if (mode == TEMPSENSE) {
2957                 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
2958
2959                 mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
2960
2961                 auxpga_vmidcourse = 8;
2962                 auxpga_vmidfine = 0x4;
2963                 auxpga_gain = 2;
2964                 mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
2965         } else {
2966                 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
2967
2968                 mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
2969
2970                 auxpga_vmidcourse = 7;
2971                 auxpga_vmidfine = 0xa;
2972                 auxpga_gain = 2;
2973         }
2974         auxpga_vmid =
2975                 (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
2976         mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
2977
2978         mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
2979
2980         mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
2981
2982         mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
2983
2984         mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
2985
2986         write_radio_reg(pi, RADIO_2064_REG112, 0x6);
2987
2988         wlc_phy_do_dummy_tx(pi, true, OFF);
2989         if (!tempsense_done(pi))
2990                 udelay(10);
2991
2992         write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
2993         write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
2994         write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
2995         write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
2996         write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
2997         write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
2998         for (i = 0; i < 14; i++)
2999                 write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
3000         wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
3001
3002         write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
3003         if (!suspend)
3004                 wlapi_enable_mac(pi->sh->physhim);
3005         udelay(999);
3006 }
3007
3008 static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
3009 {
3010         struct lcnphy_txgains tx_gains;
3011         u8 bbmult;
3012         struct phytbl_info tab;
3013         s32 a1, b0, b1;
3014         s32 tssi, pwr, maxtargetpwr, mintargetpwr;
3015         bool suspend;
3016         struct brcms_phy *pi = (struct brcms_phy *) ppi;
3017
3018         suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
3019                          MCTL_EN_MAC));
3020         if (!suspend)
3021                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
3022
3023         if (!pi->hwpwrctrl_capable) {
3024                 if (CHSPEC_IS2G(pi->radio_chanspec)) {
3025                         tx_gains.gm_gain = 4;
3026                         tx_gains.pga_gain = 12;
3027                         tx_gains.pad_gain = 12;
3028                         tx_gains.dac_gain = 0;
3029
3030                         bbmult = 150;
3031                 } else {
3032                         tx_gains.gm_gain = 7;
3033                         tx_gains.pga_gain = 15;
3034                         tx_gains.pad_gain = 14;
3035                         tx_gains.dac_gain = 0;
3036
3037                         bbmult = 150;
3038                 }
3039                 wlc_lcnphy_set_tx_gain(pi, &tx_gains);
3040                 wlc_lcnphy_set_bbmult(pi, bbmult);
3041                 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
3042         } else {
3043
3044                 wlc_lcnphy_idle_tssi_est(ppi);
3045
3046                 wlc_lcnphy_clear_tx_power_offsets(pi);
3047
3048                 b0 = pi->txpa_2g[0];
3049                 b1 = pi->txpa_2g[1];
3050                 a1 = pi->txpa_2g[2];
3051                 maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
3052                 mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
3053
3054                 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
3055                 tab.tbl_width = 32;
3056                 tab.tbl_ptr = &pwr;
3057                 tab.tbl_len = 1;
3058                 tab.tbl_offset = 0;
3059                 for (tssi = 0; tssi < 128; tssi++) {
3060                         pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
3061
3062                         pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
3063                         wlc_lcnphy_write_table(pi, &tab);
3064                         tab.tbl_offset++;
3065                 }
3066
3067                 mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
3068
3069                 write_phy_reg(pi, 0x4a8, 10);
3070
3071                 wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
3072
3073                 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
3074         }
3075         if (!suspend)
3076                 wlapi_enable_mac(pi->sh->physhim);
3077 }
3078
3079 static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi)
3080 {
3081         u16 m0m1;
3082         struct phytbl_info tab;
3083
3084         tab.tbl_ptr = &m0m1;
3085         tab.tbl_len = 1;
3086         tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
3087         tab.tbl_offset = 87;
3088         tab.tbl_width = 16;
3089         wlc_lcnphy_read_table(pi, &tab);
3090
3091         return (u8) ((m0m1 & 0xff00) >> 8);
3092 }
3093
3094 static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain)
3095 {
3096         mod_phy_reg(pi, 0x4fb,
3097                     LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
3098                     gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
3099         mod_phy_reg(pi, 0x4fd,
3100                     LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
3101                     gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
3102 }
3103
3104 void
3105 wlc_lcnphy_get_radio_loft(struct brcms_phy *pi,
3106                           u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
3107 {
3108         *ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
3109         *eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
3110         *fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
3111         *fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
3112 }
3113
3114 void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b)
3115 {
3116         struct phytbl_info tab;
3117         u16 iqcc[2];
3118
3119         iqcc[0] = a;
3120         iqcc[1] = b;
3121
3122         tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
3123         tab.tbl_width = 16;
3124         tab.tbl_ptr = iqcc;
3125         tab.tbl_len = 2;
3126         tab.tbl_offset = 80;
3127         wlc_lcnphy_write_table(pi, &tab);
3128 }
3129
3130 void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq)
3131 {
3132         struct phytbl_info tab;
3133
3134         tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
3135         tab.tbl_width = 16;
3136         tab.tbl_ptr = &didq;
3137         tab.tbl_len = 1;
3138         tab.tbl_offset = 85;
3139         wlc_lcnphy_write_table(pi, &tab);
3140 }
3141
3142 void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index)
3143 {
3144         struct phytbl_info tab;
3145         u16 a, b;
3146         u8 bb_mult;
3147         u32 bbmultiqcomp, txgain, locoeffs, rfpower;
3148         struct lcnphy_txgains gains;
3149         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3150
3151         pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
3152         pi_lcn->lcnphy_current_index = (u8) index;
3153
3154         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
3155         tab.tbl_width = 32;
3156         tab.tbl_len = 1;
3157
3158         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
3159
3160         tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
3161         tab.tbl_ptr = &bbmultiqcomp;
3162         wlc_lcnphy_read_table(pi, &tab);
3163
3164         tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
3165         tab.tbl_width = 32;
3166         tab.tbl_ptr = &txgain;
3167         wlc_lcnphy_read_table(pi, &tab);
3168
3169         gains.gm_gain = (u16) (txgain & 0xff);
3170         gains.pga_gain = (u16) (txgain >> 8) & 0xff;
3171         gains.pad_gain = (u16) (txgain >> 16) & 0xff;
3172         gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
3173         wlc_lcnphy_set_tx_gain(pi, &gains);
3174         wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
3175
3176         bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
3177         wlc_lcnphy_set_bbmult(pi, bb_mult);
3178
3179         wlc_lcnphy_enable_tx_gain_override(pi);
3180
3181         if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
3182
3183                 a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
3184                 b = (u16) (bbmultiqcomp & 0x3ff);
3185                 wlc_lcnphy_set_tx_iqcc(pi, a, b);
3186
3187                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
3188                 tab.tbl_ptr = &locoeffs;
3189                 wlc_lcnphy_read_table(pi, &tab);
3190
3191                 wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
3192
3193                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
3194                 tab.tbl_ptr = &rfpower;
3195                 wlc_lcnphy_read_table(pi, &tab);
3196                 mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
3197
3198         }
3199 }
3200
3201 static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi)
3202 {
3203         u32 j;
3204         struct phytbl_info tab;
3205         u32 temp_offset[128];
3206         tab.tbl_ptr = temp_offset;
3207         tab.tbl_len = 128;
3208         tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
3209         tab.tbl_width = 32;
3210         tab.tbl_offset = 0;
3211
3212         memset(temp_offset, 0, sizeof(temp_offset));
3213         for (j = 1; j < 128; j += 2)
3214                 temp_offset[j] = 0x80000;
3215
3216         wlc_lcnphy_write_table(pi, &tab);
3217         return;
3218 }
3219
3220 void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable)
3221 {
3222         if (!bEnable) {
3223
3224                 and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
3225
3226                 mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
3227
3228                 and_phy_reg(pi, 0x44c,
3229                             ~(u16) ((0x1 << 3) |
3230                                     (0x1 << 5) |
3231                                     (0x1 << 12) |
3232                                     (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
3233
3234                 and_phy_reg(pi, 0x44d,
3235                             ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
3236                 mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
3237
3238                 mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
3239
3240                 and_phy_reg(pi, 0x4f9,
3241                             ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
3242
3243                 and_phy_reg(pi, 0x4fa,
3244                             ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
3245         } else {
3246
3247                 mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
3248                 mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
3249
3250                 mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
3251                 mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
3252
3253                 mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
3254                 mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
3255
3256                 wlc_lcnphy_set_trsw_override(pi, true, false);
3257
3258                 mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
3259                 mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
3260
3261                 if (CHSPEC_IS2G(pi->radio_chanspec)) {
3262
3263                         mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
3264                         mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
3265
3266                         mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
3267                         mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
3268
3269                         mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
3270                         mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
3271
3272                         mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
3273                         mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
3274
3275                         mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
3276                         mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
3277                 } else {
3278
3279                         mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
3280                         mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
3281
3282                         mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
3283                         mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
3284
3285                         mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
3286                         mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
3287
3288                         mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
3289                         mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
3290
3291                         mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
3292                         mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
3293                 }
3294         }
3295 }
3296
3297 static void
3298 wlc_lcnphy_run_samples(struct brcms_phy *pi,
3299                        u16 num_samps,
3300                        u16 num_loops, u16 wait, bool iqcalmode)
3301 {
3302
3303         or_phy_reg(pi, 0x6da, 0x8080);
3304
3305         mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
3306         if (num_loops != 0xffff)
3307                 num_loops--;
3308         mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
3309
3310         mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
3311
3312         if (iqcalmode) {
3313
3314                 and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
3315                 or_phy_reg(pi, 0x453, (0x1 << 15));
3316         } else {
3317                 write_phy_reg(pi, 0x63f, 1);
3318                 wlc_lcnphy_tx_pu(pi, 1);
3319         }
3320
3321         or_radio_reg(pi, RADIO_2064_REG112, 0x6);
3322 }
3323
3324 void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode)
3325 {
3326
3327         u8 phybw40;
3328         phybw40 = CHSPEC_IS40(pi->radio_chanspec);
3329
3330         if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
3331                 mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
3332                 mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
3333         } else {
3334                 mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
3335                 mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
3336         }
3337
3338         if (phybw40 == 0) {
3339                 mod_phy_reg((pi), 0x410,
3340                             (0x1 << 6) |
3341                             (0x1 << 5),
3342                             ((CHSPEC_IS2G(
3343                                       pi->radio_chanspec)) ? (!mode) : 0) <<
3344                             6 | (!mode) << 5);
3345                 mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
3346         }
3347 }
3348
3349 void
3350 wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
3351                          bool iqcalmode)
3352 {
3353         u8 phy_bw;
3354         u16 num_samps, t, k;
3355         u32 bw;
3356         s32 theta = 0, rot = 0;
3357         struct cordic_iq tone_samp;
3358         u32 data_buf[64];
3359         u16 i_samp, q_samp;
3360         struct phytbl_info tab;
3361         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3362
3363         pi->phy_tx_tone_freq = f_kHz;
3364
3365         wlc_lcnphy_deaf_mode(pi, true);
3366
3367         phy_bw = 40;
3368         if (pi_lcn->lcnphy_spurmod) {
3369                 write_phy_reg(pi, 0x942, 0x2);
3370                 write_phy_reg(pi, 0x93b, 0x0);
3371                 write_phy_reg(pi, 0x93c, 0x0);
3372                 wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
3373         }
3374
3375         if (f_kHz) {
3376                 k = 1;
3377                 do {
3378                         bw = phy_bw * 1000 * k;
3379                         num_samps = bw / abs(f_kHz);
3380                         k++;
3381                 } while ((num_samps * (u32) (abs(f_kHz))) != bw);
3382         } else
3383                 num_samps = 2;
3384
3385         rot = ((f_kHz * 36) / phy_bw) / 100;
3386         theta = 0;
3387
3388         for (t = 0; t < num_samps; t++) {
3389
3390                 tone_samp = cordic_calc_iq(theta);
3391
3392                 theta += rot;
3393
3394                 i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
3395                 q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
3396                 data_buf[t] = (i_samp << 10) | q_samp;
3397         }
3398
3399         mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
3400
3401         mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
3402
3403         tab.tbl_ptr = data_buf;
3404         tab.tbl_len = num_samps;
3405         tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
3406         tab.tbl_offset = 0;
3407         tab.tbl_width = 32;
3408         wlc_lcnphy_write_table(pi, &tab);
3409
3410         wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
3411 }
3412
3413 void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi)
3414 {
3415         s16 playback_status;
3416         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3417
3418         pi->phy_tx_tone_freq = 0;
3419         if (pi_lcn->lcnphy_spurmod) {
3420                 write_phy_reg(pi, 0x942, 0x7);
3421                 write_phy_reg(pi, 0x93b, 0x2017);
3422                 write_phy_reg(pi, 0x93c, 0x27c5);
3423                 wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
3424         }
3425
3426         playback_status = read_phy_reg(pi, 0x644);
3427         if (playback_status & (0x1 << 0)) {
3428                 wlc_lcnphy_tx_pu(pi, 0);
3429                 mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
3430         } else if (playback_status & (0x1 << 1))
3431                 mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
3432
3433         mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
3434
3435         mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
3436
3437         mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
3438
3439         and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
3440
3441         wlc_lcnphy_deaf_mode(pi, false);
3442 }
3443
3444 static void
3445 wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y)
3446 {
3447         u16 di0dq0;
3448         u16 x, y, data_rf;
3449         int k;
3450         switch (cal_type) {
3451         case 0:
3452                 wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
3453                 break;
3454         case 2:
3455                 di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
3456                 wlc_lcnphy_set_tx_locc(pi, di0dq0);
3457                 break;
3458         case 3:
3459                 k = wlc_lcnphy_calc_floor(coeff_x, 0);
3460                 y = 8 + k;
3461                 k = wlc_lcnphy_calc_floor(coeff_x, 1);
3462                 x = 8 - k;
3463                 data_rf = (x * 16 + y);
3464                 write_radio_reg(pi, RADIO_2064_REG089, data_rf);
3465                 k = wlc_lcnphy_calc_floor(coeff_y, 0);
3466                 y = 8 + k;
3467                 k = wlc_lcnphy_calc_floor(coeff_y, 1);
3468                 x = 8 - k;
3469                 data_rf = (x * 16 + y);
3470                 write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
3471                 break;
3472         case 4:
3473                 k = wlc_lcnphy_calc_floor(coeff_x, 0);
3474                 y = 8 + k;
3475                 k = wlc_lcnphy_calc_floor(coeff_x, 1);
3476                 x = 8 - k;
3477                 data_rf = (x * 16 + y);
3478                 write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
3479                 k = wlc_lcnphy_calc_floor(coeff_y, 0);
3480                 y = 8 + k;
3481                 k = wlc_lcnphy_calc_floor(coeff_y, 1);
3482                 x = 8 - k;
3483                 data_rf = (x * 16 + y);
3484                 write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
3485                 break;
3486         }
3487 }
3488
3489 static struct lcnphy_unsign16_struct
3490 wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type)
3491 {
3492         u16 a, b, didq;
3493         u8 di0, dq0, ei, eq, fi, fq;
3494         struct lcnphy_unsign16_struct cc;
3495         cc.re = 0;
3496         cc.im = 0;
3497         switch (cal_type) {
3498         case 0:
3499                 wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
3500                 cc.re = a;
3501                 cc.im = b;
3502                 break;
3503         case 2:
3504                 didq = wlc_lcnphy_get_tx_locc(pi);
3505                 di0 = (((didq & 0xff00) << 16) >> 24);
3506                 dq0 = (((didq & 0x00ff) << 24) >> 24);
3507                 cc.re = (u16) di0;
3508                 cc.im = (u16) dq0;
3509                 break;
3510         case 3:
3511                 wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
3512                 cc.re = (u16) ei;
3513                 cc.im = (u16) eq;
3514                 break;
3515         case 4:
3516                 wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
3517                 cc.re = (u16) fi;
3518                 cc.im = (u16) fq;
3519                 break;
3520         }
3521         return cc;
3522 }
3523
3524 static void
3525 wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
3526                     s16 *ptr, int mode)
3527 {
3528         u32 curval1, curval2, stpptr, curptr, strptr, val;
3529         u16 sslpnCalibClkEnCtrl, timer;
3530         u16 old_sslpnCalibClkEnCtrl;
3531         s16 imag, real;
3532         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3533
3534         timer = 0;
3535         old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
3536
3537         curval1 = bcma_read16(pi->d11core, D11REGOFFS(psm_corectlsts));
3538         ptr[130] = 0;
3539         bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts),
3540                      ((1 << 6) | curval1));
3541
3542         bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_strptr), 0x7E00);
3543         bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_stpptr), 0x8000);
3544         udelay(20);
3545         curval2 = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
3546         bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
3547                      curval2 | 0x30);
3548
3549         write_phy_reg(pi, 0x555, 0x0);
3550         write_phy_reg(pi, 0x5a6, 0x5);
3551
3552         write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
3553         write_phy_reg(pi, 0x5cf, 3);
3554         write_phy_reg(pi, 0x5a5, 0x3);
3555         write_phy_reg(pi, 0x583, 0x0);
3556         write_phy_reg(pi, 0x584, 0x0);
3557         write_phy_reg(pi, 0x585, 0x0fff);
3558         write_phy_reg(pi, 0x586, 0x0000);
3559
3560         write_phy_reg(pi, 0x580, 0x4501);
3561
3562         sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
3563         write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
3564         stpptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_stpptr));
3565         curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
3566         do {
3567                 udelay(10);
3568                 curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
3569                 timer++;
3570         } while ((curptr != stpptr) && (timer < 500));
3571
3572         bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), 0x2);
3573         strptr = 0x7E00;
3574         bcma_write32(pi->d11core, D11REGOFFS(tplatewrptr), strptr);
3575         while (strptr < 0x8000) {
3576                 val = bcma_read32(pi->d11core, D11REGOFFS(tplatewrdata));
3577                 imag = ((val >> 16) & 0x3ff);
3578                 real = ((val) & 0x3ff);
3579                 if (imag > 511)
3580                         imag -= 1024;
3581
3582                 if (real > 511)
3583                         real -= 1024;
3584
3585                 if (pi_lcn->lcnphy_iqcal_swp_dis)
3586                         ptr[(strptr - 0x7E00) / 4] = real;
3587                 else
3588                         ptr[(strptr - 0x7E00) / 4] = imag;
3589
3590                 if (clip_detect_algo) {
3591                         if (imag > thresh || imag < -thresh) {
3592                                 strptr = 0x8000;
3593                                 ptr[130] = 1;
3594                         }
3595                 }
3596
3597                 strptr += 4;
3598         }
3599
3600         write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
3601         bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), curval2);
3602         bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts), curval1);
3603 }
3604
3605 static void
3606 wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels,
3607               int step_size_lg2)
3608 {
3609         const struct lcnphy_spb_tone *phy_c1;
3610         struct lcnphy_spb_tone phy_c2;
3611         struct lcnphy_unsign16_struct phy_c3;
3612         int phy_c4, phy_c5, k, l, j, phy_c6;
3613         u16 phy_c7, phy_c8, phy_c9;
3614         s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
3615         s16 *ptr, phy_c17;
3616         s32 phy_c18, phy_c19;
3617         u32 phy_c20, phy_c21;
3618         bool phy_c22, phy_c23, phy_c24, phy_c25;
3619         u16 phy_c26, phy_c27;
3620         u16 phy_c28, phy_c29, phy_c30;
3621         u16 phy_c31;
3622         u16 *phy_c32;
3623         phy_c21 = 0;
3624         phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
3625         ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
3626         if (NULL == ptr)
3627                 return;
3628
3629         phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
3630         if (NULL == phy_c32) {
3631                 kfree(ptr);
3632                 return;
3633         }
3634         phy_c26 = read_phy_reg(pi, 0x6da);
3635         phy_c27 = read_phy_reg(pi, 0x6db);
3636         phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
3637         write_phy_reg(pi, 0x93d, 0xC0);
3638
3639         wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
3640         write_phy_reg(pi, 0x6da, 0xffff);
3641         or_phy_reg(pi, 0x6db, 0x3);
3642
3643         wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
3644         udelay(500);
3645         phy_c28 = read_phy_reg(pi, 0x938);
3646         phy_c29 = read_phy_reg(pi, 0x4d7);
3647         phy_c30 = read_phy_reg(pi, 0x4d8);
3648         or_phy_reg(pi, 0x938, 0x1 << 2);
3649         or_phy_reg(pi, 0x4d7, 0x1 << 2);
3650         or_phy_reg(pi, 0x4d7, 0x1 << 3);
3651         mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
3652         or_phy_reg(pi, 0x4d8, 1 << 0);
3653         or_phy_reg(pi, 0x4d8, 1 << 1);
3654         mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
3655         mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
3656         phy_c1 = &lcnphy_spb_tone_3750[0];
3657         phy_c4 = 32;
3658
3659         if (num_levels == 0) {
3660                 if (cal_type != 0)
3661                         num_levels = 4;
3662                 else
3663                         num_levels = 9;
3664         }
3665         if (step_size_lg2 == 0) {
3666                 if (cal_type != 0)
3667                         step_size_lg2 = 3;
3668                 else
3669                         step_size_lg2 = 8;
3670         }
3671
3672         phy_c7 = (1 << step_size_lg2);
3673         phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
3674         phy_c15 = (s16) phy_c3.re;
3675         phy_c16 = (s16) phy_c3.im;
3676         if (cal_type == 2) {
3677                 if (phy_c3.re > 127)
3678                         phy_c15 = phy_c3.re - 256;
3679                 if (phy_c3.im > 127)
3680                         phy_c16 = phy_c3.im - 256;
3681         }
3682         wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
3683         udelay(20);
3684         for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
3685                 phy_c23 = true;
3686                 phy_c22 = false;
3687                 switch (cal_type) {
3688                 case 0:
3689                         phy_c10 = 511;
3690                         break;
3691                 case 2:
3692                         phy_c10 = 127;
3693                         break;
3694                 case 3:
3695                         phy_c10 = 15;
3696                         break;
3697                 case 4:
3698                         phy_c10 = 15;
3699                         break;
3700                 }
3701
3702                 phy_c9 = read_phy_reg(pi, 0x93d);
3703                 phy_c9 = 2 * phy_c9;
3704                 phy_c24 = false;
3705                 phy_c5 = 7;
3706                 phy_c25 = true;
3707                 while (1) {
3708                         write_radio_reg(pi, RADIO_2064_REG026,
3709                                         (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
3710                         udelay(50);
3711                         phy_c22 = false;
3712                         ptr[130] = 0;
3713                         wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
3714                         if (ptr[130] == 1)
3715                                 phy_c22 = true;
3716                         if (phy_c22)
3717                                 phy_c5 -= 1;
3718                         if ((phy_c22 != phy_c24) && (!phy_c25))
3719                                 break;
3720                         if (!phy_c22)
3721                                 phy_c5 += 1;
3722                         if (phy_c5 <= 0 || phy_c5 >= 7)
3723                                 break;
3724                         phy_c24 = phy_c22;
3725                         phy_c25 = false;
3726                 }
3727
3728                 if (phy_c5 < 0)
3729                         phy_c5 = 0;
3730                 else if (phy_c5 > 7)
3731                         phy_c5 = 7;
3732
3733                 for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
3734                         for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
3735                                 phy_c11 = phy_c15 + k;
3736                                 phy_c12 = phy_c16 + l;
3737
3738                                 if (phy_c11 < -phy_c10)
3739                                         phy_c11 = -phy_c10;
3740                                 else if (phy_c11 > phy_c10)
3741                                         phy_c11 = phy_c10;
3742                                 if (phy_c12 < -phy_c10)
3743                                         phy_c12 = -phy_c10;
3744                                 else if (phy_c12 > phy_c10)
3745                                         phy_c12 = phy_c10;
3746                                 wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
3747                                                   phy_c12);
3748                                 udelay(20);
3749                                 wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
3750
3751                                 phy_c18 = 0;
3752                                 phy_c19 = 0;
3753                                 for (j = 0; j < 128; j++) {
3754                                         if (cal_type != 0)
3755                                                 phy_c6 = j % phy_c4;
3756                                         else
3757                                                 phy_c6 = (2 * j) % phy_c4;
3758
3759                                         phy_c2.re = phy_c1[phy_c6].re;
3760                                         phy_c2.im = phy_c1[phy_c6].im;
3761                                         phy_c17 = ptr[j];
3762                                         phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
3763                                         phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
3764                                 }
3765
3766                                 phy_c18 = phy_c18 >> 10;
3767                                 phy_c19 = phy_c19 >> 10;
3768                                 phy_c20 = ((phy_c18 * phy_c18) +
3769                                            (phy_c19 * phy_c19));
3770
3771                                 if (phy_c23 || phy_c20 < phy_c21) {
3772                                         phy_c21 = phy_c20;
3773                                         phy_c13 = phy_c11;
3774                                         phy_c14 = phy_c12;
3775                                 }
3776                                 phy_c23 = false;
3777                         }
3778                 }
3779                 phy_c23 = true;
3780                 phy_c15 = phy_c13;
3781                 phy_c16 = phy_c14;
3782                 phy_c7 = phy_c7 >> 1;
3783                 wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
3784                 udelay(20);
3785         }
3786         goto cleanup;
3787 cleanup:
3788         wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
3789         wlc_lcnphy_stop_tx_tone(pi);
3790         write_phy_reg(pi, 0x6da, phy_c26);
3791         write_phy_reg(pi, 0x6db, phy_c27);
3792         write_phy_reg(pi, 0x938, phy_c28);
3793         write_phy_reg(pi, 0x4d7, phy_c29);
3794         write_phy_reg(pi, 0x4d8, phy_c30);
3795         write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
3796
3797         kfree(phy_c32);
3798         kfree(ptr);
3799 }
3800
3801 void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b)
3802 {
3803         u16 iqcc[2];
3804         struct phytbl_info tab;
3805
3806         tab.tbl_ptr = iqcc;
3807         tab.tbl_len = 2;
3808         tab.tbl_id = 0;
3809         tab.tbl_offset = 80;
3810         tab.tbl_width = 16;
3811         wlc_lcnphy_read_table(pi, &tab);
3812
3813         *a = iqcc[0];
3814         *b = iqcc[1];
3815 }
3816
3817 static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi)
3818 {
3819         struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
3820
3821         wlc_lcnphy_set_cc(pi, 0, 0, 0);
3822         wlc_lcnphy_set_cc(pi, 2, 0, 0);
3823         wlc_lcnphy_set_cc(pi, 3, 0, 0);
3824         wlc_lcnphy_set_cc(pi, 4, 0, 0);
3825
3826         wlc_lcnphy_a1(pi, 4, 0, 0);
3827         wlc_lcnphy_a1(pi, 3, 0, 0);
3828         wlc_lcnphy_a1(pi, 2, 3, 2);
3829         wlc_lcnphy_a1(pi, 0, 5, 8);
3830         wlc_lcnphy_a1(pi, 2, 2, 1);
3831         wlc_lcnphy_a1(pi, 0, 4, 3);
3832
3833         iqcc0 = wlc_lcnphy_get_cc(pi, 0);
3834         locc2 = wlc_lcnphy_get_cc(pi, 2);
3835         locc3 = wlc_lcnphy_get_cc(pi, 3);
3836         locc4 = wlc_lcnphy_get_cc(pi, 4);
3837 }
3838
3839 u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi)
3840 {
3841         struct phytbl_info tab;
3842         u16 didq;
3843
3844         tab.tbl_id = 0;
3845         tab.tbl_width = 16;
3846         tab.tbl_ptr = &didq;
3847         tab.tbl_len = 1;
3848         tab.tbl_offset = 85;
3849         wlc_lcnphy_read_table(pi, &tab);
3850
3851         return didq;
3852 }
3853
3854 static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
3855 {
3856
3857         struct lcnphy_txgains target_gains, old_gains;
3858         u8 save_bb_mult;
3859         u16 a, b, didq, save_pa_gain = 0;
3860         uint idx, SAVE_txpwrindex = 0xFF;
3861         u32 val;
3862         u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
3863         struct phytbl_info tab;
3864         u8 ei0, eq0, fi0, fq0;
3865         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3866
3867         wlc_lcnphy_get_tx_gain(pi, &old_gains);
3868         save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
3869
3870         save_bb_mult = wlc_lcnphy_get_bbmult(pi);
3871
3872         if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
3873                 SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
3874
3875         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
3876
3877         target_gains.gm_gain = 7;
3878         target_gains.pga_gain = 0;
3879         target_gains.pad_gain = 21;
3880         target_gains.dac_gain = 0;
3881         wlc_lcnphy_set_tx_gain(pi, &target_gains);
3882         wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
3883
3884         if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
3885
3886                 wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
3887
3888                 wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
3889                                        (pi_lcn->
3890                                         lcnphy_recal ? LCNPHY_CAL_RECAL :
3891                                         LCNPHY_CAL_FULL), false);
3892         } else {
3893                 wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
3894         }
3895
3896         wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
3897         if ((abs((s8) fi0) == 15) && (abs((s8) fq0) == 15)) {
3898                 if (CHSPEC_IS5G(pi->radio_chanspec)) {
3899                         target_gains.gm_gain = 255;
3900                         target_gains.pga_gain = 255;
3901                         target_gains.pad_gain = 0xf0;
3902                         target_gains.dac_gain = 0;
3903                 } else {
3904                         target_gains.gm_gain = 7;
3905                         target_gains.pga_gain = 45;
3906                         target_gains.pad_gain = 186;
3907                         target_gains.dac_gain = 0;
3908                 }
3909
3910                 if (LCNREV_IS(pi->pubpi.phy_rev, 1)
3911                     || pi_lcn->lcnphy_hw_iqcal_en) {
3912
3913                         target_gains.pga_gain = 0;
3914                         target_gains.pad_gain = 30;
3915                         wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
3916                         wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
3917                                                LCNPHY_CAL_FULL, false);
3918                 } else {
3919                         wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
3920                 }
3921         }
3922
3923         wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
3924
3925         didq = wlc_lcnphy_get_tx_locc(pi);
3926
3927         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
3928         tab.tbl_width = 32;
3929         tab.tbl_ptr = &val;
3930
3931         tab.tbl_len = 1;
3932         tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
3933
3934         for (idx = 0; idx < 128; idx++) {
3935                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
3936
3937                 wlc_lcnphy_read_table(pi, &tab);
3938                 val = (val & 0xfff00000) |
3939                       ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
3940                 wlc_lcnphy_write_table(pi, &tab);
3941
3942                 val = didq;
3943                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
3944                 wlc_lcnphy_write_table(pi, &tab);
3945         }
3946
3947         pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
3948         pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
3949         pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
3950         pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
3951         pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
3952         pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
3953         pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
3954
3955         wlc_lcnphy_set_bbmult(pi, save_bb_mult);
3956         wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
3957         wlc_lcnphy_set_tx_gain(pi, &old_gains);
3958
3959         if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
3960                 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
3961         else
3962                 wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
3963 }
3964
3965 s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode)
3966 {
3967         u16 tempsenseval1, tempsenseval2;
3968         s16 avg = 0;
3969         bool suspend = false;
3970
3971         if (mode == 1) {
3972                 suspend = (0 == (bcma_read32(pi->d11core,
3973                                              D11REGOFFS(maccontrol)) &
3974                                  MCTL_EN_MAC));
3975                 if (!suspend)
3976                         wlapi_suspend_mac_and_wait(pi->sh->physhim);
3977                 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
3978         }
3979         tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
3980         tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
3981
3982         if (tempsenseval1 > 255)
3983                 avg = (s16) (tempsenseval1 - 512);
3984         else
3985                 avg = (s16) tempsenseval1;
3986
3987         if (tempsenseval2 > 255)
3988                 avg += (s16) (tempsenseval2 - 512);
3989         else
3990                 avg += (s16) tempsenseval2;
3991
3992         avg /= 2;
3993
3994         if (mode == 1) {
3995
3996                 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
3997
3998                 udelay(100);
3999                 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
4000
4001                 if (!suspend)
4002                         wlapi_enable_mac(pi->sh->physhim);
4003         }
4004         return avg;
4005 }
4006
4007 u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode)
4008 {
4009         u16 tempsenseval1, tempsenseval2;
4010         s32 avg = 0;
4011         bool suspend = false;
4012         u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
4013         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4014
4015         if (mode == 1) {
4016                 suspend = (0 == (bcma_read32(pi->d11core,
4017                                              D11REGOFFS(maccontrol)) &
4018                                  MCTL_EN_MAC));
4019                 if (!suspend)
4020                         wlapi_suspend_mac_and_wait(pi->sh->physhim);
4021                 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
4022         }
4023         tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
4024         tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
4025
4026         if (tempsenseval1 > 255)
4027                 avg = (int)(tempsenseval1 - 512);
4028         else
4029                 avg = (int)tempsenseval1;
4030
4031         if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
4032                 if (tempsenseval2 > 255)
4033                         avg = (int)(avg - tempsenseval2 + 512);
4034                 else
4035                         avg = (int)(avg - tempsenseval2);
4036         } else {
4037                 if (tempsenseval2 > 255)
4038                         avg = (int)(avg + tempsenseval2 - 512);
4039                 else
4040                         avg = (int)(avg + tempsenseval2);
4041                 avg = avg / 2;
4042         }
4043         if (avg < 0)
4044                 avg = avg + 512;
4045
4046         if (pi_lcn->lcnphy_tempsense_option == 2)
4047                 avg = tempsenseval1;
4048
4049         if (mode)
4050                 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
4051
4052         if (mode == 1) {
4053
4054                 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
4055
4056                 udelay(100);
4057                 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
4058
4059                 if (!suspend)
4060                         wlapi_enable_mac(pi->sh->physhim);
4061         }
4062         return (u16) avg;
4063 }
4064
4065 s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode)
4066 {
4067         s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
4068         degree =
4069                 ((degree <<
4070                   10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
4071                 / LCN_TEMPSENSE_DEN;
4072         return (s8) degree;
4073 }
4074
4075 s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
4076 {
4077         u16 vbatsenseval;
4078         s32 avg = 0;
4079         bool suspend = false;
4080
4081         if (mode == 1) {
4082                 suspend = (0 == (bcma_read32(pi->d11core,
4083                                              D11REGOFFS(maccontrol)) &
4084                                  MCTL_EN_MAC));
4085                 if (!suspend)
4086                         wlapi_suspend_mac_and_wait(pi->sh->physhim);
4087                 wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
4088         }
4089
4090         vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
4091
4092         if (vbatsenseval > 255)
4093                 avg = (s32) (vbatsenseval - 512);
4094         else
4095                 avg = (s32) vbatsenseval;
4096
4097         avg =   (avg * LCN_VBAT_SCALE_NOM +
4098                  (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
4099
4100         if (mode == 1) {
4101                 if (!suspend)
4102                         wlapi_enable_mac(pi->sh->physhim);
4103         }
4104         return (s8) avg;
4105 }
4106
4107 static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode)
4108 {
4109         u8 phybw40;
4110         phybw40 = CHSPEC_IS40(pi->radio_chanspec);
4111
4112         mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
4113
4114         if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
4115             (mode == AFE_CLK_INIT_MODE_TXRX2X))
4116                 write_phy_reg(pi, 0x6d0, 0x7);
4117
4118         wlc_lcnphy_toggle_afe_pwdn(pi);
4119 }
4120
4121 static void wlc_lcnphy_temp_adj(struct brcms_phy *pi)
4122 {
4123 }
4124
4125 static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
4126 {
4127         bool suspend;
4128         s8 index;
4129         u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
4130         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4131         suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
4132                          MCTL_EN_MAC));
4133         if (!suspend)
4134                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
4135         wlc_lcnphy_deaf_mode(pi, true);
4136         pi->phy_lastcal = pi->sh->now;
4137         pi->phy_forcecal = false;
4138         index = pi_lcn->lcnphy_current_index;
4139
4140         wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
4141
4142         wlc_lcnphy_set_tx_pwr_by_index(pi, index);
4143         wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
4144         wlc_lcnphy_deaf_mode(pi, false);
4145         if (!suspend)
4146                 wlapi_enable_mac(pi->sh->physhim);
4147
4148 }
4149
4150 static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
4151 {
4152         bool suspend, full_cal;
4153         const struct lcnphy_rx_iqcomp *rx_iqcomp;
4154         int rx_iqcomp_sz;
4155         u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
4156         s8 index;
4157         struct phytbl_info tab;
4158         s32 a1, b0, b1;
4159         s32 tssi, pwr, maxtargetpwr, mintargetpwr;
4160         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4161
4162         pi->phy_lastcal = pi->sh->now;
4163         pi->phy_forcecal = false;
4164         full_cal =
4165                 (pi_lcn->lcnphy_full_cal_channel !=
4166                  CHSPEC_CHANNEL(pi->radio_chanspec));
4167         pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
4168         index = pi_lcn->lcnphy_current_index;
4169
4170         suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
4171                          MCTL_EN_MAC));
4172         if (!suspend) {
4173                 wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
4174                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
4175         }
4176
4177         wlc_lcnphy_deaf_mode(pi, true);
4178
4179         wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
4180
4181         rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
4182         rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
4183
4184         if (LCNREV_IS(pi->pubpi.phy_rev, 1))
4185                 wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
4186         else
4187                 wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
4188
4189         if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
4190
4191                 wlc_lcnphy_idle_tssi_est((struct brcms_phy_pub *) pi);
4192
4193                 b0 = pi->txpa_2g[0];
4194                 b1 = pi->txpa_2g[1];
4195                 a1 = pi->txpa_2g[2];
4196                 maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
4197                 mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
4198
4199                 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4200                 tab.tbl_width = 32;
4201                 tab.tbl_ptr = &pwr;
4202                 tab.tbl_len = 1;
4203                 tab.tbl_offset = 0;
4204                 for (tssi = 0; tssi < 128; tssi++) {
4205                         pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
4206                         pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
4207                         wlc_lcnphy_write_table(pi, &tab);
4208                         tab.tbl_offset++;
4209                 }
4210         }
4211
4212         wlc_lcnphy_set_tx_pwr_by_index(pi, index);
4213         wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
4214         wlc_lcnphy_deaf_mode(pi, false);
4215         if (!suspend)
4216                 wlapi_enable_mac(pi->sh->physhim);
4217 }
4218
4219 void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode)
4220 {
4221         u16 temp_new;
4222         int temp1, temp2, temp_diff;
4223         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4224
4225         switch (mode) {
4226         case PHY_PERICAL_CHAN:
4227                 break;
4228         case PHY_FULLCAL:
4229                 wlc_lcnphy_periodic_cal(pi);
4230                 break;
4231         case PHY_PERICAL_PHYINIT:
4232                 wlc_lcnphy_periodic_cal(pi);
4233                 break;
4234         case PHY_PERICAL_WATCHDOG:
4235                 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
4236                         temp_new = wlc_lcnphy_tempsense(pi, 0);
4237                         temp1 = LCNPHY_TEMPSENSE(temp_new);
4238                         temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
4239                         temp_diff = temp1 - temp2;
4240                         if ((pi_lcn->lcnphy_cal_counter > 90) ||
4241                             (temp_diff > 60) || (temp_diff < -60)) {
4242                                 wlc_lcnphy_glacial_timer_based_cal(pi);
4243                                 wlc_2064_vco_cal(pi);
4244                                 pi_lcn->lcnphy_cal_temper = temp_new;
4245                                 pi_lcn->lcnphy_cal_counter = 0;
4246                         } else
4247                                 pi_lcn->lcnphy_cal_counter++;
4248                 }
4249                 break;
4250         case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
4251                 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
4252                         wlc_lcnphy_tx_power_adjustment(
4253                                 (struct brcms_phy_pub *) pi);
4254                 break;
4255         }
4256 }
4257
4258 void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr)
4259 {
4260         s8 cck_offset;
4261         u16 status;
4262         status = (read_phy_reg(pi, 0x4ab));
4263         if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
4264             (status  & (0x1 << 15))) {
4265                 *ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
4266                                    >> 0) >> 1);
4267
4268                 if (wlc_phy_tpc_isenabled_lcnphy(pi))
4269                         cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
4270                 else
4271                         cck_offset = 0;
4272
4273                 *cck_pwr = *ofdm_pwr + cck_offset;
4274         } else {
4275                 *cck_pwr = 0;
4276                 *ofdm_pwr = 0;
4277         }
4278 }
4279
4280 void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi)
4281 {
4282         return;
4283
4284 }
4285
4286 void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi)
4287 {
4288         s8 index;
4289         u16 index2;
4290         struct brcms_phy *pi = (struct brcms_phy *) ppi;
4291         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4292         u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
4293         if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
4294             SAVE_txpwrctrl) {
4295                 index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
4296                 index2 = (u16) (index * 2);
4297                 mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
4298
4299                 pi_lcn->lcnphy_current_index =
4300                         (s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
4301         }
4302 }
4303
4304 static void
4305 wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
4306                               const struct lcnphy_tx_gain_tbl_entry *gain_table)
4307 {
4308         u32 j;
4309         struct phytbl_info tab;
4310         u32 val;
4311         u16 pa_gain;
4312         u16 gm_gain;
4313
4314         if (CHSPEC_IS5G(pi->radio_chanspec))
4315                 pa_gain = 0x70;
4316         else
4317                 pa_gain = 0x70;
4318
4319         if (pi->sh->boardflags & BFL_FEM)
4320                 pa_gain = 0x10;
4321         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4322         tab.tbl_width = 32;
4323         tab.tbl_len = 1;
4324         tab.tbl_ptr = &val;
4325
4326         for (j = 0; j < 128; j++) {
4327                 gm_gain = gain_table[j].gm;
4328                 val = (((u32) pa_gain << 24) |
4329                        (gain_table[j].pad << 16) |
4330                        (gain_table[j].pga << 8) | gm_gain);
4331
4332                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
4333                 wlc_lcnphy_write_table(pi, &tab);
4334
4335                 val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
4336                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
4337                 wlc_lcnphy_write_table(pi, &tab);
4338         }
4339 }
4340
4341 static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi)
4342 {
4343         struct phytbl_info tab;
4344         u32 val, bbmult, rfgain;
4345         u8 index;
4346         u8 scale_factor = 1;
4347         s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
4348
4349         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4350         tab.tbl_width = 32;
4351         tab.tbl_len = 1;
4352
4353         for (index = 0; index < 128; index++) {
4354                 tab.tbl_ptr = &bbmult;
4355                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
4356                 wlc_lcnphy_read_table(pi, &tab);
4357                 bbmult = bbmult >> 20;
4358
4359                 tab.tbl_ptr = &rfgain;
4360                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
4361                 wlc_lcnphy_read_table(pi, &tab);
4362
4363                 qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
4364                 qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
4365
4366                 if (qQ1 < qQ2) {
4367                         temp2 = qm_shr16(temp2, qQ2 - qQ1);
4368                         qQ = qQ1;
4369                 } else {
4370                         temp1 = qm_shr16(temp1, qQ1 - qQ2);
4371                         qQ = qQ2;
4372                 }
4373                 temp = qm_sub16(temp1, temp2);
4374
4375                 if (qQ >= 4)
4376                         shift = qQ - 4;
4377                 else
4378                         shift = 4 - qQ;
4379
4380                 val = (((index << shift) + (5 * temp) +
4381                         (1 << (scale_factor + shift - 3))) >> (scale_factor +
4382                                                                shift - 2));
4383
4384                 tab.tbl_ptr = &val;
4385                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
4386                 wlc_lcnphy_write_table(pi, &tab);
4387         }
4388 }
4389
4390 static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi)
4391 {
4392         or_phy_reg(pi, 0x805, 0x1);
4393
4394         mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
4395
4396         mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
4397
4398         write_phy_reg(pi, 0x414, 0x1e10);
4399         write_phy_reg(pi, 0x415, 0x0640);
4400
4401         mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
4402
4403         or_phy_reg(pi, 0x44a, 0x44);
4404         write_phy_reg(pi, 0x44a, 0x80);
4405         mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
4406
4407         mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
4408
4409         if (!(pi->sh->boardrev < 0x1204))
4410                 mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
4411
4412         write_phy_reg(pi, 0x7d6, 0x0902);
4413         mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
4414
4415         mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
4416
4417         if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
4418                 mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
4419
4420                 mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
4421
4422                 mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
4423
4424                 mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
4425
4426                 mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
4427
4428                 mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
4429                 mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
4430                 mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
4431                 mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
4432                 mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
4433
4434                 mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
4435
4436                 wlc_lcnphy_clear_tx_power_offsets(pi);
4437                 mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
4438
4439         }
4440 }
4441
4442 static void wlc_lcnphy_rcal(struct brcms_phy *pi)
4443 {
4444         u8 rcal_value;
4445
4446         and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
4447
4448         or_radio_reg(pi, RADIO_2064_REG004, 0x40);
4449         or_radio_reg(pi, RADIO_2064_REG120, 0x10);
4450
4451         or_radio_reg(pi, RADIO_2064_REG078, 0x80);
4452         or_radio_reg(pi, RADIO_2064_REG129, 0x02);
4453
4454         or_radio_reg(pi, RADIO_2064_REG057, 0x01);
4455
4456         or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
4457         mdelay(5);
4458         SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
4459
4460         if (wlc_radio_2064_rcal_done(pi)) {
4461                 rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
4462                 rcal_value = rcal_value & 0x1f;
4463         }
4464
4465         and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
4466
4467         and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
4468 }
4469
4470 static void wlc_lcnphy_rc_cal(struct brcms_phy *pi)
4471 {
4472         u8 dflt_rc_cal_val;
4473         u16 flt_val;
4474
4475         dflt_rc_cal_val = 7;
4476         if (LCNREV_IS(pi->pubpi.phy_rev, 1))
4477                 dflt_rc_cal_val = 11;
4478         flt_val =
4479                 (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
4480                 (dflt_rc_cal_val);
4481         write_phy_reg(pi, 0x933, flt_val);
4482         write_phy_reg(pi, 0x934, flt_val);
4483         write_phy_reg(pi, 0x935, flt_val);
4484         write_phy_reg(pi, 0x936, flt_val);
4485         write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
4486
4487         return;
4488 }
4489
4490 static void wlc_radio_2064_init(struct brcms_phy *pi)
4491 {
4492         u32 i;
4493         const struct lcnphy_radio_regs *lcnphyregs = NULL;
4494
4495         lcnphyregs = lcnphy_radio_regs_2064;
4496
4497         for (i = 0; lcnphyregs[i].address != 0xffff; i++)
4498                 if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
4499                         write_radio_reg(pi,
4500                                         ((lcnphyregs[i].address & 0x3fff) |
4501                                          RADIO_DEFAULT_CORE),
4502                                         (u16) lcnphyregs[i].init_a);
4503                 else if (lcnphyregs[i].do_init_g)
4504                         write_radio_reg(pi,
4505                                         ((lcnphyregs[i].address & 0x3fff) |
4506                                          RADIO_DEFAULT_CORE),
4507                                         (u16) lcnphyregs[i].init_g);
4508
4509         write_radio_reg(pi, RADIO_2064_REG032, 0x62);
4510         write_radio_reg(pi, RADIO_2064_REG033, 0x19);
4511
4512         write_radio_reg(pi, RADIO_2064_REG090, 0x10);
4513
4514         write_radio_reg(pi, RADIO_2064_REG010, 0x00);
4515
4516         if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
4517
4518                 write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
4519                 write_radio_reg(pi, RADIO_2064_REG061, 0x72);
4520                 write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
4521         }
4522
4523         write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
4524         write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
4525
4526         mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
4527
4528         mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
4529
4530         mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
4531
4532         mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
4533
4534         mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
4535
4536         write_phy_reg(pi, 0x4ea, 0x4688);
4537
4538         mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
4539
4540         mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
4541
4542         mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
4543
4544         wlc_lcnphy_set_tx_locc(pi, 0);
4545
4546         wlc_lcnphy_rcal(pi);
4547
4548         wlc_lcnphy_rc_cal(pi);
4549 }
4550
4551 static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
4552 {
4553         wlc_radio_2064_init(pi);
4554 }
4555
4556 static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
4557 {
4558         uint idx;
4559         u8 phybw40;
4560         struct phytbl_info tab;
4561         u32 val;
4562
4563         phybw40 = CHSPEC_IS40(pi->radio_chanspec);
4564
4565         for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++)
4566                 wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
4567
4568         if (pi->sh->boardflags & BFL_FEM_BT) {
4569                 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
4570                 tab.tbl_width = 16;
4571                 tab.tbl_ptr = &val;
4572                 tab.tbl_len = 1;
4573                 val = 100;
4574                 tab.tbl_offset = 4;
4575                 wlc_lcnphy_write_table(pi, &tab);
4576         }
4577
4578         tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
4579         tab.tbl_width = 16;
4580         tab.tbl_ptr = &val;
4581         tab.tbl_len = 1;
4582
4583         val = 114;
4584         tab.tbl_offset = 0;
4585         wlc_lcnphy_write_table(pi, &tab);
4586
4587         val = 130;
4588         tab.tbl_offset = 1;
4589         wlc_lcnphy_write_table(pi, &tab);
4590
4591         val = 6;
4592         tab.tbl_offset = 8;
4593         wlc_lcnphy_write_table(pi, &tab);
4594
4595         if (CHSPEC_IS2G(pi->radio_chanspec)) {
4596                 if (pi->sh->boardflags & BFL_FEM)
4597                         wlc_lcnphy_load_tx_gain_table(
4598                                 pi,
4599                                 dot11lcnphy_2GHz_extPA_gaintable_rev0);
4600                 else
4601                         wlc_lcnphy_load_tx_gain_table(
4602                                 pi,
4603                                 dot11lcnphy_2GHz_gaintable_rev0);
4604         }
4605
4606         if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
4607                 const struct phytbl_info *tb;
4608                 int l;
4609
4610                 if (CHSPEC_IS2G(pi->radio_chanspec)) {
4611                         l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
4612                         if (pi->sh->boardflags & BFL_EXTLNA)
4613                                 tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2;
4614                         else
4615                                 tb = dot11lcnphytbl_rx_gain_info_2G_rev2;
4616                 } else {
4617                         l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
4618                         if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
4619                                 tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2;
4620                         else
4621                                 tb = dot11lcnphytbl_rx_gain_info_5G_rev2;
4622                 }
4623
4624                 for (idx = 0; idx < l; idx++)
4625                         wlc_lcnphy_write_table(pi, &tb[idx]);
4626         }
4627
4628         if ((pi->sh->boardflags & BFL_FEM)
4629             && !(pi->sh->boardflags & BFL_FEM_BT))
4630                 wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
4631         else if (pi->sh->boardflags & BFL_FEM_BT) {
4632                 if (pi->sh->boardrev < 0x1250)
4633                         wlc_lcnphy_write_table(
4634                                 pi,
4635                                 &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
4636                 else
4637                         wlc_lcnphy_write_table(
4638                                 pi,
4639                                 &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
4640         } else
4641                 wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
4642
4643         wlc_lcnphy_load_rfpower(pi);
4644
4645         wlc_lcnphy_clear_papd_comptable(pi);
4646 }
4647
4648 static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi)
4649 {
4650         u16 afectrl1;
4651         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4652
4653         write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
4654
4655         write_phy_reg(pi, 0x43b, 0x0);
4656         write_phy_reg(pi, 0x43c, 0x0);
4657         write_phy_reg(pi, 0x44c, 0x0);
4658         write_phy_reg(pi, 0x4e6, 0x0);
4659         write_phy_reg(pi, 0x4f9, 0x0);
4660         write_phy_reg(pi, 0x4b0, 0x0);
4661         write_phy_reg(pi, 0x938, 0x0);
4662         write_phy_reg(pi, 0x4b0, 0x0);
4663         write_phy_reg(pi, 0x44e, 0);
4664
4665         or_phy_reg(pi, 0x567, 0x03);
4666
4667         or_phy_reg(pi, 0x44a, 0x44);
4668         write_phy_reg(pi, 0x44a, 0x80);
4669
4670         if (!(pi->sh->boardflags & BFL_FEM))
4671                 wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
4672
4673         if (0) {
4674                 afectrl1 = 0;
4675                 afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
4676                                   (pi_lcn->lcnphy_rssi_vc << 4) |
4677                                   (pi_lcn->lcnphy_rssi_gs << 10));
4678                 write_phy_reg(pi, 0x43e, afectrl1);
4679         }
4680
4681         mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
4682         if (pi->sh->boardflags & BFL_FEM) {
4683                 mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
4684
4685                 write_phy_reg(pi, 0x910, 0x1);
4686         }
4687
4688         mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
4689         mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
4690         mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
4691
4692 }
4693
4694 static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi)
4695 {
4696         if (CHSPEC_IS5G(pi->radio_chanspec)) {
4697                 mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
4698                 mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
4699         }
4700 }
4701
4702 static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
4703 {
4704         s16 temp;
4705         struct phytbl_info tab;
4706         u32 tableBuffer[2];
4707         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4708
4709         temp = (s16) read_phy_reg(pi, 0x4df);
4710         pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
4711
4712         if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
4713                 pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
4714
4715         pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
4716
4717         if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
4718                 pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
4719
4720         tab.tbl_ptr = tableBuffer;
4721         tab.tbl_len = 2;
4722         tab.tbl_id = 17;
4723         tab.tbl_offset = 59;
4724         tab.tbl_width = 32;
4725         wlc_lcnphy_read_table(pi, &tab);
4726
4727         if (tableBuffer[0] > 63)
4728                 tableBuffer[0] -= 128;
4729         pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
4730
4731         if (tableBuffer[1] > 63)
4732                 tableBuffer[1] -= 128;
4733         pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
4734
4735         temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0));
4736         if (temp > 127)
4737                 temp -= 256;
4738         pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
4739
4740         pi_lcn->lcnphy_Med_Low_Gain_db =
4741                 (read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8;
4742         pi_lcn->lcnphy_Very_Low_Gain_db =
4743                 (read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0;
4744
4745         tab.tbl_ptr = tableBuffer;
4746         tab.tbl_len = 2;
4747         tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
4748         tab.tbl_offset = 28;
4749         tab.tbl_width = 32;
4750         wlc_lcnphy_read_table(pi, &tab);
4751
4752         pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
4753         pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
4754
4755 }
4756
4757 static void wlc_lcnphy_baseband_init(struct brcms_phy *pi)
4758 {
4759
4760         wlc_lcnphy_tbl_init(pi);
4761         wlc_lcnphy_rev0_baseband_init(pi);
4762         if (LCNREV_IS(pi->pubpi.phy_rev, 2))
4763                 wlc_lcnphy_rev2_baseband_init(pi);
4764         wlc_lcnphy_bu_tweaks(pi);
4765 }
4766
4767 void wlc_phy_init_lcnphy(struct brcms_phy *pi)
4768 {
4769         u8 phybw40;
4770         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4771         phybw40 = CHSPEC_IS40(pi->radio_chanspec);
4772
4773         pi_lcn->lcnphy_cal_counter = 0;
4774         pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
4775
4776         or_phy_reg(pi, 0x44a, 0x80);
4777         and_phy_reg(pi, 0x44a, 0x7f);
4778
4779         wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
4780
4781         write_phy_reg(pi, 0x60a, 160);
4782
4783         write_phy_reg(pi, 0x46a, 25);
4784
4785         wlc_lcnphy_baseband_init(pi);
4786
4787         wlc_lcnphy_radio_init(pi);
4788
4789         if (CHSPEC_IS2G(pi->radio_chanspec))
4790                 wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi);
4791
4792         wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
4793
4794         si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
4795
4796         si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
4797
4798         if ((pi->sh->boardflags & BFL_FEM)
4799             && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
4800                 wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
4801
4802         wlc_lcnphy_agc_temp_init(pi);
4803
4804         wlc_lcnphy_temp_adj(pi);
4805
4806         mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
4807
4808         udelay(100);
4809         mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
4810
4811         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
4812         pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
4813         wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
4814 }
4815
4816 static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
4817 {
4818         s8 txpwr = 0;
4819         int i;
4820         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4821         struct phy_shim_info *shim = pi->sh->physhim;
4822
4823         if (CHSPEC_IS2G(pi->radio_chanspec)) {
4824                 u16 cckpo = 0;
4825                 u32 offset_ofdm, offset_mcs;
4826
4827                 pi_lcn->lcnphy_tr_isolation_mid =
4828                         (u8)wlapi_getintvar(shim, BRCMS_SROM_TRISO2G);
4829
4830                 pi_lcn->lcnphy_rx_power_offset =
4831                         (u8)wlapi_getintvar(shim, BRCMS_SROM_RXPO2G);
4832
4833                 pi->txpa_2g[0] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B0);
4834                 pi->txpa_2g[1] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B1);
4835                 pi->txpa_2g[2] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B2);
4836
4837                 pi_lcn->lcnphy_rssi_vf =
4838                                 (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMF2G);
4839                 pi_lcn->lcnphy_rssi_vc =
4840                                 (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMC2G);
4841                 pi_lcn->lcnphy_rssi_gs =
4842                                 (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISAV2G);
4843
4844                 pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
4845                 pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
4846                 pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
4847
4848                 pi_lcn->lcnphy_rssi_vf_hightemp = pi_lcn->lcnphy_rssi_vf;
4849                 pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc;
4850                 pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs;
4851
4852                 txpwr = (s8)wlapi_getintvar(shim, BRCMS_SROM_MAXP2GA0);
4853                 pi->tx_srom_max_2g = txpwr;
4854
4855                 for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
4856                         pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
4857                         pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
4858                 }
4859
4860                 cckpo = (u16)wlapi_getintvar(shim, BRCMS_SROM_CCK2GPO);
4861                 offset_ofdm = (u32)wlapi_getintvar(shim, BRCMS_SROM_OFDM2GPO);
4862                 if (cckpo) {
4863                         uint max_pwr_chan = txpwr;
4864
4865                         for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
4866                                 pi->tx_srom_max_rate_2g[i] =
4867                                         max_pwr_chan - ((cckpo & 0xf) * 2);
4868                                 cckpo >>= 4;
4869                         }
4870
4871                         for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
4872                                 pi->tx_srom_max_rate_2g[i] =
4873                                         max_pwr_chan -
4874                                         ((offset_ofdm & 0xf) * 2);
4875                                 offset_ofdm >>= 4;
4876                         }
4877                 } else {
4878                         u8 opo = 0;
4879
4880                         opo = (u8)wlapi_getintvar(shim, BRCMS_SROM_OPO);
4881
4882                         for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++)
4883                                 pi->tx_srom_max_rate_2g[i] = txpwr;
4884
4885                         for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
4886                                 pi->tx_srom_max_rate_2g[i] = txpwr -
4887                                                 ((offset_ofdm & 0xf) * 2);
4888                                 offset_ofdm >>= 4;
4889                         }
4890                         offset_mcs =
4891                                 wlapi_getintvar(shim,
4892                                                 BRCMS_SROM_MCS2GPO1) << 16;
4893                         offset_mcs |=
4894                                 (u16) wlapi_getintvar(shim,
4895                                                       BRCMS_SROM_MCS2GPO0);
4896                         pi_lcn->lcnphy_mcs20_po = offset_mcs;
4897                         for (i = TXP_FIRST_SISO_MCS_20;
4898                              i <= TXP_LAST_SISO_MCS_20; i++) {
4899                                 pi->tx_srom_max_rate_2g[i] =
4900                                         txpwr - ((offset_mcs & 0xf) * 2);
4901                                 offset_mcs >>= 4;
4902                         }
4903                 }
4904
4905                 pi_lcn->lcnphy_rawtempsense =
4906                         (u16)wlapi_getintvar(shim, BRCMS_SROM_RAWTEMPSENSE);
4907                 pi_lcn->lcnphy_measPower =
4908                         (u8)wlapi_getintvar(shim, BRCMS_SROM_MEASPOWER);
4909                 pi_lcn->lcnphy_tempsense_slope =
4910                         (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_SLOPE);
4911                 pi_lcn->lcnphy_hw_iqcal_en =
4912                         (bool)wlapi_getintvar(shim, BRCMS_SROM_HW_IQCAL_EN);
4913                 pi_lcn->lcnphy_iqcal_swp_dis =
4914                         (bool)wlapi_getintvar(shim, BRCMS_SROM_IQCAL_SWP_DIS);
4915                 pi_lcn->lcnphy_tempcorrx =
4916                         (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPCORRX);
4917                 pi_lcn->lcnphy_tempsense_option =
4918                         (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_OPTION);
4919                 pi_lcn->lcnphy_freqoffset_corr =
4920                         (u8)wlapi_getintvar(shim, BRCMS_SROM_FREQOFFSET_CORR);
4921                 if ((u8)wlapi_getintvar(shim, BRCMS_SROM_AA2G) > 1)
4922                         wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi,
4923                                 (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G));
4924         }
4925         pi_lcn->lcnphy_cck_dig_filt_type = -1;
4926
4927         return true;
4928 }
4929
4930 void wlc_2064_vco_cal(struct brcms_phy *pi)
4931 {
4932         u8 calnrst;
4933
4934         mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
4935         calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
4936         write_radio_reg(pi, RADIO_2064_REG056, calnrst);
4937         udelay(1);
4938         write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
4939         udelay(1);
4940         write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
4941         udelay(300);
4942         mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
4943 }
4944
4945 bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi)
4946 {
4947         if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
4948                 return 0;
4949         else
4950                 return (LCNPHY_TX_PWR_CTRL_HW ==
4951                         wlc_lcnphy_get_tx_pwr_ctrl((pi)));
4952 }
4953
4954 void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi)
4955 {
4956         u16 pwr_ctrl;
4957         if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
4958                 wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
4959         } else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
4960                 pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
4961                 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
4962                 wlc_lcnphy_txpower_recalc_target(pi);
4963                 wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
4964         }
4965 }
4966
4967 void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
4968 {
4969         kfree(pi->u.pi_lcnphy);
4970 }
4971
4972 bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
4973 {
4974         struct brcms_phy_lcnphy *pi_lcn;
4975
4976         pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC);
4977         if (pi->u.pi_lcnphy == NULL)
4978                 return false;
4979
4980         pi_lcn = pi->u.pi_lcnphy;
4981
4982         if (0 == (pi->sh->boardflags & BFL_NOPA)) {
4983                 pi->hwpwrctrl = true;
4984                 pi->hwpwrctrl_capable = true;
4985         }
4986
4987         pi->xtalfreq = si_pmu_alp_clock(pi->sh->sih);
4988         pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
4989
4990         pi->pi_fptr.init = wlc_phy_init_lcnphy;
4991         pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
4992         pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
4993         pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
4994         pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
4995         pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
4996         pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
4997         pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
4998         pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
4999
5000         if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
5001                 return false;
5002
5003         if ((pi->sh->boardflags & BFL_FEM) &&
5004             (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
5005                 if (pi_lcn->lcnphy_tempsense_option == 3) {
5006                         pi->hwpwrctrl = true;
5007                         pi->hwpwrctrl_capable = true;
5008                         pi->temppwrctrl_capable = false;
5009                 } else {
5010                         pi->hwpwrctrl = false;
5011                         pi->hwpwrctrl_capable = false;
5012                         pi->temppwrctrl_capable = true;
5013                 }
5014         }
5015
5016         return true;
5017 }
5018
5019 static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain)
5020 {
5021         u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
5022
5023         trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
5024         ext_lna = (u16) (gain >> 29) & 0x01;
5025         lna1 = (u16) (gain >> 0) & 0x0f;
5026         lna2 = (u16) (gain >> 4) & 0x0f;
5027         tia = (u16) (gain >> 8) & 0xf;
5028         biq0 = (u16) (gain >> 12) & 0xf;
5029         biq1 = (u16) (gain >> 16) & 0xf;
5030
5031         gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
5032                           ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
5033                           ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
5034         gain16_19 = biq1;
5035
5036         mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
5037         mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
5038         mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
5039         mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
5040         mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
5041
5042         if (CHSPEC_IS2G(pi->radio_chanspec)) {
5043                 mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
5044                 mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
5045         }
5046         wlc_lcnphy_rx_gain_override_enable(pi, true);
5047 }
5048
5049 static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index)
5050 {
5051         u32 received_power = 0;
5052         s32 max_index = 0;
5053         u32 gain_code = 0;
5054         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
5055
5056         max_index = 36;
5057         if (*gain_index >= 0)
5058                 gain_code = lcnphy_23bitgaincode_table[*gain_index];
5059
5060         if (-1 == *gain_index) {
5061                 *gain_index = 0;
5062                 while ((*gain_index <= (s32) max_index)
5063                        && (received_power < 700)) {
5064                         wlc_lcnphy_set_rx_gain(pi,
5065                                                lcnphy_23bitgaincode_table
5066                                                [*gain_index]);
5067                         received_power =
5068                                 wlc_lcnphy_measure_digital_power(
5069                                         pi,
5070                                         pi_lcn->
5071                                         lcnphy_noise_samples);
5072                         (*gain_index)++;
5073                 }
5074                 (*gain_index)--;
5075         } else {
5076                 wlc_lcnphy_set_rx_gain(pi, gain_code);
5077                 received_power =
5078                         wlc_lcnphy_measure_digital_power(pi,
5079                                                          pi_lcn->
5080                                                          lcnphy_noise_samples);
5081         }
5082
5083         return received_power;
5084 }
5085
5086 s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
5087 {
5088         s32 gain = 0;
5089         s32 nominal_power_db;
5090         s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
5091             input_power_db;
5092         s32 received_power, temperature;
5093         u32 power;
5094         u32 msb1, msb2, val1, val2, diff1, diff2;
5095         uint freq;
5096         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
5097
5098         received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
5099
5100         gain = lcnphy_gain_table[gain_index];
5101
5102         nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
5103
5104         power = (received_power * 16);
5105         msb1 = ffs(power) - 1;
5106         msb2 = msb1 + 1;
5107         val1 = 1 << msb1;
5108         val2 = 1 << msb2;
5109         diff1 = (power - val1);
5110         diff2 = (val2 - power);
5111         if (diff1 < diff2)
5112                 log_val = msb1;
5113         else
5114                 log_val = msb2;
5115
5116         log_val = log_val * 3;
5117
5118         gain_mismatch = (nominal_power_db / 2) - (log_val);
5119
5120         desired_gain = gain + gain_mismatch;
5121
5122         input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
5123
5124         if (input_power_offset_db > 127)
5125                 input_power_offset_db -= 256;
5126
5127         input_power_db = input_power_offset_db - desired_gain;
5128
5129         input_power_db =
5130                 input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
5131
5132         freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
5133         if ((freq > 2427) && (freq <= 2467))
5134                 input_power_db = input_power_db - 1;
5135
5136         temperature = pi_lcn->lcnphy_lastsensed_temperature;
5137
5138         if ((temperature - 15) < -30)
5139                 input_power_db =
5140                         input_power_db +
5141                         (((temperature - 10 - 25) * 286) >> 12) -
5142                         7;
5143         else if ((temperature - 15) < 4)
5144                 input_power_db =
5145                         input_power_db +
5146                         (((temperature - 10 - 25) * 286) >> 12) -
5147                         3;
5148         else
5149                 input_power_db = input_power_db +
5150                                         (((temperature - 10 - 25) * 286) >> 12);
5151
5152         wlc_lcnphy_rx_gain_override_enable(pi, 0);
5153
5154         return input_power_db;
5155 }