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