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