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