~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

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