]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
Merge branch 'stable' of git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux...
[karo-tx-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                 bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
1599                                       0x03000c04);
1600                 bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
1601                                         ~0x00ffffff, 0x0);
1602                 bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
1603                                       0x200005c0);
1604
1605                 bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
1606                               BCMA_CC_PMU_CTL_PLL_UPD);
1607                 write_phy_reg(pi, 0x942, 0);
1608                 wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
1609                 pi_lcn->lcnphy_spurmod = false;
1610                 mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
1611
1612                 write_phy_reg(pi, 0x425, 0x5907);
1613         } else {
1614                 bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x2,
1615                                       0x03140c04);
1616                 bcma_chipco_pll_maskset(&pi->d11core->bus->drv_cc, 0x3,
1617                                         ~0x00ffffff, 0x333333);
1618                 bcma_chipco_pll_write(&pi->d11core->bus->drv_cc, 0x4,
1619                                       0x202c2820);
1620
1621                 bcma_cc_set32(&pi->d11core->bus->drv_cc, BCMA_CC_PMU_CTL,
1622                               BCMA_CC_PMU_CTL_PLL_UPD);
1623                 write_phy_reg(pi, 0x942, 0);
1624                 wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
1625
1626                 pi_lcn->lcnphy_spurmod = false;
1627                 mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
1628
1629                 write_phy_reg(pi, 0x425, 0x590a);
1630         }
1631
1632         or_phy_reg(pi, 0x44a, 0x44);
1633         write_phy_reg(pi, 0x44a, 0x80);
1634 }
1635
1636 static void
1637 wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
1638 {
1639         uint i;
1640         const struct chan_info_2064_lcnphy *ci;
1641         u8 rfpll_doubler = 0;
1642         u8 pll_pwrup, pll_pwrup_ovr;
1643         s32 qFxtal, qFref, qFvco, qFcal;
1644         u8 d15, d16, f16, e44, e45;
1645         u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
1646         u16 loop_bw, d30, setCount;
1647
1648         u8 h29, h28_ten, e30, h30_ten, cp_current;
1649         u16 g30, d28;
1650
1651         ci = &chan_info_2064_lcnphy[0];
1652         rfpll_doubler = 1;
1653
1654         mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
1655
1656         write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
1657         if (!rfpll_doubler) {
1658                 loop_bw = PLL_2064_LOOP_BW;
1659                 d30 = PLL_2064_D30;
1660         } else {
1661                 loop_bw = PLL_2064_LOOP_BW_DOUBLER;
1662                 d30 = PLL_2064_D30_DOUBLER;
1663         }
1664
1665         if (CHSPEC_IS2G(pi->radio_chanspec)) {
1666                 for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
1667                         if (chan_info_2064_lcnphy[i].chan == channel)
1668                                 break;
1669
1670                 if (i >= ARRAY_SIZE(chan_info_2064_lcnphy))
1671                         return;
1672
1673                 ci = &chan_info_2064_lcnphy[i];
1674         }
1675
1676         write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
1677
1678         mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
1679
1680         mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
1681
1682         mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
1683
1684         mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
1685                       (ci->logen_rccr_rx) << 2);
1686
1687         mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
1688
1689         mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
1690                       (ci->pa_rxrf_lna2_freq_tune) << 4);
1691
1692         write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
1693
1694         pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
1695         pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
1696
1697         or_radio_reg(pi, RADIO_2064_REG044, 0x07);
1698
1699         or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
1700         e44 = 0;
1701         e45 = 0;
1702
1703         fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
1704         if (pi->xtalfreq > 26000000)
1705                 e44 = 1;
1706         if (pi->xtalfreq > 52000000)
1707                 e45 = 1;
1708         if (e44 == 0)
1709                 fcal_div = 1;
1710         else if (e45 == 0)
1711                 fcal_div = 2;
1712         else
1713                 fcal_div = 4;
1714         fvco3 = (ci->freq * 3);
1715         fref3 = 2 * fpfd;
1716
1717         qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
1718         qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
1719         qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
1720         qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
1721
1722         write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
1723
1724         d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
1725         write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
1726         write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
1727
1728         d16 = (qFcal * 8 / (d15 + 1)) - 1;
1729         write_radio_reg(pi, RADIO_2064_REG051, d16);
1730
1731         f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
1732         setCount = f16 * 3 * (ci->freq) / 32 - 1;
1733         mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
1734                       (u8) (setCount >> 8));
1735
1736         or_radio_reg(pi, RADIO_2064_REG053, 0x10);
1737         write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
1738
1739         div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
1740
1741         div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
1742         while (div_frac >= fref3) {
1743                 div_int++;
1744                 div_frac -= fref3;
1745         }
1746         div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
1747
1748         mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
1749                       (u8) (div_int >> 4));
1750         mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
1751                       (u8) (div_int << 4));
1752         mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
1753                       (u8) (div_frac >> 16));
1754         write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
1755         write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
1756
1757         write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
1758
1759         write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
1760         write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
1761         write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
1762
1763         h29 = LCN_BW_LMT / loop_bw;
1764         d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
1765                 (fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
1766                (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
1767               + PLL_2064_LOW_END_KVCO;
1768         h28_ten = (d28 * 10) / LCN_VCO_DIV;
1769         e30 = (d30 - LCN_OFFSET) / LCN_FACT;
1770         g30 = LCN_OFFSET + (e30 * LCN_FACT);
1771         h30_ten = (g30 * 10) / LCN_CUR_DIV;
1772         cp_current = ((LCN_CUR_LMT * h29 * LCN_MULT * 100) / h28_ten) / h30_ten;
1773         mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
1774
1775         if (channel >= 1 && channel <= 5)
1776                 write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
1777         else
1778                 write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
1779         write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
1780
1781         mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
1782         udelay(1);
1783
1784         wlc_2064_vco_cal(pi);
1785
1786         write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
1787         write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
1788         if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
1789                 write_radio_reg(pi, RADIO_2064_REG038, 3);
1790                 write_radio_reg(pi, RADIO_2064_REG091, 7);
1791         }
1792 }
1793
1794 static int
1795 wlc_lcnphy_load_tx_iir_filter(struct brcms_phy *pi, bool is_ofdm, s16 filt_type)
1796 {
1797         s16 filt_index = -1;
1798         int j;
1799
1800         u16 addr[] = {
1801                 0x910,
1802                 0x91e,
1803                 0x91f,
1804                 0x924,
1805                 0x925,
1806                 0x926,
1807                 0x920,
1808                 0x921,
1809                 0x927,
1810                 0x928,
1811                 0x929,
1812                 0x922,
1813                 0x923,
1814                 0x930,
1815                 0x931,
1816                 0x932
1817         };
1818
1819         u16 addr_ofdm[] = {
1820                 0x90f,
1821                 0x900,
1822                 0x901,
1823                 0x906,
1824                 0x907,
1825                 0x908,
1826                 0x902,
1827                 0x903,
1828                 0x909,
1829                 0x90a,
1830                 0x90b,
1831                 0x904,
1832                 0x905,
1833                 0x90c,
1834                 0x90d,
1835                 0x90e
1836         };
1837
1838         if (!is_ofdm) {
1839                 for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
1840                         if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
1841                                 filt_index = (s16) j;
1842                                 break;
1843                         }
1844                 }
1845
1846                 if (filt_index != -1) {
1847                         for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
1848                                 write_phy_reg(pi, addr[j],
1849                                               LCNPHY_txdigfiltcoeffs_cck
1850                                               [filt_index][j + 1]);
1851                 }
1852         } else {
1853                 for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
1854                         if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
1855                                 filt_index = (s16) j;
1856                                 break;
1857                         }
1858                 }
1859
1860                 if (filt_index != -1) {
1861                         for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++)
1862                                 write_phy_reg(pi, addr_ofdm[j],
1863                                               LCNPHY_txdigfiltcoeffs_ofdm
1864                                               [filt_index][j + 1]);
1865                 }
1866         }
1867
1868         return (filt_index != -1) ? 0 : -1;
1869 }
1870
1871 static u16 wlc_lcnphy_get_pa_gain(struct brcms_phy *pi)
1872 {
1873         u16 pa_gain;
1874
1875         pa_gain = (read_phy_reg(pi, 0x4fb) &
1876                    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
1877                   LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
1878
1879         return pa_gain;
1880 }
1881
1882 static void wlc_lcnphy_set_tx_gain(struct brcms_phy *pi,
1883                                    struct lcnphy_txgains *target_gains)
1884 {
1885         u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
1886
1887         mod_phy_reg(
1888                 pi, 0x4b5,
1889                 (0xffff << 0),
1890                 ((target_gains->gm_gain) |
1891                  (target_gains->pga_gain << 8)) <<
1892                 0);
1893         mod_phy_reg(pi, 0x4fb,
1894                     (0x7fff << 0),
1895                     ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
1896
1897         mod_phy_reg(
1898                 pi, 0x4fc,
1899                 (0xffff << 0),
1900                 ((target_gains->gm_gain) |
1901                  (target_gains->pga_gain << 8)) <<
1902                 0);
1903         mod_phy_reg(pi, 0x4fd,
1904                     (0x7fff << 0),
1905                     ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
1906
1907         wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
1908
1909         wlc_lcnphy_enable_tx_gain_override(pi);
1910 }
1911
1912 static u8 wlc_lcnphy_get_bbmult(struct brcms_phy *pi)
1913 {
1914         u16 m0m1;
1915         struct phytbl_info tab;
1916
1917         tab.tbl_ptr = &m0m1;
1918         tab.tbl_len = 1;
1919         tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
1920         tab.tbl_offset = 87;
1921         tab.tbl_width = 16;
1922         wlc_lcnphy_read_table(pi, &tab);
1923
1924         return (u8) ((m0m1 & 0xff00) >> 8);
1925 }
1926
1927 static void wlc_lcnphy_set_bbmult(struct brcms_phy *pi, u8 m0)
1928 {
1929         u16 m0m1 = (u16) m0 << 8;
1930         struct phytbl_info tab;
1931
1932         tab.tbl_ptr = &m0m1;
1933         tab.tbl_len = 1;
1934         tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
1935         tab.tbl_offset = 87;
1936         tab.tbl_width = 16;
1937         wlc_lcnphy_write_table(pi, &tab);
1938 }
1939
1940 static void wlc_lcnphy_clear_tx_power_offsets(struct brcms_phy *pi)
1941 {
1942         u32 data_buf[64];
1943         struct phytbl_info tab;
1944
1945         memset(data_buf, 0, sizeof(data_buf));
1946
1947         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1948         tab.tbl_width = 32;
1949         tab.tbl_ptr = data_buf;
1950
1951         if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
1952
1953                 tab.tbl_len = 30;
1954                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
1955                 wlc_lcnphy_write_table(pi, &tab);
1956         }
1957
1958         tab.tbl_len = 64;
1959         tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
1960         wlc_lcnphy_write_table(pi, &tab);
1961 }
1962
1963 enum lcnphy_tssi_mode {
1964         LCNPHY_TSSI_PRE_PA,
1965         LCNPHY_TSSI_POST_PA,
1966         LCNPHY_TSSI_EXT
1967 };
1968
1969 static void
1970 wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
1971 {
1972         mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
1973
1974         mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
1975
1976         if (LCNPHY_TSSI_POST_PA == pos) {
1977                 mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
1978
1979                 mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
1980
1981                 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1982                         mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
1983                 } else {
1984                         mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
1985                         mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
1986                 }
1987         } else {
1988                 mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
1989
1990                 mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
1991
1992                 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1993                         mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
1994                 } else {
1995                         mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
1996                         mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
1997                 }
1998         }
1999         mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
2000
2001         if (LCNPHY_TSSI_EXT == pos) {
2002                 write_radio_reg(pi, RADIO_2064_REG07F, 1);
2003                 mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
2004                 mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
2005                 mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
2006         }
2007 }
2008
2009 static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(struct brcms_phy *pi)
2010 {
2011         u16 N1, N2, N3, N4, N5, N6, N;
2012         N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
2013               >> 0);
2014         N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
2015                    >> 12);
2016         N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
2017               >> 0);
2018         N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8))
2019                    >> 8);
2020         N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0))
2021               >> 0);
2022         N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8))
2023                    >> 8);
2024         N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80;
2025         if (N < 1600)
2026                 N = 1600;
2027         return N;
2028 }
2029
2030 static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
2031 {
2032         u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
2033         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2034
2035         auxpga_vmid = (2 << 8) |
2036                       (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
2037         auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
2038         auxpga_gain_temp = 2;
2039
2040         mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0);
2041
2042         mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1);
2043
2044         mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3);
2045
2046         mod_phy_reg(pi, 0x4db,
2047                     (0x3ff << 0) |
2048                     (0x7 << 12),
2049                     (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
2050
2051         mod_phy_reg(pi, 0x4dc,
2052                     (0x3ff << 0) |
2053                     (0x7 << 12),
2054                     (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
2055
2056         mod_phy_reg(pi, 0x40a,
2057                     (0x3ff << 0) |
2058                     (0x7 << 12),
2059                     (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
2060
2061         mod_phy_reg(pi, 0x40b,
2062                     (0x3ff << 0) |
2063                     (0x7 << 12),
2064                     (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
2065
2066         mod_phy_reg(pi, 0x40c,
2067                     (0x3ff << 0) |
2068                     (0x7 << 12),
2069                     (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
2070
2071         mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
2072 }
2073
2074 static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
2075 {
2076         struct phytbl_info tab;
2077         u32 rfseq, ind;
2078
2079         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
2080         tab.tbl_width = 32;
2081         tab.tbl_ptr = &ind;
2082         tab.tbl_len = 1;
2083         tab.tbl_offset = 0;
2084         for (ind = 0; ind < 128; ind++) {
2085                 wlc_lcnphy_write_table(pi, &tab);
2086                 tab.tbl_offset++;
2087         }
2088         tab.tbl_offset = 704;
2089         for (ind = 0; ind < 128; ind++) {
2090                 wlc_lcnphy_write_table(pi, &tab);
2091                 tab.tbl_offset++;
2092         }
2093         mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
2094
2095         mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
2096
2097         mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
2098
2099         wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
2100         mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
2101
2102         mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
2103
2104         mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
2105
2106         mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0);
2107
2108         mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
2109
2110         mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
2111
2112         mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
2113
2114         mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
2115
2116         mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8);
2117
2118         mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
2119
2120         mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8);
2121
2122         mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6);
2123
2124         mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0);
2125
2126         wlc_lcnphy_clear_tx_power_offsets(pi);
2127
2128         mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
2129
2130         mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0);
2131
2132         mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
2133
2134         if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
2135                 mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
2136                 mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
2137         } else {
2138                 mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
2139                 mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
2140         }
2141
2142         write_radio_reg(pi, RADIO_2064_REG025, 0xc);
2143
2144         if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
2145                 mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
2146         } else {
2147                 if (CHSPEC_IS2G(pi->radio_chanspec))
2148                         mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
2149                 else
2150                         mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1);
2151         }
2152
2153         if (LCNREV_IS(pi->pubpi.phy_rev, 2))
2154                 mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
2155         else
2156                 mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2);
2157
2158         mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0);
2159
2160         mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
2161
2162         if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
2163                 mod_phy_reg(pi, 0x4d7,
2164                             (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
2165
2166         rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
2167         tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
2168         tab.tbl_width = 16;
2169         tab.tbl_ptr = &rfseq;
2170         tab.tbl_len = 1;
2171         tab.tbl_offset = 6;
2172         wlc_lcnphy_write_table(pi, &tab);
2173
2174         mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
2175
2176         mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
2177
2178         mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
2179
2180         mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2);
2181
2182         mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
2183
2184         wlc_lcnphy_pwrctrl_rssiparams(pi);
2185 }
2186
2187 void wlc_lcnphy_tx_pwr_update_npt(struct brcms_phy *pi)
2188 {
2189         u16 tx_cnt, tx_total, npt;
2190         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2191
2192         tx_total = wlc_lcnphy_total_tx_frames(pi);
2193         tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt;
2194         npt = wlc_lcnphy_get_tx_pwr_npt(pi);
2195
2196         if (tx_cnt > (1 << npt)) {
2197
2198                 pi_lcn->lcnphy_tssi_tx_cnt = tx_total;
2199
2200                 pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi);
2201                 pi_lcn->lcnphy_tssi_npt = npt;
2202
2203         }
2204 }
2205
2206 s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1)
2207 {
2208         s32 a, b, p;
2209
2210         a = 32768 + (a1 * tssi);
2211         b = (1024 * b0) + (64 * b1 * tssi);
2212         p = ((2 * b) + a) / (2 * a);
2213
2214         return p;
2215 }
2216
2217 static void wlc_lcnphy_txpower_reset_npt(struct brcms_phy *pi)
2218 {
2219         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2220         if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
2221                 return;
2222
2223         pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313;
2224         pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT;
2225 }
2226
2227 void wlc_lcnphy_txpower_recalc_target(struct brcms_phy *pi)
2228 {
2229         struct phytbl_info tab;
2230         u32 rate_table[BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM +
2231                        BRCMS_NUM_RATES_MCS_1_STREAM];
2232         uint i, j;
2233         if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
2234                 return;
2235
2236         for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) {
2237
2238                 if (i == BRCMS_NUM_RATES_CCK + BRCMS_NUM_RATES_OFDM)
2239                         j = TXP_FIRST_MCS_20_SISO;
2240
2241                 rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j]));
2242         }
2243
2244         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
2245         tab.tbl_width = 32;
2246         tab.tbl_len = ARRAY_SIZE(rate_table);
2247         tab.tbl_ptr = rate_table;
2248         tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
2249         wlc_lcnphy_write_table(pi, &tab);
2250
2251         if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) {
2252                 wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min);
2253
2254                 wlc_lcnphy_txpower_reset_npt(pi);
2255         }
2256 }
2257
2258 static void wlc_lcnphy_set_tx_pwr_soft_ctrl(struct brcms_phy *pi, s8 index)
2259 {
2260         u32 cck_offset[4] = { 22, 22, 22, 22 };
2261         u32 ofdm_offset, reg_offset_cck;
2262         int i;
2263         u16 index2;
2264         struct phytbl_info tab;
2265
2266         if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
2267                 return;
2268
2269         mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
2270
2271         mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14);
2272
2273         or_phy_reg(pi, 0x6da, 0x0040);
2274
2275         reg_offset_cck = 0;
2276         for (i = 0; i < 4; i++)
2277                 cck_offset[i] -= reg_offset_cck;
2278         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
2279         tab.tbl_width = 32;
2280         tab.tbl_len = 4;
2281         tab.tbl_ptr = cck_offset;
2282         tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
2283         wlc_lcnphy_write_table(pi, &tab);
2284         ofdm_offset = 0;
2285         tab.tbl_len = 1;
2286         tab.tbl_ptr = &ofdm_offset;
2287         for (i = 836; i < 862; i++) {
2288                 tab.tbl_offset = i;
2289                 wlc_lcnphy_write_table(pi, &tab);
2290         }
2291
2292         mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15);
2293
2294         mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
2295
2296         mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13);
2297
2298         mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7);
2299
2300         mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6);
2301
2302         mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15);
2303
2304         index2 = (u16) (index * 2);
2305         mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
2306
2307         mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4);
2308
2309 }
2310
2311 static s8 wlc_lcnphy_tempcompensated_txpwrctrl(struct brcms_phy *pi)
2312 {
2313         s8 index, delta_brd, delta_temp, new_index, tempcorrx;
2314         s16 manp, meas_temp, temp_diff;
2315         bool neg = false;
2316         u16 temp;
2317         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2318
2319         if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
2320                 return pi_lcn->lcnphy_current_index;
2321
2322         index = FIXED_TXPWR;
2323
2324         if (pi_lcn->lcnphy_tempsense_slope == 0)
2325                 return index;
2326
2327         temp = (u16) wlc_lcnphy_tempsense(pi, 0);
2328         meas_temp = LCNPHY_TEMPSENSE(temp);
2329
2330         if (pi->tx_power_min != 0)
2331                 delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
2332         else
2333                 delta_brd = 0;
2334
2335         manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
2336         temp_diff = manp - meas_temp;
2337         if (temp_diff < 0) {
2338                 neg = true;
2339                 temp_diff = -temp_diff;
2340         }
2341
2342         delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
2343                                                   (u32) (pi_lcn->
2344                                                          lcnphy_tempsense_slope
2345                                                          * 10), 0);
2346         if (neg)
2347                 delta_temp = -delta_temp;
2348
2349         if (pi_lcn->lcnphy_tempsense_option == 3
2350             && LCNREV_IS(pi->pubpi.phy_rev, 0))
2351                 delta_temp = 0;
2352         if (pi_lcn->lcnphy_tempcorrx > 31)
2353                 tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64);
2354         else
2355                 tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx;
2356         if (LCNREV_IS(pi->pubpi.phy_rev, 1))
2357                 tempcorrx = 4;
2358         new_index =
2359                 index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
2360         new_index += tempcorrx;
2361
2362         if (LCNREV_IS(pi->pubpi.phy_rev, 1))
2363                 index = 127;
2364
2365         if (new_index < 0 || new_index > 126)
2366                 return index;
2367
2368         return new_index;
2369 }
2370
2371 static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(struct brcms_phy *pi, u16 mode)
2372 {
2373
2374         u16 current_mode = mode;
2375         if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
2376             mode == LCNPHY_TX_PWR_CTRL_HW)
2377                 current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED;
2378         if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
2379             mode == LCNPHY_TX_PWR_CTRL_TEMPBASED)
2380                 current_mode = LCNPHY_TX_PWR_CTRL_HW;
2381         return current_mode;
2382 }
2383
2384 void wlc_lcnphy_set_tx_pwr_ctrl(struct brcms_phy *pi, u16 mode)
2385 {
2386         u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi);
2387         s8 index;
2388         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2389
2390         mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode);
2391         old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode);
2392
2393         mod_phy_reg(pi, 0x6da, (0x1 << 6),
2394                     ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6);
2395
2396         mod_phy_reg(pi, 0x6a3, (0x1 << 4),
2397                     ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4);
2398
2399         if (old_mode != mode) {
2400                 if (LCNPHY_TX_PWR_CTRL_HW == old_mode) {
2401
2402                         wlc_lcnphy_tx_pwr_update_npt(pi);
2403
2404                         wlc_lcnphy_clear_tx_power_offsets(pi);
2405                 }
2406                 if (LCNPHY_TX_PWR_CTRL_HW == mode) {
2407
2408                         wlc_lcnphy_txpower_recalc_target(pi);
2409
2410                         wlc_lcnphy_set_start_tx_pwr_idx(pi,
2411                                                         pi_lcn->
2412                                                         lcnphy_tssi_idx);
2413                         wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt);
2414                         mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
2415
2416                         pi_lcn->lcnphy_tssi_tx_cnt =
2417                                 wlc_lcnphy_total_tx_frames(pi);
2418
2419                         wlc_lcnphy_disable_tx_gain_override(pi);
2420                         pi_lcn->lcnphy_tx_power_idx_override = -1;
2421                 } else
2422                         wlc_lcnphy_enable_tx_gain_override(pi);
2423
2424                 mod_phy_reg(pi, 0x4a4,
2425                             ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode);
2426                 if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) {
2427                         index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
2428                         wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
2429                         pi_lcn->lcnphy_current_index = (s8)
2430                                                        ((read_phy_reg(pi,
2431                                                                       0x4a9) &
2432                                                          0xFF) / 2);
2433                 }
2434         }
2435 }
2436
2437 static void
2438 wlc_lcnphy_tx_iqlo_loopback(struct brcms_phy *pi, u16 *values_to_save)
2439 {
2440         u16 vmid;
2441         int i;
2442         for (i = 0; i < 20; i++)
2443                 values_to_save[i] =
2444                         read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
2445
2446         mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
2447         mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
2448
2449         mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
2450         mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
2451
2452         mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
2453         mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
2454
2455         mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
2456         mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
2457
2458         if (LCNREV_IS(pi->pubpi.phy_rev, 2))
2459                 and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
2460         else
2461                 and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
2462         or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
2463
2464         or_radio_reg(pi, RADIO_2064_REG036, 0x01);
2465         or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
2466         udelay(20);
2467
2468         if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
2469                 if (CHSPEC_IS5G(pi->radio_chanspec))
2470                         mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
2471                 else
2472                         or_radio_reg(pi, RADIO_2064_REG03A, 1);
2473         } else {
2474                 if (CHSPEC_IS5G(pi->radio_chanspec))
2475                         mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
2476                 else
2477                         or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
2478         }
2479
2480         udelay(20);
2481
2482         write_radio_reg(pi, RADIO_2064_REG025, 0xF);
2483         if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
2484                 if (CHSPEC_IS5G(pi->radio_chanspec))
2485                         mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
2486                 else
2487                         mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
2488         } else {
2489                 if (CHSPEC_IS5G(pi->radio_chanspec))
2490                         mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
2491                 else
2492                         mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
2493         }
2494
2495         udelay(20);
2496
2497         write_radio_reg(pi, RADIO_2064_REG005, 0x8);
2498         or_radio_reg(pi, RADIO_2064_REG112, 0x80);
2499         udelay(20);
2500
2501         or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
2502         or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
2503         udelay(20);
2504
2505         or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
2506         or_radio_reg(pi, RADIO_2064_REG113, 0x10);
2507         udelay(20);
2508
2509         write_radio_reg(pi, RADIO_2064_REG007, 0x1);
2510         udelay(20);
2511
2512         vmid = 0x2A6;
2513         mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
2514         write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
2515         or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
2516         udelay(20);
2517
2518         or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
2519         udelay(20);
2520         write_radio_reg(pi, RADIO_2064_REG012, 0x02);
2521         or_radio_reg(pi, RADIO_2064_REG112, 0x06);
2522         write_radio_reg(pi, RADIO_2064_REG036, 0x11);
2523         write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
2524         write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
2525         write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
2526         write_radio_reg(pi, RADIO_2064_REG092, 0x15);
2527 }
2528
2529 static bool wlc_lcnphy_iqcal_wait(struct brcms_phy *pi)
2530 {
2531         uint delay_count = 0;
2532
2533         while (wlc_lcnphy_iqcal_active(pi)) {
2534                 udelay(100);
2535                 delay_count++;
2536
2537                 if (delay_count > (10 * 500))
2538                         break;
2539         }
2540
2541         return (0 == wlc_lcnphy_iqcal_active(pi));
2542 }
2543
2544 static void
2545 wlc_lcnphy_tx_iqlo_loopback_cleanup(struct brcms_phy *pi, u16 *values_to_save)
2546 {
2547         int i;
2548
2549         and_phy_reg(pi, 0x44c, 0x0 >> 11);
2550
2551         and_phy_reg(pi, 0x43b, 0xC);
2552
2553         for (i = 0; i < 20; i++)
2554                 write_radio_reg(pi, iqlo_loopback_rf_regs[i],
2555                                 values_to_save[i]);
2556 }
2557
2558 static void
2559 wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
2560                        struct lcnphy_txgains *target_gains,
2561                        enum lcnphy_cal_mode cal_mode, bool keep_tone)
2562 {
2563
2564         struct lcnphy_txgains cal_gains, temp_gains;
2565         u16 hash;
2566         u8 band_idx;
2567         int j;
2568         u16 ncorr_override[5];
2569         u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2570                               0x0000, 0x0000, 0x0000, 0x0000, 0x0000};
2571
2572         u16 commands_fullcal[] = {
2573                 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234
2574         };
2575
2576         u16 commands_recal[] = {
2577                 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234
2578         };
2579
2580         u16 command_nums_fullcal[] = {
2581                 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97
2582         };
2583
2584         u16 command_nums_recal[] = {
2585                 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97
2586         };
2587         u16 *command_nums = command_nums_fullcal;
2588
2589         u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
2590         u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2;
2591         u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl;
2592         bool tx_gain_override_old;
2593         struct lcnphy_txgains old_gains;
2594         uint i, n_cal_cmds = 0, n_cal_start = 0;
2595         u16 *values_to_save;
2596         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2597
2598         values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
2599         if (NULL == values_to_save)
2600                 return;
2601
2602         save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
2603         save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
2604
2605         or_phy_reg(pi, 0x6da, 0x40);
2606         or_phy_reg(pi, 0x6db, 0x3);
2607
2608         switch (cal_mode) {
2609         case LCNPHY_CAL_FULL:
2610                 start_coeffs = syst_coeffs;
2611                 cal_cmds = commands_fullcal;
2612                 n_cal_cmds = ARRAY_SIZE(commands_fullcal);
2613                 break;
2614
2615         case LCNPHY_CAL_RECAL:
2616                 start_coeffs = syst_coeffs;
2617                 cal_cmds = commands_recal;
2618                 n_cal_cmds = ARRAY_SIZE(commands_recal);
2619                 command_nums = command_nums_recal;
2620                 break;
2621
2622         default:
2623                 break;
2624         }
2625
2626         wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2627                                       start_coeffs, 11, 16, 64);
2628
2629         write_phy_reg(pi, 0x6da, 0xffff);
2630         mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3);
2631
2632         tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi);
2633
2634         mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
2635
2636         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2637
2638         save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db);
2639
2640         mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0);
2641
2642         mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12);
2643
2644         wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save);
2645
2646         tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
2647         if (tx_gain_override_old)
2648                 wlc_lcnphy_get_tx_gain(pi, &old_gains);
2649
2650         if (!target_gains) {
2651                 if (!tx_gain_override_old)
2652                         wlc_lcnphy_set_tx_pwr_by_index(pi,
2653                                                        pi_lcn->lcnphy_tssi_idx);
2654                 wlc_lcnphy_get_tx_gain(pi, &temp_gains);
2655                 target_gains = &temp_gains;
2656         }
2657
2658         hash = (target_gains->gm_gain << 8) |
2659                (target_gains->pga_gain << 4) | (target_gains->pad_gain);
2660
2661         band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
2662
2663         cal_gains = *target_gains;
2664         memset(ncorr_override, 0, sizeof(ncorr_override));
2665         for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
2666                 if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
2667                         cal_gains.gm_gain =
2668                                 tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
2669                         cal_gains.pga_gain =
2670                                 tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
2671                         cal_gains.pad_gain =
2672                                 tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
2673                         memcpy(ncorr_override,
2674                                &tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
2675                                sizeof(ncorr_override));
2676                         break;
2677                 }
2678         }
2679
2680         wlc_lcnphy_set_tx_gain(pi, &cal_gains);
2681
2682         write_phy_reg(pi, 0x453, 0xaa9);
2683         write_phy_reg(pi, 0x93d, 0xc0);
2684
2685         wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2686                                       lcnphy_iqcal_loft_gainladder,
2687                                       ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
2688                                       16, 0);
2689
2690         wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2691                                       lcnphy_iqcal_ir_gainladder,
2692                                       ARRAY_SIZE(
2693                                               lcnphy_iqcal_ir_gainladder), 16,
2694                                       32);
2695
2696         if (pi->phy_tx_tone_freq) {
2697
2698                 wlc_lcnphy_stop_tx_tone(pi);
2699                 udelay(5);
2700                 wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
2701         } else {
2702                 wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
2703         }
2704
2705         write_phy_reg(pi, 0x6da, 0xffff);
2706
2707         for (i = n_cal_start; i < n_cal_cmds; i++) {
2708                 u16 zero_diq = 0;
2709                 u16 best_coeffs[11];
2710                 u16 command_num;
2711
2712                 cal_type = (cal_cmds[i] & 0x0f00) >> 8;
2713
2714                 command_num = command_nums[i];
2715                 if (ncorr_override[cal_type])
2716                         command_num =
2717                                 ncorr_override[cal_type] << 8 | (command_num &
2718                                                                  0xff);
2719
2720                 write_phy_reg(pi, 0x452, command_num);
2721
2722                 if ((cal_type == 3) || (cal_type == 4)) {
2723                         wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2724                                                      &diq_start, 1, 16, 69);
2725
2726                         wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2727                                                       &zero_diq, 1, 16, 69);
2728                 }
2729
2730                 write_phy_reg(pi, 0x451, cal_cmds[i]);
2731
2732                 if (!wlc_lcnphy_iqcal_wait(pi))
2733                         goto cleanup;
2734
2735                 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2736                                              best_coeffs,
2737                                              ARRAY_SIZE(best_coeffs), 16, 96);
2738                 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2739                                               best_coeffs,
2740                                               ARRAY_SIZE(best_coeffs), 16, 64);
2741
2742                 if ((cal_type == 3) || (cal_type == 4))
2743                         wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2744                                                       &diq_start, 1, 16, 69);
2745                 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2746                                              pi_lcn->lcnphy_cal_results.
2747                                              txiqlocal_bestcoeffs,
2748                                              ARRAY_SIZE(pi_lcn->
2749                                                         lcnphy_cal_results.
2750                                                         txiqlocal_bestcoeffs),
2751                                              16, 96);
2752         }
2753
2754         wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2755                                      pi_lcn->lcnphy_cal_results.
2756                                      txiqlocal_bestcoeffs,
2757                                      ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
2758                                                 txiqlocal_bestcoeffs), 16, 96);
2759         pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
2760
2761         wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2762                                       &pi_lcn->lcnphy_cal_results.
2763                                       txiqlocal_bestcoeffs[0], 4, 16, 80);
2764
2765         wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2766                                       &pi_lcn->lcnphy_cal_results.
2767                                       txiqlocal_bestcoeffs[5], 2, 16, 85);
2768
2769 cleanup:
2770         wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
2771         kfree(values_to_save);
2772
2773         if (!keep_tone)
2774                 wlc_lcnphy_stop_tx_tone(pi);
2775
2776         write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2);
2777
2778         write_phy_reg(pi, 0x453, 0);
2779
2780         if (tx_gain_override_old)
2781                 wlc_lcnphy_set_tx_gain(pi, &old_gains);
2782         wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old);
2783
2784         write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl);
2785         write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl);
2786
2787 }
2788
2789 static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
2790 {
2791         bool suspend, tx_gain_override_old;
2792         struct lcnphy_txgains old_gains;
2793         struct brcms_phy *pi = (struct brcms_phy *) ppi;
2794         u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB,
2795             idleTssi0_regvalue_2C;
2796         u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
2797         u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
2798         u16 SAVE_jtag_bb_afe_switch =
2799                 read_radio_reg(pi, RADIO_2064_REG007) & 1;
2800         u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
2801         u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
2802         idleTssi = read_phy_reg(pi, 0x4ab);
2803         suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
2804                          MCTL_EN_MAC));
2805         if (!suspend)
2806                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2807         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2808
2809         tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
2810         wlc_lcnphy_get_tx_gain(pi, &old_gains);
2811
2812         wlc_lcnphy_enable_tx_gain_override(pi);
2813         wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
2814         write_radio_reg(pi, RADIO_2064_REG112, 0x6);
2815         mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
2816         mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
2817         mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
2818         wlc_lcnphy_tssi_setup(pi);
2819         wlc_phy_do_dummy_tx(pi, true, OFF);
2820         idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
2821                     >> 0);
2822
2823         idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
2824                         >> 0);
2825
2826         if (idleTssi0_2C >= 256)
2827                 idleTssi0_OB = idleTssi0_2C - 256;
2828         else
2829                 idleTssi0_OB = idleTssi0_2C + 256;
2830
2831         idleTssi0_regvalue_OB = idleTssi0_OB;
2832         if (idleTssi0_regvalue_OB >= 256)
2833                 idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
2834         else
2835                 idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
2836         mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
2837
2838         mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
2839
2840         wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
2841         wlc_lcnphy_set_tx_gain(pi, &old_gains);
2842         wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
2843
2844         write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
2845         mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
2846         mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
2847         mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
2848         mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
2849         if (!suspend)
2850                 wlapi_enable_mac(pi->sh->physhim);
2851 }
2852
2853 static void wlc_lcnphy_vbat_temp_sense_setup(struct brcms_phy *pi, u8 mode)
2854 {
2855         bool suspend;
2856         u16 save_txpwrCtrlEn;
2857         u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
2858         u16 auxpga_vmid;
2859         struct phytbl_info tab;
2860         u32 val;
2861         u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
2862            save_reg112;
2863         u16 values_to_save[14];
2864         s8 index;
2865         int i;
2866         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2867         udelay(999);
2868
2869         save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
2870         save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
2871         save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
2872         save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
2873         save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
2874         save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
2875
2876         for (i = 0; i < 14; i++)
2877                 values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
2878         suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
2879                          MCTL_EN_MAC));
2880         if (!suspend)
2881                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2882         save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
2883
2884         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2885         index = pi_lcn->lcnphy_current_index;
2886         wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
2887         mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
2888         mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
2889         mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
2890         mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
2891
2892         mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
2893
2894         mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
2895
2896         mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
2897
2898         mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
2899
2900         mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
2901
2902         mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
2903
2904         mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
2905
2906         mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
2907
2908         mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
2909
2910         mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
2911
2912         mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
2913
2914         mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
2915
2916         mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
2917
2918         mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
2919
2920         mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
2921
2922         mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
2923
2924         mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
2925
2926         write_radio_reg(pi, RADIO_2064_REG025, 0xC);
2927
2928         mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
2929
2930         mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
2931
2932         mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
2933
2934         mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
2935
2936         val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
2937         tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
2938         tab.tbl_width = 16;
2939         tab.tbl_len = 1;
2940         tab.tbl_ptr = &val;
2941         tab.tbl_offset = 6;
2942         wlc_lcnphy_write_table(pi, &tab);
2943         if (mode == TEMPSENSE) {
2944                 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
2945
2946                 mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
2947
2948                 auxpga_vmidcourse = 8;
2949                 auxpga_vmidfine = 0x4;
2950                 auxpga_gain = 2;
2951                 mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
2952         } else {
2953                 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
2954
2955                 mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
2956
2957                 auxpga_vmidcourse = 7;
2958                 auxpga_vmidfine = 0xa;
2959                 auxpga_gain = 2;
2960         }
2961         auxpga_vmid =
2962                 (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
2963         mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
2964
2965         mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
2966
2967         mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
2968
2969         mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
2970
2971         mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
2972
2973         write_radio_reg(pi, RADIO_2064_REG112, 0x6);
2974
2975         wlc_phy_do_dummy_tx(pi, true, OFF);
2976         if (!tempsense_done(pi))
2977                 udelay(10);
2978
2979         write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
2980         write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
2981         write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
2982         write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
2983         write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
2984         write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
2985         for (i = 0; i < 14; i++)
2986                 write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
2987         wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
2988
2989         write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
2990         if (!suspend)
2991                 wlapi_enable_mac(pi->sh->physhim);
2992         udelay(999);
2993 }
2994
2995 static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
2996 {
2997         struct lcnphy_txgains tx_gains;
2998         u8 bbmult;
2999         struct phytbl_info tab;
3000         s32 a1, b0, b1;
3001         s32 tssi, pwr, maxtargetpwr, mintargetpwr;
3002         bool suspend;
3003         struct brcms_phy *pi = (struct brcms_phy *) ppi;
3004
3005         suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
3006                          MCTL_EN_MAC));
3007         if (!suspend)
3008                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
3009
3010         if (!pi->hwpwrctrl_capable) {
3011                 if (CHSPEC_IS2G(pi->radio_chanspec)) {
3012                         tx_gains.gm_gain = 4;
3013                         tx_gains.pga_gain = 12;
3014                         tx_gains.pad_gain = 12;
3015                         tx_gains.dac_gain = 0;
3016
3017                         bbmult = 150;
3018                 } else {
3019                         tx_gains.gm_gain = 7;
3020                         tx_gains.pga_gain = 15;
3021                         tx_gains.pad_gain = 14;
3022                         tx_gains.dac_gain = 0;
3023
3024                         bbmult = 150;
3025                 }
3026                 wlc_lcnphy_set_tx_gain(pi, &tx_gains);
3027                 wlc_lcnphy_set_bbmult(pi, bbmult);
3028                 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
3029         } else {
3030
3031                 wlc_lcnphy_idle_tssi_est(ppi);
3032
3033                 wlc_lcnphy_clear_tx_power_offsets(pi);
3034
3035                 b0 = pi->txpa_2g[0];
3036                 b1 = pi->txpa_2g[1];
3037                 a1 = pi->txpa_2g[2];
3038                 maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
3039                 mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
3040
3041                 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
3042                 tab.tbl_width = 32;
3043                 tab.tbl_ptr = &pwr;
3044                 tab.tbl_len = 1;
3045                 tab.tbl_offset = 0;
3046                 for (tssi = 0; tssi < 128; tssi++) {
3047                         pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
3048
3049                         pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
3050                         wlc_lcnphy_write_table(pi, &tab);
3051                         tab.tbl_offset++;
3052                 }
3053
3054                 mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
3055
3056                 write_phy_reg(pi, 0x4a8, 10);
3057
3058                 wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
3059
3060                 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
3061         }
3062         if (!suspend)
3063                 wlapi_enable_mac(pi->sh->physhim);
3064 }
3065
3066 static void wlc_lcnphy_set_pa_gain(struct brcms_phy *pi, u16 gain)
3067 {
3068         mod_phy_reg(pi, 0x4fb,
3069                     LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
3070                     gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
3071         mod_phy_reg(pi, 0x4fd,
3072                     LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
3073                     gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
3074 }
3075
3076 void
3077 wlc_lcnphy_get_radio_loft(struct brcms_phy *pi,
3078                           u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
3079 {
3080         *ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
3081         *eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
3082         *fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
3083         *fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
3084 }
3085
3086 void wlc_lcnphy_set_tx_iqcc(struct brcms_phy *pi, u16 a, u16 b)
3087 {
3088         struct phytbl_info tab;
3089         u16 iqcc[2];
3090
3091         iqcc[0] = a;
3092         iqcc[1] = b;
3093
3094         tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
3095         tab.tbl_width = 16;
3096         tab.tbl_ptr = iqcc;
3097         tab.tbl_len = 2;
3098         tab.tbl_offset = 80;
3099         wlc_lcnphy_write_table(pi, &tab);
3100 }
3101
3102 void wlc_lcnphy_set_tx_locc(struct brcms_phy *pi, u16 didq)
3103 {
3104         struct phytbl_info tab;
3105
3106         tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
3107         tab.tbl_width = 16;
3108         tab.tbl_ptr = &didq;
3109         tab.tbl_len = 1;
3110         tab.tbl_offset = 85;
3111         wlc_lcnphy_write_table(pi, &tab);
3112 }
3113
3114 void wlc_lcnphy_set_tx_pwr_by_index(struct brcms_phy *pi, int index)
3115 {
3116         struct phytbl_info tab;
3117         u16 a, b;
3118         u8 bb_mult;
3119         u32 bbmultiqcomp, txgain, locoeffs, rfpower;
3120         struct lcnphy_txgains gains;
3121         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3122
3123         pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
3124         pi_lcn->lcnphy_current_index = (u8) index;
3125
3126         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
3127         tab.tbl_width = 32;
3128         tab.tbl_len = 1;
3129
3130         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
3131
3132         tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
3133         tab.tbl_ptr = &bbmultiqcomp;
3134         wlc_lcnphy_read_table(pi, &tab);
3135
3136         tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
3137         tab.tbl_width = 32;
3138         tab.tbl_ptr = &txgain;
3139         wlc_lcnphy_read_table(pi, &tab);
3140
3141         gains.gm_gain = (u16) (txgain & 0xff);
3142         gains.pga_gain = (u16) (txgain >> 8) & 0xff;
3143         gains.pad_gain = (u16) (txgain >> 16) & 0xff;
3144         gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
3145         wlc_lcnphy_set_tx_gain(pi, &gains);
3146         wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
3147
3148         bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
3149         wlc_lcnphy_set_bbmult(pi, bb_mult);
3150
3151         wlc_lcnphy_enable_tx_gain_override(pi);
3152
3153         if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
3154
3155                 a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
3156                 b = (u16) (bbmultiqcomp & 0x3ff);
3157                 wlc_lcnphy_set_tx_iqcc(pi, a, b);
3158
3159                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
3160                 tab.tbl_ptr = &locoeffs;
3161                 wlc_lcnphy_read_table(pi, &tab);
3162
3163                 wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
3164
3165                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
3166                 tab.tbl_ptr = &rfpower;
3167                 wlc_lcnphy_read_table(pi, &tab);
3168                 mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
3169
3170         }
3171 }
3172
3173 static void wlc_lcnphy_clear_papd_comptable(struct brcms_phy *pi)
3174 {
3175         u32 j;
3176         struct phytbl_info tab;
3177         u32 temp_offset[128];
3178         tab.tbl_ptr = temp_offset;
3179         tab.tbl_len = 128;
3180         tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
3181         tab.tbl_width = 32;
3182         tab.tbl_offset = 0;
3183
3184         memset(temp_offset, 0, sizeof(temp_offset));
3185         for (j = 1; j < 128; j += 2)
3186                 temp_offset[j] = 0x80000;
3187
3188         wlc_lcnphy_write_table(pi, &tab);
3189         return;
3190 }
3191
3192 void wlc_lcnphy_tx_pu(struct brcms_phy *pi, bool bEnable)
3193 {
3194         if (!bEnable) {
3195
3196                 and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
3197
3198                 mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
3199
3200                 and_phy_reg(pi, 0x44c,
3201                             ~(u16) ((0x1 << 3) |
3202                                     (0x1 << 5) |
3203                                     (0x1 << 12) |
3204                                     (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
3205
3206                 and_phy_reg(pi, 0x44d,
3207                             ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
3208                 mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
3209
3210                 mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
3211
3212                 and_phy_reg(pi, 0x4f9,
3213                             ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
3214
3215                 and_phy_reg(pi, 0x4fa,
3216                             ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
3217         } else {
3218
3219                 mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
3220                 mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
3221
3222                 mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
3223                 mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
3224
3225                 mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
3226                 mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
3227
3228                 wlc_lcnphy_set_trsw_override(pi, true, false);
3229
3230                 mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
3231                 mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
3232
3233                 if (CHSPEC_IS2G(pi->radio_chanspec)) {
3234
3235                         mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
3236                         mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
3237
3238                         mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
3239                         mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
3240
3241                         mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
3242                         mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
3243
3244                         mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
3245                         mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
3246
3247                         mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
3248                         mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
3249                 } else {
3250
3251                         mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
3252                         mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
3253
3254                         mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
3255                         mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
3256
3257                         mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
3258                         mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
3259
3260                         mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
3261                         mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
3262
3263                         mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
3264                         mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
3265                 }
3266         }
3267 }
3268
3269 static void
3270 wlc_lcnphy_run_samples(struct brcms_phy *pi,
3271                        u16 num_samps,
3272                        u16 num_loops, u16 wait, bool iqcalmode)
3273 {
3274
3275         or_phy_reg(pi, 0x6da, 0x8080);
3276
3277         mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
3278         if (num_loops != 0xffff)
3279                 num_loops--;
3280         mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
3281
3282         mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
3283
3284         if (iqcalmode) {
3285
3286                 and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
3287                 or_phy_reg(pi, 0x453, (0x1 << 15));
3288         } else {
3289                 write_phy_reg(pi, 0x63f, 1);
3290                 wlc_lcnphy_tx_pu(pi, 1);
3291         }
3292
3293         or_radio_reg(pi, RADIO_2064_REG112, 0x6);
3294 }
3295
3296 void wlc_lcnphy_deaf_mode(struct brcms_phy *pi, bool mode)
3297 {
3298
3299         u8 phybw40;
3300         phybw40 = CHSPEC_IS40(pi->radio_chanspec);
3301
3302         if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
3303                 mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
3304                 mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
3305         } else {
3306                 mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
3307                 mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
3308         }
3309
3310         if (phybw40 == 0) {
3311                 mod_phy_reg((pi), 0x410,
3312                             (0x1 << 6) |
3313                             (0x1 << 5),
3314                             ((CHSPEC_IS2G(
3315                                       pi->radio_chanspec)) ? (!mode) : 0) <<
3316                             6 | (!mode) << 5);
3317                 mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
3318         }
3319 }
3320
3321 void
3322 wlc_lcnphy_start_tx_tone(struct brcms_phy *pi, s32 f_kHz, u16 max_val,
3323                          bool iqcalmode)
3324 {
3325         u8 phy_bw;
3326         u16 num_samps, t, k;
3327         u32 bw;
3328         s32 theta = 0, rot = 0;
3329         struct cordic_iq tone_samp;
3330         u32 data_buf[64];
3331         u16 i_samp, q_samp;
3332         struct phytbl_info tab;
3333         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3334
3335         pi->phy_tx_tone_freq = f_kHz;
3336
3337         wlc_lcnphy_deaf_mode(pi, true);
3338
3339         phy_bw = 40;
3340         if (pi_lcn->lcnphy_spurmod) {
3341                 write_phy_reg(pi, 0x942, 0x2);
3342                 write_phy_reg(pi, 0x93b, 0x0);
3343                 write_phy_reg(pi, 0x93c, 0x0);
3344                 wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
3345         }
3346
3347         if (f_kHz) {
3348                 k = 1;
3349                 do {
3350                         bw = phy_bw * 1000 * k;
3351                         num_samps = bw / abs(f_kHz);
3352                         k++;
3353                 } while ((num_samps * (u32) (abs(f_kHz))) != bw);
3354         } else
3355                 num_samps = 2;
3356
3357         rot = ((f_kHz * 36) / phy_bw) / 100;
3358         theta = 0;
3359
3360         for (t = 0; t < num_samps; t++) {
3361
3362                 tone_samp = cordic_calc_iq(theta);
3363
3364                 theta += rot;
3365
3366                 i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
3367                 q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
3368                 data_buf[t] = (i_samp << 10) | q_samp;
3369         }
3370
3371         mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
3372
3373         mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
3374
3375         tab.tbl_ptr = data_buf;
3376         tab.tbl_len = num_samps;
3377         tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
3378         tab.tbl_offset = 0;
3379         tab.tbl_width = 32;
3380         wlc_lcnphy_write_table(pi, &tab);
3381
3382         wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
3383 }
3384
3385 void wlc_lcnphy_stop_tx_tone(struct brcms_phy *pi)
3386 {
3387         s16 playback_status;
3388         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3389
3390         pi->phy_tx_tone_freq = 0;
3391         if (pi_lcn->lcnphy_spurmod) {
3392                 write_phy_reg(pi, 0x942, 0x7);
3393                 write_phy_reg(pi, 0x93b, 0x2017);
3394                 write_phy_reg(pi, 0x93c, 0x27c5);
3395                 wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
3396         }
3397
3398         playback_status = read_phy_reg(pi, 0x644);
3399         if (playback_status & (0x1 << 0)) {
3400                 wlc_lcnphy_tx_pu(pi, 0);
3401                 mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
3402         } else if (playback_status & (0x1 << 1))
3403                 mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
3404
3405         mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
3406
3407         mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
3408
3409         mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
3410
3411         and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
3412
3413         wlc_lcnphy_deaf_mode(pi, false);
3414 }
3415
3416 static void
3417 wlc_lcnphy_set_cc(struct brcms_phy *pi, int cal_type, s16 coeff_x, s16 coeff_y)
3418 {
3419         u16 di0dq0;
3420         u16 x, y, data_rf;
3421         int k;
3422         switch (cal_type) {
3423         case 0:
3424                 wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
3425                 break;
3426         case 2:
3427                 di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
3428                 wlc_lcnphy_set_tx_locc(pi, di0dq0);
3429                 break;
3430         case 3:
3431                 k = wlc_lcnphy_calc_floor(coeff_x, 0);
3432                 y = 8 + k;
3433                 k = wlc_lcnphy_calc_floor(coeff_x, 1);
3434                 x = 8 - k;
3435                 data_rf = (x * 16 + y);
3436                 write_radio_reg(pi, RADIO_2064_REG089, data_rf);
3437                 k = wlc_lcnphy_calc_floor(coeff_y, 0);
3438                 y = 8 + k;
3439                 k = wlc_lcnphy_calc_floor(coeff_y, 1);
3440                 x = 8 - k;
3441                 data_rf = (x * 16 + y);
3442                 write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
3443                 break;
3444         case 4:
3445                 k = wlc_lcnphy_calc_floor(coeff_x, 0);
3446                 y = 8 + k;
3447                 k = wlc_lcnphy_calc_floor(coeff_x, 1);
3448                 x = 8 - k;
3449                 data_rf = (x * 16 + y);
3450                 write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
3451                 k = wlc_lcnphy_calc_floor(coeff_y, 0);
3452                 y = 8 + k;
3453                 k = wlc_lcnphy_calc_floor(coeff_y, 1);
3454                 x = 8 - k;
3455                 data_rf = (x * 16 + y);
3456                 write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
3457                 break;
3458         }
3459 }
3460
3461 static struct lcnphy_unsign16_struct
3462 wlc_lcnphy_get_cc(struct brcms_phy *pi, int cal_type)
3463 {
3464         u16 a, b, didq;
3465         u8 di0, dq0, ei, eq, fi, fq;
3466         struct lcnphy_unsign16_struct cc;
3467         cc.re = 0;
3468         cc.im = 0;
3469         switch (cal_type) {
3470         case 0:
3471                 wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
3472                 cc.re = a;
3473                 cc.im = b;
3474                 break;
3475         case 2:
3476                 didq = wlc_lcnphy_get_tx_locc(pi);
3477                 di0 = (((didq & 0xff00) << 16) >> 24);
3478                 dq0 = (((didq & 0x00ff) << 24) >> 24);
3479                 cc.re = (u16) di0;
3480                 cc.im = (u16) dq0;
3481                 break;
3482         case 3:
3483                 wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
3484                 cc.re = (u16) ei;
3485                 cc.im = (u16) eq;
3486                 break;
3487         case 4:
3488                 wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
3489                 cc.re = (u16) fi;
3490                 cc.im = (u16) fq;
3491                 break;
3492         }
3493         return cc;
3494 }
3495
3496 static void
3497 wlc_lcnphy_samp_cap(struct brcms_phy *pi, int clip_detect_algo, u16 thresh,
3498                     s16 *ptr, int mode)
3499 {
3500         u32 curval1, curval2, stpptr, curptr, strptr, val;
3501         u16 sslpnCalibClkEnCtrl, timer;
3502         u16 old_sslpnCalibClkEnCtrl;
3503         s16 imag, real;
3504         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3505
3506         timer = 0;
3507         old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
3508
3509         curval1 = bcma_read16(pi->d11core, D11REGOFFS(psm_corectlsts));
3510         ptr[130] = 0;
3511         bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts),
3512                      ((1 << 6) | curval1));
3513
3514         bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_strptr), 0x7E00);
3515         bcma_write16(pi->d11core, D11REGOFFS(smpl_clct_stpptr), 0x8000);
3516         udelay(20);
3517         curval2 = bcma_read16(pi->d11core, D11REGOFFS(psm_phy_hdr_param));
3518         bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param),
3519                      curval2 | 0x30);
3520
3521         write_phy_reg(pi, 0x555, 0x0);
3522         write_phy_reg(pi, 0x5a6, 0x5);
3523
3524         write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
3525         write_phy_reg(pi, 0x5cf, 3);
3526         write_phy_reg(pi, 0x5a5, 0x3);
3527         write_phy_reg(pi, 0x583, 0x0);
3528         write_phy_reg(pi, 0x584, 0x0);
3529         write_phy_reg(pi, 0x585, 0x0fff);
3530         write_phy_reg(pi, 0x586, 0x0000);
3531
3532         write_phy_reg(pi, 0x580, 0x4501);
3533
3534         sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
3535         write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
3536         stpptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_stpptr));
3537         curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
3538         do {
3539                 udelay(10);
3540                 curptr = bcma_read16(pi->d11core, D11REGOFFS(smpl_clct_curptr));
3541                 timer++;
3542         } while ((curptr != stpptr) && (timer < 500));
3543
3544         bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), 0x2);
3545         strptr = 0x7E00;
3546         bcma_write32(pi->d11core, D11REGOFFS(tplatewrptr), strptr);
3547         while (strptr < 0x8000) {
3548                 val = bcma_read32(pi->d11core, D11REGOFFS(tplatewrdata));
3549                 imag = ((val >> 16) & 0x3ff);
3550                 real = ((val) & 0x3ff);
3551                 if (imag > 511)
3552                         imag -= 1024;
3553
3554                 if (real > 511)
3555                         real -= 1024;
3556
3557                 if (pi_lcn->lcnphy_iqcal_swp_dis)
3558                         ptr[(strptr - 0x7E00) / 4] = real;
3559                 else
3560                         ptr[(strptr - 0x7E00) / 4] = imag;
3561
3562                 if (clip_detect_algo) {
3563                         if (imag > thresh || imag < -thresh) {
3564                                 strptr = 0x8000;
3565                                 ptr[130] = 1;
3566                         }
3567                 }
3568
3569                 strptr += 4;
3570         }
3571
3572         write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
3573         bcma_write16(pi->d11core, D11REGOFFS(psm_phy_hdr_param), curval2);
3574         bcma_write16(pi->d11core, D11REGOFFS(psm_corectlsts), curval1);
3575 }
3576
3577 static void
3578 wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels,
3579               int step_size_lg2)
3580 {
3581         const struct lcnphy_spb_tone *phy_c1;
3582         struct lcnphy_spb_tone phy_c2;
3583         struct lcnphy_unsign16_struct phy_c3;
3584         int phy_c4, phy_c5, k, l, j, phy_c6;
3585         u16 phy_c7, phy_c8, phy_c9;
3586         s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
3587         s16 *ptr, phy_c17;
3588         s32 phy_c18, phy_c19;
3589         u32 phy_c20, phy_c21;
3590         bool phy_c22, phy_c23, phy_c24, phy_c25;
3591         u16 phy_c26, phy_c27;
3592         u16 phy_c28, phy_c29, phy_c30;
3593         u16 phy_c31;
3594         u16 *phy_c32;
3595         phy_c21 = 0;
3596         phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
3597         ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
3598         if (NULL == ptr)
3599                 return;
3600
3601         phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
3602         if (NULL == phy_c32) {
3603                 kfree(ptr);
3604                 return;
3605         }
3606         phy_c26 = read_phy_reg(pi, 0x6da);
3607         phy_c27 = read_phy_reg(pi, 0x6db);
3608         phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
3609         write_phy_reg(pi, 0x93d, 0xC0);
3610
3611         wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
3612         write_phy_reg(pi, 0x6da, 0xffff);
3613         or_phy_reg(pi, 0x6db, 0x3);
3614
3615         wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
3616         udelay(500);
3617         phy_c28 = read_phy_reg(pi, 0x938);
3618         phy_c29 = read_phy_reg(pi, 0x4d7);
3619         phy_c30 = read_phy_reg(pi, 0x4d8);
3620         or_phy_reg(pi, 0x938, 0x1 << 2);
3621         or_phy_reg(pi, 0x4d7, 0x1 << 2);
3622         or_phy_reg(pi, 0x4d7, 0x1 << 3);
3623         mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
3624         or_phy_reg(pi, 0x4d8, 1 << 0);
3625         or_phy_reg(pi, 0x4d8, 1 << 1);
3626         mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
3627         mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
3628         phy_c1 = &lcnphy_spb_tone_3750[0];
3629         phy_c4 = 32;
3630
3631         if (num_levels == 0) {
3632                 if (cal_type != 0)
3633                         num_levels = 4;
3634                 else
3635                         num_levels = 9;
3636         }
3637         if (step_size_lg2 == 0) {
3638                 if (cal_type != 0)
3639                         step_size_lg2 = 3;
3640                 else
3641                         step_size_lg2 = 8;
3642         }
3643
3644         phy_c7 = (1 << step_size_lg2);
3645         phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
3646         phy_c15 = (s16) phy_c3.re;
3647         phy_c16 = (s16) phy_c3.im;
3648         if (cal_type == 2) {
3649                 if (phy_c3.re > 127)
3650                         phy_c15 = phy_c3.re - 256;
3651                 if (phy_c3.im > 127)
3652                         phy_c16 = phy_c3.im - 256;
3653         }
3654         wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
3655         udelay(20);
3656         for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
3657                 phy_c23 = true;
3658                 phy_c22 = false;
3659                 switch (cal_type) {
3660                 case 0:
3661                         phy_c10 = 511;
3662                         break;
3663                 case 2:
3664                         phy_c10 = 127;
3665                         break;
3666                 case 3:
3667                         phy_c10 = 15;
3668                         break;
3669                 case 4:
3670                         phy_c10 = 15;
3671                         break;
3672                 }
3673
3674                 phy_c9 = read_phy_reg(pi, 0x93d);
3675                 phy_c9 = 2 * phy_c9;
3676                 phy_c24 = false;
3677                 phy_c5 = 7;
3678                 phy_c25 = true;
3679                 while (1) {
3680                         write_radio_reg(pi, RADIO_2064_REG026,
3681                                         (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
3682                         udelay(50);
3683                         phy_c22 = false;
3684                         ptr[130] = 0;
3685                         wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
3686                         if (ptr[130] == 1)
3687                                 phy_c22 = true;
3688                         if (phy_c22)
3689                                 phy_c5 -= 1;
3690                         if ((phy_c22 != phy_c24) && (!phy_c25))
3691                                 break;
3692                         if (!phy_c22)
3693                                 phy_c5 += 1;
3694                         if (phy_c5 <= 0 || phy_c5 >= 7)
3695                                 break;
3696                         phy_c24 = phy_c22;
3697                         phy_c25 = false;
3698                 }
3699
3700                 if (phy_c5 < 0)
3701                         phy_c5 = 0;
3702                 else if (phy_c5 > 7)
3703                         phy_c5 = 7;
3704
3705                 for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
3706                         for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
3707                                 phy_c11 = phy_c15 + k;
3708                                 phy_c12 = phy_c16 + l;
3709
3710                                 if (phy_c11 < -phy_c10)
3711                                         phy_c11 = -phy_c10;
3712                                 else if (phy_c11 > phy_c10)
3713                                         phy_c11 = phy_c10;
3714                                 if (phy_c12 < -phy_c10)
3715                                         phy_c12 = -phy_c10;
3716                                 else if (phy_c12 > phy_c10)
3717                                         phy_c12 = phy_c10;
3718                                 wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
3719                                                   phy_c12);
3720                                 udelay(20);
3721                                 wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
3722
3723                                 phy_c18 = 0;
3724                                 phy_c19 = 0;
3725                                 for (j = 0; j < 128; j++) {
3726                                         if (cal_type != 0)
3727                                                 phy_c6 = j % phy_c4;
3728                                         else
3729                                                 phy_c6 = (2 * j) % phy_c4;
3730
3731                                         phy_c2.re = phy_c1[phy_c6].re;
3732                                         phy_c2.im = phy_c1[phy_c6].im;
3733                                         phy_c17 = ptr[j];
3734                                         phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
3735                                         phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
3736                                 }
3737
3738                                 phy_c18 = phy_c18 >> 10;
3739                                 phy_c19 = phy_c19 >> 10;
3740                                 phy_c20 = ((phy_c18 * phy_c18) +
3741                                            (phy_c19 * phy_c19));
3742
3743                                 if (phy_c23 || phy_c20 < phy_c21) {
3744                                         phy_c21 = phy_c20;
3745                                         phy_c13 = phy_c11;
3746                                         phy_c14 = phy_c12;
3747                                 }
3748                                 phy_c23 = false;
3749                         }
3750                 }
3751                 phy_c23 = true;
3752                 phy_c15 = phy_c13;
3753                 phy_c16 = phy_c14;
3754                 phy_c7 = phy_c7 >> 1;
3755                 wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
3756                 udelay(20);
3757         }
3758         goto cleanup;
3759 cleanup:
3760         wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
3761         wlc_lcnphy_stop_tx_tone(pi);
3762         write_phy_reg(pi, 0x6da, phy_c26);
3763         write_phy_reg(pi, 0x6db, phy_c27);
3764         write_phy_reg(pi, 0x938, phy_c28);
3765         write_phy_reg(pi, 0x4d7, phy_c29);
3766         write_phy_reg(pi, 0x4d8, phy_c30);
3767         write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
3768
3769         kfree(phy_c32);
3770         kfree(ptr);
3771 }
3772
3773 void wlc_lcnphy_get_tx_iqcc(struct brcms_phy *pi, u16 *a, u16 *b)
3774 {
3775         u16 iqcc[2];
3776         struct phytbl_info tab;
3777
3778         tab.tbl_ptr = iqcc;
3779         tab.tbl_len = 2;
3780         tab.tbl_id = 0;
3781         tab.tbl_offset = 80;
3782         tab.tbl_width = 16;
3783         wlc_lcnphy_read_table(pi, &tab);
3784
3785         *a = iqcc[0];
3786         *b = iqcc[1];
3787 }
3788
3789 static void wlc_lcnphy_tx_iqlo_soft_cal_full(struct brcms_phy *pi)
3790 {
3791         struct lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
3792
3793         wlc_lcnphy_set_cc(pi, 0, 0, 0);
3794         wlc_lcnphy_set_cc(pi, 2, 0, 0);
3795         wlc_lcnphy_set_cc(pi, 3, 0, 0);
3796         wlc_lcnphy_set_cc(pi, 4, 0, 0);
3797
3798         wlc_lcnphy_a1(pi, 4, 0, 0);
3799         wlc_lcnphy_a1(pi, 3, 0, 0);
3800         wlc_lcnphy_a1(pi, 2, 3, 2);
3801         wlc_lcnphy_a1(pi, 0, 5, 8);
3802         wlc_lcnphy_a1(pi, 2, 2, 1);
3803         wlc_lcnphy_a1(pi, 0, 4, 3);
3804
3805         iqcc0 = wlc_lcnphy_get_cc(pi, 0);
3806         locc2 = wlc_lcnphy_get_cc(pi, 2);
3807         locc3 = wlc_lcnphy_get_cc(pi, 3);
3808         locc4 = wlc_lcnphy_get_cc(pi, 4);
3809 }
3810
3811 u16 wlc_lcnphy_get_tx_locc(struct brcms_phy *pi)
3812 {
3813         struct phytbl_info tab;
3814         u16 didq;
3815
3816         tab.tbl_id = 0;
3817         tab.tbl_width = 16;
3818         tab.tbl_ptr = &didq;
3819         tab.tbl_len = 1;
3820         tab.tbl_offset = 85;
3821         wlc_lcnphy_read_table(pi, &tab);
3822
3823         return didq;
3824 }
3825
3826 static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
3827 {
3828
3829         struct lcnphy_txgains target_gains, old_gains;
3830         u8 save_bb_mult;
3831         u16 a, b, didq, save_pa_gain = 0;
3832         uint idx, SAVE_txpwrindex = 0xFF;
3833         u32 val;
3834         u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
3835         struct phytbl_info tab;
3836         u8 ei0, eq0, fi0, fq0;
3837         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3838
3839         wlc_lcnphy_get_tx_gain(pi, &old_gains);
3840         save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
3841
3842         save_bb_mult = wlc_lcnphy_get_bbmult(pi);
3843
3844         if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
3845                 SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
3846
3847         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
3848
3849         target_gains.gm_gain = 7;
3850         target_gains.pga_gain = 0;
3851         target_gains.pad_gain = 21;
3852         target_gains.dac_gain = 0;
3853         wlc_lcnphy_set_tx_gain(pi, &target_gains);
3854         wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
3855
3856         if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
3857
3858                 wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
3859
3860                 wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
3861                                        (pi_lcn->
3862                                         lcnphy_recal ? LCNPHY_CAL_RECAL :
3863                                         LCNPHY_CAL_FULL), false);
3864         } else {
3865                 wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
3866         }
3867
3868         wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
3869         if ((abs((s8) fi0) == 15) && (abs((s8) fq0) == 15)) {
3870                 if (CHSPEC_IS5G(pi->radio_chanspec)) {
3871                         target_gains.gm_gain = 255;
3872                         target_gains.pga_gain = 255;
3873                         target_gains.pad_gain = 0xf0;
3874                         target_gains.dac_gain = 0;
3875                 } else {
3876                         target_gains.gm_gain = 7;
3877                         target_gains.pga_gain = 45;
3878                         target_gains.pad_gain = 186;
3879                         target_gains.dac_gain = 0;
3880                 }
3881
3882                 if (LCNREV_IS(pi->pubpi.phy_rev, 1)
3883                     || pi_lcn->lcnphy_hw_iqcal_en) {
3884
3885                         target_gains.pga_gain = 0;
3886                         target_gains.pad_gain = 30;
3887                         wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
3888                         wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
3889                                                LCNPHY_CAL_FULL, false);
3890                 } else {
3891                         wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
3892                 }
3893         }
3894
3895         wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
3896
3897         didq = wlc_lcnphy_get_tx_locc(pi);
3898
3899         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
3900         tab.tbl_width = 32;
3901         tab.tbl_ptr = &val;
3902
3903         tab.tbl_len = 1;
3904         tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
3905
3906         for (idx = 0; idx < 128; idx++) {
3907                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
3908
3909                 wlc_lcnphy_read_table(pi, &tab);
3910                 val = (val & 0xfff00000) |
3911                       ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
3912                 wlc_lcnphy_write_table(pi, &tab);
3913
3914                 val = didq;
3915                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
3916                 wlc_lcnphy_write_table(pi, &tab);
3917         }
3918
3919         pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
3920         pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
3921         pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
3922         pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
3923         pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
3924         pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
3925         pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
3926
3927         wlc_lcnphy_set_bbmult(pi, save_bb_mult);
3928         wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
3929         wlc_lcnphy_set_tx_gain(pi, &old_gains);
3930
3931         if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
3932                 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
3933         else
3934                 wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
3935 }
3936
3937 s16 wlc_lcnphy_tempsense_new(struct brcms_phy *pi, bool mode)
3938 {
3939         u16 tempsenseval1, tempsenseval2;
3940         s16 avg = 0;
3941         bool suspend = false;
3942
3943         if (mode == 1) {
3944                 suspend = (0 == (bcma_read32(pi->d11core,
3945                                              D11REGOFFS(maccontrol)) &
3946                                  MCTL_EN_MAC));
3947                 if (!suspend)
3948                         wlapi_suspend_mac_and_wait(pi->sh->physhim);
3949                 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
3950         }
3951         tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
3952         tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
3953
3954         if (tempsenseval1 > 255)
3955                 avg = (s16) (tempsenseval1 - 512);
3956         else
3957                 avg = (s16) tempsenseval1;
3958
3959         if (tempsenseval2 > 255)
3960                 avg += (s16) (tempsenseval2 - 512);
3961         else
3962                 avg += (s16) tempsenseval2;
3963
3964         avg /= 2;
3965
3966         if (mode == 1) {
3967
3968                 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
3969
3970                 udelay(100);
3971                 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
3972
3973                 if (!suspend)
3974                         wlapi_enable_mac(pi->sh->physhim);
3975         }
3976         return avg;
3977 }
3978
3979 u16 wlc_lcnphy_tempsense(struct brcms_phy *pi, bool mode)
3980 {
3981         u16 tempsenseval1, tempsenseval2;
3982         s32 avg = 0;
3983         bool suspend = false;
3984         u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
3985         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
3986
3987         if (mode == 1) {
3988                 suspend = (0 == (bcma_read32(pi->d11core,
3989                                              D11REGOFFS(maccontrol)) &
3990                                  MCTL_EN_MAC));
3991                 if (!suspend)
3992                         wlapi_suspend_mac_and_wait(pi->sh->physhim);
3993                 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
3994         }
3995         tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
3996         tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
3997
3998         if (tempsenseval1 > 255)
3999                 avg = (int)(tempsenseval1 - 512);
4000         else
4001                 avg = (int)tempsenseval1;
4002
4003         if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
4004                 if (tempsenseval2 > 255)
4005                         avg = (int)(avg - tempsenseval2 + 512);
4006                 else
4007                         avg = (int)(avg - tempsenseval2);
4008         } else {
4009                 if (tempsenseval2 > 255)
4010                         avg = (int)(avg + tempsenseval2 - 512);
4011                 else
4012                         avg = (int)(avg + tempsenseval2);
4013                 avg = avg / 2;
4014         }
4015         if (avg < 0)
4016                 avg = avg + 512;
4017
4018         if (pi_lcn->lcnphy_tempsense_option == 2)
4019                 avg = tempsenseval1;
4020
4021         if (mode)
4022                 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
4023
4024         if (mode == 1) {
4025
4026                 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
4027
4028                 udelay(100);
4029                 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
4030
4031                 if (!suspend)
4032                         wlapi_enable_mac(pi->sh->physhim);
4033         }
4034         return (u16) avg;
4035 }
4036
4037 s8 wlc_lcnphy_tempsense_degree(struct brcms_phy *pi, bool mode)
4038 {
4039         s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
4040         degree =
4041                 ((degree <<
4042                   10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
4043                 / LCN_TEMPSENSE_DEN;
4044         return (s8) degree;
4045 }
4046
4047 s8 wlc_lcnphy_vbatsense(struct brcms_phy *pi, bool mode)
4048 {
4049         u16 vbatsenseval;
4050         s32 avg = 0;
4051         bool suspend = false;
4052
4053         if (mode == 1) {
4054                 suspend = (0 == (bcma_read32(pi->d11core,
4055                                              D11REGOFFS(maccontrol)) &
4056                                  MCTL_EN_MAC));
4057                 if (!suspend)
4058                         wlapi_suspend_mac_and_wait(pi->sh->physhim);
4059                 wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
4060         }
4061
4062         vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
4063
4064         if (vbatsenseval > 255)
4065                 avg = (s32) (vbatsenseval - 512);
4066         else
4067                 avg = (s32) vbatsenseval;
4068
4069         avg =   (avg * LCN_VBAT_SCALE_NOM +
4070                  (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
4071
4072         if (mode == 1) {
4073                 if (!suspend)
4074                         wlapi_enable_mac(pi->sh->physhim);
4075         }
4076         return (s8) avg;
4077 }
4078
4079 static void wlc_lcnphy_afe_clk_init(struct brcms_phy *pi, u8 mode)
4080 {
4081         u8 phybw40;
4082         phybw40 = CHSPEC_IS40(pi->radio_chanspec);
4083
4084         mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
4085
4086         if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
4087             (mode == AFE_CLK_INIT_MODE_TXRX2X))
4088                 write_phy_reg(pi, 0x6d0, 0x7);
4089
4090         wlc_lcnphy_toggle_afe_pwdn(pi);
4091 }
4092
4093 static void wlc_lcnphy_temp_adj(struct brcms_phy *pi)
4094 {
4095 }
4096
4097 static void wlc_lcnphy_glacial_timer_based_cal(struct brcms_phy *pi)
4098 {
4099         bool suspend;
4100         s8 index;
4101         u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
4102         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4103         suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
4104                          MCTL_EN_MAC));
4105         if (!suspend)
4106                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
4107         wlc_lcnphy_deaf_mode(pi, true);
4108         pi->phy_lastcal = pi->sh->now;
4109         pi->phy_forcecal = false;
4110         index = pi_lcn->lcnphy_current_index;
4111
4112         wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
4113
4114         wlc_lcnphy_set_tx_pwr_by_index(pi, index);
4115         wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
4116         wlc_lcnphy_deaf_mode(pi, false);
4117         if (!suspend)
4118                 wlapi_enable_mac(pi->sh->physhim);
4119
4120 }
4121
4122 static void wlc_lcnphy_periodic_cal(struct brcms_phy *pi)
4123 {
4124         bool suspend, full_cal;
4125         const struct lcnphy_rx_iqcomp *rx_iqcomp;
4126         int rx_iqcomp_sz;
4127         u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
4128         s8 index;
4129         struct phytbl_info tab;
4130         s32 a1, b0, b1;
4131         s32 tssi, pwr, maxtargetpwr, mintargetpwr;
4132         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4133
4134         pi->phy_lastcal = pi->sh->now;
4135         pi->phy_forcecal = false;
4136         full_cal =
4137                 (pi_lcn->lcnphy_full_cal_channel !=
4138                  CHSPEC_CHANNEL(pi->radio_chanspec));
4139         pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
4140         index = pi_lcn->lcnphy_current_index;
4141
4142         suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
4143                          MCTL_EN_MAC));
4144         if (!suspend) {
4145                 wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
4146                 wlapi_suspend_mac_and_wait(pi->sh->physhim);
4147         }
4148
4149         wlc_lcnphy_deaf_mode(pi, true);
4150
4151         wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
4152
4153         rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
4154         rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
4155
4156         if (LCNREV_IS(pi->pubpi.phy_rev, 1))
4157                 wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
4158         else
4159                 wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
4160
4161         if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
4162
4163                 wlc_lcnphy_idle_tssi_est((struct brcms_phy_pub *) pi);
4164
4165                 b0 = pi->txpa_2g[0];
4166                 b1 = pi->txpa_2g[1];
4167                 a1 = pi->txpa_2g[2];
4168                 maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
4169                 mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
4170
4171                 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4172                 tab.tbl_width = 32;
4173                 tab.tbl_ptr = &pwr;
4174                 tab.tbl_len = 1;
4175                 tab.tbl_offset = 0;
4176                 for (tssi = 0; tssi < 128; tssi++) {
4177                         pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
4178                         pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
4179                         wlc_lcnphy_write_table(pi, &tab);
4180                         tab.tbl_offset++;
4181                 }
4182         }
4183
4184         wlc_lcnphy_set_tx_pwr_by_index(pi, index);
4185         wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
4186         wlc_lcnphy_deaf_mode(pi, false);
4187         if (!suspend)
4188                 wlapi_enable_mac(pi->sh->physhim);
4189 }
4190
4191 void wlc_lcnphy_calib_modes(struct brcms_phy *pi, uint mode)
4192 {
4193         u16 temp_new;
4194         int temp1, temp2, temp_diff;
4195         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4196
4197         switch (mode) {
4198         case PHY_PERICAL_CHAN:
4199                 break;
4200         case PHY_FULLCAL:
4201                 wlc_lcnphy_periodic_cal(pi);
4202                 break;
4203         case PHY_PERICAL_PHYINIT:
4204                 wlc_lcnphy_periodic_cal(pi);
4205                 break;
4206         case PHY_PERICAL_WATCHDOG:
4207                 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
4208                         temp_new = wlc_lcnphy_tempsense(pi, 0);
4209                         temp1 = LCNPHY_TEMPSENSE(temp_new);
4210                         temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
4211                         temp_diff = temp1 - temp2;
4212                         if ((pi_lcn->lcnphy_cal_counter > 90) ||
4213                             (temp_diff > 60) || (temp_diff < -60)) {
4214                                 wlc_lcnphy_glacial_timer_based_cal(pi);
4215                                 wlc_2064_vco_cal(pi);
4216                                 pi_lcn->lcnphy_cal_temper = temp_new;
4217                                 pi_lcn->lcnphy_cal_counter = 0;
4218                         } else
4219                                 pi_lcn->lcnphy_cal_counter++;
4220                 }
4221                 break;
4222         case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
4223                 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
4224                         wlc_lcnphy_tx_power_adjustment(
4225                                 (struct brcms_phy_pub *) pi);
4226                 break;
4227         }
4228 }
4229
4230 void wlc_lcnphy_get_tssi(struct brcms_phy *pi, s8 *ofdm_pwr, s8 *cck_pwr)
4231 {
4232         s8 cck_offset;
4233         u16 status;
4234         status = (read_phy_reg(pi, 0x4ab));
4235         if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
4236             (status  & (0x1 << 15))) {
4237                 *ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
4238                                    >> 0) >> 1);
4239
4240                 if (wlc_phy_tpc_isenabled_lcnphy(pi))
4241                         cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
4242                 else
4243                         cck_offset = 0;
4244
4245                 *cck_pwr = *ofdm_pwr + cck_offset;
4246         } else {
4247                 *cck_pwr = 0;
4248                 *ofdm_pwr = 0;
4249         }
4250 }
4251
4252 void wlc_phy_cal_init_lcnphy(struct brcms_phy *pi)
4253 {
4254         return;
4255
4256 }
4257
4258 void wlc_lcnphy_tx_power_adjustment(struct brcms_phy_pub *ppi)
4259 {
4260         s8 index;
4261         u16 index2;
4262         struct brcms_phy *pi = (struct brcms_phy *) ppi;
4263         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4264         u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
4265         if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
4266             SAVE_txpwrctrl) {
4267                 index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
4268                 index2 = (u16) (index * 2);
4269                 mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
4270
4271                 pi_lcn->lcnphy_current_index =
4272                         (s8)((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
4273         }
4274 }
4275
4276 static void
4277 wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
4278                               const struct lcnphy_tx_gain_tbl_entry *gain_table)
4279 {
4280         u32 j;
4281         struct phytbl_info tab;
4282         u32 val;
4283         u16 pa_gain;
4284         u16 gm_gain;
4285
4286         if (CHSPEC_IS5G(pi->radio_chanspec))
4287                 pa_gain = 0x70;
4288         else
4289                 pa_gain = 0x70;
4290
4291         if (pi->sh->boardflags & BFL_FEM)
4292                 pa_gain = 0x10;
4293         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4294         tab.tbl_width = 32;
4295         tab.tbl_len = 1;
4296         tab.tbl_ptr = &val;
4297
4298         for (j = 0; j < 128; j++) {
4299                 gm_gain = gain_table[j].gm;
4300                 val = (((u32) pa_gain << 24) |
4301                        (gain_table[j].pad << 16) |
4302                        (gain_table[j].pga << 8) | gm_gain);
4303
4304                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
4305                 wlc_lcnphy_write_table(pi, &tab);
4306
4307                 val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
4308                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
4309                 wlc_lcnphy_write_table(pi, &tab);
4310         }
4311 }
4312
4313 static void wlc_lcnphy_load_rfpower(struct brcms_phy *pi)
4314 {
4315         struct phytbl_info tab;
4316         u32 val, bbmult, rfgain;
4317         u8 index;
4318         u8 scale_factor = 1;
4319         s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
4320
4321         tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4322         tab.tbl_width = 32;
4323         tab.tbl_len = 1;
4324
4325         for (index = 0; index < 128; index++) {
4326                 tab.tbl_ptr = &bbmult;
4327                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
4328                 wlc_lcnphy_read_table(pi, &tab);
4329                 bbmult = bbmult >> 20;
4330
4331                 tab.tbl_ptr = &rfgain;
4332                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
4333                 wlc_lcnphy_read_table(pi, &tab);
4334
4335                 qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
4336                 qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
4337
4338                 if (qQ1 < qQ2) {
4339                         temp2 = qm_shr16(temp2, qQ2 - qQ1);
4340                         qQ = qQ1;
4341                 } else {
4342                         temp1 = qm_shr16(temp1, qQ1 - qQ2);
4343                         qQ = qQ2;
4344                 }
4345                 temp = qm_sub16(temp1, temp2);
4346
4347                 if (qQ >= 4)
4348                         shift = qQ - 4;
4349                 else
4350                         shift = 4 - qQ;
4351
4352                 val = (((index << shift) + (5 * temp) +
4353                         (1 << (scale_factor + shift - 3))) >> (scale_factor +
4354                                                                shift - 2));
4355
4356                 tab.tbl_ptr = &val;
4357                 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
4358                 wlc_lcnphy_write_table(pi, &tab);
4359         }
4360 }
4361
4362 static void wlc_lcnphy_bu_tweaks(struct brcms_phy *pi)
4363 {
4364         or_phy_reg(pi, 0x805, 0x1);
4365
4366         mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
4367
4368         mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
4369
4370         write_phy_reg(pi, 0x414, 0x1e10);
4371         write_phy_reg(pi, 0x415, 0x0640);
4372
4373         mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
4374
4375         or_phy_reg(pi, 0x44a, 0x44);
4376         write_phy_reg(pi, 0x44a, 0x80);
4377         mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
4378
4379         mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
4380
4381         if (!(pi->sh->boardrev < 0x1204))
4382                 mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
4383
4384         write_phy_reg(pi, 0x7d6, 0x0902);
4385         mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
4386
4387         mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
4388
4389         if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
4390                 mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
4391
4392                 mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
4393
4394                 mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
4395
4396                 mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
4397
4398                 mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
4399
4400                 mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
4401                 mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
4402                 mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
4403                 mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
4404                 mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
4405
4406                 mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
4407
4408                 wlc_lcnphy_clear_tx_power_offsets(pi);
4409                 mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
4410
4411         }
4412 }
4413
4414 static void wlc_lcnphy_rcal(struct brcms_phy *pi)
4415 {
4416         u8 rcal_value;
4417
4418         and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
4419
4420         or_radio_reg(pi, RADIO_2064_REG004, 0x40);
4421         or_radio_reg(pi, RADIO_2064_REG120, 0x10);
4422
4423         or_radio_reg(pi, RADIO_2064_REG078, 0x80);
4424         or_radio_reg(pi, RADIO_2064_REG129, 0x02);
4425
4426         or_radio_reg(pi, RADIO_2064_REG057, 0x01);
4427
4428         or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
4429         mdelay(5);
4430         SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
4431
4432         if (wlc_radio_2064_rcal_done(pi)) {
4433                 rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
4434                 rcal_value = rcal_value & 0x1f;
4435         }
4436
4437         and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
4438
4439         and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
4440 }
4441
4442 static void wlc_lcnphy_rc_cal(struct brcms_phy *pi)
4443 {
4444         u8 dflt_rc_cal_val;
4445         u16 flt_val;
4446
4447         dflt_rc_cal_val = 7;
4448         if (LCNREV_IS(pi->pubpi.phy_rev, 1))
4449                 dflt_rc_cal_val = 11;
4450         flt_val =
4451                 (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
4452                 (dflt_rc_cal_val);
4453         write_phy_reg(pi, 0x933, flt_val);
4454         write_phy_reg(pi, 0x934, flt_val);
4455         write_phy_reg(pi, 0x935, flt_val);
4456         write_phy_reg(pi, 0x936, flt_val);
4457         write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
4458
4459         return;
4460 }
4461
4462 static void wlc_radio_2064_init(struct brcms_phy *pi)
4463 {
4464         u32 i;
4465         const struct lcnphy_radio_regs *lcnphyregs = NULL;
4466
4467         lcnphyregs = lcnphy_radio_regs_2064;
4468
4469         for (i = 0; lcnphyregs[i].address != 0xffff; i++)
4470                 if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
4471                         write_radio_reg(pi,
4472                                         ((lcnphyregs[i].address & 0x3fff) |
4473                                          RADIO_DEFAULT_CORE),
4474                                         (u16) lcnphyregs[i].init_a);
4475                 else if (lcnphyregs[i].do_init_g)
4476                         write_radio_reg(pi,
4477                                         ((lcnphyregs[i].address & 0x3fff) |
4478                                          RADIO_DEFAULT_CORE),
4479                                         (u16) lcnphyregs[i].init_g);
4480
4481         write_radio_reg(pi, RADIO_2064_REG032, 0x62);
4482         write_radio_reg(pi, RADIO_2064_REG033, 0x19);
4483
4484         write_radio_reg(pi, RADIO_2064_REG090, 0x10);
4485
4486         write_radio_reg(pi, RADIO_2064_REG010, 0x00);
4487
4488         if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
4489
4490                 write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
4491                 write_radio_reg(pi, RADIO_2064_REG061, 0x72);
4492                 write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
4493         }
4494
4495         write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
4496         write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
4497
4498         mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
4499
4500         mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
4501
4502         mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
4503
4504         mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
4505
4506         mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
4507
4508         write_phy_reg(pi, 0x4ea, 0x4688);
4509
4510         mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
4511
4512         mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
4513
4514         mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
4515
4516         wlc_lcnphy_set_tx_locc(pi, 0);
4517
4518         wlc_lcnphy_rcal(pi);
4519
4520         wlc_lcnphy_rc_cal(pi);
4521 }
4522
4523 static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
4524 {
4525         wlc_radio_2064_init(pi);
4526 }
4527
4528 static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
4529 {
4530         uint idx;
4531         u8 phybw40;
4532         struct phytbl_info tab;
4533         u32 val;
4534
4535         phybw40 = CHSPEC_IS40(pi->radio_chanspec);
4536
4537         for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++)
4538                 wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
4539
4540         if (pi->sh->boardflags & BFL_FEM_BT) {
4541                 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
4542                 tab.tbl_width = 16;
4543                 tab.tbl_ptr = &val;
4544                 tab.tbl_len = 1;
4545                 val = 100;
4546                 tab.tbl_offset = 4;
4547                 wlc_lcnphy_write_table(pi, &tab);
4548         }
4549
4550         tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
4551         tab.tbl_width = 16;
4552         tab.tbl_ptr = &val;
4553         tab.tbl_len = 1;
4554
4555         val = 114;
4556         tab.tbl_offset = 0;
4557         wlc_lcnphy_write_table(pi, &tab);
4558
4559         val = 130;
4560         tab.tbl_offset = 1;
4561         wlc_lcnphy_write_table(pi, &tab);
4562
4563         val = 6;
4564         tab.tbl_offset = 8;
4565         wlc_lcnphy_write_table(pi, &tab);
4566
4567         if (CHSPEC_IS2G(pi->radio_chanspec)) {
4568                 if (pi->sh->boardflags & BFL_FEM)
4569                         wlc_lcnphy_load_tx_gain_table(
4570                                 pi,
4571                                 dot11lcnphy_2GHz_extPA_gaintable_rev0);
4572                 else
4573                         wlc_lcnphy_load_tx_gain_table(
4574                                 pi,
4575                                 dot11lcnphy_2GHz_gaintable_rev0);
4576         }
4577
4578         if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
4579                 const struct phytbl_info *tb;
4580                 int l;
4581
4582                 if (CHSPEC_IS2G(pi->radio_chanspec)) {
4583                         l = dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
4584                         if (pi->sh->boardflags & BFL_EXTLNA)
4585                                 tb = dot11lcnphytbl_rx_gain_info_extlna_2G_rev2;
4586                         else
4587                                 tb = dot11lcnphytbl_rx_gain_info_2G_rev2;
4588                 } else {
4589                         l = dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
4590                         if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
4591                                 tb = dot11lcnphytbl_rx_gain_info_extlna_5G_rev2;
4592                         else
4593                                 tb = dot11lcnphytbl_rx_gain_info_5G_rev2;
4594                 }
4595
4596                 for (idx = 0; idx < l; idx++)
4597                         wlc_lcnphy_write_table(pi, &tb[idx]);
4598         }
4599
4600         if ((pi->sh->boardflags & BFL_FEM)
4601             && !(pi->sh->boardflags & BFL_FEM_BT))
4602                 wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
4603         else if (pi->sh->boardflags & BFL_FEM_BT) {
4604                 if (pi->sh->boardrev < 0x1250)
4605                         wlc_lcnphy_write_table(
4606                                 pi,
4607                                 &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
4608                 else
4609                         wlc_lcnphy_write_table(
4610                                 pi,
4611                                 &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
4612         } else
4613                 wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
4614
4615         wlc_lcnphy_load_rfpower(pi);
4616
4617         wlc_lcnphy_clear_papd_comptable(pi);
4618 }
4619
4620 static void wlc_lcnphy_rev0_baseband_init(struct brcms_phy *pi)
4621 {
4622         u16 afectrl1;
4623         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4624
4625         write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
4626
4627         write_phy_reg(pi, 0x43b, 0x0);
4628         write_phy_reg(pi, 0x43c, 0x0);
4629         write_phy_reg(pi, 0x44c, 0x0);
4630         write_phy_reg(pi, 0x4e6, 0x0);
4631         write_phy_reg(pi, 0x4f9, 0x0);
4632         write_phy_reg(pi, 0x4b0, 0x0);
4633         write_phy_reg(pi, 0x938, 0x0);
4634         write_phy_reg(pi, 0x4b0, 0x0);
4635         write_phy_reg(pi, 0x44e, 0);
4636
4637         or_phy_reg(pi, 0x567, 0x03);
4638
4639         or_phy_reg(pi, 0x44a, 0x44);
4640         write_phy_reg(pi, 0x44a, 0x80);
4641
4642         if (!(pi->sh->boardflags & BFL_FEM))
4643                 wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
4644
4645         if (0) {
4646                 afectrl1 = 0;
4647                 afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
4648                                   (pi_lcn->lcnphy_rssi_vc << 4) |
4649                                   (pi_lcn->lcnphy_rssi_gs << 10));
4650                 write_phy_reg(pi, 0x43e, afectrl1);
4651         }
4652
4653         mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
4654         if (pi->sh->boardflags & BFL_FEM) {
4655                 mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
4656
4657                 write_phy_reg(pi, 0x910, 0x1);
4658         }
4659
4660         mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
4661         mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
4662         mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
4663
4664 }
4665
4666 static void wlc_lcnphy_rev2_baseband_init(struct brcms_phy *pi)
4667 {
4668         if (CHSPEC_IS5G(pi->radio_chanspec)) {
4669                 mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
4670                 mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
4671         }
4672 }
4673
4674 static void wlc_lcnphy_agc_temp_init(struct brcms_phy *pi)
4675 {
4676         s16 temp;
4677         struct phytbl_info tab;
4678         u32 tableBuffer[2];
4679         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4680
4681         temp = (s16) read_phy_reg(pi, 0x4df);
4682         pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
4683
4684         if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
4685                 pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
4686
4687         pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
4688
4689         if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
4690                 pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
4691
4692         tab.tbl_ptr = tableBuffer;
4693         tab.tbl_len = 2;
4694         tab.tbl_id = 17;
4695         tab.tbl_offset = 59;
4696         tab.tbl_width = 32;
4697         wlc_lcnphy_read_table(pi, &tab);
4698
4699         if (tableBuffer[0] > 63)
4700                 tableBuffer[0] -= 128;
4701         pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
4702
4703         if (tableBuffer[1] > 63)
4704                 tableBuffer[1] -= 128;
4705         pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
4706
4707         temp = (s16) (read_phy_reg(pi, 0x434) & (0xff << 0));
4708         if (temp > 127)
4709                 temp -= 256;
4710         pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
4711
4712         pi_lcn->lcnphy_Med_Low_Gain_db =
4713                 (read_phy_reg(pi, 0x424) & (0xff << 8)) >> 8;
4714         pi_lcn->lcnphy_Very_Low_Gain_db =
4715                 (read_phy_reg(pi, 0x425) & (0xff << 0)) >> 0;
4716
4717         tab.tbl_ptr = tableBuffer;
4718         tab.tbl_len = 2;
4719         tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
4720         tab.tbl_offset = 28;
4721         tab.tbl_width = 32;
4722         wlc_lcnphy_read_table(pi, &tab);
4723
4724         pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
4725         pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
4726
4727 }
4728
4729 static void wlc_lcnphy_baseband_init(struct brcms_phy *pi)
4730 {
4731
4732         wlc_lcnphy_tbl_init(pi);
4733         wlc_lcnphy_rev0_baseband_init(pi);
4734         if (LCNREV_IS(pi->pubpi.phy_rev, 2))
4735                 wlc_lcnphy_rev2_baseband_init(pi);
4736         wlc_lcnphy_bu_tweaks(pi);
4737 }
4738
4739 void wlc_phy_init_lcnphy(struct brcms_phy *pi)
4740 {
4741         u8 phybw40;
4742         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4743         phybw40 = CHSPEC_IS40(pi->radio_chanspec);
4744
4745         pi_lcn->lcnphy_cal_counter = 0;
4746         pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
4747
4748         or_phy_reg(pi, 0x44a, 0x80);
4749         and_phy_reg(pi, 0x44a, 0x7f);
4750
4751         wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
4752
4753         write_phy_reg(pi, 0x60a, 160);
4754
4755         write_phy_reg(pi, 0x46a, 25);
4756
4757         wlc_lcnphy_baseband_init(pi);
4758
4759         wlc_lcnphy_radio_init(pi);
4760
4761         if (CHSPEC_IS2G(pi->radio_chanspec))
4762                 wlc_lcnphy_tx_pwr_ctrl_init((struct brcms_phy_pub *) pi);
4763
4764         wlc_phy_chanspec_set((struct brcms_phy_pub *) pi, pi->radio_chanspec);
4765
4766         bcma_chipco_regctl_maskset(&pi->d11core->bus->drv_cc, 0, ~0xf, 0x9);
4767
4768         bcma_chipco_chipctl_maskset(&pi->d11core->bus->drv_cc, 0, 0x0,
4769                                     0x03CDDDDD);
4770
4771         if ((pi->sh->boardflags & BFL_FEM)
4772             && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
4773                 wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
4774
4775         wlc_lcnphy_agc_temp_init(pi);
4776
4777         wlc_lcnphy_temp_adj(pi);
4778
4779         mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
4780
4781         udelay(100);
4782         mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
4783
4784         wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
4785         pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
4786         wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
4787 }
4788
4789 static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi)
4790 {
4791         s8 txpwr = 0;
4792         int i;
4793         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
4794         struct ssb_sprom *sprom = &pi->d11core->bus->sprom;
4795
4796         if (CHSPEC_IS2G(pi->radio_chanspec)) {
4797                 u16 cckpo = 0;
4798                 u32 offset_ofdm, offset_mcs;
4799
4800                 pi_lcn->lcnphy_tr_isolation_mid = sprom->fem.ghz2.tr_iso;
4801
4802                 pi_lcn->lcnphy_rx_power_offset = sprom->rxpo2g;
4803
4804                 pi->txpa_2g[0] = sprom->pa0b0;
4805                 pi->txpa_2g[1] = sprom->pa0b1;
4806                 pi->txpa_2g[2] = sprom->pa0b2;
4807
4808                 pi_lcn->lcnphy_rssi_vf = sprom->rssismf2g;
4809                 pi_lcn->lcnphy_rssi_vc = sprom->rssismc2g;
4810                 pi_lcn->lcnphy_rssi_gs = sprom->rssisav2g;
4811
4812                 pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
4813                 pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
4814                 pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
4815
4816                 pi_lcn->lcnphy_rssi_vf_hightemp = pi_lcn->lcnphy_rssi_vf;
4817                 pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc;
4818                 pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs;
4819
4820                 txpwr = sprom->core_pwr_info[0].maxpwr_2g;
4821                 pi->tx_srom_max_2g = txpwr;
4822
4823                 for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
4824                         pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
4825                         pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
4826                 }
4827
4828                 cckpo = sprom->cck2gpo;
4829                 offset_ofdm = sprom->ofdm2gpo;
4830                 if (cckpo) {
4831                         uint max_pwr_chan = txpwr;
4832
4833                         for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
4834                                 pi->tx_srom_max_rate_2g[i] =
4835                                         max_pwr_chan - ((cckpo & 0xf) * 2);
4836                                 cckpo >>= 4;
4837                         }
4838
4839                         for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
4840                                 pi->tx_srom_max_rate_2g[i] =
4841                                         max_pwr_chan -
4842                                         ((offset_ofdm & 0xf) * 2);
4843                                 offset_ofdm >>= 4;
4844                         }
4845                 } else {
4846                         u8 opo = 0;
4847
4848                         opo = sprom->opo;
4849
4850                         for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++)
4851                                 pi->tx_srom_max_rate_2g[i] = txpwr;
4852
4853                         for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
4854                                 pi->tx_srom_max_rate_2g[i] = txpwr -
4855                                                 ((offset_ofdm & 0xf) * 2);
4856                                 offset_ofdm >>= 4;
4857                         }
4858                         offset_mcs = sprom->mcs2gpo[1] << 16;
4859                         offset_mcs |= sprom->mcs2gpo[0];
4860                         pi_lcn->lcnphy_mcs20_po = offset_mcs;
4861                         for (i = TXP_FIRST_SISO_MCS_20;
4862                              i <= TXP_LAST_SISO_MCS_20; i++) {
4863                                 pi->tx_srom_max_rate_2g[i] =
4864                                         txpwr - ((offset_mcs & 0xf) * 2);
4865                                 offset_mcs >>= 4;
4866                         }
4867                 }
4868
4869                 pi_lcn->lcnphy_rawtempsense = sprom->rawtempsense;
4870                 pi_lcn->lcnphy_measPower = sprom->measpower;
4871                 pi_lcn->lcnphy_tempsense_slope = sprom->tempsense_slope;
4872                 pi_lcn->lcnphy_hw_iqcal_en = sprom->hw_iqcal_en;
4873                 pi_lcn->lcnphy_iqcal_swp_dis = sprom->iqcal_swp_dis;
4874                 pi_lcn->lcnphy_tempcorrx = sprom->tempcorrx;
4875                 pi_lcn->lcnphy_tempsense_option = sprom->tempsense_option;
4876                 pi_lcn->lcnphy_freqoffset_corr = sprom->freqoffset_corr;
4877                 if (sprom->ant_available_bg > 1)
4878                         wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi,
4879                                 sprom->ant_available_bg);
4880         }
4881         pi_lcn->lcnphy_cck_dig_filt_type = -1;
4882
4883         return true;
4884 }
4885
4886 void wlc_2064_vco_cal(struct brcms_phy *pi)
4887 {
4888         u8 calnrst;
4889
4890         mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
4891         calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
4892         write_radio_reg(pi, RADIO_2064_REG056, calnrst);
4893         udelay(1);
4894         write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
4895         udelay(1);
4896         write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
4897         udelay(300);
4898         mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
4899 }
4900
4901 bool wlc_phy_tpc_isenabled_lcnphy(struct brcms_phy *pi)
4902 {
4903         if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
4904                 return 0;
4905         else
4906                 return (LCNPHY_TX_PWR_CTRL_HW ==
4907                         wlc_lcnphy_get_tx_pwr_ctrl((pi)));
4908 }
4909
4910 void wlc_phy_txpower_recalc_target_lcnphy(struct brcms_phy *pi)
4911 {
4912         u16 pwr_ctrl;
4913         if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
4914                 wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
4915         } else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
4916                 pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
4917                 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
4918                 wlc_lcnphy_txpower_recalc_target(pi);
4919                 wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
4920         }
4921 }
4922
4923 void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
4924 {
4925         u8 channel = CHSPEC_CHANNEL(chanspec);
4926
4927         wlc_phy_chanspec_radio_set((struct brcms_phy_pub *)pi, chanspec);
4928
4929         wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
4930
4931         or_phy_reg(pi, 0x44a, 0x44);
4932         write_phy_reg(pi, 0x44a, 0x80);
4933
4934         wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
4935         udelay(1000);
4936
4937         wlc_lcnphy_toggle_afe_pwdn(pi);
4938
4939         write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
4940         write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
4941
4942         if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
4943                 mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
4944
4945                 wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
4946         } else {
4947                 mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
4948
4949                 wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
4950         }
4951
4952         if (pi->sh->boardflags & BFL_FEM)
4953                 wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
4954         else
4955                 wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
4956
4957         mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
4958 }
4959
4960 void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
4961 {
4962         kfree(pi->u.pi_lcnphy);
4963 }
4964
4965 bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
4966 {
4967         struct brcms_phy_lcnphy *pi_lcn;
4968
4969         pi->u.pi_lcnphy = kzalloc(sizeof(struct brcms_phy_lcnphy), GFP_ATOMIC);
4970         if (pi->u.pi_lcnphy == NULL)
4971                 return false;
4972
4973         pi_lcn = pi->u.pi_lcnphy;
4974
4975         if (0 == (pi->sh->boardflags & BFL_NOPA)) {
4976                 pi->hwpwrctrl = true;
4977                 pi->hwpwrctrl_capable = true;
4978         }
4979
4980         pi->xtalfreq = bcma_chipco_get_alp_clock(&pi->d11core->bus->drv_cc);
4981         pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
4982
4983         pi->pi_fptr.init = wlc_phy_init_lcnphy;
4984         pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
4985         pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
4986         pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
4987         pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
4988         pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
4989         pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
4990         pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
4991         pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
4992
4993         if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
4994                 return false;
4995
4996         if ((pi->sh->boardflags & BFL_FEM) &&
4997             (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
4998                 if (pi_lcn->lcnphy_tempsense_option == 3) {
4999                         pi->hwpwrctrl = true;
5000                         pi->hwpwrctrl_capable = true;
5001                         pi->temppwrctrl_capable = false;
5002                 } else {
5003                         pi->hwpwrctrl = false;
5004                         pi->hwpwrctrl_capable = false;
5005                         pi->temppwrctrl_capable = true;
5006                 }
5007         }
5008
5009         return true;
5010 }
5011
5012 static void wlc_lcnphy_set_rx_gain(struct brcms_phy *pi, u32 gain)
5013 {
5014         u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
5015
5016         trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
5017         ext_lna = (u16) (gain >> 29) & 0x01;
5018         lna1 = (u16) (gain >> 0) & 0x0f;
5019         lna2 = (u16) (gain >> 4) & 0x0f;
5020         tia = (u16) (gain >> 8) & 0xf;
5021         biq0 = (u16) (gain >> 12) & 0xf;
5022         biq1 = (u16) (gain >> 16) & 0xf;
5023
5024         gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
5025                           ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
5026                           ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
5027         gain16_19 = biq1;
5028
5029         mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
5030         mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
5031         mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
5032         mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
5033         mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
5034
5035         if (CHSPEC_IS2G(pi->radio_chanspec)) {
5036                 mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
5037                 mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
5038         }
5039         wlc_lcnphy_rx_gain_override_enable(pi, true);
5040 }
5041
5042 static u32 wlc_lcnphy_get_receive_power(struct brcms_phy *pi, s32 *gain_index)
5043 {
5044         u32 received_power = 0;
5045         s32 max_index = 0;
5046         u32 gain_code = 0;
5047         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
5048
5049         max_index = 36;
5050         if (*gain_index >= 0)
5051                 gain_code = lcnphy_23bitgaincode_table[*gain_index];
5052
5053         if (-1 == *gain_index) {
5054                 *gain_index = 0;
5055                 while ((*gain_index <= (s32) max_index)
5056                        && (received_power < 700)) {
5057                         wlc_lcnphy_set_rx_gain(pi,
5058                                                lcnphy_23bitgaincode_table
5059                                                [*gain_index]);
5060                         received_power =
5061                                 wlc_lcnphy_measure_digital_power(
5062                                         pi,
5063                                         pi_lcn->
5064                                         lcnphy_noise_samples);
5065                         (*gain_index)++;
5066                 }
5067                 (*gain_index)--;
5068         } else {
5069                 wlc_lcnphy_set_rx_gain(pi, gain_code);
5070                 received_power =
5071                         wlc_lcnphy_measure_digital_power(pi,
5072                                                          pi_lcn->
5073                                                          lcnphy_noise_samples);
5074         }
5075
5076         return received_power;
5077 }
5078
5079 s32 wlc_lcnphy_rx_signal_power(struct brcms_phy *pi, s32 gain_index)
5080 {
5081         s32 gain = 0;
5082         s32 nominal_power_db;
5083         s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
5084             input_power_db;
5085         s32 received_power, temperature;
5086         u32 power;
5087         u32 msb1, msb2, val1, val2, diff1, diff2;
5088         uint freq;
5089         struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
5090
5091         received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
5092
5093         gain = lcnphy_gain_table[gain_index];
5094
5095         nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
5096
5097         power = (received_power * 16);
5098         msb1 = ffs(power) - 1;
5099         msb2 = msb1 + 1;
5100         val1 = 1 << msb1;
5101         val2 = 1 << msb2;
5102         diff1 = (power - val1);
5103         diff2 = (val2 - power);
5104         if (diff1 < diff2)
5105                 log_val = msb1;
5106         else
5107                 log_val = msb2;
5108
5109         log_val = log_val * 3;
5110
5111         gain_mismatch = (nominal_power_db / 2) - (log_val);
5112
5113         desired_gain = gain + gain_mismatch;
5114
5115         input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
5116
5117         if (input_power_offset_db > 127)
5118                 input_power_offset_db -= 256;
5119
5120         input_power_db = input_power_offset_db - desired_gain;
5121
5122         input_power_db =
5123                 input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
5124
5125         freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
5126         if ((freq > 2427) && (freq <= 2467))
5127                 input_power_db = input_power_db - 1;
5128
5129         temperature = pi_lcn->lcnphy_lastsensed_temperature;
5130
5131         if ((temperature - 15) < -30)
5132                 input_power_db =
5133                         input_power_db +
5134                         (((temperature - 10 - 25) * 286) >> 12) -
5135                         7;
5136         else if ((temperature - 15) < 4)
5137                 input_power_db =
5138                         input_power_db +
5139                         (((temperature - 10 - 25) * 286) >> 12) -
5140                         3;
5141         else
5142                 input_power_db = input_power_db +
5143                                         (((temperature - 10 - 25) * 286) >> 12);
5144
5145         wlc_lcnphy_rx_gain_override_enable(pi, 0);
5146
5147         return input_power_db;
5148 }