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