blob: 9492ca5421f8b79199a4b9997b8ed77edcfc587b [file] [log] [blame]
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001/*
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
Greg Kroah-Hartmana1c16ed2010-10-21 11:17:44 -070017#include <linux/kernel.h>
18#include <linux/string.h>
19#include <linux/bitops.h>
Henry Ptasinskia9533e72010-09-08 21:04:42 -070020#include <wlc_cfg.h>
21#include <qmath.h>
22#include <osl.h>
Brett Rudleyc6ac24e2010-10-26 11:55:23 -070023#include <linux/pci.h>
Henry Ptasinskia9533e72010-09-08 21:04:42 -070024#include <siutils.h>
Henry Ptasinskia9533e72010-09-08 21:04:42 -070025#include <hndpmu.h>
26
Brett Rudleya52ba662010-10-26 09:17:06 -070027#include <bcmdevs.h>
28#include <sbhndpio.h>
29#include <sbhnddma.h>
30
Henry Ptasinskia9533e72010-09-08 21:04:42 -070031#include <wlc_phy_radio.h>
32#include <wlc_phy_int.h>
33#include <wlc_phy_lcn.h>
34#include <wlc_phytbl_lcn.h>
35
36#define PLL_2064_NDIV 90
37#define PLL_2064_LOW_END_VCO 3000
38#define PLL_2064_LOW_END_KVCO 27
39#define PLL_2064_HIGH_END_VCO 4200
40#define PLL_2064_HIGH_END_KVCO 68
41#define PLL_2064_LOOP_BW_DOUBLER 200
42#define PLL_2064_D30_DOUBLER 10500
43#define PLL_2064_LOOP_BW 260
44#define PLL_2064_D30 8000
45#define PLL_2064_CAL_REF_TO 8
46#define PLL_2064_MHZ 1000000
47#define PLL_2064_OPEN_LOOP_DELAY 5
48
49#define TEMPSENSE 1
50#define VBATSENSE 2
51
52#define NOISE_IF_UPD_CHK_INTERVAL 1
53#define NOISE_IF_UPD_RST_INTERVAL 60
54#define NOISE_IF_UPD_THRESHOLD_CNT 1
55#define NOISE_IF_UPD_TRHRESHOLD 50
56#define NOISE_IF_UPD_TIMEOUT 1000
57#define NOISE_IF_OFF 0
58#define NOISE_IF_CHK 1
59#define NOISE_IF_ON 2
60
61#define PAPD_BLANKING_PROFILE 3
62#define PAPD2LUT 0
63#define PAPD_CORR_NORM 0
64#define PAPD_BLANKING_THRESHOLD 0
65#define PAPD_STOP_AFTER_LAST_UPDATE 0
66
67#define LCN_TARGET_PWR 60
68
69#define LCN_VBAT_OFFSET_433X 34649679
70#define LCN_VBAT_SLOPE_433X 8258032
71
72#define LCN_VBAT_SCALE_NOM 53
73#define LCN_VBAT_SCALE_DEN 432
74
75#define LCN_TEMPSENSE_OFFSET 80812
76#define LCN_TEMPSENSE_DEN 2647
77
78#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
79 (0 + 8)
80#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
81 (0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
82
83#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
84 (0 + 8)
85#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
86 (0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
87
88#define wlc_lcnphy_enable_tx_gain_override(pi) \
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -070089 wlc_lcnphy_set_tx_gain_override(pi, true)
Henry Ptasinskia9533e72010-09-08 21:04:42 -070090#define wlc_lcnphy_disable_tx_gain_override(pi) \
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -070091 wlc_lcnphy_set_tx_gain_override(pi, false)
Henry Ptasinskia9533e72010-09-08 21:04:42 -070092
93#define wlc_lcnphy_iqcal_active(pi) \
94 (read_phy_reg((pi), 0x451) & \
95 ((0x1 << 15) | (0x1 << 14)))
96
97#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
98#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
99 (pi->temppwrctrl_capable)
100#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
101 (pi->hwpwrctrl_capable)
102
103#define SWCTRL_BT_TX 0x18
104#define SWCTRL_OVR_DISABLE 0x40
105
106#define AFE_CLK_INIT_MODE_TXRX2X 1
107#define AFE_CLK_INIT_MODE_PAPD 0
108
109#define LCNPHY_TBL_ID_IQLOCAL 0x00
110
111#define LCNPHY_TBL_ID_RFSEQ 0x08
112#define LCNPHY_TBL_ID_GAIN_IDX 0x0d
113#define LCNPHY_TBL_ID_SW_CTRL 0x0f
114#define LCNPHY_TBL_ID_GAIN_TBL 0x12
115#define LCNPHY_TBL_ID_SPUR 0x14
116#define LCNPHY_TBL_ID_SAMPLEPLAY 0x15
117#define LCNPHY_TBL_ID_SAMPLEPLAY1 0x16
118
119#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 832
120#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 128
121#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 192
122#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET 320
123#define LCNPHY_TX_PWR_CTRL_LO_OFFSET 448
124#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET 576
125
126#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313 140
127
128#define LCNPHY_TX_PWR_CTRL_START_NPT 1
129#define LCNPHY_TX_PWR_CTRL_MAX_NPT 7
130
131#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
132
133#define LCNPHY_ACI_DETECT_START 1
134#define LCNPHY_ACI_DETECT_PROGRESS 2
135#define LCNPHY_ACI_DETECT_STOP 3
136
137#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
138#define LCNPHY_ACI_GLITCH_TRSH 2000
139#define LCNPHY_ACI_TMOUT 250
140#define LCNPHY_ACI_DETECT_TIMEOUT 2
141#define LCNPHY_ACI_START_DELAY 0
142
143#define wlc_lcnphy_tx_gain_override_enabled(pi) \
144 (0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
145
146#define wlc_lcnphy_total_tx_frames(pi) \
Greg Kroah-Hartmance0f1b82010-10-08 11:44:45 -0700147 wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + offsetof(macstat_t, txallfrm))
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700148
149typedef struct {
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700150 u16 gm_gain;
151 u16 pga_gain;
152 u16 pad_gain;
153 u16 dac_gain;
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700154} lcnphy_txgains_t;
155
156typedef enum {
157 LCNPHY_CAL_FULL,
158 LCNPHY_CAL_RECAL,
159 LCNPHY_CAL_CURRECAL,
160 LCNPHY_CAL_DIGCAL,
161 LCNPHY_CAL_GCTRL
162} lcnphy_cal_mode_t;
163
164typedef struct {
165 lcnphy_txgains_t gains;
166 bool useindex;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -0700167 u8 index;
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700168} lcnphy_txcalgains_t;
169
170typedef struct {
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -0700171 u8 chan;
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -0700172 s16 a;
173 s16 b;
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700174} lcnphy_rx_iqcomp_t;
175
176typedef struct {
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -0700177 s16 re;
178 s16 im;
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700179} lcnphy_spb_tone_t;
180
181typedef struct {
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700182 u16 re;
183 u16 im;
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700184} lcnphy_unsign16_struct;
185
186typedef struct {
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700187 u32 iq_prod;
188 u32 i_pwr;
189 u32 q_pwr;
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700190} lcnphy_iq_est_t;
191
192typedef struct {
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700193 u16 ptcentreTs20;
194 u16 ptcentreFactor;
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700195} lcnphy_sfo_cfg_t;
196
197typedef enum {
198 LCNPHY_PAPD_CAL_CW,
199 LCNPHY_PAPD_CAL_OFDM
200} lcnphy_papd_cal_type_t;
201
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700202typedef u16 iqcal_gain_params_lcnphy[9];
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700203
204static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
205 {0, 0, 0, 0, 0, 0, 0, 0, 0},
206};
207
208static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
209 tbl_iqcal_gainparams_lcnphy_2G,
210};
211
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700212static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700213 sizeof(tbl_iqcal_gainparams_lcnphy_2G) /
214 sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
215};
216
217static const lcnphy_sfo_cfg_t lcnphy_sfo_cfg[] = {
218 {965, 1087},
219 {967, 1085},
220 {969, 1082},
221 {971, 1080},
222 {973, 1078},
223 {975, 1076},
224 {977, 1073},
225 {979, 1071},
226 {981, 1069},
227 {983, 1067},
228 {985, 1065},
229 {987, 1063},
230 {989, 1060},
231 {994, 1055}
232};
233
234static const
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700235u16 lcnphy_iqcal_loft_gainladder[] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700236 ((2 << 8) | 0),
237 ((3 << 8) | 0),
238 ((4 << 8) | 0),
239 ((6 << 8) | 0),
240 ((8 << 8) | 0),
241 ((11 << 8) | 0),
242 ((16 << 8) | 0),
243 ((16 << 8) | 1),
244 ((16 << 8) | 2),
245 ((16 << 8) | 3),
246 ((16 << 8) | 4),
247 ((16 << 8) | 5),
248 ((16 << 8) | 6),
249 ((16 << 8) | 7),
250 ((23 << 8) | 7),
251 ((32 << 8) | 7),
252 ((45 << 8) | 7),
253 ((64 << 8) | 7),
254 ((91 << 8) | 7),
255 ((128 << 8) | 7)
256};
257
258static const
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700259u16 lcnphy_iqcal_ir_gainladder[] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700260 ((1 << 8) | 0),
261 ((2 << 8) | 0),
262 ((4 << 8) | 0),
263 ((6 << 8) | 0),
264 ((8 << 8) | 0),
265 ((11 << 8) | 0),
266 ((16 << 8) | 0),
267 ((23 << 8) | 0),
268 ((32 << 8) | 0),
269 ((45 << 8) | 0),
270 ((64 << 8) | 0),
271 ((64 << 8) | 1),
272 ((64 << 8) | 2),
273 ((64 << 8) | 3),
274 ((64 << 8) | 4),
275 ((64 << 8) | 5),
276 ((64 << 8) | 6),
277 ((64 << 8) | 7),
278 ((91 << 8) | 7),
279 ((128 << 8) | 7)
280};
281
282static const
283lcnphy_spb_tone_t lcnphy_spb_tone_3750[] = {
284 {88, 0},
285 {73, 49},
286 {34, 81},
287 {-17, 86},
288 {-62, 62},
289 {-86, 17},
290 {-81, -34},
291 {-49, -73},
292 {0, -88},
293 {49, -73},
294 {81, -34},
295 {86, 17},
296 {62, 62},
297 {17, 86},
298 {-34, 81},
299 {-73, 49},
300 {-88, 0},
301 {-73, -49},
302 {-34, -81},
303 {17, -86},
304 {62, -62},
305 {86, -17},
306 {81, 34},
307 {49, 73},
308 {0, 88},
309 {-49, 73},
310 {-81, 34},
311 {-86, -17},
312 {-62, -62},
313 {-17, -86},
314 {34, -81},
315 {73, -49},
316};
317
318static const
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700319u16 iqlo_loopback_rf_regs[20] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700320 RADIO_2064_REG036,
321 RADIO_2064_REG11A,
322 RADIO_2064_REG03A,
323 RADIO_2064_REG025,
324 RADIO_2064_REG028,
325 RADIO_2064_REG005,
326 RADIO_2064_REG112,
327 RADIO_2064_REG0FF,
328 RADIO_2064_REG11F,
329 RADIO_2064_REG00B,
330 RADIO_2064_REG113,
331 RADIO_2064_REG007,
332 RADIO_2064_REG0FC,
333 RADIO_2064_REG0FD,
334 RADIO_2064_REG012,
335 RADIO_2064_REG057,
336 RADIO_2064_REG059,
337 RADIO_2064_REG05C,
338 RADIO_2064_REG078,
339 RADIO_2064_REG092,
340};
341
342static const
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700343u16 tempsense_phy_regs[14] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700344 0x503,
345 0x4a4,
346 0x4d0,
347 0x4d9,
348 0x4da,
349 0x4a6,
350 0x938,
351 0x939,
352 0x4d8,
353 0x4d0,
354 0x4d7,
355 0x4a5,
356 0x40d,
357 0x4a2,
358};
359
360static const
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700361u16 rxiq_cal_rf_reg[11] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700362 RADIO_2064_REG098,
363 RADIO_2064_REG116,
364 RADIO_2064_REG12C,
365 RADIO_2064_REG06A,
366 RADIO_2064_REG00B,
367 RADIO_2064_REG01B,
368 RADIO_2064_REG113,
369 RADIO_2064_REG01D,
370 RADIO_2064_REG114,
371 RADIO_2064_REG02E,
372 RADIO_2064_REG12A,
373};
374
375static const
376lcnphy_rx_iqcomp_t lcnphy_rx_iqcomp_table_rev0[] = {
377 {1, 0, 0},
378 {2, 0, 0},
379 {3, 0, 0},
380 {4, 0, 0},
381 {5, 0, 0},
382 {6, 0, 0},
383 {7, 0, 0},
384 {8, 0, 0},
385 {9, 0, 0},
386 {10, 0, 0},
387 {11, 0, 0},
388 {12, 0, 0},
389 {13, 0, 0},
390 {14, 0, 0},
391 {34, 0, 0},
392 {38, 0, 0},
393 {42, 0, 0},
394 {46, 0, 0},
395 {36, 0, 0},
396 {40, 0, 0},
397 {44, 0, 0},
398 {48, 0, 0},
399 {52, 0, 0},
400 {56, 0, 0},
401 {60, 0, 0},
402 {64, 0, 0},
403 {100, 0, 0},
404 {104, 0, 0},
405 {108, 0, 0},
406 {112, 0, 0},
407 {116, 0, 0},
408 {120, 0, 0},
409 {124, 0, 0},
410 {128, 0, 0},
411 {132, 0, 0},
412 {136, 0, 0},
413 {140, 0, 0},
414 {149, 0, 0},
415 {153, 0, 0},
416 {157, 0, 0},
417 {161, 0, 0},
418 {165, 0, 0},
419 {184, 0, 0},
420 {188, 0, 0},
421 {192, 0, 0},
422 {196, 0, 0},
423 {200, 0, 0},
424 {204, 0, 0},
425 {208, 0, 0},
426 {212, 0, 0},
427 {216, 0, 0},
428};
429
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700430static const u32 lcnphy_23bitgaincode_table[] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700431 0x200100,
432 0x200200,
433 0x200004,
434 0x200014,
435 0x200024,
436 0x200034,
437 0x200134,
438 0x200234,
439 0x200334,
440 0x200434,
441 0x200037,
442 0x200137,
443 0x200237,
444 0x200337,
445 0x200437,
446 0x000035,
447 0x000135,
448 0x000235,
449 0x000037,
450 0x000137,
451 0x000237,
452 0x000337,
453 0x00013f,
454 0x00023f,
455 0x00033f,
456 0x00034f,
457 0x00044f,
458 0x00144f,
459 0x00244f,
460 0x00254f,
461 0x00354f,
462 0x00454f,
463 0x00464f,
464 0x01464f,
465 0x02464f,
466 0x03464f,
467 0x04464f,
468};
469
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -0700470static const s8 lcnphy_gain_table[] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700471 -16,
472 -13,
473 10,
474 7,
475 4,
476 0,
477 3,
478 6,
479 9,
480 12,
481 15,
482 18,
483 21,
484 24,
485 27,
486 30,
487 33,
488 36,
489 39,
490 42,
491 45,
492 48,
493 50,
494 53,
495 56,
496 59,
497 62,
498 65,
499 68,
500 71,
501 74,
502 77,
503 80,
504 83,
505 86,
506 89,
507 92,
508};
509
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -0700510static const s8 lcnphy_gain_index_offset_for_rssi[] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700511 7,
512 7,
513 7,
514 7,
515 7,
516 7,
517 7,
518 8,
519 7,
520 7,
521 6,
522 7,
523 7,
524 4,
525 4,
526 4,
527 4,
528 4,
529 4,
530 4,
531 4,
532 3,
533 3,
534 3,
535 3,
536 3,
537 3,
538 4,
539 2,
540 2,
541 2,
542 2,
543 2,
544 2,
545 -1,
546 -2,
547 -2,
548 -2
549};
550
Greg Kroah-Hartmandf8501c2010-10-05 11:18:31 -0700551extern const u8 spur_tbl_rev0[];
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700552extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev1;
Greg Kroah-Hartmandf8501c2010-10-05 11:18:31 -0700553extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev1[];
554extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
555extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700556
557typedef struct _chan_info_2064_lcnphy {
558 uint chan;
559 uint freq;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -0700560 u8 logen_buftune;
561 u8 logen_rccr_tx;
562 u8 txrf_mix_tune_ctrl;
563 u8 pa_input_tune_g;
564 u8 logen_rccr_rx;
565 u8 pa_rxrf_lna1_freq_tune;
566 u8 pa_rxrf_lna2_freq_tune;
567 u8 rxrf_rxrf_spare1;
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700568} chan_info_2064_lcnphy_t;
569
570static chan_info_2064_lcnphy_t chan_info_2064_lcnphy[] = {
571 {1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
572 {2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
573 {3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
574 {4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
575 {5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
576 {6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
577 {7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
578 {8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
579 {9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
580 {10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
581 {11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
582 {12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
583 {13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
584 {14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
585};
586
587lcnphy_radio_regs_t lcnphy_radio_regs_2064[] = {
588 {0x00, 0, 0, 0, 0},
589 {0x01, 0x64, 0x64, 0, 0},
590 {0x02, 0x20, 0x20, 0, 0},
591 {0x03, 0x66, 0x66, 0, 0},
592 {0x04, 0xf8, 0xf8, 0, 0},
593 {0x05, 0, 0, 0, 0},
594 {0x06, 0x10, 0x10, 0, 0},
595 {0x07, 0, 0, 0, 0},
596 {0x08, 0, 0, 0, 0},
597 {0x09, 0, 0, 0, 0},
598 {0x0A, 0x37, 0x37, 0, 0},
599 {0x0B, 0x6, 0x6, 0, 0},
600 {0x0C, 0x55, 0x55, 0, 0},
601 {0x0D, 0x8b, 0x8b, 0, 0},
602 {0x0E, 0, 0, 0, 0},
603 {0x0F, 0x5, 0x5, 0, 0},
604 {0x10, 0, 0, 0, 0},
605 {0x11, 0xe, 0xe, 0, 0},
606 {0x12, 0, 0, 0, 0},
607 {0x13, 0xb, 0xb, 0, 0},
608 {0x14, 0x2, 0x2, 0, 0},
609 {0x15, 0x12, 0x12, 0, 0},
610 {0x16, 0x12, 0x12, 0, 0},
611 {0x17, 0xc, 0xc, 0, 0},
612 {0x18, 0xc, 0xc, 0, 0},
613 {0x19, 0xc, 0xc, 0, 0},
614 {0x1A, 0x8, 0x8, 0, 0},
615 {0x1B, 0x2, 0x2, 0, 0},
616 {0x1C, 0, 0, 0, 0},
617 {0x1D, 0x1, 0x1, 0, 0},
618 {0x1E, 0x12, 0x12, 0, 0},
619 {0x1F, 0x6e, 0x6e, 0, 0},
620 {0x20, 0x2, 0x2, 0, 0},
621 {0x21, 0x23, 0x23, 0, 0},
622 {0x22, 0x8, 0x8, 0, 0},
623 {0x23, 0, 0, 0, 0},
624 {0x24, 0, 0, 0, 0},
625 {0x25, 0xc, 0xc, 0, 0},
626 {0x26, 0x33, 0x33, 0, 0},
627 {0x27, 0x55, 0x55, 0, 0},
628 {0x28, 0, 0, 0, 0},
629 {0x29, 0x30, 0x30, 0, 0},
630 {0x2A, 0xb, 0xb, 0, 0},
631 {0x2B, 0x1b, 0x1b, 0, 0},
632 {0x2C, 0x3, 0x3, 0, 0},
633 {0x2D, 0x1b, 0x1b, 0, 0},
634 {0x2E, 0, 0, 0, 0},
635 {0x2F, 0x20, 0x20, 0, 0},
636 {0x30, 0xa, 0xa, 0, 0},
637 {0x31, 0, 0, 0, 0},
638 {0x32, 0x62, 0x62, 0, 0},
639 {0x33, 0x19, 0x19, 0, 0},
640 {0x34, 0x33, 0x33, 0, 0},
641 {0x35, 0x77, 0x77, 0, 0},
642 {0x36, 0, 0, 0, 0},
643 {0x37, 0x70, 0x70, 0, 0},
644 {0x38, 0x3, 0x3, 0, 0},
645 {0x39, 0xf, 0xf, 0, 0},
646 {0x3A, 0x6, 0x6, 0, 0},
647 {0x3B, 0xcf, 0xcf, 0, 0},
648 {0x3C, 0x1a, 0x1a, 0, 0},
649 {0x3D, 0x6, 0x6, 0, 0},
650 {0x3E, 0x42, 0x42, 0, 0},
651 {0x3F, 0, 0, 0, 0},
652 {0x40, 0xfb, 0xfb, 0, 0},
653 {0x41, 0x9a, 0x9a, 0, 0},
654 {0x42, 0x7a, 0x7a, 0, 0},
655 {0x43, 0x29, 0x29, 0, 0},
656 {0x44, 0, 0, 0, 0},
657 {0x45, 0x8, 0x8, 0, 0},
658 {0x46, 0xce, 0xce, 0, 0},
659 {0x47, 0x27, 0x27, 0, 0},
660 {0x48, 0x62, 0x62, 0, 0},
661 {0x49, 0x6, 0x6, 0, 0},
662 {0x4A, 0x58, 0x58, 0, 0},
663 {0x4B, 0xf7, 0xf7, 0, 0},
664 {0x4C, 0, 0, 0, 0},
665 {0x4D, 0xb3, 0xb3, 0, 0},
666 {0x4E, 0, 0, 0, 0},
667 {0x4F, 0x2, 0x2, 0, 0},
668 {0x50, 0, 0, 0, 0},
669 {0x51, 0x9, 0x9, 0, 0},
670 {0x52, 0x5, 0x5, 0, 0},
671 {0x53, 0x17, 0x17, 0, 0},
672 {0x54, 0x38, 0x38, 0, 0},
673 {0x55, 0, 0, 0, 0},
674 {0x56, 0, 0, 0, 0},
675 {0x57, 0xb, 0xb, 0, 0},
676 {0x58, 0, 0, 0, 0},
677 {0x59, 0, 0, 0, 0},
678 {0x5A, 0, 0, 0, 0},
679 {0x5B, 0, 0, 0, 0},
680 {0x5C, 0, 0, 0, 0},
681 {0x5D, 0, 0, 0, 0},
682 {0x5E, 0x88, 0x88, 0, 0},
683 {0x5F, 0xcc, 0xcc, 0, 0},
684 {0x60, 0x74, 0x74, 0, 0},
685 {0x61, 0x74, 0x74, 0, 0},
686 {0x62, 0x74, 0x74, 0, 0},
687 {0x63, 0x44, 0x44, 0, 0},
688 {0x64, 0x77, 0x77, 0, 0},
689 {0x65, 0x44, 0x44, 0, 0},
690 {0x66, 0x77, 0x77, 0, 0},
691 {0x67, 0x55, 0x55, 0, 0},
692 {0x68, 0x77, 0x77, 0, 0},
693 {0x69, 0x77, 0x77, 0, 0},
694 {0x6A, 0, 0, 0, 0},
695 {0x6B, 0x7f, 0x7f, 0, 0},
696 {0x6C, 0x8, 0x8, 0, 0},
697 {0x6D, 0, 0, 0, 0},
698 {0x6E, 0x88, 0x88, 0, 0},
699 {0x6F, 0x66, 0x66, 0, 0},
700 {0x70, 0x66, 0x66, 0, 0},
701 {0x71, 0x28, 0x28, 0, 0},
702 {0x72, 0x55, 0x55, 0, 0},
703 {0x73, 0x4, 0x4, 0, 0},
704 {0x74, 0, 0, 0, 0},
705 {0x75, 0, 0, 0, 0},
706 {0x76, 0, 0, 0, 0},
707 {0x77, 0x1, 0x1, 0, 0},
708 {0x78, 0xd6, 0xd6, 0, 0},
709 {0x79, 0, 0, 0, 0},
710 {0x7A, 0, 0, 0, 0},
711 {0x7B, 0, 0, 0, 0},
712 {0x7C, 0, 0, 0, 0},
713 {0x7D, 0, 0, 0, 0},
714 {0x7E, 0, 0, 0, 0},
715 {0x7F, 0, 0, 0, 0},
716 {0x80, 0, 0, 0, 0},
717 {0x81, 0, 0, 0, 0},
718 {0x82, 0, 0, 0, 0},
719 {0x83, 0xb4, 0xb4, 0, 0},
720 {0x84, 0x1, 0x1, 0, 0},
721 {0x85, 0x20, 0x20, 0, 0},
722 {0x86, 0x5, 0x5, 0, 0},
723 {0x87, 0xff, 0xff, 0, 0},
724 {0x88, 0x7, 0x7, 0, 0},
725 {0x89, 0x77, 0x77, 0, 0},
726 {0x8A, 0x77, 0x77, 0, 0},
727 {0x8B, 0x77, 0x77, 0, 0},
728 {0x8C, 0x77, 0x77, 0, 0},
729 {0x8D, 0x8, 0x8, 0, 0},
730 {0x8E, 0xa, 0xa, 0, 0},
731 {0x8F, 0x8, 0x8, 0, 0},
732 {0x90, 0x18, 0x18, 0, 0},
733 {0x91, 0x5, 0x5, 0, 0},
734 {0x92, 0x1f, 0x1f, 0, 0},
735 {0x93, 0x10, 0x10, 0, 0},
736 {0x94, 0x3, 0x3, 0, 0},
737 {0x95, 0, 0, 0, 0},
738 {0x96, 0, 0, 0, 0},
739 {0x97, 0xaa, 0xaa, 0, 0},
740 {0x98, 0, 0, 0, 0},
741 {0x99, 0x23, 0x23, 0, 0},
742 {0x9A, 0x7, 0x7, 0, 0},
743 {0x9B, 0xf, 0xf, 0, 0},
744 {0x9C, 0x10, 0x10, 0, 0},
745 {0x9D, 0x3, 0x3, 0, 0},
746 {0x9E, 0x4, 0x4, 0, 0},
747 {0x9F, 0x20, 0x20, 0, 0},
748 {0xA0, 0, 0, 0, 0},
749 {0xA1, 0, 0, 0, 0},
750 {0xA2, 0, 0, 0, 0},
751 {0xA3, 0, 0, 0, 0},
752 {0xA4, 0x1, 0x1, 0, 0},
753 {0xA5, 0x77, 0x77, 0, 0},
754 {0xA6, 0x77, 0x77, 0, 0},
755 {0xA7, 0x77, 0x77, 0, 0},
756 {0xA8, 0x77, 0x77, 0, 0},
757 {0xA9, 0x8c, 0x8c, 0, 0},
758 {0xAA, 0x88, 0x88, 0, 0},
759 {0xAB, 0x78, 0x78, 0, 0},
760 {0xAC, 0x57, 0x57, 0, 0},
761 {0xAD, 0x88, 0x88, 0, 0},
762 {0xAE, 0, 0, 0, 0},
763 {0xAF, 0x8, 0x8, 0, 0},
764 {0xB0, 0x88, 0x88, 0, 0},
765 {0xB1, 0, 0, 0, 0},
766 {0xB2, 0x1b, 0x1b, 0, 0},
767 {0xB3, 0x3, 0x3, 0, 0},
768 {0xB4, 0x24, 0x24, 0, 0},
769 {0xB5, 0x3, 0x3, 0, 0},
770 {0xB6, 0x1b, 0x1b, 0, 0},
771 {0xB7, 0x24, 0x24, 0, 0},
772 {0xB8, 0x3, 0x3, 0, 0},
773 {0xB9, 0, 0, 0, 0},
774 {0xBA, 0xaa, 0xaa, 0, 0},
775 {0xBB, 0, 0, 0, 0},
776 {0xBC, 0x4, 0x4, 0, 0},
777 {0xBD, 0, 0, 0, 0},
778 {0xBE, 0x8, 0x8, 0, 0},
779 {0xBF, 0x11, 0x11, 0, 0},
780 {0xC0, 0, 0, 0, 0},
781 {0xC1, 0, 0, 0, 0},
782 {0xC2, 0x62, 0x62, 0, 0},
783 {0xC3, 0x1e, 0x1e, 0, 0},
784 {0xC4, 0x33, 0x33, 0, 0},
785 {0xC5, 0x37, 0x37, 0, 0},
786 {0xC6, 0, 0, 0, 0},
787 {0xC7, 0x70, 0x70, 0, 0},
788 {0xC8, 0x1e, 0x1e, 0, 0},
789 {0xC9, 0x6, 0x6, 0, 0},
790 {0xCA, 0x4, 0x4, 0, 0},
791 {0xCB, 0x2f, 0x2f, 0, 0},
792 {0xCC, 0xf, 0xf, 0, 0},
793 {0xCD, 0, 0, 0, 0},
794 {0xCE, 0xff, 0xff, 0, 0},
795 {0xCF, 0x8, 0x8, 0, 0},
796 {0xD0, 0x3f, 0x3f, 0, 0},
797 {0xD1, 0x3f, 0x3f, 0, 0},
798 {0xD2, 0x3f, 0x3f, 0, 0},
799 {0xD3, 0, 0, 0, 0},
800 {0xD4, 0, 0, 0, 0},
801 {0xD5, 0, 0, 0, 0},
802 {0xD6, 0xcc, 0xcc, 0, 0},
803 {0xD7, 0, 0, 0, 0},
804 {0xD8, 0x8, 0x8, 0, 0},
805 {0xD9, 0x8, 0x8, 0, 0},
806 {0xDA, 0x8, 0x8, 0, 0},
807 {0xDB, 0x11, 0x11, 0, 0},
808 {0xDC, 0, 0, 0, 0},
809 {0xDD, 0x87, 0x87, 0, 0},
810 {0xDE, 0x88, 0x88, 0, 0},
811 {0xDF, 0x8, 0x8, 0, 0},
812 {0xE0, 0x8, 0x8, 0, 0},
813 {0xE1, 0x8, 0x8, 0, 0},
814 {0xE2, 0, 0, 0, 0},
815 {0xE3, 0, 0, 0, 0},
816 {0xE4, 0, 0, 0, 0},
817 {0xE5, 0xf5, 0xf5, 0, 0},
818 {0xE6, 0x30, 0x30, 0, 0},
819 {0xE7, 0x1, 0x1, 0, 0},
820 {0xE8, 0, 0, 0, 0},
821 {0xE9, 0xff, 0xff, 0, 0},
822 {0xEA, 0, 0, 0, 0},
823 {0xEB, 0, 0, 0, 0},
824 {0xEC, 0x22, 0x22, 0, 0},
825 {0xED, 0, 0, 0, 0},
826 {0xEE, 0, 0, 0, 0},
827 {0xEF, 0, 0, 0, 0},
828 {0xF0, 0x3, 0x3, 0, 0},
829 {0xF1, 0x1, 0x1, 0, 0},
830 {0xF2, 0, 0, 0, 0},
831 {0xF3, 0, 0, 0, 0},
832 {0xF4, 0, 0, 0, 0},
833 {0xF5, 0, 0, 0, 0},
834 {0xF6, 0, 0, 0, 0},
835 {0xF7, 0x6, 0x6, 0, 0},
836 {0xF8, 0, 0, 0, 0},
837 {0xF9, 0, 0, 0, 0},
838 {0xFA, 0x40, 0x40, 0, 0},
839 {0xFB, 0, 0, 0, 0},
840 {0xFC, 0x1, 0x1, 0, 0},
841 {0xFD, 0x80, 0x80, 0, 0},
842 {0xFE, 0x2, 0x2, 0, 0},
843 {0xFF, 0x10, 0x10, 0, 0},
844 {0x100, 0x2, 0x2, 0, 0},
845 {0x101, 0x1e, 0x1e, 0, 0},
846 {0x102, 0x1e, 0x1e, 0, 0},
847 {0x103, 0, 0, 0, 0},
848 {0x104, 0x1f, 0x1f, 0, 0},
849 {0x105, 0, 0x8, 0, 1},
850 {0x106, 0x2a, 0x2a, 0, 0},
851 {0x107, 0xf, 0xf, 0, 0},
852 {0x108, 0, 0, 0, 0},
853 {0x109, 0, 0, 0, 0},
854 {0x10A, 0, 0, 0, 0},
855 {0x10B, 0, 0, 0, 0},
856 {0x10C, 0, 0, 0, 0},
857 {0x10D, 0, 0, 0, 0},
858 {0x10E, 0, 0, 0, 0},
859 {0x10F, 0, 0, 0, 0},
860 {0x110, 0, 0, 0, 0},
861 {0x111, 0, 0, 0, 0},
862 {0x112, 0, 0, 0, 0},
863 {0x113, 0, 0, 0, 0},
864 {0x114, 0, 0, 0, 0},
865 {0x115, 0, 0, 0, 0},
866 {0x116, 0, 0, 0, 0},
867 {0x117, 0, 0, 0, 0},
868 {0x118, 0, 0, 0, 0},
869 {0x119, 0, 0, 0, 0},
870 {0x11A, 0, 0, 0, 0},
871 {0x11B, 0, 0, 0, 0},
872 {0x11C, 0x1, 0x1, 0, 0},
873 {0x11D, 0, 0, 0, 0},
874 {0x11E, 0, 0, 0, 0},
875 {0x11F, 0, 0, 0, 0},
876 {0x120, 0, 0, 0, 0},
877 {0x121, 0, 0, 0, 0},
878 {0x122, 0x80, 0x80, 0, 0},
879 {0x123, 0, 0, 0, 0},
880 {0x124, 0xf8, 0xf8, 0, 0},
881 {0x125, 0, 0, 0, 0},
882 {0x126, 0, 0, 0, 0},
883 {0x127, 0, 0, 0, 0},
884 {0x128, 0, 0, 0, 0},
885 {0x129, 0, 0, 0, 0},
886 {0x12A, 0, 0, 0, 0},
887 {0x12B, 0, 0, 0, 0},
888 {0x12C, 0, 0, 0, 0},
889 {0x12D, 0, 0, 0, 0},
890 {0x12E, 0, 0, 0, 0},
891 {0x12F, 0, 0, 0, 0},
892 {0x130, 0, 0, 0, 0},
893 {0xFFFF, 0, 0, 0, 0}
894};
895
896#define LCNPHY_NUM_DIG_FILT_COEFFS 16
897#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
898
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700899u16
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700900 LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
901 [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
902 {0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
903 128, 64,},
904 {1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93,
905 167, 93,},
906 {2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64,
907 128, 64,},
908 {3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760,
909 170, 340, 170,},
910 {20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760,
911 256, 185, 256,},
912 {21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760,
913 256, 273, 256,},
914 {22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760,
915 256, 352, 256,},
916 {23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760,
917 128, 233, 128,},
918 {24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256,
919 1881, 256,},
920 {25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256,
921 1881, 256,},
922 {26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128,
923 384, 288,},
924 {27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864,
925 128, 384, 288,},
926 {30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760,
927 170, 340, 170,},
928};
929
930#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700931u16
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700932 LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
933 [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
934 {0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
935 0x278, 0xfea0, 0x80, 0x100, 0x80,},
936 {1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50,
937 750, 0xFE2B, 212, 0xFFCE, 212,},
938 {2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
939 0xFEF2, 128, 0xFFE2, 128}
940};
941
942#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
943 mod_phy_reg(pi, 0x4a4, \
944 (0x1ff << 0), \
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700945 (u16)(idx) << 0)
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700946
947#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
948 mod_phy_reg(pi, 0x4a5, \
949 (0x7 << 8), \
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700950 (u16)(npt) << 8)
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700951
952#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
953 (read_phy_reg((pi), 0x4a4) & \
954 ((0x1 << 15) | \
955 (0x1 << 14) | \
956 (0x1 << 13)))
957
958#define wlc_lcnphy_get_tx_pwr_npt(pi) \
959 ((read_phy_reg(pi, 0x4a5) & \
960 (0x7 << 8)) >> \
961 8)
962
963#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
964 (read_phy_reg(pi, 0x473) & 0x1ff)
965
966#define wlc_lcnphy_get_target_tx_pwr(pi) \
967 ((read_phy_reg(pi, 0x4a7) & \
968 (0xff << 0)) >> \
969 0)
970
971#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
972 mod_phy_reg(pi, 0x4a7, \
973 (0xff << 0), \
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700974 (u16)(target) << 0)
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700975
976#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
977#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
978
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -0700979#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700980#define FIXED_TXPWR 78
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -0700981#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
Henry Ptasinskia9533e72010-09-08 21:04:42 -0700982
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -0700983static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor,
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -0700984 u8 precision);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -0400985static void wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700986 u16 ext_lna, u16 trsw,
987 u16 biq2, u16 biq1,
988 u16 tia, u16 lna2,
989 u16 lna1);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -0400990static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -0700991static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -0400992static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx);
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -0700993static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0);
994static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -0400995static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains);
996static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable);
997static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi);
998static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable);
999static void wlc_lcnphy_set_tx_gain(phy_info_t *pi,
1000 lcnphy_txgains_t *target_gains);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001001static bool wlc_lcnphy_rx_iq_est(phy_info_t *pi, u16 num_samps,
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07001002 u8 wait_time, lcnphy_iq_est_t *iq_est);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001003static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps);
1004static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi);
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07001005static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001006extern void wlc_lcnphy_tx_pwr_ctrl_init(wlc_phy_t *ppi);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001007static void wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi,
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07001008 u8 channel);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001009
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001010static void wlc_lcnphy_load_tx_gain_table(phy_info_t *pi,
1011 const lcnphy_tx_gain_tbl_entry *g);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001012
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001013static void wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo,
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07001014 u16 thresh, s16 *ptr, int mode);
1015static int wlc_lcnphy_calc_floor(s16 coeff, int type);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001016static void wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001017 u16 *values_to_save);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001018static void wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001019 u16 *values_to_save);
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07001020static void wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x,
1021 s16 coeff_y);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001022static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type);
1023static void wlc_lcnphy_a1(phy_info_t *pi, int cal_type,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001024 int num_levels, int step_size_lg2);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001025static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001026
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001027static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001028 chanspec_t chanspec);
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001029static void wlc_lcnphy_agc_temp_init(phy_info_t *pi);
1030static void wlc_lcnphy_temp_adj(phy_info_t *pi);
1031static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi);
1032static void wlc_lcnphy_baseband_init(phy_info_t *pi);
1033static void wlc_lcnphy_radio_init(phy_info_t *pi);
1034static void wlc_lcnphy_rc_cal(phy_info_t *pi);
1035static void wlc_lcnphy_rcal(phy_info_t *pi);
1036static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable);
1037static int wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm,
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07001038 s16 filt_type);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001039static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001040
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001041void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001042{
1043 wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
1044}
1045
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001046void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001047{
1048 wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456);
1049}
1050
1051static void
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001052wlc_lcnphy_common_read_table(phy_info_t *pi, u32 tbl_id,
1053 const void *tbl_ptr, u32 tbl_len,
1054 u32 tbl_width, u32 tbl_offset)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001055{
1056 phytbl_info_t tab;
1057 tab.tbl_id = tbl_id;
1058 tab.tbl_ptr = tbl_ptr;
1059 tab.tbl_len = tbl_len;
1060 tab.tbl_width = tbl_width;
1061 tab.tbl_offset = tbl_offset;
1062 wlc_lcnphy_read_table(pi, &tab);
1063}
1064
1065static void
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001066wlc_lcnphy_common_write_table(phy_info_t *pi, u32 tbl_id,
1067 const void *tbl_ptr, u32 tbl_len,
1068 u32 tbl_width, u32 tbl_offset)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001069{
1070
1071 phytbl_info_t tab;
1072 tab.tbl_id = tbl_id;
1073 tab.tbl_ptr = tbl_ptr;
1074 tab.tbl_len = tbl_len;
1075 tab.tbl_width = tbl_width;
1076 tab.tbl_offset = tbl_offset;
1077 wlc_lcnphy_write_table(pi, &tab);
1078}
1079
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001080static u32
1081wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001082{
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001083 u32 quotient, remainder, roundup, rbit;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001084
1085 ASSERT(divisor);
1086
1087 quotient = dividend / divisor;
1088 remainder = dividend % divisor;
1089 rbit = divisor & 1;
1090 roundup = (divisor >> 1) + rbit;
1091
1092 while (precision--) {
1093 quotient <<= 1;
1094 if (remainder >= roundup) {
1095 quotient++;
1096 remainder = ((remainder - roundup) << 1) + rbit;
1097 } else {
1098 remainder <<= 1;
1099 }
1100 }
1101
1102 if (remainder >= roundup)
1103 quotient++;
1104
1105 return quotient;
1106}
1107
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07001108static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001109{
1110 int k;
1111 k = 0;
1112 if (type == 0) {
1113 if (coeff_x < 0) {
1114 k = (coeff_x - 1) / 2;
1115 } else {
1116 k = coeff_x / 2;
1117 }
1118 }
1119 if (type == 1) {
1120 if ((coeff_x + 1) < 0)
1121 k = (coeff_x) / 2;
1122 else
1123 k = (coeff_x + 1) / 2;
1124 }
1125 return k;
1126}
1127
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001128s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001129{
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001130 s8 index;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001131 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1132
1133 if (txpwrctrl_off(pi))
1134 index = pi_lcn->lcnphy_current_index;
1135 else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
1136 index =
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001137 (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001138 / 2);
1139 else
1140 index = pi_lcn->lcnphy_current_index;
1141 return index;
1142}
1143
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001144static u32 wlc_lcnphy_measure_digital_power(phy_info_t *pi, u16 nsamples)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001145{
1146 lcnphy_iq_est_t iq_est = { 0, 0, 0 };
1147
1148 if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est))
1149 return 0;
1150 return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
1151}
1152
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001153void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001154{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001155 u16 afectrlovr, afectrlovrval;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001156 afectrlovr = read_phy_reg(pi, 0x43b);
1157 afectrlovrval = read_phy_reg(pi, 0x43c);
1158 if (channel != 0) {
1159 mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1);
1160
1161 mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1);
1162
1163 mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4);
1164
1165 mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6);
1166
1167 write_phy_reg(pi, 0x44b, 0xffff);
1168 wlc_lcnphy_tx_pu(pi, 1);
1169
1170 mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8);
1171
1172 or_phy_reg(pi, 0x6da, 0x0080);
1173
1174 or_phy_reg(pi, 0x00a, 0x228);
1175 } else {
1176 and_phy_reg(pi, 0x00a, ~(0x228));
1177
1178 and_phy_reg(pi, 0x6da, 0xFF7F);
1179 write_phy_reg(pi, 0x43b, afectrlovr);
1180 write_phy_reg(pi, 0x43c, afectrlovrval);
1181 }
1182}
1183
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001184static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001185{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001186 u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001187
1188 save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c);
1189 save_AfeCtrlOvr = read_phy_reg(pi, 0x43b);
1190
1191 write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1);
1192 write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1);
1193
1194 write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe);
1195 write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe);
1196
1197 write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal);
1198 write_phy_reg(pi, 0x43b, save_AfeCtrlOvr);
1199}
1200
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001201static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001202{
1203 if (enable) {
1204 write_phy_reg(pi, 0x942, 0x7);
1205 write_phy_reg(pi, 0x93b, ((1 << 13) + 23));
1206 write_phy_reg(pi, 0x93c, ((1 << 13) + 1989));
1207
1208 write_phy_reg(pi, 0x44a, 0x084);
1209 write_phy_reg(pi, 0x44a, 0x080);
1210 write_phy_reg(pi, 0x6d3, 0x2222);
1211 write_phy_reg(pi, 0x6d3, 0x2220);
1212 } else {
1213 write_phy_reg(pi, 0x942, 0x0);
1214 write_phy_reg(pi, 0x93b, ((0 << 13) + 23));
1215 write_phy_reg(pi, 0x93c, ((0 << 13) + 1989));
1216 }
1217 wlapi_switch_macfreq(pi->sh->physhim, enable);
1218}
1219
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001220void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001221{
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07001222 u8 channel = CHSPEC_CHANNEL(chanspec);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001223
1224 wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
1225
1226 wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
1227
1228 or_phy_reg(pi, 0x44a, 0x44);
1229 write_phy_reg(pi, 0x44a, 0x80);
1230
1231 if (!NORADIO_ENAB(pi->pubpi)) {
1232 wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02001233 udelay(1000);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001234 }
1235
1236 wlc_lcnphy_toggle_afe_pwdn(pi);
1237
1238 write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
1239 write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
1240
1241 if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
1242 mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
1243
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07001244 wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001245 } else {
1246 mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
1247
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07001248 wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001249 }
1250
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07001251 wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001252
1253 mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
1254
1255}
1256
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001257static void wlc_lcnphy_set_dac_gain(phy_info_t *pi, u16 dac_gain)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001258{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001259 u16 dac_ctrl;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001260
1261 dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
1262 dac_ctrl = dac_ctrl & 0xc7f;
1263 dac_ctrl = dac_ctrl | (dac_gain << 7);
1264 mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
1265
1266}
1267
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001268static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001269{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001270 u16 bit = bEnable ? 1 : 0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001271
1272 mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
1273
1274 mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
1275
1276 mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
1277}
1278
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001279static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001280{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001281 u16 pa_gain;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001282
1283 pa_gain = (read_phy_reg(pi, 0x4fb) &
1284 LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
1285 LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
1286
1287 return pa_gain;
1288}
1289
1290static void
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001291wlc_lcnphy_set_tx_gain(phy_info_t *pi, lcnphy_txgains_t *target_gains)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001292{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001293 u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001294
1295 mod_phy_reg(pi, 0x4b5,
1296 (0xffff << 0),
1297 ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
1298 0);
1299 mod_phy_reg(pi, 0x4fb,
1300 (0x7fff << 0),
1301 ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
1302
1303 mod_phy_reg(pi, 0x4fc,
1304 (0xffff << 0),
1305 ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
1306 0);
1307 mod_phy_reg(pi, 0x4fd,
1308 (0x7fff << 0),
1309 ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
1310
1311 wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
1312
1313 wlc_lcnphy_enable_tx_gain_override(pi);
1314}
1315
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07001316static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001317{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001318 u16 m0m1 = (u16) m0 << 8;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001319 phytbl_info_t tab;
1320
1321 tab.tbl_ptr = &m0m1;
1322 tab.tbl_len = 1;
1323 tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
1324 tab.tbl_offset = 87;
1325 tab.tbl_width = 16;
1326 wlc_lcnphy_write_table(pi, &tab);
1327}
1328
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001329static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001330{
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001331 u32 data_buf[64];
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001332 phytbl_info_t tab;
1333
Brett Rudley9249ede2010-11-30 20:09:49 -08001334 memset(data_buf, 0, sizeof(data_buf));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001335
1336 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1337 tab.tbl_width = 32;
1338 tab.tbl_ptr = data_buf;
1339
1340 if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
1341
1342 tab.tbl_len = 30;
1343 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
1344 wlc_lcnphy_write_table(pi, &tab);
1345 }
1346
1347 tab.tbl_len = 64;
1348 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
1349 wlc_lcnphy_write_table(pi, &tab);
1350}
1351
1352typedef enum {
1353 LCNPHY_TSSI_PRE_PA,
1354 LCNPHY_TSSI_POST_PA,
1355 LCNPHY_TSSI_EXT
1356} lcnphy_tssi_mode_t;
1357
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001358static void wlc_lcnphy_set_tssi_mux(phy_info_t *pi, lcnphy_tssi_mode_t pos)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001359{
1360 mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
1361
1362 mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
1363
1364 if (LCNPHY_TSSI_POST_PA == pos) {
1365 mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
1366
1367 mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
1368
1369 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1370 mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
1371 } else {
1372 mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
1373 mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
1374 }
1375 } else {
1376 mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
1377
1378 mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
1379
1380 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1381 mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
1382 } else {
1383 mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
1384 mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
1385 }
1386 }
1387 mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
1388
1389 if (LCNPHY_TSSI_EXT == pos) {
1390 write_radio_reg(pi, RADIO_2064_REG07F, 1);
1391 mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
1392 mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
1393 mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
1394 }
1395}
1396
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001397static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001398{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001399 u16 N1, N2, N3, N4, N5, N6, N;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001400 N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
1401 >> 0);
1402 N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
1403 >> 12);
1404 N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
1405 >> 0);
1406 N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8))
1407 >> 8);
1408 N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0))
1409 >> 0);
1410 N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8))
1411 >> 8);
1412 N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80;
1413 if (N < 1600)
1414 N = 1600;
1415 return N;
1416}
1417
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001418static void wlc_lcnphy_pwrctrl_rssiparams(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001419{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001420 u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001421 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1422
1423 auxpga_vmid =
1424 (2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
1425 auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
1426 auxpga_gain_temp = 2;
1427
1428 mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0);
1429
1430 mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1);
1431
1432 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3);
1433
1434 mod_phy_reg(pi, 0x4db,
1435 (0x3ff << 0) |
1436 (0x7 << 12),
1437 (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
1438
1439 mod_phy_reg(pi, 0x4dc,
1440 (0x3ff << 0) |
1441 (0x7 << 12),
1442 (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
1443
1444 mod_phy_reg(pi, 0x40a,
1445 (0x3ff << 0) |
1446 (0x7 << 12),
1447 (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
1448
1449 mod_phy_reg(pi, 0x40b,
1450 (0x3ff << 0) |
1451 (0x7 << 12),
1452 (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
1453
1454 mod_phy_reg(pi, 0x40c,
1455 (0x3ff << 0) |
1456 (0x7 << 12),
1457 (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
1458
1459 mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
1460}
1461
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001462static void wlc_lcnphy_tssi_setup(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001463{
1464 phytbl_info_t tab;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001465 u32 rfseq, ind;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001466
1467 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1468 tab.tbl_width = 32;
1469 tab.tbl_ptr = &ind;
1470 tab.tbl_len = 1;
1471 tab.tbl_offset = 0;
1472 for (ind = 0; ind < 128; ind++) {
1473 wlc_lcnphy_write_table(pi, &tab);
1474 tab.tbl_offset++;
1475 }
1476 tab.tbl_offset = 704;
1477 for (ind = 0; ind < 128; ind++) {
1478 wlc_lcnphy_write_table(pi, &tab);
1479 tab.tbl_offset++;
1480 }
1481 mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
1482
1483 mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
1484
1485 mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
1486
1487 wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
1488 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
1489
1490 mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
1491
1492 mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
1493
1494 mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0);
1495
1496 mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
1497
1498 mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
1499
1500 mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
1501
1502 mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
1503
1504 mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8);
1505
1506 mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
1507
1508 mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8);
1509
1510 mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6);
1511
1512 mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0);
1513
1514 wlc_lcnphy_clear_tx_power_offsets(pi);
1515
1516 mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
1517
1518 mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0);
1519
1520 mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
1521
1522 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1523 mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
1524 mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
1525 } else {
1526 mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
1527 mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
1528 }
1529
1530 write_radio_reg(pi, RADIO_2064_REG025, 0xc);
1531
1532 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
1533 mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
1534 } else {
1535 if (CHSPEC_IS2G(pi->radio_chanspec))
1536 mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
1537 else
1538 mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1);
1539 }
1540
1541 if (LCNREV_IS(pi->pubpi.phy_rev, 2))
1542 mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
1543 else
1544 mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2);
1545
1546 mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0);
1547
1548 mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
1549
1550 if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
1551 mod_phy_reg(pi, 0x4d7,
1552 (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
1553 }
1554
1555 rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
1556 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
1557 tab.tbl_width = 16;
1558 tab.tbl_ptr = &rfseq;
1559 tab.tbl_len = 1;
1560 tab.tbl_offset = 6;
1561 wlc_lcnphy_write_table(pi, &tab);
1562
1563 mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
1564
1565 mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
1566
1567 mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
1568
1569 mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2);
1570
1571 mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
1572
1573 wlc_lcnphy_pwrctrl_rssiparams(pi);
1574}
1575
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001576void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001577{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001578 u16 tx_cnt, tx_total, npt;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001579 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1580
1581 tx_total = wlc_lcnphy_total_tx_frames(pi);
1582 tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt;
1583 npt = wlc_lcnphy_get_tx_pwr_npt(pi);
1584
1585 if (tx_cnt > (1 << npt)) {
1586
1587 pi_lcn->lcnphy_tssi_tx_cnt = tx_total;
1588
1589 pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi);
1590 pi_lcn->lcnphy_tssi_npt = npt;
1591
1592 }
1593}
1594
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07001595s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001596{
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07001597 s32 a, b, p;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001598
1599 a = 32768 + (a1 * tssi);
1600 b = (1024 * b0) + (64 * b1 * tssi);
1601 p = ((2 * b) + a) / (2 * a);
1602
1603 return p;
1604}
1605
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001606static void wlc_lcnphy_txpower_reset_npt(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001607{
1608 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1609 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
1610 return;
1611
1612 pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313;
1613 pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT;
1614}
1615
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001616void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001617{
1618 phytbl_info_t tab;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001619 u32 rate_table[WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM +
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001620 WLC_NUM_RATES_MCS_1_STREAM];
1621 uint i, j;
1622 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
1623 return;
1624
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07001625 for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) {
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001626
1627 if (i == WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM)
1628 j = TXP_FIRST_MCS_20_SISO;
1629
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07001630 rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j]));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001631 }
1632
1633 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1634 tab.tbl_width = 32;
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07001635 tab.tbl_len = ARRAY_SIZE(rate_table);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001636 tab.tbl_ptr = rate_table;
1637 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
1638 wlc_lcnphy_write_table(pi, &tab);
1639
1640 if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) {
1641 wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min);
1642
1643 wlc_lcnphy_txpower_reset_npt(pi);
1644 }
1645}
1646
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001647static void wlc_lcnphy_set_tx_pwr_soft_ctrl(phy_info_t *pi, s8 index)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001648{
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001649 u32 cck_offset[4] = { 22, 22, 22, 22 };
1650 u32 ofdm_offset, reg_offset_cck;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001651 int i;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001652 u16 index2;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001653 phytbl_info_t tab;
1654
1655 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
1656 return;
1657
1658 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
1659
1660 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14);
1661
1662 or_phy_reg(pi, 0x6da, 0x0040);
1663
1664 reg_offset_cck = 0;
1665 for (i = 0; i < 4; i++)
1666 cck_offset[i] -= reg_offset_cck;
1667 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
1668 tab.tbl_width = 32;
1669 tab.tbl_len = 4;
1670 tab.tbl_ptr = cck_offset;
1671 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
1672 wlc_lcnphy_write_table(pi, &tab);
1673 ofdm_offset = 0;
1674 tab.tbl_len = 1;
1675 tab.tbl_ptr = &ofdm_offset;
1676 for (i = 836; i < 862; i++) {
1677 tab.tbl_offset = i;
1678 wlc_lcnphy_write_table(pi, &tab);
1679 }
1680
1681 mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15);
1682
1683 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
1684
1685 mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13);
1686
1687 mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7);
1688
1689 mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6);
1690
1691 mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15);
1692
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001693 index2 = (u16) (index * 2);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001694 mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
1695
1696 mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4);
1697
1698}
1699
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001700static s8 wlc_lcnphy_tempcompensated_txpwrctrl(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001701{
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001702 s8 index, delta_brd, delta_temp, new_index, tempcorrx;
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07001703 s16 manp, meas_temp, temp_diff;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001704 bool neg = 0;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001705 u16 temp;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001706 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1707
1708 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
1709 return pi_lcn->lcnphy_current_index;
1710
1711 index = FIXED_TXPWR;
1712
1713 if (NORADIO_ENAB(pi->pubpi))
1714 return index;
1715
1716 if (pi_lcn->lcnphy_tempsense_slope == 0) {
1717 return index;
1718 }
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001719 temp = (u16) wlc_lcnphy_tempsense(pi, 0);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001720 meas_temp = LCNPHY_TEMPSENSE(temp);
1721
1722 if (pi->tx_power_min != 0) {
1723 delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
1724 } else {
1725 delta_brd = 0;
1726 }
1727
1728 manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
1729 temp_diff = manp - meas_temp;
1730 if (temp_diff < 0) {
1731
1732 neg = 1;
1733
1734 temp_diff = -temp_diff;
1735 }
1736
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07001737 delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
1738 (u32) (pi_lcn->
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001739 lcnphy_tempsense_slope
1740 * 10), 0);
1741 if (neg)
1742 delta_temp = -delta_temp;
1743
1744 if (pi_lcn->lcnphy_tempsense_option == 3
1745 && LCNREV_IS(pi->pubpi.phy_rev, 0))
1746 delta_temp = 0;
1747 if (pi_lcn->lcnphy_tempcorrx > 31)
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001748 tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001749 else
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001750 tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001751 if (LCNREV_IS(pi->pubpi.phy_rev, 1))
1752 tempcorrx = 4;
1753 new_index =
1754 index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
1755 new_index += tempcorrx;
1756
1757 if (LCNREV_IS(pi->pubpi.phy_rev, 1))
1758 index = 127;
1759 if (new_index < 0 || new_index > 126) {
1760 return index;
1761 }
1762 return new_index;
1763}
1764
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001765static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(phy_info_t *pi, u16 mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001766{
1767
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001768 u16 current_mode = mode;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001769 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
1770 mode == LCNPHY_TX_PWR_CTRL_HW)
1771 current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED;
1772 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
1773 mode == LCNPHY_TX_PWR_CTRL_TEMPBASED)
1774 current_mode = LCNPHY_TX_PWR_CTRL_HW;
1775 return current_mode;
1776}
1777
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001778void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001779{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001780 u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi);
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001781 s8 index;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001782 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1783
1784 ASSERT((LCNPHY_TX_PWR_CTRL_OFF == mode) ||
1785 (LCNPHY_TX_PWR_CTRL_SW == mode) ||
1786 (LCNPHY_TX_PWR_CTRL_HW == mode) ||
1787 (LCNPHY_TX_PWR_CTRL_TEMPBASED == mode));
1788
1789 mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode);
1790 old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode);
1791
1792 mod_phy_reg(pi, 0x6da, (0x1 << 6),
1793 ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6);
1794
1795 mod_phy_reg(pi, 0x6a3, (0x1 << 4),
1796 ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4);
1797
1798 if (old_mode != mode) {
1799 if (LCNPHY_TX_PWR_CTRL_HW == old_mode) {
1800
1801 wlc_lcnphy_tx_pwr_update_npt(pi);
1802
1803 wlc_lcnphy_clear_tx_power_offsets(pi);
1804 }
1805 if (LCNPHY_TX_PWR_CTRL_HW == mode) {
1806
1807 wlc_lcnphy_txpower_recalc_target(pi);
1808
1809 wlc_lcnphy_set_start_tx_pwr_idx(pi,
1810 pi_lcn->
1811 lcnphy_tssi_idx);
1812 wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt);
1813 mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
1814
1815 pi_lcn->lcnphy_tssi_tx_cnt =
1816 wlc_lcnphy_total_tx_frames(pi);
1817
1818 wlc_lcnphy_disable_tx_gain_override(pi);
1819 pi_lcn->lcnphy_tx_power_idx_override = -1;
1820 } else
1821 wlc_lcnphy_enable_tx_gain_override(pi);
1822
1823 mod_phy_reg(pi, 0x4a4,
1824 ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode);
1825 if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) {
1826 index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
1827 wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07001828 pi_lcn->lcnphy_current_index = (s8)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001829 ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
1830 }
1831 }
1832}
1833
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001834static bool wlc_lcnphy_iqcal_wait(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001835{
1836 uint delay_count = 0;
1837
1838 while (wlc_lcnphy_iqcal_active(pi)) {
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02001839 udelay(100);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001840 delay_count++;
1841
1842 if (delay_count > (10 * 500))
1843 break;
1844 }
1845
1846 return (0 == wlc_lcnphy_iqcal_active(pi));
1847}
1848
1849static void
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04001850wlc_lcnphy_tx_iqlo_cal(phy_info_t *pi,
1851 lcnphy_txgains_t *target_gains,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001852 lcnphy_cal_mode_t cal_mode, bool keep_tone)
1853{
1854
1855 lcnphy_txgains_t cal_gains, temp_gains;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001856 u16 hash;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07001857 u8 band_idx;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001858 int j;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001859 u16 ncorr_override[5];
1860 u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001861 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
1862 };
1863
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001864 u16 commands_fullcal[] = {
Jason Coopere5c45362010-09-14 09:45:35 -04001865 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001866
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001867 u16 commands_recal[] = {
Jason Coopere5c45362010-09-14 09:45:35 -04001868 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001869
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001870 u16 command_nums_fullcal[] = {
Jason Coopere5c45362010-09-14 09:45:35 -04001871 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001872
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001873 u16 command_nums_recal[] = {
Jason Coopere5c45362010-09-14 09:45:35 -04001874 0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001875 u16 *command_nums = command_nums_fullcal;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001876
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001877 u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
1878 u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2;
1879 u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001880 bool tx_gain_override_old;
1881 lcnphy_txgains_t old_gains;
1882 uint i, n_cal_cmds = 0, n_cal_start = 0;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07001883 u16 *values_to_save;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001884 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
1885
1886 if (NORADIO_ENAB(pi->pubpi))
1887 return;
1888
mike.rapoport@gmail.com5fcc1fc2010-10-13 00:09:10 +02001889 values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
Jason Cooperca8c1e52010-09-14 09:45:33 -04001890 if (NULL == values_to_save) {
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001891 return;
1892 }
1893
1894 save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
1895 save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
1896
1897 or_phy_reg(pi, 0x6da, 0x40);
1898 or_phy_reg(pi, 0x6db, 0x3);
1899
1900 switch (cal_mode) {
1901 case LCNPHY_CAL_FULL:
1902 start_coeffs = syst_coeffs;
1903 cal_cmds = commands_fullcal;
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07001904 n_cal_cmds = ARRAY_SIZE(commands_fullcal);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001905 break;
1906
1907 case LCNPHY_CAL_RECAL:
1908 ASSERT(pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid);
1909
1910 start_coeffs = syst_coeffs;
1911
1912 cal_cmds = commands_recal;
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07001913 n_cal_cmds = ARRAY_SIZE(commands_recal);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001914 command_nums = command_nums_recal;
1915 break;
1916 default:
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07001917 ASSERT(false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001918 }
1919
1920 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
1921 start_coeffs, 11, 16, 64);
1922
1923 write_phy_reg(pi, 0x6da, 0xffff);
1924 mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3);
1925
1926 tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi);
1927
1928 mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
1929
1930 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
1931
1932 save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db);
1933
1934 mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0);
1935
1936 mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12);
1937
1938 wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save);
1939
1940 tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
1941 if (tx_gain_override_old)
1942 wlc_lcnphy_get_tx_gain(pi, &old_gains);
1943
1944 if (!target_gains) {
1945 if (!tx_gain_override_old)
1946 wlc_lcnphy_set_tx_pwr_by_index(pi,
1947 pi_lcn->lcnphy_tssi_idx);
1948 wlc_lcnphy_get_tx_gain(pi, &temp_gains);
1949 target_gains = &temp_gains;
1950 }
1951
1952 hash = (target_gains->gm_gain << 8) |
1953 (target_gains->pga_gain << 4) | (target_gains->pad_gain);
1954
1955 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
1956
1957 cal_gains = *target_gains;
Brett Rudley9249ede2010-11-30 20:09:49 -08001958 memset(ncorr_override, 0, sizeof(ncorr_override));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001959 for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
1960 if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
1961 cal_gains.gm_gain =
1962 tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
1963 cal_gains.pga_gain =
1964 tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
1965 cal_gains.pad_gain =
1966 tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
1967 bcopy(&tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
1968 ncorr_override, sizeof(ncorr_override));
1969 break;
1970 }
1971 }
1972
1973 wlc_lcnphy_set_tx_gain(pi, &cal_gains);
1974
1975 write_phy_reg(pi, 0x453, 0xaa9);
1976 write_phy_reg(pi, 0x93d, 0xc0);
1977
1978 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
Greg Kroah-Hartmandf8501c2010-10-05 11:18:31 -07001979 (const void *)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001980 lcnphy_iqcal_loft_gainladder,
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07001981 ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001982 16, 0);
1983
1984 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
Greg Kroah-Hartmandf8501c2010-10-05 11:18:31 -07001985 (const void *)lcnphy_iqcal_ir_gainladder,
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07001986 ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001987 32);
1988
1989 if (pi->phy_tx_tone_freq) {
1990
1991 wlc_lcnphy_stop_tx_tone(pi);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02001992 udelay(5);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07001993 wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
1994 } else {
1995 wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
1996 }
1997
1998 write_phy_reg(pi, 0x6da, 0xffff);
1999
2000 for (i = n_cal_start; i < n_cal_cmds; i++) {
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002001 u16 zero_diq = 0;
2002 u16 best_coeffs[11];
2003 u16 command_num;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002004
2005 cal_type = (cal_cmds[i] & 0x0f00) >> 8;
2006
2007 command_num = command_nums[i];
2008 if (ncorr_override[cal_type])
2009 command_num =
2010 ncorr_override[cal_type] << 8 | (command_num &
2011 0xff);
2012
2013 write_phy_reg(pi, 0x452, command_num);
2014
2015 if ((cal_type == 3) || (cal_type == 4)) {
2016
2017 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2018 &diq_start, 1, 16, 69);
2019
2020 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2021 &zero_diq, 1, 16, 69);
2022 }
2023
2024 write_phy_reg(pi, 0x451, cal_cmds[i]);
2025
2026 if (!wlc_lcnphy_iqcal_wait(pi)) {
2027
2028 goto cleanup;
2029 }
2030
2031 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2032 best_coeffs,
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07002033 ARRAY_SIZE(best_coeffs), 16, 96);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002034 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2035 best_coeffs,
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07002036 ARRAY_SIZE(best_coeffs), 16, 64);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002037
2038 if ((cal_type == 3) || (cal_type == 4)) {
2039 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2040 &diq_start, 1, 16, 69);
2041 }
2042 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2043 pi_lcn->lcnphy_cal_results.
2044 txiqlocal_bestcoeffs,
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07002045 ARRAY_SIZE(pi_lcn->
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002046 lcnphy_cal_results.
2047 txiqlocal_bestcoeffs),
2048 16, 96);
2049 }
2050
2051 wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2052 pi_lcn->lcnphy_cal_results.
2053 txiqlocal_bestcoeffs,
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07002054 ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002055 txiqlocal_bestcoeffs), 16, 96);
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07002056 pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002057
2058 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2059 &pi_lcn->lcnphy_cal_results.
2060 txiqlocal_bestcoeffs[0], 4, 16, 80);
2061
2062 wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
2063 &pi_lcn->lcnphy_cal_results.
2064 txiqlocal_bestcoeffs[5], 2, 16, 85);
2065
2066 cleanup:
2067 wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
mike.rapoport@gmail.com182acb32010-10-13 00:09:12 +02002068 kfree(values_to_save);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002069
2070 if (!keep_tone)
2071 wlc_lcnphy_stop_tx_tone(pi);
2072
2073 write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2);
2074
2075 write_phy_reg(pi, 0x453, 0);
2076
2077 if (tx_gain_override_old)
2078 wlc_lcnphy_set_tx_gain(pi, &old_gains);
2079 wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old);
2080
2081 write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl);
2082 write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl);
2083
2084}
2085
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002086static void wlc_lcnphy_idle_tssi_est(wlc_phy_t *ppi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002087{
2088 bool suspend, tx_gain_override_old;
2089 lcnphy_txgains_t old_gains;
2090 phy_info_t *pi = (phy_info_t *) ppi;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002091 u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002092 idleTssi0_regvalue_2C;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002093 u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
2094 u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
2095 u16 SAVE_jtag_bb_afe_switch =
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002096 read_radio_reg(pi, RADIO_2064_REG007) & 1;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002097 u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
2098 u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002099 idleTssi = read_phy_reg(pi, 0x4ab);
2100 suspend =
2101 (0 ==
2102 (R_REG(pi->sh->osh, &((phy_info_t *) pi)->regs->maccontrol) &
2103 MCTL_EN_MAC));
2104 if (!suspend)
2105 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2106 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2107
2108 tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
2109 wlc_lcnphy_get_tx_gain(pi, &old_gains);
2110
2111 wlc_lcnphy_enable_tx_gain_override(pi);
2112 wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
2113 write_radio_reg(pi, RADIO_2064_REG112, 0x6);
2114 mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
2115 mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
2116 mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
2117 wlc_lcnphy_tssi_setup(pi);
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07002118 wlc_phy_do_dummy_tx(pi, true, OFF);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002119 idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
2120 >> 0);
2121
2122 idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
2123 >> 0);
2124
2125 if (idleTssi0_2C >= 256)
2126 idleTssi0_OB = idleTssi0_2C - 256;
2127 else
2128 idleTssi0_OB = idleTssi0_2C + 256;
2129
2130 idleTssi0_regvalue_OB = idleTssi0_OB;
2131 if (idleTssi0_regvalue_OB >= 256)
2132 idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
2133 else
2134 idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
2135 mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
2136
2137 mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
2138
2139 wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
2140 wlc_lcnphy_set_tx_gain(pi, &old_gains);
2141 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
2142
2143 write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
2144 mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
2145 mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
2146 mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
2147 mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
2148 if (!suspend)
2149 wlapi_enable_mac(pi->sh->physhim);
2150}
2151
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002152static void wlc_lcnphy_vbat_temp_sense_setup(phy_info_t *pi, u8 mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002153{
2154 bool suspend;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002155 u16 save_txpwrCtrlEn;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002156 u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002157 u16 auxpga_vmid;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002158 phytbl_info_t tab;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07002159 u32 val;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002160 u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002161 save_reg112;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002162 u16 values_to_save[14];
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07002163 s8 index;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002164 int i;
2165 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02002166 udelay(999);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002167
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002168 save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
2169 save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
2170 save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
2171 save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
2172 save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
2173 save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002174
2175 for (i = 0; i < 14; i++)
2176 values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
2177 suspend =
2178 (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
2179 if (!suspend)
2180 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2181 save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
2182
2183 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2184 index = pi_lcn->lcnphy_current_index;
2185 wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
2186 mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
2187 mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
2188 mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
2189 mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
2190
2191 mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
2192
2193 mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
2194
2195 mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
2196
2197 mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
2198
2199 mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
2200
2201 mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
2202
2203 mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
2204
2205 mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
2206
2207 mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
2208
2209 mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
2210
2211 mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
2212
2213 mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
2214
2215 mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
2216
2217 mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
2218
2219 mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
2220
2221 mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
2222
2223 mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
2224
2225 write_radio_reg(pi, RADIO_2064_REG025, 0xC);
2226
2227 mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
2228
2229 mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
2230
2231 mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
2232
2233 mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
2234
2235 val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
2236 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
2237 tab.tbl_width = 16;
2238 tab.tbl_len = 1;
2239 tab.tbl_ptr = &val;
2240 tab.tbl_offset = 6;
2241 wlc_lcnphy_write_table(pi, &tab);
2242 if (mode == TEMPSENSE) {
2243 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
2244
2245 mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
2246
2247 auxpga_vmidcourse = 8;
2248 auxpga_vmidfine = 0x4;
2249 auxpga_gain = 2;
2250 mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
2251 } else {
2252 mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
2253
2254 mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
2255
2256 auxpga_vmidcourse = 7;
2257 auxpga_vmidfine = 0xa;
2258 auxpga_gain = 2;
2259 }
2260 auxpga_vmid =
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002261 (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002262 mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
2263
2264 mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
2265
2266 mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
2267
2268 mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
2269
2270 mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
2271
2272 write_radio_reg(pi, RADIO_2064_REG112, 0x6);
2273
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07002274 wlc_phy_do_dummy_tx(pi, true, OFF);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002275 if (!tempsense_done(pi))
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02002276 udelay(10);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002277
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002278 write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
2279 write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
2280 write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
2281 write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
2282 write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
2283 write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002284 for (i = 0; i < 14; i++)
2285 write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
2286 wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
2287
2288 write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
2289 if (!suspend)
2290 wlapi_enable_mac(pi->sh->physhim);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02002291 udelay(999);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002292}
2293
Jason Coopera2627bc2010-09-14 09:45:31 -04002294void WLBANDINITFN(wlc_lcnphy_tx_pwr_ctrl_init) (wlc_phy_t *ppi)
2295{
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002296 lcnphy_txgains_t tx_gains;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002297 u8 bbmult;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002298 phytbl_info_t tab;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07002299 s32 a1, b0, b1;
2300 s32 tssi, pwr, maxtargetpwr, mintargetpwr;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002301 bool suspend;
2302 phy_info_t *pi = (phy_info_t *) ppi;
2303
2304 suspend =
2305 (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
2306 if (!suspend)
2307 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2308
2309 if (NORADIO_ENAB(pi->pubpi)) {
2310 wlc_lcnphy_set_bbmult(pi, 0x30);
2311 if (!suspend)
2312 wlapi_enable_mac(pi->sh->physhim);
2313 return;
2314 }
2315
2316 if (!pi->hwpwrctrl_capable) {
2317 if (CHSPEC_IS2G(pi->radio_chanspec)) {
2318 tx_gains.gm_gain = 4;
2319 tx_gains.pga_gain = 12;
2320 tx_gains.pad_gain = 12;
2321 tx_gains.dac_gain = 0;
2322
2323 bbmult = 150;
2324 } else {
2325 tx_gains.gm_gain = 7;
2326 tx_gains.pga_gain = 15;
2327 tx_gains.pad_gain = 14;
2328 tx_gains.dac_gain = 0;
2329
2330 bbmult = 150;
2331 }
2332 wlc_lcnphy_set_tx_gain(pi, &tx_gains);
2333 wlc_lcnphy_set_bbmult(pi, bbmult);
2334 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
2335 } else {
2336
2337 wlc_lcnphy_idle_tssi_est(ppi);
2338
2339 wlc_lcnphy_clear_tx_power_offsets(pi);
2340
2341 b0 = pi->txpa_2g[0];
2342 b1 = pi->txpa_2g[1];
2343 a1 = pi->txpa_2g[2];
2344 maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
2345 mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
2346
2347 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
2348 tab.tbl_width = 32;
2349 tab.tbl_ptr = &pwr;
2350 tab.tbl_len = 1;
2351 tab.tbl_offset = 0;
2352 for (tssi = 0; tssi < 128; tssi++) {
2353 pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
2354
2355 pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
2356 wlc_lcnphy_write_table(pi, &tab);
2357 tab.tbl_offset++;
2358 }
2359
2360 mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
2361
2362 write_phy_reg(pi, 0x4a8, 10);
2363
2364 wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
2365
2366 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
2367 }
2368 if (!suspend)
2369 wlapi_enable_mac(pi->sh->physhim);
2370}
2371
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002372static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002373{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002374 u16 m0m1;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002375 phytbl_info_t tab;
2376
2377 tab.tbl_ptr = &m0m1;
2378 tab.tbl_len = 1;
2379 tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
2380 tab.tbl_offset = 87;
2381 tab.tbl_width = 16;
2382 wlc_lcnphy_read_table(pi, &tab);
2383
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002384 return (u8) ((m0m1 & 0xff00) >> 8);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002385}
2386
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002387static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002388{
2389 mod_phy_reg(pi, 0x4fb,
2390 LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
2391 gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
2392 mod_phy_reg(pi, 0x4fd,
2393 LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
2394 gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
2395}
2396
2397void
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002398wlc_lcnphy_get_radio_loft(phy_info_t *pi,
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002399 u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002400{
2401 *ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
2402 *eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
2403 *fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
2404 *fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
2405}
2406
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002407static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002408{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002409 u16 dac_gain;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002410
2411 dac_gain = read_phy_reg(pi, 0x439) >> 0;
2412 gains->dac_gain = (dac_gain & 0x380) >> 7;
2413
2414 {
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002415 u16 rfgain0, rfgain1;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002416
2417 rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
2418 rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
2419
2420 gains->gm_gain = rfgain0 & 0xff;
2421 gains->pga_gain = (rfgain0 >> 8) & 0xff;
2422 gains->pad_gain = rfgain1 & 0xff;
2423 }
2424}
2425
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002426void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002427{
2428 phytbl_info_t tab;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002429 u16 iqcc[2];
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002430
2431 iqcc[0] = a;
2432 iqcc[1] = b;
2433
2434 tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
2435 tab.tbl_width = 16;
2436 tab.tbl_ptr = iqcc;
2437 tab.tbl_len = 2;
2438 tab.tbl_offset = 80;
2439 wlc_lcnphy_write_table(pi, &tab);
2440}
2441
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002442void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002443{
2444 phytbl_info_t tab;
2445
2446 tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
2447 tab.tbl_width = 16;
2448 tab.tbl_ptr = &didq;
2449 tab.tbl_len = 1;
2450 tab.tbl_offset = 85;
2451 wlc_lcnphy_write_table(pi, &tab);
2452}
2453
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002454void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002455{
2456 phytbl_info_t tab;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002457 u16 a, b;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002458 u8 bb_mult;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07002459 u32 bbmultiqcomp, txgain, locoeffs, rfpower;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002460 lcnphy_txgains_t gains;
2461 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
2462
2463 ASSERT(index <= LCNPHY_MAX_TX_POWER_INDEX);
2464
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07002465 pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002466 pi_lcn->lcnphy_current_index = (u8) index;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002467
2468 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
2469 tab.tbl_width = 32;
2470 tab.tbl_len = 1;
2471
2472 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2473
2474 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
2475 tab.tbl_ptr = &bbmultiqcomp;
2476 wlc_lcnphy_read_table(pi, &tab);
2477
2478 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
2479 tab.tbl_width = 32;
2480 tab.tbl_ptr = &txgain;
2481 wlc_lcnphy_read_table(pi, &tab);
2482
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002483 gains.gm_gain = (u16) (txgain & 0xff);
2484 gains.pga_gain = (u16) (txgain >> 8) & 0xff;
2485 gains.pad_gain = (u16) (txgain >> 16) & 0xff;
2486 gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002487 wlc_lcnphy_set_tx_gain(pi, &gains);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002488 wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002489
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002490 bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002491 wlc_lcnphy_set_bbmult(pi, bb_mult);
2492
2493 wlc_lcnphy_enable_tx_gain_override(pi);
2494
2495 if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
2496
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002497 a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
2498 b = (u16) (bbmultiqcomp & 0x3ff);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002499 wlc_lcnphy_set_tx_iqcc(pi, a, b);
2500
2501 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
2502 tab.tbl_ptr = &locoeffs;
2503 wlc_lcnphy_read_table(pi, &tab);
2504
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002505 wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002506
2507 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
2508 tab.tbl_ptr = &rfpower;
2509 wlc_lcnphy_read_table(pi, &tab);
2510 mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
2511
2512 }
2513}
2514
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002515static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002516{
2517
2518 mod_phy_reg(pi, 0x44d,
2519 (0x1 << 1) |
2520 (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
2521
2522 or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
2523}
2524
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002525static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002526{
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07002527 u32 j;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002528 phytbl_info_t tab;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07002529 u32 temp_offset[128];
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002530 tab.tbl_ptr = temp_offset;
2531 tab.tbl_len = 128;
2532 tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
2533 tab.tbl_width = 32;
2534 tab.tbl_offset = 0;
2535
Brett Rudley9249ede2010-11-30 20:09:49 -08002536 memset(temp_offset, 0, sizeof(temp_offset));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002537 for (j = 1; j < 128; j += 2)
2538 temp_offset[j] = 0x80000;
2539
2540 wlc_lcnphy_write_table(pi, &tab);
2541 return;
2542}
2543
2544static void
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002545wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002546 u16 trsw,
2547 u16 ext_lna,
2548 u16 biq2,
2549 u16 biq1,
2550 u16 tia, u16 lna2, u16 lna1)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002551{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002552 u16 gain0_15, gain16_19;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002553
2554 gain16_19 = biq2 & 0xf;
2555 gain0_15 = ((biq1 & 0xf) << 12) |
2556 ((tia & 0xf) << 8) |
2557 ((lna2 & 0x3) << 6) |
2558 ((lna2 & 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
2559
2560 mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
2561 mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
2562 mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
2563
2564 if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
2565 mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
2566 mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
2567 } else {
2568 mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
2569
2570 mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
2571
2572 mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
2573 }
2574
2575 mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
2576
2577}
2578
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002579static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002580{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002581 u16 ebit = enable ? 1 : 0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002582
2583 mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
2584
2585 mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
2586
2587 if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
2588 mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
2589 mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
2590 mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
2591 mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
2592 } else {
2593 mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
2594 mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
2595 mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
2596 }
2597
2598 if (CHSPEC_IS2G(pi->radio_chanspec)) {
2599 mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
2600 mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
2601 }
2602}
2603
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002604void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002605{
2606 if (!bEnable) {
2607
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002608 and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002609
2610 mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
2611
2612 and_phy_reg(pi, 0x44c,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002613 ~(u16) ((0x1 << 3) |
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002614 (0x1 << 5) |
2615 (0x1 << 12) |
2616 (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
2617
2618 and_phy_reg(pi, 0x44d,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002619 ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002620 mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
2621
2622 mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
2623
2624 and_phy_reg(pi, 0x4f9,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002625 ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002626
2627 and_phy_reg(pi, 0x4fa,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002628 ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002629 } else {
2630
2631 mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
2632 mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
2633
2634 mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
2635 mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
2636
2637 mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
2638 mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
2639
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07002640 wlc_lcnphy_set_trsw_override(pi, true, false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002641
2642 mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
2643 mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
2644
2645 if (CHSPEC_IS2G(pi->radio_chanspec)) {
2646
2647 mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
2648 mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
2649
2650 mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
2651 mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
2652
2653 mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
2654 mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
2655
2656 mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
2657 mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
2658
2659 mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
2660 mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
2661 } else {
2662
2663 mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
2664 mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
2665
2666 mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
2667 mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
2668
2669 mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
2670 mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
2671
2672 mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
2673 mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
2674
2675 mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
2676 mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
2677 }
2678 }
2679}
2680
2681static void
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002682wlc_lcnphy_run_samples(phy_info_t *pi,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002683 u16 num_samps,
2684 u16 num_loops, u16 wait, bool iqcalmode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002685{
2686
2687 or_phy_reg(pi, 0x6da, 0x8080);
2688
2689 mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
2690 if (num_loops != 0xffff)
2691 num_loops--;
2692 mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
2693
2694 mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
2695
2696 if (iqcalmode) {
2697
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002698 and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002699 or_phy_reg(pi, 0x453, (0x1 << 15));
2700 } else {
2701 write_phy_reg(pi, 0x63f, 1);
2702 wlc_lcnphy_tx_pu(pi, 1);
2703 }
2704
2705 or_radio_reg(pi, RADIO_2064_REG112, 0x6);
2706}
2707
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002708void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002709{
2710
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002711 u8 phybw40;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002712 phybw40 = CHSPEC_IS40(pi->radio_chanspec);
2713
2714 if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
2715 mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
2716 mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
2717 } else {
2718 mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
2719 mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
2720 }
2721
2722 if (phybw40 == 0) {
2723 mod_phy_reg((pi), 0x410,
2724 (0x1 << 6) |
2725 (0x1 << 5),
2726 ((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) <<
2727 6 | (!mode) << 5);
2728 mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
2729 }
2730}
2731
2732void
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07002733wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz, u16 max_val,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002734 bool iqcalmode)
2735{
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002736 u8 phy_bw;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002737 u16 num_samps, t, k;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07002738 u32 bw;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002739 fixed theta = 0, rot = 0;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07002740 cs32 tone_samp;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07002741 u32 data_buf[64];
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002742 u16 i_samp, q_samp;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002743 phytbl_info_t tab;
2744 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
2745
2746 pi->phy_tx_tone_freq = f_kHz;
2747
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07002748 wlc_lcnphy_deaf_mode(pi, true);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002749
2750 phy_bw = 40;
2751 if (pi_lcn->lcnphy_spurmod) {
2752 write_phy_reg(pi, 0x942, 0x2);
2753 write_phy_reg(pi, 0x93b, 0x0);
2754 write_phy_reg(pi, 0x93c, 0x0);
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07002755 wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002756 }
2757
2758 if (f_kHz) {
2759 k = 1;
2760 do {
2761 bw = phy_bw * 1000 * k;
2762 num_samps = bw / ABS(f_kHz);
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07002763 ASSERT(num_samps <= ARRAY_SIZE(data_buf));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002764 k++;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07002765 } while ((num_samps * (u32) (ABS(f_kHz))) != bw);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002766 } else
2767 num_samps = 2;
2768
2769 rot = FIXED((f_kHz * 36) / phy_bw) / 100;
2770 theta = 0;
2771
2772 for (t = 0; t < num_samps; t++) {
2773
2774 wlc_phy_cordic(theta, &tone_samp);
2775
2776 theta += rot;
2777
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002778 i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
2779 q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002780 data_buf[t] = (i_samp << 10) | q_samp;
2781 }
2782
2783 mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
2784
2785 mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
2786
2787 tab.tbl_ptr = data_buf;
2788 tab.tbl_len = num_samps;
2789 tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
2790 tab.tbl_offset = 0;
2791 tab.tbl_width = 32;
2792 wlc_lcnphy_write_table(pi, &tab);
2793
2794 wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
2795}
2796
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002797void wlc_lcnphy_stop_tx_tone(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002798{
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07002799 s16 playback_status;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002800 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
2801
2802 pi->phy_tx_tone_freq = 0;
2803 if (pi_lcn->lcnphy_spurmod) {
2804 write_phy_reg(pi, 0x942, 0x7);
2805 write_phy_reg(pi, 0x93b, 0x2017);
2806 write_phy_reg(pi, 0x93c, 0x27c5);
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07002807 wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002808 }
2809
2810 playback_status = read_phy_reg(pi, 0x644);
2811 if (playback_status & (0x1 << 0)) {
2812 wlc_lcnphy_tx_pu(pi, 0);
2813 mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
2814 } else if (playback_status & (0x1 << 1))
2815 mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
2816
2817 mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
2818
2819 mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
2820
2821 mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
2822
2823 and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
2824
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07002825 wlc_lcnphy_deaf_mode(pi, false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002826}
2827
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002828static void wlc_lcnphy_clear_trsw_override(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002829{
2830
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002831 and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002832}
2833
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002834void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002835{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002836 u16 iqcc[2];
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002837 phytbl_info_t tab;
2838
2839 tab.tbl_ptr = iqcc;
2840 tab.tbl_len = 2;
2841 tab.tbl_id = 0;
2842 tab.tbl_offset = 80;
2843 tab.tbl_width = 16;
2844 wlc_lcnphy_read_table(pi, &tab);
2845
2846 *a = iqcc[0];
2847 *b = iqcc[1];
2848}
2849
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002850u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002851{
2852 phytbl_info_t tab;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002853 u16 didq;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002854
2855 tab.tbl_id = 0;
2856 tab.tbl_width = 16;
2857 tab.tbl_ptr = &didq;
2858 tab.tbl_len = 1;
2859 tab.tbl_offset = 85;
2860 wlc_lcnphy_read_table(pi, &tab);
2861
2862 return didq;
2863}
2864
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04002865static void wlc_lcnphy_txpwrtbl_iqlo_cal(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002866{
2867
2868 lcnphy_txgains_t target_gains, old_gains;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002869 u8 save_bb_mult;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002870 u16 a, b, didq, save_pa_gain = 0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002871 uint idx, SAVE_txpwrindex = 0xFF;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07002872 u32 val;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002873 u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002874 phytbl_info_t tab;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07002875 u8 ei0, eq0, fi0, fq0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002876 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
2877
2878 wlc_lcnphy_get_tx_gain(pi, &old_gains);
2879 save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
2880
2881 save_bb_mult = wlc_lcnphy_get_bbmult(pi);
2882
2883 if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
2884 SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
2885
2886 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
2887
2888 target_gains.gm_gain = 7;
2889 target_gains.pga_gain = 0;
2890 target_gains.pad_gain = 21;
2891 target_gains.dac_gain = 0;
2892 wlc_lcnphy_set_tx_gain(pi, &target_gains);
2893 wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
2894
2895 if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
2896
2897 wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
2898
2899 wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
2900 (pi_lcn->
2901 lcnphy_recal ? LCNPHY_CAL_RECAL :
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07002902 LCNPHY_CAL_FULL), false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002903 } else {
2904
2905 wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
2906 }
2907
2908 wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07002909 if ((ABS((s8) fi0) == 15) && (ABS((s8) fq0) == 15)) {
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002910 if (CHSPEC_IS5G(pi->radio_chanspec)) {
2911 target_gains.gm_gain = 255;
2912 target_gains.pga_gain = 255;
2913 target_gains.pad_gain = 0xf0;
2914 target_gains.dac_gain = 0;
2915 } else {
2916 target_gains.gm_gain = 7;
2917 target_gains.pga_gain = 45;
2918 target_gains.pad_gain = 186;
2919 target_gains.dac_gain = 0;
2920 }
2921
2922 if (LCNREV_IS(pi->pubpi.phy_rev, 1)
2923 || pi_lcn->lcnphy_hw_iqcal_en) {
2924
2925 target_gains.pga_gain = 0;
2926 target_gains.pad_gain = 30;
2927 wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
2928 wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07002929 LCNPHY_CAL_FULL, false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002930 } else {
2931
2932 wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
2933 }
2934
2935 }
2936
2937 wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
2938
2939 didq = wlc_lcnphy_get_tx_locc(pi);
2940
2941 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
2942 tab.tbl_width = 32;
2943 tab.tbl_ptr = &val;
2944
2945 tab.tbl_len = 1;
2946 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
2947
2948 for (idx = 0; idx < 128; idx++) {
2949 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
2950
2951 wlc_lcnphy_read_table(pi, &tab);
2952 val = (val & 0xfff00000) |
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07002953 ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002954 wlc_lcnphy_write_table(pi, &tab);
2955
2956 val = didq;
2957 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
2958 wlc_lcnphy_write_table(pi, &tab);
2959 }
2960
2961 pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
2962 pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
2963 pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
2964 pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
2965 pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
2966 pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
2967 pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
2968
2969 wlc_lcnphy_set_bbmult(pi, save_bb_mult);
2970 wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
2971 wlc_lcnphy_set_tx_gain(pi, &old_gains);
2972
2973 if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
2974 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
2975 else
2976 wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
2977}
2978
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07002979s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002980{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07002981 u16 tempsenseval1, tempsenseval2;
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07002982 s16 avg = 0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07002983 bool suspend = 0;
2984
2985 if (NORADIO_ENAB(pi->pubpi))
2986 return -1;
2987
2988 if (mode == 1) {
2989 suspend =
2990 (0 ==
2991 (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
2992 if (!suspend)
2993 wlapi_suspend_mac_and_wait(pi->sh->physhim);
2994 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
2995 }
2996 tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
2997 tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
2998
2999 if (tempsenseval1 > 255)
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07003000 avg = (s16) (tempsenseval1 - 512);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003001 else
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07003002 avg = (s16) tempsenseval1;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003003
3004 if (tempsenseval2 > 255)
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07003005 avg += (s16) (tempsenseval2 - 512);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003006 else
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07003007 avg += (s16) tempsenseval2;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003008
3009 avg /= 2;
3010
3011 if (mode == 1) {
3012
3013 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
3014
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003015 udelay(100);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003016 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
3017
3018 if (!suspend)
3019 wlapi_enable_mac(pi->sh->physhim);
3020 }
3021 return avg;
3022}
3023
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003024u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003025{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003026 u16 tempsenseval1, tempsenseval2;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003027 s32 avg = 0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003028 bool suspend = 0;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003029 u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003030 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3031
3032 if (NORADIO_ENAB(pi->pubpi))
3033 return -1;
3034
3035 if (mode == 1) {
3036 suspend =
3037 (0 ==
3038 (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
3039 if (!suspend)
3040 wlapi_suspend_mac_and_wait(pi->sh->physhim);
3041 wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
3042 }
3043 tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
3044 tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
3045
3046 if (tempsenseval1 > 255)
3047 avg = (int)(tempsenseval1 - 512);
3048 else
3049 avg = (int)tempsenseval1;
3050
3051 if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
3052 if (tempsenseval2 > 255)
3053 avg = (int)(avg - tempsenseval2 + 512);
3054 else
3055 avg = (int)(avg - tempsenseval2);
3056 } else {
3057 if (tempsenseval2 > 255)
3058 avg = (int)(avg + tempsenseval2 - 512);
3059 else
3060 avg = (int)(avg + tempsenseval2);
3061 avg = avg / 2;
3062 }
3063 if (avg < 0)
3064 avg = avg + 512;
3065
3066 if (pi_lcn->lcnphy_tempsense_option == 2)
3067 avg = tempsenseval1;
3068
3069 if (mode)
3070 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
3071
3072 if (mode == 1) {
3073
3074 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
3075
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003076 udelay(100);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003077 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
3078
3079 if (!suspend)
3080 wlapi_enable_mac(pi->sh->physhim);
3081 }
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003082 return (u16) avg;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003083}
3084
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003085s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003086{
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003087 s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003088 degree =
3089 ((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
3090 / LCN_TEMPSENSE_DEN;
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003091 return (s8) degree;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003092}
3093
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003094s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003095{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003096 u16 vbatsenseval;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003097 s32 avg = 0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003098 bool suspend = 0;
3099
3100 if (NORADIO_ENAB(pi->pubpi))
3101 return -1;
3102
3103 if (mode == 1) {
3104 suspend =
3105 (0 ==
3106 (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
3107 if (!suspend)
3108 wlapi_suspend_mac_and_wait(pi->sh->physhim);
3109 wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
3110 }
3111
3112 vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
3113
3114 if (vbatsenseval > 255)
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003115 avg = (s32) (vbatsenseval - 512);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003116 else
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003117 avg = (s32) vbatsenseval;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003118
3119 avg =
3120 (avg * LCN_VBAT_SCALE_NOM +
3121 (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
3122
3123 if (mode == 1) {
3124 if (!suspend)
3125 wlapi_enable_mac(pi->sh->physhim);
3126 }
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003127 return (s8) avg;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003128}
3129
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07003130static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003131{
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07003132 u8 phybw40;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003133 phybw40 = CHSPEC_IS40(pi->radio_chanspec);
3134
3135 mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
3136
3137 if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
3138 (mode == AFE_CLK_INIT_MODE_TXRX2X))
3139 write_phy_reg(pi, 0x6d0, 0x7);
3140
3141 wlc_lcnphy_toggle_afe_pwdn(pi);
3142}
3143
3144static bool
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003145wlc_lcnphy_rx_iq_est(phy_info_t *pi,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003146 u16 num_samps,
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07003147 u8 wait_time, lcnphy_iq_est_t *iq_est)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003148{
3149 int wait_count = 0;
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07003150 bool result = true;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07003151 u8 phybw40;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003152 phybw40 = CHSPEC_IS40(pi->radio_chanspec);
3153
3154 mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
3155
3156 mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
3157
3158 mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
3159
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003160 mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003161
3162 mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
3163
3164 mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
3165
3166 while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
3167
3168 if (wait_count > (10 * 500)) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003169 result = false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003170 goto cleanup;
3171 }
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003172 udelay(100);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003173 wait_count++;
3174 }
3175
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07003176 iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
3177 (u32) read_phy_reg(pi, 0x484);
3178 iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
3179 (u32) read_phy_reg(pi, 0x486);
3180 iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
3181 (u32) read_phy_reg(pi, 0x488);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003182
3183 cleanup:
3184 mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
3185
3186 mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
3187
3188 return result;
3189}
3190
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003191static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003192{
3193#define LCNPHY_MIN_RXIQ_PWR 2
3194 bool result;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003195 u16 a0_new, b0_new;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003196 lcnphy_iq_est_t iq_est = { 0, 0, 0 };
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003197 s32 a, b, temp;
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07003198 s16 iq_nbits, qq_nbits, arsh, brsh;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003199 s32 iq;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07003200 u32 ii, qq;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003201 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3202
3203 a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
3204 b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
3205 mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
3206
3207 mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
3208
3209 wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
3210
Jason Cooperca8c1e52010-09-14 09:45:33 -04003211 result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
3212 if (!result)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003213 goto cleanup;
3214
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003215 iq = (s32) iq_est.iq_prod;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003216 ii = iq_est.i_pwr;
3217 qq = iq_est.q_pwr;
3218
3219 if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003220 result = false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003221 goto cleanup;
3222 }
3223
3224 iq_nbits = wlc_phy_nbits(iq);
3225 qq_nbits = wlc_phy_nbits(qq);
3226
3227 arsh = 10 - (30 - iq_nbits);
3228 if (arsh >= 0) {
3229 a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003230 temp = (s32) (ii >> arsh);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003231 if (temp == 0) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003232 return false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003233 }
3234 } else {
3235 a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003236 temp = (s32) (ii << -arsh);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003237 if (temp == 0) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003238 return false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003239 }
3240 }
3241 a /= temp;
3242 brsh = qq_nbits - 31 + 20;
3243 if (brsh >= 0) {
3244 b = (qq << (31 - qq_nbits));
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003245 temp = (s32) (ii >> brsh);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003246 if (temp == 0) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003247 return false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003248 }
3249 } else {
3250 b = (qq << (31 - qq_nbits));
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003251 temp = (s32) (ii << -brsh);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003252 if (temp == 0) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003253 return false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003254 }
3255 }
3256 b /= temp;
3257 b -= a * a;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003258 b = (s32) wlc_phy_sqrt_int((u32) b);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003259 b -= (1 << 10);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003260 a0_new = (u16) (a & 0x3ff);
3261 b0_new = (u16) (b & 0x3ff);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003262 cleanup:
3263
3264 wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
3265
3266 mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
3267
3268 mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
3269
3270 pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
3271 pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
3272
3273 return result;
3274}
3275
3276static bool
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003277wlc_lcnphy_rx_iq_cal(phy_info_t *pi, const lcnphy_rx_iqcomp_t *iqcomp,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003278 int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
3279 int tx_gain_idx)
3280{
3281 lcnphy_txgains_t old_gains;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003282 u16 tx_pwr_ctrl;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07003283 u8 tx_gain_index_old = 0;
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003284 bool result = false, tx_gain_override_old = false;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003285 u16 i, Core1TxControl_old, RFOverride0_old,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003286 RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
3287 rfoverride3_old, rfoverride3val_old, rfoverride4_old,
3288 rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
3289 int tia_gain;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07003290 u32 received_power, rx_pwr_threshold;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003291 u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
3292 u16 values_to_save[11];
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07003293 s16 *ptr;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003294 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3295
mike.rapoport@gmail.com5fcc1fc2010-10-13 00:09:10 +02003296 ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
Jason Cooperca8c1e52010-09-14 09:45:33 -04003297 if (NULL == ptr) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003298 return false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003299 }
3300 if (module == 2) {
3301 ASSERT(iqcomp_sz);
3302
3303 while (iqcomp_sz--) {
3304 if (iqcomp[iqcomp_sz].chan ==
3305 CHSPEC_CHANNEL(pi->radio_chanspec)) {
3306
3307 wlc_lcnphy_set_rx_iq_comp(pi,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003308 (u16)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003309 iqcomp[iqcomp_sz].a,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003310 (u16)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003311 iqcomp[iqcomp_sz].b);
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07003312 result = true;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003313 break;
3314 }
3315 }
3316 ASSERT(result);
3317 goto cal_done;
3318 }
3319
3320 if (module == 1) {
3321
3322 tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
3323 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
3324
3325 for (i = 0; i < 11; i++) {
3326 values_to_save[i] =
3327 read_radio_reg(pi, rxiq_cal_rf_reg[i]);
3328 }
3329 Core1TxControl_old = read_phy_reg(pi, 0x631);
3330
3331 or_phy_reg(pi, 0x631, 0x0015);
3332
3333 RFOverride0_old = read_phy_reg(pi, 0x44c);
3334 RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
3335 rfoverride2_old = read_phy_reg(pi, 0x4b0);
3336 rfoverride2val_old = read_phy_reg(pi, 0x4b1);
3337 rfoverride3_old = read_phy_reg(pi, 0x4f9);
3338 rfoverride3val_old = read_phy_reg(pi, 0x4fa);
3339 rfoverride4_old = read_phy_reg(pi, 0x938);
3340 rfoverride4val_old = read_phy_reg(pi, 0x939);
3341 afectrlovr_old = read_phy_reg(pi, 0x43b);
3342 afectrlovrval_old = read_phy_reg(pi, 0x43c);
3343 old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
3344 old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
3345
3346 tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
3347 if (tx_gain_override_old) {
3348 wlc_lcnphy_get_tx_gain(pi, &old_gains);
3349 tx_gain_index_old = pi_lcn->lcnphy_current_index;
3350 }
3351
3352 wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
3353
3354 mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
3355 mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
3356
3357 mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
3358 mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
3359
3360 write_radio_reg(pi, RADIO_2064_REG116, 0x06);
3361 write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
3362 write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
3363 write_radio_reg(pi, RADIO_2064_REG098, 0x03);
3364 write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
3365 mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
3366 write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
3367 write_radio_reg(pi, RADIO_2064_REG114, 0x01);
3368 write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
3369 write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
3370
3371 mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
3372 mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
3373 mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
3374 mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
3375 mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
3376 mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
3377 mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
3378 mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
3379 mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
3380 mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
3381
3382 mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
3383 mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
3384
3385 wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
3386 write_phy_reg(pi, 0x6da, 0xffff);
3387 or_phy_reg(pi, 0x6db, 0x3);
3388 wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07003389 wlc_lcnphy_rx_gain_override_enable(pi, true);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003390
3391 tia_gain = 8;
3392 rx_pwr_threshold = 950;
3393 while (tia_gain > 0) {
3394 tia_gain -= 1;
3395 wlc_lcnphy_set_rx_gain_by_distribution(pi,
3396 0, 0, 2, 2,
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003397 (u16)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003398 tia_gain, 1, 0);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003399 udelay(500);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003400
3401 received_power =
3402 wlc_lcnphy_measure_digital_power(pi, 2000);
3403 if (received_power < rx_pwr_threshold)
3404 break;
3405 }
3406 result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
3407
3408 wlc_lcnphy_stop_tx_tone(pi);
3409
3410 write_phy_reg(pi, 0x631, Core1TxControl_old);
3411
3412 write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
3413 write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
3414 write_phy_reg(pi, 0x4b0, rfoverride2_old);
3415 write_phy_reg(pi, 0x4b1, rfoverride2val_old);
3416 write_phy_reg(pi, 0x4f9, rfoverride3_old);
3417 write_phy_reg(pi, 0x4fa, rfoverride3val_old);
3418 write_phy_reg(pi, 0x938, rfoverride4_old);
3419 write_phy_reg(pi, 0x939, rfoverride4val_old);
3420 write_phy_reg(pi, 0x43b, afectrlovr_old);
3421 write_phy_reg(pi, 0x43c, afectrlovrval_old);
3422 write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
3423 write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
3424
3425 wlc_lcnphy_clear_trsw_override(pi);
3426
3427 mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
3428
3429 for (i = 0; i < 11; i++) {
3430 write_radio_reg(pi, rxiq_cal_rf_reg[i],
3431 values_to_save[i]);
3432 }
3433
3434 if (tx_gain_override_old) {
3435 wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
3436 } else
3437 wlc_lcnphy_disable_tx_gain_override(pi);
3438 wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
3439
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003440 wlc_lcnphy_rx_gain_override_enable(pi, false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003441 }
3442
3443 cal_done:
mike.rapoport@gmail.com182acb32010-10-13 00:09:12 +02003444 kfree(ptr);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003445 return result;
3446}
3447
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003448static void wlc_lcnphy_temp_adj(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003449{
3450 if (NORADIO_ENAB(pi->pubpi))
3451 return;
3452}
3453
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003454static void wlc_lcnphy_glacial_timer_based_cal(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003455{
3456 bool suspend;
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003457 s8 index;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003458 u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003459 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3460 suspend =
3461 (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
3462 if (!suspend)
3463 wlapi_suspend_mac_and_wait(pi->sh->physhim);
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07003464 wlc_lcnphy_deaf_mode(pi, true);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003465 pi->phy_lastcal = pi->sh->now;
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003466 pi->phy_forcecal = false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003467 index = pi_lcn->lcnphy_current_index;
3468
3469 wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
3470
3471 wlc_lcnphy_set_tx_pwr_by_index(pi, index);
3472 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003473 wlc_lcnphy_deaf_mode(pi, false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003474 if (!suspend)
3475 wlapi_enable_mac(pi->sh->physhim);
3476
3477}
3478
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003479static void wlc_lcnphy_periodic_cal(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003480{
3481 bool suspend, full_cal;
3482 const lcnphy_rx_iqcomp_t *rx_iqcomp;
3483 int rx_iqcomp_sz;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003484 u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003485 s8 index;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003486 phytbl_info_t tab;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07003487 s32 a1, b0, b1;
3488 s32 tssi, pwr, maxtargetpwr, mintargetpwr;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003489 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3490
3491 if (NORADIO_ENAB(pi->pubpi))
3492 return;
3493
3494 pi->phy_lastcal = pi->sh->now;
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003495 pi->phy_forcecal = false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003496 full_cal =
3497 (pi_lcn->lcnphy_full_cal_channel !=
3498 CHSPEC_CHANNEL(pi->radio_chanspec));
3499 pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
3500 index = pi_lcn->lcnphy_current_index;
3501
3502 suspend =
3503 (0 == (R_REG(pi->sh->osh, &pi->regs->maccontrol) & MCTL_EN_MAC));
3504 if (!suspend) {
3505
3506 wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
3507 wlapi_suspend_mac_and_wait(pi->sh->physhim);
3508 }
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07003509 wlc_lcnphy_deaf_mode(pi, true);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003510
3511 wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
3512
3513 rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07003514 rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003515
3516 if (LCNREV_IS(pi->pubpi.phy_rev, 1))
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003517 wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003518 else
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003519 wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003520
3521 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
3522
3523 wlc_lcnphy_idle_tssi_est((wlc_phy_t *) pi);
3524
3525 b0 = pi->txpa_2g[0];
3526 b1 = pi->txpa_2g[1];
3527 a1 = pi->txpa_2g[2];
3528 maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
3529 mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
3530
3531 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
3532 tab.tbl_width = 32;
3533 tab.tbl_ptr = &pwr;
3534 tab.tbl_len = 1;
3535 tab.tbl_offset = 0;
3536 for (tssi = 0; tssi < 128; tssi++) {
3537 pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
3538 pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
3539 wlc_lcnphy_write_table(pi, &tab);
3540 tab.tbl_offset++;
3541 }
3542 }
3543
3544 wlc_lcnphy_set_tx_pwr_by_index(pi, index);
3545 wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003546 wlc_lcnphy_deaf_mode(pi, false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003547 if (!suspend)
3548 wlapi_enable_mac(pi->sh->physhim);
3549}
3550
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003551void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003552{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003553 u16 temp_new;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003554 int temp1, temp2, temp_diff;
3555 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3556
3557 switch (mode) {
3558 case PHY_PERICAL_CHAN:
3559
3560 break;
3561 case PHY_FULLCAL:
3562 wlc_lcnphy_periodic_cal(pi);
3563 break;
3564 case PHY_PERICAL_PHYINIT:
3565 wlc_lcnphy_periodic_cal(pi);
3566 break;
3567 case PHY_PERICAL_WATCHDOG:
3568 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
3569 temp_new = wlc_lcnphy_tempsense(pi, 0);
3570 temp1 = LCNPHY_TEMPSENSE(temp_new);
3571 temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
3572 temp_diff = temp1 - temp2;
3573 if ((pi_lcn->lcnphy_cal_counter > 90) ||
3574 (temp_diff > 60) || (temp_diff < -60)) {
3575 wlc_lcnphy_glacial_timer_based_cal(pi);
3576 wlc_2064_vco_cal(pi);
3577 pi_lcn->lcnphy_cal_temper = temp_new;
3578 pi_lcn->lcnphy_cal_counter = 0;
3579 } else
3580 pi_lcn->lcnphy_cal_counter++;
3581 }
3582 break;
3583 case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
3584 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
3585 wlc_lcnphy_tx_power_adjustment((wlc_phy_t *) pi);
3586 break;
3587 default:
3588 ASSERT(0);
3589 break;
3590 }
3591}
3592
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003593void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr, s8 *cck_pwr)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003594{
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003595 s8 cck_offset;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003596 u16 status;
Jason Cooperca8c1e52010-09-14 09:45:33 -04003597 status = (read_phy_reg(pi, 0x4ab));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003598 if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
Jason Cooperca8c1e52010-09-14 09:45:33 -04003599 (status & (0x1 << 15))) {
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003600 *ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003601 >> 0) >> 1);
3602
3603 if (wlc_phy_tpc_isenabled_lcnphy(pi))
3604 cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
3605 else
3606 cck_offset = 0;
3607
3608 *cck_pwr = *ofdm_pwr + cck_offset;
3609 } else {
3610 *cck_pwr = 0;
3611 *ofdm_pwr = 0;
3612 }
3613}
3614
Jason Coopera2627bc2010-09-14 09:45:31 -04003615void WLBANDINITFN(wlc_phy_cal_init_lcnphy) (phy_info_t *pi)
3616{
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003617 return;
3618
3619}
3620
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003621static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi, chanspec_t chanspec)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003622{
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07003623 u8 channel = CHSPEC_CHANNEL(chanspec);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003624 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3625
3626 if (NORADIO_ENAB(pi->pubpi))
3627 return;
3628
3629 if (channel == 14) {
3630 mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
3631
3632 } else {
3633 mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
3634
3635 }
3636 pi_lcn->lcnphy_bandedge_corr = 2;
3637 if (channel == 1)
3638 pi_lcn->lcnphy_bandedge_corr = 4;
3639
3640 if (channel == 1 || channel == 2 || channel == 3 ||
3641 channel == 4 || channel == 9 ||
3642 channel == 10 || channel == 11 || channel == 12) {
3643 si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
3644 si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
3645 si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
3646
3647 si_pmu_pllupd(pi->sh->sih);
3648 write_phy_reg(pi, 0x942, 0);
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07003649 wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003650 pi_lcn->lcnphy_spurmod = 0;
3651 mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
3652
3653 write_phy_reg(pi, 0x425, 0x5907);
3654 } else {
3655 si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
3656 si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
3657 si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
3658
3659 si_pmu_pllupd(pi->sh->sih);
3660 write_phy_reg(pi, 0x942, 0);
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07003661 wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003662
3663 pi_lcn->lcnphy_spurmod = 0;
3664 mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
3665
3666 write_phy_reg(pi, 0x425, 0x590a);
3667 }
3668
3669 or_phy_reg(pi, 0x44a, 0x44);
3670 write_phy_reg(pi, 0x44a, 0x80);
3671}
3672
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003673void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003674{
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003675 s8 index;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003676 u16 index2;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003677 phy_info_t *pi = (phy_info_t *) ppi;
3678 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003679 u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003680 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) {
3681 index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003682 index2 = (u16) (index * 2);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003683 mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
3684
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07003685 pi_lcn->lcnphy_current_index = (s8)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003686 ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
3687 }
3688}
3689
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003690static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003691{
3692 mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
3693
3694 mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
3695
3696 mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
3697
3698 mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
3699
3700 mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
3701
3702 mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
3703
3704}
3705
Jason Coopera2627bc2010-09-14 09:45:31 -04003706void WLBANDINITFN(wlc_phy_init_lcnphy) (phy_info_t *pi)
3707{
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07003708 u8 phybw40;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003709 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3710 phybw40 = CHSPEC_IS40(pi->radio_chanspec);
3711
3712 pi_lcn->lcnphy_cal_counter = 0;
3713 pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
3714
3715 or_phy_reg(pi, 0x44a, 0x80);
3716 and_phy_reg(pi, 0x44a, 0x7f);
3717
3718 wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
3719
3720 write_phy_reg(pi, 0x60a, 160);
3721
3722 write_phy_reg(pi, 0x46a, 25);
3723
3724 wlc_lcnphy_baseband_init(pi);
3725
3726 wlc_lcnphy_radio_init(pi);
3727
3728 if (CHSPEC_IS2G(pi->radio_chanspec))
3729 wlc_lcnphy_tx_pwr_ctrl_init((wlc_phy_t *) pi);
3730
3731 wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
3732
3733 si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
3734
3735 si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
3736
3737 if ((pi->sh->boardflags & BFL_FEM)
3738 && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
3739 wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
3740
3741 wlc_lcnphy_agc_temp_init(pi);
3742
3743 wlc_lcnphy_temp_adj(pi);
3744
3745 mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
3746
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003747 udelay(100);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003748 mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
3749
3750 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
3751 pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
3752 wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
3753}
3754
3755static void
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003756wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi, u16 *values_to_save)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003757{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003758 u16 vmid;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003759 int i;
3760 for (i = 0; i < 20; i++) {
3761 values_to_save[i] =
3762 read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
3763 }
3764
3765 mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
3766 mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
3767
3768 mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
3769 mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
3770
3771 mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
3772 mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
3773
3774 mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
3775 mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
3776
3777 if (LCNREV_IS(pi->pubpi.phy_rev, 2))
3778 and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
3779 else
3780 and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
3781 or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
3782
3783 or_radio_reg(pi, RADIO_2064_REG036, 0x01);
3784 or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003785 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003786
3787 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
3788 if (CHSPEC_IS5G(pi->radio_chanspec))
3789 mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
3790 else
3791 or_radio_reg(pi, RADIO_2064_REG03A, 1);
3792 } else {
3793 if (CHSPEC_IS5G(pi->radio_chanspec))
3794 mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
3795 else
3796 or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
3797 }
3798
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003799 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003800
3801 write_radio_reg(pi, RADIO_2064_REG025, 0xF);
3802 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
3803 if (CHSPEC_IS5G(pi->radio_chanspec))
3804 mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
3805 else
3806 mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
3807 } else {
3808 if (CHSPEC_IS5G(pi->radio_chanspec))
3809 mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
3810 else
3811 mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
3812 }
3813
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003814 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003815
3816 write_radio_reg(pi, RADIO_2064_REG005, 0x8);
3817 or_radio_reg(pi, RADIO_2064_REG112, 0x80);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003818 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003819
3820 or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
3821 or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003822 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003823
3824 or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
3825 or_radio_reg(pi, RADIO_2064_REG113, 0x10);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003826 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003827
3828 write_radio_reg(pi, RADIO_2064_REG007, 0x1);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003829 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003830
3831 vmid = 0x2A6;
3832 mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
3833 write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
3834 or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003835 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003836
3837 or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003838 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003839 write_radio_reg(pi, RADIO_2064_REG012, 0x02);
3840 or_radio_reg(pi, RADIO_2064_REG112, 0x06);
3841 write_radio_reg(pi, RADIO_2064_REG036, 0x11);
3842 write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
3843 write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
3844 write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
3845 write_radio_reg(pi, RADIO_2064_REG092, 0x15);
3846}
3847
3848static void
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003849wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo, u16 thresh,
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07003850 s16 *ptr, int mode)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003851{
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07003852 u32 curval1, curval2, stpptr, curptr, strptr, val;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003853 u16 sslpnCalibClkEnCtrl, timer;
3854 u16 old_sslpnCalibClkEnCtrl;
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07003855 s16 imag, real;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003856 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
3857
3858 timer = 0;
3859 old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
3860
3861 curval1 = R_REG(pi->sh->osh, &pi->regs->psm_corectlsts);
3862 ptr[130] = 0;
3863 W_REG(pi->sh->osh, &pi->regs->psm_corectlsts, ((1 << 6) | curval1));
3864
3865 W_REG(pi->sh->osh, &pi->regs->smpl_clct_strptr, 0x7E00);
3866 W_REG(pi->sh->osh, &pi->regs->smpl_clct_stpptr, 0x8000);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003867 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003868 curval2 = R_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param);
3869 W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param, curval2 | 0x30);
3870
3871 write_phy_reg(pi, 0x555, 0x0);
3872 write_phy_reg(pi, 0x5a6, 0x5);
3873
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003874 write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003875 write_phy_reg(pi, 0x5cf, 3);
3876 write_phy_reg(pi, 0x5a5, 0x3);
3877 write_phy_reg(pi, 0x583, 0x0);
3878 write_phy_reg(pi, 0x584, 0x0);
3879 write_phy_reg(pi, 0x585, 0x0fff);
3880 write_phy_reg(pi, 0x586, 0x0000);
3881
3882 write_phy_reg(pi, 0x580, 0x4501);
3883
3884 sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07003885 write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003886 stpptr = R_REG(pi->sh->osh, &pi->regs->smpl_clct_stpptr);
3887 curptr = R_REG(pi->sh->osh, &pi->regs->smpl_clct_curptr);
3888 do {
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02003889 udelay(10);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003890 curptr = R_REG(pi->sh->osh, &pi->regs->smpl_clct_curptr);
3891 timer++;
3892 } while ((curptr != stpptr) && (timer < 500));
3893
3894 W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param, 0x2);
3895 strptr = 0x7E00;
3896 W_REG(pi->sh->osh, &pi->regs->tplatewrptr, strptr);
3897 while (strptr < 0x8000) {
3898 val = R_REG(pi->sh->osh, &pi->regs->tplatewrdata);
3899 imag = ((val >> 16) & 0x3ff);
3900 real = ((val) & 0x3ff);
3901 if (imag > 511) {
3902 imag -= 1024;
3903 }
3904 if (real > 511) {
3905 real -= 1024;
3906 }
3907 if (pi_lcn->lcnphy_iqcal_swp_dis)
3908 ptr[(strptr - 0x7E00) / 4] = real;
3909 else
3910 ptr[(strptr - 0x7E00) / 4] = imag;
3911 if (clip_detect_algo) {
3912 if (imag > thresh || imag < -thresh) {
3913 strptr = 0x8000;
3914 ptr[130] = 1;
3915 }
3916 }
3917 strptr += 4;
3918 }
3919
3920 write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
3921 W_REG(pi->sh->osh, &pi->regs->psm_phy_hdr_param, curval2);
3922 W_REG(pi->sh->osh, &pi->regs->psm_corectlsts, curval1);
3923}
3924
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003925static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003926{
3927 lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
3928
3929 wlc_lcnphy_set_cc(pi, 0, 0, 0);
3930 wlc_lcnphy_set_cc(pi, 2, 0, 0);
3931 wlc_lcnphy_set_cc(pi, 3, 0, 0);
3932 wlc_lcnphy_set_cc(pi, 4, 0, 0);
3933
3934 wlc_lcnphy_a1(pi, 4, 0, 0);
3935 wlc_lcnphy_a1(pi, 3, 0, 0);
3936 wlc_lcnphy_a1(pi, 2, 3, 2);
3937 wlc_lcnphy_a1(pi, 0, 5, 8);
3938 wlc_lcnphy_a1(pi, 2, 2, 1);
3939 wlc_lcnphy_a1(pi, 0, 4, 3);
3940
3941 iqcc0 = wlc_lcnphy_get_cc(pi, 0);
3942 locc2 = wlc_lcnphy_get_cc(pi, 2);
3943 locc3 = wlc_lcnphy_get_cc(pi, 3);
3944 locc4 = wlc_lcnphy_get_cc(pi, 4);
3945}
3946
3947static void
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07003948wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x, s16 coeff_y)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003949{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003950 u16 di0dq0;
3951 u16 x, y, data_rf;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003952 int k;
3953 switch (cal_type) {
3954 case 0:
3955 wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
3956 break;
3957 case 2:
3958 di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
3959 wlc_lcnphy_set_tx_locc(pi, di0dq0);
3960 break;
3961 case 3:
3962 k = wlc_lcnphy_calc_floor(coeff_x, 0);
3963 y = 8 + k;
3964 k = wlc_lcnphy_calc_floor(coeff_x, 1);
3965 x = 8 - k;
3966 data_rf = (x * 16 + y);
3967 write_radio_reg(pi, RADIO_2064_REG089, data_rf);
3968 k = wlc_lcnphy_calc_floor(coeff_y, 0);
3969 y = 8 + k;
3970 k = wlc_lcnphy_calc_floor(coeff_y, 1);
3971 x = 8 - k;
3972 data_rf = (x * 16 + y);
3973 write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
3974 break;
3975 case 4:
3976 k = wlc_lcnphy_calc_floor(coeff_x, 0);
3977 y = 8 + k;
3978 k = wlc_lcnphy_calc_floor(coeff_x, 1);
3979 x = 8 - k;
3980 data_rf = (x * 16 + y);
3981 write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
3982 k = wlc_lcnphy_calc_floor(coeff_y, 0);
3983 y = 8 + k;
3984 k = wlc_lcnphy_calc_floor(coeff_y, 1);
3985 x = 8 - k;
3986 data_rf = (x * 16 + y);
3987 write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
3988 break;
3989 }
3990}
3991
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04003992static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003993{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07003994 u16 a, b, didq;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07003995 u8 di0, dq0, ei, eq, fi, fq;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07003996 lcnphy_unsign16_struct cc;
3997 cc.re = 0;
3998 cc.im = 0;
3999 switch (cal_type) {
4000 case 0:
4001 wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
4002 cc.re = a;
4003 cc.im = b;
4004 break;
4005 case 2:
4006 didq = wlc_lcnphy_get_tx_locc(pi);
4007 di0 = (((didq & 0xff00) << 16) >> 24);
4008 dq0 = (((didq & 0x00ff) << 24) >> 24);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004009 cc.re = (u16) di0;
4010 cc.im = (u16) dq0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004011 break;
4012 case 3:
4013 wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004014 cc.re = (u16) ei;
4015 cc.im = (u16) eq;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004016 break;
4017 case 4:
4018 wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004019 cc.re = (u16) fi;
4020 cc.im = (u16) fq;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004021 break;
4022 }
4023 return cc;
4024}
4025
4026static void
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04004027wlc_lcnphy_a1(phy_info_t *pi, int cal_type, int num_levels, int step_size_lg2)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004028{
4029 const lcnphy_spb_tone_t *phy_c1;
4030 lcnphy_spb_tone_t phy_c2;
4031 lcnphy_unsign16_struct phy_c3;
4032 int phy_c4, phy_c5, k, l, j, phy_c6;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004033 u16 phy_c7, phy_c8, phy_c9;
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07004034 s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
4035 s16 *ptr, phy_c17;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07004036 s32 phy_c18, phy_c19;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004037 u32 phy_c20, phy_c21;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004038 bool phy_c22, phy_c23, phy_c24, phy_c25;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004039 u16 phy_c26, phy_c27;
4040 u16 phy_c28, phy_c29, phy_c30;
4041 u16 phy_c31;
4042 u16 *phy_c32;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004043 phy_c21 = 0;
4044 phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
mike.rapoport@gmail.com5fcc1fc2010-10-13 00:09:10 +02004045 ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
Jason Cooperca8c1e52010-09-14 09:45:33 -04004046 if (NULL == ptr) {
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004047 return;
4048 }
4049
mike.rapoport@gmail.com5fcc1fc2010-10-13 00:09:10 +02004050 phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
Jason Cooperca8c1e52010-09-14 09:45:33 -04004051 if (NULL == phy_c32) {
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004052 return;
4053 }
4054 phy_c26 = read_phy_reg(pi, 0x6da);
4055 phy_c27 = read_phy_reg(pi, 0x6db);
4056 phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
4057 write_phy_reg(pi, 0x93d, 0xC0);
4058
4059 wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
4060 write_phy_reg(pi, 0x6da, 0xffff);
4061 or_phy_reg(pi, 0x6db, 0x3);
4062
4063 wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02004064 udelay(500);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004065 phy_c28 = read_phy_reg(pi, 0x938);
4066 phy_c29 = read_phy_reg(pi, 0x4d7);
4067 phy_c30 = read_phy_reg(pi, 0x4d8);
4068 or_phy_reg(pi, 0x938, 0x1 << 2);
4069 or_phy_reg(pi, 0x4d7, 0x1 << 2);
4070 or_phy_reg(pi, 0x4d7, 0x1 << 3);
4071 mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
4072 or_phy_reg(pi, 0x4d8, 1 << 0);
4073 or_phy_reg(pi, 0x4d8, 1 << 1);
4074 mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
4075 mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
4076 phy_c1 = &lcnphy_spb_tone_3750[0];
4077 phy_c4 = 32;
4078
4079 if (num_levels == 0) {
4080 if (cal_type != 0) {
4081 num_levels = 4;
4082 } else {
4083 num_levels = 9;
4084 }
4085 }
4086 if (step_size_lg2 == 0) {
4087 if (cal_type != 0) {
4088 step_size_lg2 = 3;
4089 } else {
4090 step_size_lg2 = 8;
4091 }
4092 }
4093
4094 phy_c7 = (1 << step_size_lg2);
4095 phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07004096 phy_c15 = (s16) phy_c3.re;
4097 phy_c16 = (s16) phy_c3.im;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004098 if (cal_type == 2) {
4099 if (phy_c3.re > 127)
4100 phy_c15 = phy_c3.re - 256;
4101 if (phy_c3.im > 127)
4102 phy_c16 = phy_c3.im - 256;
4103 }
4104 wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02004105 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004106 for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
4107 phy_c23 = 1;
4108 phy_c22 = 0;
4109 switch (cal_type) {
4110 case 0:
4111 phy_c10 = 511;
4112 break;
4113 case 2:
4114 phy_c10 = 127;
4115 break;
4116 case 3:
4117 phy_c10 = 15;
4118 break;
4119 case 4:
4120 phy_c10 = 15;
4121 break;
4122 }
4123
4124 phy_c9 = read_phy_reg(pi, 0x93d);
4125 phy_c9 = 2 * phy_c9;
4126 phy_c24 = 0;
4127 phy_c5 = 7;
4128 phy_c25 = 1;
4129 while (1) {
4130 write_radio_reg(pi, RADIO_2064_REG026,
4131 (phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02004132 udelay(50);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004133 phy_c22 = 0;
4134 ptr[130] = 0;
4135 wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
4136 if (ptr[130] == 1)
4137 phy_c22 = 1;
4138 if (phy_c22)
4139 phy_c5 -= 1;
4140 if ((phy_c22 != phy_c24) && (!phy_c25))
4141 break;
4142 if (!phy_c22)
4143 phy_c5 += 1;
4144 if (phy_c5 <= 0 || phy_c5 >= 7)
4145 break;
4146 phy_c24 = phy_c22;
4147 phy_c25 = 0;
4148 }
4149
4150 if (phy_c5 < 0)
4151 phy_c5 = 0;
4152 else if (phy_c5 > 7)
4153 phy_c5 = 7;
4154
4155 for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
4156 for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
4157 phy_c11 = phy_c15 + k;
4158 phy_c12 = phy_c16 + l;
4159
4160 if (phy_c11 < -phy_c10)
4161 phy_c11 = -phy_c10;
4162 else if (phy_c11 > phy_c10)
4163 phy_c11 = phy_c10;
4164 if (phy_c12 < -phy_c10)
4165 phy_c12 = -phy_c10;
4166 else if (phy_c12 > phy_c10)
4167 phy_c12 = phy_c10;
4168 wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
4169 phy_c12);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02004170 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004171 wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
4172
4173 phy_c18 = 0;
4174 phy_c19 = 0;
4175 for (j = 0; j < 128; j++) {
4176 if (cal_type != 0) {
4177 phy_c6 = j % phy_c4;
4178 } else {
4179 phy_c6 = (2 * j) % phy_c4;
4180 }
4181 phy_c2.re = phy_c1[phy_c6].re;
4182 phy_c2.im = phy_c1[phy_c6].im;
4183 phy_c17 = ptr[j];
4184 phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
4185 phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
4186 }
4187
4188 phy_c18 = phy_c18 >> 10;
4189 phy_c19 = phy_c19 >> 10;
4190 phy_c20 =
4191 ((phy_c18 * phy_c18) + (phy_c19 * phy_c19));
4192
4193 if (phy_c23 || phy_c20 < phy_c21) {
4194 phy_c21 = phy_c20;
4195 phy_c13 = phy_c11;
4196 phy_c14 = phy_c12;
4197 }
4198 phy_c23 = 0;
4199 }
4200 }
4201 phy_c23 = 1;
4202 phy_c15 = phy_c13;
4203 phy_c16 = phy_c14;
4204 phy_c7 = phy_c7 >> 1;
4205 wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02004206 udelay(20);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004207 }
4208 goto cleanup;
4209 cleanup:
4210 wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
4211 wlc_lcnphy_stop_tx_tone(pi);
4212 write_phy_reg(pi, 0x6da, phy_c26);
4213 write_phy_reg(pi, 0x6db, phy_c27);
4214 write_phy_reg(pi, 0x938, phy_c28);
4215 write_phy_reg(pi, 0x4d7, phy_c29);
4216 write_phy_reg(pi, 0x4d8, phy_c30);
4217 write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
4218
mike.rapoport@gmail.com182acb32010-10-13 00:09:12 +02004219 kfree(phy_c32);
4220 kfree(ptr);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004221}
4222
4223static void
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004224wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi, u16 *values_to_save)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004225{
4226 int i;
4227
4228 and_phy_reg(pi, 0x44c, 0x0 >> 11);
4229
4230 and_phy_reg(pi, 0x43b, 0xC);
4231
4232 for (i = 0; i < 20; i++) {
4233 write_radio_reg(pi, iqlo_loopback_rf_regs[i],
4234 values_to_save[i]);
4235 }
4236}
4237
4238static void
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04004239WLBANDINITFN(wlc_lcnphy_load_tx_gain_table) (phy_info_t *pi,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004240 const lcnphy_tx_gain_tbl_entry *
4241 gain_table) {
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004242 u32 j;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004243 phytbl_info_t tab;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004244 u32 val;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004245 u16 pa_gain;
4246 u16 gm_gain;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004247
4248 if (CHSPEC_IS5G(pi->radio_chanspec))
4249 pa_gain = 0x70;
4250 else
4251 pa_gain = 0x70;
4252
4253 if (pi->sh->boardflags & BFL_FEM)
4254 pa_gain = 0x10;
4255 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4256 tab.tbl_width = 32;
4257 tab.tbl_len = 1;
4258 tab.tbl_ptr = &val;
4259
4260 for (j = 0; j < 128; j++) {
4261 gm_gain = gain_table[j].gm;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004262 val = (((u32) pa_gain << 24) |
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004263 (gain_table[j].pad << 16) |
4264 (gain_table[j].pga << 8) | gm_gain);
4265
4266 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
4267 wlc_lcnphy_write_table(pi, &tab);
4268
4269 val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
4270 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
4271 wlc_lcnphy_write_table(pi, &tab);
4272 }
4273}
4274
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04004275static void wlc_lcnphy_load_rfpower(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004276{
4277 phytbl_info_t tab;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004278 u32 val, bbmult, rfgain;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004279 u8 index;
4280 u8 scale_factor = 1;
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07004281 s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004282
4283 tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
4284 tab.tbl_width = 32;
4285 tab.tbl_len = 1;
4286
4287 for (index = 0; index < 128; index++) {
4288 tab.tbl_ptr = &bbmult;
4289 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
4290 wlc_lcnphy_read_table(pi, &tab);
4291 bbmult = bbmult >> 20;
4292
4293 tab.tbl_ptr = &rfgain;
4294 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
4295 wlc_lcnphy_read_table(pi, &tab);
4296
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07004297 qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
4298 qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004299
4300 if (qQ1 < qQ2) {
4301 temp2 = qm_shr16(temp2, qQ2 - qQ1);
4302 qQ = qQ1;
4303 } else {
4304 temp1 = qm_shr16(temp1, qQ1 - qQ2);
4305 qQ = qQ2;
4306 }
4307 temp = qm_sub16(temp1, temp2);
4308
4309 if (qQ >= 4)
4310 shift = qQ - 4;
4311 else
4312 shift = 4 - qQ;
4313
4314 val = (((index << shift) + (5 * temp) +
4315 (1 << (scale_factor + shift - 3))) >> (scale_factor +
4316 shift - 2));
4317
4318 tab.tbl_ptr = &val;
4319 tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
4320 wlc_lcnphy_write_table(pi, &tab);
4321 }
4322}
4323
Jason Coopera2627bc2010-09-14 09:45:31 -04004324static void WLBANDINITFN(wlc_lcnphy_tbl_init) (phy_info_t *pi)
4325{
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004326 uint idx;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004327 u8 phybw40;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004328 phytbl_info_t tab;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004329 u32 val;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004330
4331 phybw40 = CHSPEC_IS40(pi->radio_chanspec);
4332
4333 for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) {
4334 wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
4335 }
4336
4337 if (pi->sh->boardflags & BFL_FEM_BT) {
4338 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
4339 tab.tbl_width = 16;
4340 tab.tbl_ptr = &val;
4341 tab.tbl_len = 1;
4342 val = 100;
4343 tab.tbl_offset = 4;
4344 wlc_lcnphy_write_table(pi, &tab);
4345 }
4346
4347 tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
4348 tab.tbl_width = 16;
4349 tab.tbl_ptr = &val;
4350 tab.tbl_len = 1;
4351
4352 val = 114;
4353 tab.tbl_offset = 0;
4354 wlc_lcnphy_write_table(pi, &tab);
4355
4356 val = 130;
4357 tab.tbl_offset = 1;
4358 wlc_lcnphy_write_table(pi, &tab);
4359
4360 val = 6;
4361 tab.tbl_offset = 8;
4362 wlc_lcnphy_write_table(pi, &tab);
4363
4364 if (CHSPEC_IS2G(pi->radio_chanspec)) {
4365 if (pi->sh->boardflags & BFL_FEM)
4366 wlc_lcnphy_load_tx_gain_table(pi,
4367 dot11lcnphy_2GHz_extPA_gaintable_rev0);
4368 else
4369 wlc_lcnphy_load_tx_gain_table(pi,
4370 dot11lcnphy_2GHz_gaintable_rev0);
4371 }
4372
4373 if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
4374 if (CHSPEC_IS2G(pi->radio_chanspec)) {
4375 for (idx = 0;
4376 idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
4377 idx++)
4378 if (pi->sh->boardflags & BFL_EXTLNA)
4379 wlc_lcnphy_write_table(pi,
4380 &dot11lcnphytbl_rx_gain_info_extlna_2G_rev2
4381 [idx]);
4382 else
4383 wlc_lcnphy_write_table(pi,
4384 &dot11lcnphytbl_rx_gain_info_2G_rev2
4385 [idx]);
4386 } else {
4387 for (idx = 0;
4388 idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
4389 idx++)
4390 if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
4391 wlc_lcnphy_write_table(pi,
4392 &dot11lcnphytbl_rx_gain_info_extlna_5G_rev2
4393 [idx]);
4394 else
4395 wlc_lcnphy_write_table(pi,
4396 &dot11lcnphytbl_rx_gain_info_5G_rev2
4397 [idx]);
4398 }
4399 }
4400
4401 if ((pi->sh->boardflags & BFL_FEM)
4402 && !(pi->sh->boardflags & BFL_FEM_BT))
4403 wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
4404 else if (pi->sh->boardflags & BFL_FEM_BT) {
4405 if (pi->sh->boardrev < 0x1250)
4406 wlc_lcnphy_write_table(pi,
4407 &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
4408 else
4409 wlc_lcnphy_write_table(pi,
4410 &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
4411 } else
4412 wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
4413
4414 wlc_lcnphy_load_rfpower(pi);
4415
4416 wlc_lcnphy_clear_papd_comptable(pi);
4417}
4418
Jason Coopera2627bc2010-09-14 09:45:31 -04004419static void WLBANDINITFN(wlc_lcnphy_rev0_baseband_init) (phy_info_t *pi)
4420{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004421 u16 afectrl1;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004422 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
4423
4424 write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
4425
4426 write_phy_reg(pi, 0x43b, 0x0);
4427 write_phy_reg(pi, 0x43c, 0x0);
4428 write_phy_reg(pi, 0x44c, 0x0);
4429 write_phy_reg(pi, 0x4e6, 0x0);
4430 write_phy_reg(pi, 0x4f9, 0x0);
4431 write_phy_reg(pi, 0x4b0, 0x0);
4432 write_phy_reg(pi, 0x938, 0x0);
4433 write_phy_reg(pi, 0x4b0, 0x0);
4434 write_phy_reg(pi, 0x44e, 0);
4435
4436 or_phy_reg(pi, 0x567, 0x03);
4437
4438 or_phy_reg(pi, 0x44a, 0x44);
4439 write_phy_reg(pi, 0x44a, 0x80);
4440
4441 if (!(pi->sh->boardflags & BFL_FEM))
4442 wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
4443
4444 if (0) {
4445 afectrl1 = 0;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004446 afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004447 (pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn->
4448 lcnphy_rssi_gs
4449 << 10));
4450 write_phy_reg(pi, 0x43e, afectrl1);
4451 }
4452
4453 mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
4454 if (pi->sh->boardflags & BFL_FEM) {
4455 mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
4456
4457 write_phy_reg(pi, 0x910, 0x1);
4458 }
4459
4460 mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
4461 mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
4462 mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
4463
4464}
4465
Jason Coopera2627bc2010-09-14 09:45:31 -04004466static void WLBANDINITFN(wlc_lcnphy_rev2_baseband_init) (phy_info_t *pi)
4467{
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004468 if (CHSPEC_IS5G(pi->radio_chanspec)) {
4469 mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
4470
4471 mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
4472 }
4473}
4474
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04004475static void wlc_lcnphy_agc_temp_init(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004476{
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07004477 s16 temp;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004478 phytbl_info_t tab;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004479 u32 tableBuffer[2];
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004480 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
4481
4482 if (NORADIO_ENAB(pi->pubpi))
4483 return;
4484
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07004485 temp = (s16) read_phy_reg(pi, 0x4df);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004486 pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
4487
4488 if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
4489 pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
4490
4491 pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
4492
4493 if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
4494 pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
4495
4496 tab.tbl_ptr = tableBuffer;
4497 tab.tbl_len = 2;
4498 tab.tbl_id = 17;
4499 tab.tbl_offset = 59;
4500 tab.tbl_width = 32;
4501 wlc_lcnphy_read_table(pi, &tab);
4502
4503 if (tableBuffer[0] > 63)
4504 tableBuffer[0] -= 128;
4505 pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
4506
4507 if (tableBuffer[1] > 63)
4508 tableBuffer[1] -= 128;
4509 pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
4510
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07004511 temp = (s16) (read_phy_reg(pi, 0x434)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004512 & (0xff << 0));
4513 if (temp > 127)
4514 temp -= 256;
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07004515 pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004516
4517 pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424)
4518 & (0xff << 8))
4519 >> 8;
4520 pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425)
4521 & (0xff << 0))
4522 >> 0;
4523
4524 tab.tbl_ptr = tableBuffer;
4525 tab.tbl_len = 2;
4526 tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
4527 tab.tbl_offset = 28;
4528 tab.tbl_width = 32;
4529 wlc_lcnphy_read_table(pi, &tab);
4530
4531 pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
4532 pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
4533
4534}
4535
Jason Coopera2627bc2010-09-14 09:45:31 -04004536static void WLBANDINITFN(wlc_lcnphy_bu_tweaks) (phy_info_t *pi)
4537{
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004538 if (NORADIO_ENAB(pi->pubpi))
4539 return;
4540
4541 or_phy_reg(pi, 0x805, 0x1);
4542
4543 mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
4544
4545 mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
4546
4547 write_phy_reg(pi, 0x414, 0x1e10);
4548 write_phy_reg(pi, 0x415, 0x0640);
4549
4550 mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
4551
4552 or_phy_reg(pi, 0x44a, 0x44);
4553 write_phy_reg(pi, 0x44a, 0x80);
4554 mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
4555
4556 mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
4557
4558 if (!(pi->sh->boardrev < 0x1204))
4559 mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
4560
4561 write_phy_reg(pi, 0x7d6, 0x0902);
4562 mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
4563
4564 mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
4565
4566 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
4567 mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
4568
4569 mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
4570
4571 mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
4572
4573 mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
4574
4575 mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
4576
4577 mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
4578 mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
4579 mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
4580 mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
4581 mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
4582
4583 mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
4584
4585 wlc_lcnphy_clear_tx_power_offsets(pi);
4586 mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
4587
4588 }
4589}
4590
Jason Coopera2627bc2010-09-14 09:45:31 -04004591static void WLBANDINITFN(wlc_lcnphy_baseband_init) (phy_info_t *pi)
4592{
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004593
4594 wlc_lcnphy_tbl_init(pi);
4595 wlc_lcnphy_rev0_baseband_init(pi);
4596 if (LCNREV_IS(pi->pubpi.phy_rev, 2))
4597 wlc_lcnphy_rev2_baseband_init(pi);
4598 wlc_lcnphy_bu_tweaks(pi);
4599}
4600
Jason Coopera2627bc2010-09-14 09:45:31 -04004601static void WLBANDINITFN(wlc_radio_2064_init) (phy_info_t *pi)
4602{
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004603 u32 i;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004604 lcnphy_radio_regs_t *lcnphyregs = NULL;
4605
4606 lcnphyregs = lcnphy_radio_regs_2064;
4607
4608 for (i = 0; lcnphyregs[i].address != 0xffff; i++)
4609 if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
4610 write_radio_reg(pi,
4611 ((lcnphyregs[i].address & 0x3fff) |
4612 RADIO_DEFAULT_CORE),
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004613 (u16) lcnphyregs[i].init_a);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004614 else if (lcnphyregs[i].do_init_g)
4615 write_radio_reg(pi,
4616 ((lcnphyregs[i].address & 0x3fff) |
4617 RADIO_DEFAULT_CORE),
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004618 (u16) lcnphyregs[i].init_g);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004619
4620 write_radio_reg(pi, RADIO_2064_REG032, 0x62);
4621 write_radio_reg(pi, RADIO_2064_REG033, 0x19);
4622
4623 write_radio_reg(pi, RADIO_2064_REG090, 0x10);
4624
4625 write_radio_reg(pi, RADIO_2064_REG010, 0x00);
4626
4627 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
4628
4629 write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
4630 write_radio_reg(pi, RADIO_2064_REG061, 0x72);
4631 write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
4632 }
4633
4634 write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
4635 write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
4636
4637 mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
4638
4639 mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
4640
4641 mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
4642
4643 mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
4644
4645 mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
4646
4647 write_phy_reg(pi, 0x4ea, 0x4688);
4648
4649 mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
4650
4651 mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
4652
4653 mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
4654
4655 wlc_lcnphy_set_tx_locc(pi, 0);
4656
4657 wlc_lcnphy_rcal(pi);
4658
4659 wlc_lcnphy_rc_cal(pi);
4660}
4661
Jason Coopera2627bc2010-09-14 09:45:31 -04004662static void WLBANDINITFN(wlc_lcnphy_radio_init) (phy_info_t *pi)
4663{
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004664 if (NORADIO_ENAB(pi->pubpi))
4665 return;
4666
4667 wlc_radio_2064_init(pi);
4668}
4669
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04004670static void wlc_lcnphy_rcal(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004671{
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004672 u8 rcal_value;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004673
4674 if (NORADIO_ENAB(pi->pubpi))
4675 return;
4676
4677 and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
4678
4679 or_radio_reg(pi, RADIO_2064_REG004, 0x40);
4680 or_radio_reg(pi, RADIO_2064_REG120, 0x10);
4681
4682 or_radio_reg(pi, RADIO_2064_REG078, 0x80);
4683 or_radio_reg(pi, RADIO_2064_REG129, 0x02);
4684
4685 or_radio_reg(pi, RADIO_2064_REG057, 0x01);
4686
4687 or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02004688 mdelay(5);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004689 SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
4690
4691 if (wlc_radio_2064_rcal_done(pi)) {
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004692 rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004693 rcal_value = rcal_value & 0x1f;
4694 }
4695
4696 and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
4697
4698 and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
4699}
4700
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04004701static void wlc_lcnphy_rc_cal(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004702{
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004703 u8 dflt_rc_cal_val;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004704 u16 flt_val;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004705
4706 if (NORADIO_ENAB(pi->pubpi))
4707 return;
4708
4709 dflt_rc_cal_val = 7;
4710 if (LCNREV_IS(pi->pubpi.phy_rev, 1))
4711 dflt_rc_cal_val = 11;
4712 flt_val =
4713 (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
4714 (dflt_rc_cal_val);
4715 write_phy_reg(pi, 0x933, flt_val);
4716 write_phy_reg(pi, 0x934, flt_val);
4717 write_phy_reg(pi, 0x935, flt_val);
4718 write_phy_reg(pi, 0x936, flt_val);
4719 write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
4720
4721 return;
4722}
4723
Greg Kroah-Hartman0d2f0722010-10-08 14:28:21 -07004724static bool wlc_phy_txpwr_srom_read_lcnphy(phy_info_t *pi)
Jason Coopera2627bc2010-09-14 09:45:31 -04004725{
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07004726 s8 txpwr = 0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004727 int i;
4728 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
4729
4730 if (CHSPEC_IS2G(pi->radio_chanspec)) {
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004731 u16 cckpo = 0;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004732 u32 offset_ofdm, offset_mcs;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004733
4734 pi_lcn->lcnphy_tr_isolation_mid =
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004735 (u8) PHY_GETINTVAR(pi, "triso2g");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004736
4737 pi_lcn->lcnphy_rx_power_offset =
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004738 (u8) PHY_GETINTVAR(pi, "rxpo2g");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004739
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07004740 pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0");
4741 pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1");
4742 pi->txpa_2g[2] = (s16) PHY_GETINTVAR(pi, "pa0b2");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004743
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004744 pi_lcn->lcnphy_rssi_vf = (u8) PHY_GETINTVAR(pi, "rssismf2g");
4745 pi_lcn->lcnphy_rssi_vc = (u8) PHY_GETINTVAR(pi, "rssismc2g");
4746 pi_lcn->lcnphy_rssi_gs = (u8) PHY_GETINTVAR(pi, "rssisav2g");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004747
4748 {
4749 pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
4750 pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
4751 pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
4752
4753 pi_lcn->lcnphy_rssi_vf_hightemp =
4754 pi_lcn->lcnphy_rssi_vf;
4755 pi_lcn->lcnphy_rssi_vc_hightemp =
4756 pi_lcn->lcnphy_rssi_vc;
4757 pi_lcn->lcnphy_rssi_gs_hightemp =
4758 pi_lcn->lcnphy_rssi_gs;
4759 }
4760
Greg Kroah-Hartman562c8852010-10-05 11:04:17 -07004761 txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004762 pi->tx_srom_max_2g = txpwr;
4763
4764 for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
4765 pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
4766 pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
4767 }
4768
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004769 cckpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004770 if (cckpo) {
4771 uint max_pwr_chan = txpwr;
4772
4773 for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
4774 pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
4775 ((cckpo & 0xf) * 2);
4776 cckpo >>= 4;
4777 }
4778
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004779 offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004780 for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
4781 pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
4782 ((offset_ofdm & 0xf) * 2);
4783 offset_ofdm >>= 4;
4784 }
4785 } else {
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004786 u8 opo = 0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004787
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004788 opo = (u8) PHY_GETINTVAR(pi, "opo");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004789
4790 for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
4791 pi->tx_srom_max_rate_2g[i] = txpwr;
4792 }
4793
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004794 offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004795
4796 for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
4797 pi->tx_srom_max_rate_2g[i] = txpwr -
4798 ((offset_ofdm & 0xf) * 2);
4799 offset_ofdm >>= 4;
4800 }
4801 offset_mcs =
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004802 ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) |
4803 (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004804 pi_lcn->lcnphy_mcs20_po = offset_mcs;
4805 for (i = TXP_FIRST_SISO_MCS_20;
4806 i <= TXP_LAST_SISO_MCS_20; i++) {
4807 pi->tx_srom_max_rate_2g[i] =
4808 txpwr - ((offset_mcs & 0xf) * 2);
4809 offset_mcs >>= 4;
4810 }
4811 }
4812
4813 pi_lcn->lcnphy_rawtempsense =
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004814 (u16) PHY_GETINTVAR(pi, "rawtempsense");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004815 pi_lcn->lcnphy_measPower =
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004816 (u8) PHY_GETINTVAR(pi, "measpower");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004817 pi_lcn->lcnphy_tempsense_slope =
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004818 (u8) PHY_GETINTVAR(pi, "tempsense_slope");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004819 pi_lcn->lcnphy_hw_iqcal_en =
4820 (bool) PHY_GETINTVAR(pi, "hw_iqcal_en");
4821 pi_lcn->lcnphy_iqcal_swp_dis =
4822 (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis");
4823 pi_lcn->lcnphy_tempcorrx =
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004824 (u8) PHY_GETINTVAR(pi, "tempcorrx");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004825 pi_lcn->lcnphy_tempsense_option =
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004826 (u8) PHY_GETINTVAR(pi, "tempsense_option");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004827 pi_lcn->lcnphy_freqoffset_corr =
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004828 (u8) PHY_GETINTVAR(pi, "freqoffset_corr");
4829 if ((u8) getintvar(pi->vars, "aa2g") > 1)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004830 wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi,
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004831 (u8) getintvar(pi->vars,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004832 "aa2g"));
4833 }
4834 pi_lcn->lcnphy_cck_dig_filt_type = -1;
4835 if (PHY_GETVAR(pi, "cckdigfilttype")) {
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07004836 s16 temp;
4837 temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype");
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004838 if (temp >= 0) {
4839 pi_lcn->lcnphy_cck_dig_filt_type = temp;
4840 }
4841 }
4842
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07004843 return true;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004844}
4845
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04004846void wlc_2064_vco_cal(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004847{
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004848 u8 calnrst;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004849
4850 mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004851 calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004852 write_radio_reg(pi, RADIO_2064_REG056, calnrst);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02004853 udelay(1);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004854 write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02004855 udelay(1);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004856 write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02004857 udelay(300);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004858 mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
4859}
4860
4861static void
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004862wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi, u8 channel)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004863{
4864 uint i;
4865 const chan_info_2064_lcnphy_t *ci;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004866 u8 rfpll_doubler = 0;
4867 u8 pll_pwrup, pll_pwrup_ovr;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004868 fixed qFxtal, qFref, qFvco, qFcal;
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004869 u8 d15, d16, f16, e44, e45;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07004870 u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004871 u16 loop_bw, d30, setCount;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004872 if (NORADIO_ENAB(pi->pubpi))
4873 return;
4874 ci = &chan_info_2064_lcnphy[0];
4875 rfpll_doubler = 1;
4876
4877 mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
4878
4879 write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
4880 if (!rfpll_doubler) {
4881 loop_bw = PLL_2064_LOOP_BW;
4882 d30 = PLL_2064_D30;
4883 } else {
4884 loop_bw = PLL_2064_LOOP_BW_DOUBLER;
4885 d30 = PLL_2064_D30_DOUBLER;
4886 }
4887
4888 if (CHSPEC_IS2G(pi->radio_chanspec)) {
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07004889 for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004890 if (chan_info_2064_lcnphy[i].chan == channel)
4891 break;
4892
Greg Kroah-Hartman8d3d6a62010-10-08 11:47:11 -07004893 if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) {
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004894 return;
4895 }
4896
4897 ci = &chan_info_2064_lcnphy[i];
4898 }
4899
4900 write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
4901
4902 mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
4903
4904 mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
4905
4906 mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
4907
4908 mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
4909 (ci->logen_rccr_rx) << 2);
4910
4911 mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
4912
4913 mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
4914 (ci->pa_rxrf_lna2_freq_tune) << 4);
4915
4916 write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
4917
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004918 pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
4919 pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004920
4921 or_radio_reg(pi, RADIO_2064_REG044, 0x07);
4922
4923 or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
4924 e44 = 0;
4925 e45 = 0;
4926
4927 fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
4928 if (pi->xtalfreq > 26000000)
4929 e44 = 1;
4930 if (pi->xtalfreq > 52000000)
4931 e45 = 1;
4932 if (e44 == 0)
4933 fcal_div = 1;
4934 else if (e45 == 0)
4935 fcal_div = 2;
4936 else
4937 fcal_div = 4;
4938 fvco3 = (ci->freq * 3);
4939 fref3 = 2 * fpfd;
4940
4941 qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
4942 qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
4943 qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
4944 qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
4945
4946 write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
4947
4948 d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
4949 write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
4950 write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
4951
4952 d16 = (qFcal * 8 / (d15 + 1)) - 1;
4953 write_radio_reg(pi, RADIO_2064_REG051, d16);
4954
4955 f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
4956 setCount = f16 * 3 * (ci->freq) / 32 - 1;
4957 mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004958 (u8) (setCount >> 8));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004959
4960 or_radio_reg(pi, RADIO_2064_REG053, 0x10);
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004961 write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004962
4963 div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
4964
4965 div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
4966 while (div_frac >= fref3) {
4967 div_int++;
4968 div_frac -= fref3;
4969 }
4970 div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
4971
4972 mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004973 (u8) (div_int >> 4));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004974 mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004975 (u8) (div_int << 4));
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004976 mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004977 (u8) (div_frac >> 16));
4978 write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
4979 write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004980
4981 write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
4982
4983 write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
4984 write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
4985 write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
4986
4987 {
Greg Kroah-Hartmane868ab02010-10-05 10:14:26 -07004988 u8 h29, h23, c28, d29, h28_ten, e30, h30_ten, cp_current;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07004989 u16 c29, c38, c30, g30, d28;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07004990 c29 = loop_bw;
4991 d29 = 200;
4992 c38 = 1250;
4993 h29 = d29 / c29;
4994 h23 = 1;
4995 c28 = 30;
4996 d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
4997 (fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
4998 (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
4999 + PLL_2064_LOW_END_KVCO;
5000 h28_ten = (d28 * 10) / c28;
5001 c30 = 2640;
5002 e30 = (d30 - 680) / 490;
5003 g30 = 680 + (e30 * 490);
5004 h30_ten = (g30 * 10) / c30;
5005 cp_current = ((c38 * h29 * h23 * 100) / h28_ten) / h30_ten;
5006 mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
5007 }
5008 if (channel >= 1 && channel <= 5)
5009 write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
5010 else
5011 write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
5012 write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
5013
5014 mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
mike.rapoport@gmail.com73831412010-10-13 00:09:07 +02005015 udelay(1);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005016
5017 wlc_2064_vco_cal(pi);
5018
5019 write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
5020 write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
5021 if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
5022 write_radio_reg(pi, RADIO_2064_REG038, 3);
5023 write_radio_reg(pi, RADIO_2064_REG091, 7);
5024 }
5025}
5026
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04005027bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005028{
5029 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
5030 return 0;
5031 else
5032 return (LCNPHY_TX_PWR_CTRL_HW ==
5033 wlc_lcnphy_get_tx_pwr_ctrl((pi)));
5034}
5035
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04005036void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005037{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07005038 u16 pwr_ctrl;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005039 if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
5040 wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
5041 } else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
5042
5043 pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
5044 wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
5045 wlc_lcnphy_txpower_recalc_target(pi);
5046
5047 wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
5048 } else
5049 return;
5050}
5051
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04005052void wlc_phy_detach_lcnphy(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005053{
mike.rapoport@gmail.com182acb32010-10-13 00:09:12 +02005054 kfree(pi->u.pi_lcnphy);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005055}
5056
Jason Cooper7cc4a4c2010-09-14 09:45:30 -04005057bool wlc_phy_attach_lcnphy(phy_info_t *pi)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005058{
5059 phy_info_lcnphy_t *pi_lcn;
5060
mike.rapoport@gmail.com5fcc1fc2010-10-13 00:09:10 +02005061 pi->u.pi_lcnphy = kzalloc(sizeof(phy_info_lcnphy_t), GFP_ATOMIC);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005062 if (pi->u.pi_lcnphy == NULL) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07005063 return false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005064 }
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005065
5066 pi_lcn = pi->u.pi_lcnphy;
5067
5068 if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) {
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07005069 pi->hwpwrctrl = true;
5070 pi->hwpwrctrl_capable = true;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005071 }
5072
5073 pi->xtalfreq = si_alp_clock(pi->sh->sih);
5074 ASSERT(0 == (pi->xtalfreq % 1000));
5075
5076 pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
5077
5078 pi->pi_fptr.init = wlc_phy_init_lcnphy;
5079 pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
5080 pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
5081 pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
5082 pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
5083 pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
5084 pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
5085 pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
5086 pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
5087
5088 if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07005089 return false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005090
5091 if ((pi->sh->boardflags & BFL_FEM) && (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
5092 if (pi_lcn->lcnphy_tempsense_option == 3) {
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07005093 pi->hwpwrctrl = true;
5094 pi->hwpwrctrl_capable = true;
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07005095 pi->temppwrctrl_capable = false;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005096 } else {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07005097 pi->hwpwrctrl = false;
5098 pi->hwpwrctrl_capable = false;
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07005099 pi->temppwrctrl_capable = true;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005100 }
5101 }
5102
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07005103 return true;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005104}
5105
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07005106static void wlc_lcnphy_set_rx_gain(phy_info_t *pi, u32 gain)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005107{
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07005108 u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005109
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07005110 trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07005111 ext_lna = (u16) (gain >> 29) & 0x01;
5112 lna1 = (u16) (gain >> 0) & 0x0f;
5113 lna2 = (u16) (gain >> 4) & 0x0f;
5114 tia = (u16) (gain >> 8) & 0xf;
5115 biq0 = (u16) (gain >> 12) & 0xf;
5116 biq1 = (u16) (gain >> 16) & 0xf;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005117
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07005118 gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005119 ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
5120 ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
5121 gain16_19 = biq1;
5122
5123 mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
5124 mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
5125 mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
5126 mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
5127 mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
5128
5129 if (CHSPEC_IS2G(pi->radio_chanspec)) {
5130 mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
5131 mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
5132 }
Greg Kroah-Hartman0f0881b2010-10-12 12:15:18 -07005133 wlc_lcnphy_rx_gain_override_enable(pi, true);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005134}
5135
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07005136static u32 wlc_lcnphy_get_receive_power(phy_info_t *pi, s32 *gain_index)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005137{
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07005138 u32 received_power = 0;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07005139 s32 max_index = 0;
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07005140 u32 gain_code = 0;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005141 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
5142
5143 max_index = 36;
5144 if (*gain_index >= 0)
5145 gain_code = lcnphy_23bitgaincode_table[*gain_index];
5146
5147 if (-1 == *gain_index) {
5148 *gain_index = 0;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07005149 while ((*gain_index <= (s32) max_index)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005150 && (received_power < 700)) {
5151 wlc_lcnphy_set_rx_gain(pi,
5152 lcnphy_23bitgaincode_table
5153 [*gain_index]);
5154 received_power =
5155 wlc_lcnphy_measure_digital_power(pi,
5156 pi_lcn->
5157 lcnphy_noise_samples);
5158 (*gain_index)++;
5159 }
5160 (*gain_index)--;
5161 } else {
5162 wlc_lcnphy_set_rx_gain(pi, gain_code);
5163 received_power =
5164 wlc_lcnphy_measure_digital_power(pi,
5165 pi_lcn->
5166 lcnphy_noise_samples);
5167 }
5168
5169 return received_power;
5170}
5171
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07005172s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005173{
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07005174 s32 gain = 0;
5175 s32 nominal_power_db;
5176 s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005177 input_power_db;
Greg Kroah-Hartman3e264162010-10-08 11:11:13 -07005178 s32 received_power, temperature;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005179 uint freq;
5180 phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
5181
5182 received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
5183
5184 gain = lcnphy_gain_table[gain_index];
5185
5186 nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
5187
5188 {
Greg Kroah-Hartman66cbd3a2010-10-08 11:05:47 -07005189 u32 power = (received_power * 16);
5190 u32 msb1, msb2, val1, val2, diff1, diff2;
Henry Ptasinskid953a052010-10-07 19:52:05 -07005191 msb1 = ffs(power) - 1;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005192 msb2 = msb1 + 1;
5193 val1 = 1 << msb1;
5194 val2 = 1 << msb2;
5195 diff1 = (power - val1);
5196 diff2 = (val2 - power);
5197 if (diff1 < diff2)
5198 log_val = msb1;
5199 else
5200 log_val = msb2;
5201 }
5202
5203 log_val = log_val * 3;
5204
5205 gain_mismatch = (nominal_power_db / 2) - (log_val);
5206
5207 desired_gain = gain + gain_mismatch;
5208
5209 input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
5210
5211 if (input_power_offset_db > 127)
5212 input_power_offset_db -= 256;
5213
5214 input_power_db = input_power_offset_db - desired_gain;
5215
5216 input_power_db =
5217 input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
5218
5219 freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
5220 if ((freq > 2427) && (freq <= 2467))
5221 input_power_db = input_power_db - 1;
5222
5223 temperature = pi_lcn->lcnphy_lastsensed_temperature;
5224
5225 if ((temperature - 15) < -30) {
5226 input_power_db =
5227 input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
5228 7;
5229 } else if ((temperature - 15) < 4) {
5230 input_power_db =
5231 input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
5232 3;
5233 } else {
5234 input_power_db =
5235 input_power_db + (((temperature - 10 - 25) * 286) >> 12);
5236 }
5237
5238 wlc_lcnphy_rx_gain_override_enable(pi, 0);
5239
5240 return input_power_db;
5241}
5242
5243static int
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07005244wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm, s16 filt_type)
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005245{
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07005246 s16 filt_index = -1;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005247 int j;
5248
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07005249 u16 addr[] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005250 0x910,
5251 0x91e,
5252 0x91f,
5253 0x924,
5254 0x925,
5255 0x926,
5256 0x920,
5257 0x921,
5258 0x927,
5259 0x928,
5260 0x929,
5261 0x922,
5262 0x923,
5263 0x930,
5264 0x931,
5265 0x932
5266 };
5267
Greg Kroah-Hartman7d4df482010-10-07 17:04:47 -07005268 u16 addr_ofdm[] = {
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005269 0x90f,
5270 0x900,
5271 0x901,
5272 0x906,
5273 0x907,
5274 0x908,
5275 0x902,
5276 0x903,
5277 0x909,
5278 0x90a,
5279 0x90b,
5280 0x904,
5281 0x905,
5282 0x90c,
5283 0x90d,
5284 0x90e
5285 };
5286
5287 if (!is_ofdm) {
5288 for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
5289 if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07005290 filt_index = (s16) j;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005291 break;
5292 }
5293 }
5294
5295 if (filt_index == -1) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07005296 ASSERT(false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005297 } else {
5298 for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
5299 write_phy_reg(pi, addr[j],
5300 LCNPHY_txdigfiltcoeffs_cck
5301 [filt_index][j + 1]);
5302 }
5303 }
5304 } else {
5305 for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
5306 if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
Greg Kroah-Hartmane59fe082010-10-07 17:08:21 -07005307 filt_index = (s16) j;
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005308 break;
5309 }
5310 }
5311
5312 if (filt_index == -1) {
Greg Kroah-Hartman0965ae82010-10-12 12:50:15 -07005313 ASSERT(false);
Henry Ptasinskia9533e72010-09-08 21:04:42 -07005314 } else {
5315 for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
5316 write_phy_reg(pi, addr_ofdm[j],
5317 LCNPHY_txdigfiltcoeffs_ofdm
5318 [filt_index][j + 1]);
5319 }
5320 }
5321 }
5322
5323 return (filt_index != -1) ? 0 : -1;
5324}