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