~ubuntu-branches/ubuntu/natty/linux-backports-modules-2.6.38/natty-proposed

« back to all changes in this revision

Viewing changes to updates/compat-wireless-2.6.37/drivers/staging/brcm80211/phy/wlc_phy_lcn.c

  • Committer: Bazaar Package Importer
  • Author(s): Tim Gardner, Tim Gardner
  • Date: 2011-06-08 10:44:09 UTC
  • Revision ID: james.westby@ubuntu.com-20110608104409-fnl8carkdo15bwsz
Tags: 2.6.38-10.6
[ Tim Gardner ]

Shorten compat-wireless package name to cw to accomodate
CDROM file name length restrictions.

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