~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

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