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