Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c
178701 views
1
// SPDX-License-Identifier: ISC
2
/*
3
* Copyright (c) 2010 Broadcom Corporation
4
*/
5
#include <linux/kernel.h>
6
#include <linux/delay.h>
7
#include <linux/bitops.h>
8
9
#include <brcm_hw_ids.h>
10
#include <chipcommon.h>
11
#include <aiutils.h>
12
#include <d11.h>
13
#include <phy_shim.h>
14
#include "phy_hal.h"
15
#include "phy_int.h"
16
#include "phy_radio.h"
17
#include "phy_lcn.h"
18
#include "phyreg_n.h"
19
20
#define VALID_N_RADIO(radioid) ((radioid == BCM2055_ID) || \
21
(radioid == BCM2056_ID) || \
22
(radioid == BCM2057_ID))
23
24
#define VALID_LCN_RADIO(radioid) (radioid == BCM2064_ID)
25
26
#define VALID_RADIO(pi, radioid) ( \
27
(ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
28
(ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
29
30
/* basic mux operation - can be optimized on several architectures */
31
#define MUX(pred, true, false) ((pred) ? (true) : (false))
32
33
/* modulo inc/dec - assumes x E [0, bound - 1] */
34
#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1)
35
36
/* modulo inc/dec, bound = 2^k */
37
#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1))
38
#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1))
39
40
struct chan_info_basic {
41
u16 chan;
42
u16 freq;
43
};
44
45
static const struct chan_info_basic chan_info_all[] = {
46
{1, 2412},
47
{2, 2417},
48
{3, 2422},
49
{4, 2427},
50
{5, 2432},
51
{6, 2437},
52
{7, 2442},
53
{8, 2447},
54
{9, 2452},
55
{10, 2457},
56
{11, 2462},
57
{12, 2467},
58
{13, 2472},
59
{14, 2484},
60
61
{34, 5170},
62
{38, 5190},
63
{42, 5210},
64
{46, 5230},
65
66
{36, 5180},
67
{40, 5200},
68
{44, 5220},
69
{48, 5240},
70
{52, 5260},
71
{56, 5280},
72
{60, 5300},
73
{64, 5320},
74
75
{100, 5500},
76
{104, 5520},
77
{108, 5540},
78
{112, 5560},
79
{116, 5580},
80
{120, 5600},
81
{124, 5620},
82
{128, 5640},
83
{132, 5660},
84
{136, 5680},
85
{140, 5700},
86
87
{149, 5745},
88
{153, 5765},
89
{157, 5785},
90
{161, 5805},
91
{165, 5825},
92
93
{184, 4920},
94
{188, 4940},
95
{192, 4960},
96
{196, 4980},
97
{200, 5000},
98
{204, 5020},
99
{208, 5040},
100
{212, 5060},
101
{216, 5080}
102
};
103
104
static const u8 ofdm_rate_lookup[] = {
105
106
BRCM_RATE_48M,
107
BRCM_RATE_24M,
108
BRCM_RATE_12M,
109
BRCM_RATE_6M,
110
BRCM_RATE_54M,
111
BRCM_RATE_36M,
112
BRCM_RATE_18M,
113
BRCM_RATE_9M
114
};
115
116
#define PHY_WREG_LIMIT 24
117
118
void wlc_phyreg_enter(struct brcms_phy_pub *pih)
119
{
120
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
121
wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim);
122
}
123
124
void wlc_phyreg_exit(struct brcms_phy_pub *pih)
125
{
126
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
127
wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim);
128
}
129
130
u16 read_radio_reg(struct brcms_phy *pi, u16 addr)
131
{
132
u16 data;
133
134
if (addr == RADIO_IDCODE)
135
return 0xffff;
136
137
switch (pi->pubpi.phy_type) {
138
case PHY_TYPE_N:
139
if (!CONF_HAS(PHYTYPE, PHY_TYPE_N))
140
break;
141
if (NREV_GE(pi->pubpi.phy_rev, 7))
142
addr |= RADIO_2057_READ_OFF;
143
else
144
addr |= RADIO_2055_READ_OFF;
145
break;
146
147
case PHY_TYPE_LCN:
148
if (!CONF_HAS(PHYTYPE, PHY_TYPE_LCN))
149
break;
150
addr |= RADIO_2064_READ_OFF;
151
break;
152
153
default:
154
break;
155
}
156
157
if ((D11REV_GE(pi->sh->corerev, 24)) ||
158
(D11REV_IS(pi->sh->corerev, 22)
159
&& (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
160
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr);
161
data = bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
162
} else {
163
bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr);
164
data = bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo));
165
}
166
pi->phy_wreg = 0;
167
168
return data;
169
}
170
171
void write_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
172
{
173
if ((D11REV_GE(pi->sh->corerev, 24)) ||
174
(D11REV_IS(pi->sh->corerev, 22)
175
&& (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
176
177
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), addr);
178
bcma_write16(pi->d11core, D11REGOFFS(radioregdata), val);
179
} else {
180
bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), addr);
181
bcma_write16(pi->d11core, D11REGOFFS(phy4wdatalo), val);
182
}
183
184
if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) &&
185
(++pi->phy_wreg >= pi->phy_wreg_limit)) {
186
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
187
pi->phy_wreg = 0;
188
}
189
}
190
191
static u32 read_radio_id(struct brcms_phy *pi)
192
{
193
u32 id;
194
195
if (D11REV_GE(pi->sh->corerev, 24)) {
196
u32 b0, b1, b2;
197
198
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 0);
199
b0 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
200
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 1);
201
b1 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
202
bcma_wflush16(pi->d11core, D11REGOFFS(radioregaddr), 2);
203
b2 = (u32) bcma_read16(pi->d11core, D11REGOFFS(radioregdata));
204
205
id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
206
& 0xf);
207
} else {
208
bcma_wflush16(pi->d11core, D11REGOFFS(phy4waddr), RADIO_IDCODE);
209
id = (u32) bcma_read16(pi->d11core, D11REGOFFS(phy4wdatalo));
210
id |= (u32) bcma_read16(pi->d11core,
211
D11REGOFFS(phy4wdatahi)) << 16;
212
}
213
pi->phy_wreg = 0;
214
return id;
215
}
216
217
void and_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
218
{
219
u16 rval;
220
221
rval = read_radio_reg(pi, addr);
222
write_radio_reg(pi, addr, (rval & val));
223
}
224
225
void or_radio_reg(struct brcms_phy *pi, u16 addr, u16 val)
226
{
227
u16 rval;
228
229
rval = read_radio_reg(pi, addr);
230
write_radio_reg(pi, addr, (rval | val));
231
}
232
233
void xor_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask)
234
{
235
u16 rval;
236
237
rval = read_radio_reg(pi, addr);
238
write_radio_reg(pi, addr, (rval ^ mask));
239
}
240
241
void mod_radio_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
242
{
243
u16 rval;
244
245
rval = read_radio_reg(pi, addr);
246
write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
247
}
248
249
u16 read_phy_reg(struct brcms_phy *pi, u16 addr)
250
{
251
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
252
253
pi->phy_wreg = 0;
254
return bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
255
}
256
257
void write_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
258
{
259
#ifdef CONFIG_BCM47XX
260
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
261
bcma_write16(pi->d11core, D11REGOFFS(phyregdata), val);
262
if (addr == 0x72)
263
(void)bcma_read16(pi->d11core, D11REGOFFS(phyregdata));
264
#else
265
bcma_write32(pi->d11core, D11REGOFFS(phyregaddr), addr | (val << 16));
266
if ((pi->d11core->bus->hosttype == BCMA_HOSTTYPE_PCI) &&
267
(++pi->phy_wreg >= pi->phy_wreg_limit)) {
268
pi->phy_wreg = 0;
269
(void)bcma_read16(pi->d11core, D11REGOFFS(phyversion));
270
}
271
#endif
272
}
273
274
void and_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
275
{
276
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
277
bcma_mask16(pi->d11core, D11REGOFFS(phyregdata), val);
278
pi->phy_wreg = 0;
279
}
280
281
void or_phy_reg(struct brcms_phy *pi, u16 addr, u16 val)
282
{
283
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
284
bcma_set16(pi->d11core, D11REGOFFS(phyregdata), val);
285
pi->phy_wreg = 0;
286
}
287
288
void mod_phy_reg(struct brcms_phy *pi, u16 addr, u16 mask, u16 val)
289
{
290
val &= mask;
291
bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr), addr);
292
bcma_maskset16(pi->d11core, D11REGOFFS(phyregdata), ~mask, val);
293
pi->phy_wreg = 0;
294
}
295
296
static void wlc_set_phy_uninitted(struct brcms_phy *pi)
297
{
298
int i, j;
299
300
pi->initialized = false;
301
302
pi->tx_vos = 0xffff;
303
pi->nrssi_table_delta = 0x7fffffff;
304
pi->rc_cal = 0xffff;
305
pi->mintxbias = 0xffff;
306
pi->txpwridx = -1;
307
if (ISNPHY(pi)) {
308
pi->phy_spuravoid = SPURAVOID_DISABLE;
309
310
if (NREV_GE(pi->pubpi.phy_rev, 3)
311
&& NREV_LT(pi->pubpi.phy_rev, 7))
312
pi->phy_spuravoid = SPURAVOID_AUTO;
313
314
pi->nphy_papd_skip = 0;
315
pi->nphy_papd_epsilon_offset[0] = 0xf588;
316
pi->nphy_papd_epsilon_offset[1] = 0xf588;
317
pi->nphy_txpwr_idx[0] = 128;
318
pi->nphy_txpwr_idx[1] = 128;
319
pi->nphy_txpwrindex[0].index_internal = 40;
320
pi->nphy_txpwrindex[1].index_internal = 40;
321
pi->phy_pabias = 0;
322
} else {
323
pi->phy_spuravoid = SPURAVOID_AUTO;
324
}
325
pi->radiopwr = 0xffff;
326
for (i = 0; i < STATIC_NUM_RF; i++) {
327
for (j = 0; j < STATIC_NUM_BB; j++)
328
pi->stats_11b_txpower[i][j] = -1;
329
}
330
}
331
332
struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
333
{
334
struct shared_phy *sh;
335
336
sh = kzalloc(sizeof(*sh), GFP_ATOMIC);
337
if (sh == NULL)
338
return NULL;
339
340
sh->physhim = shp->physhim;
341
sh->unit = shp->unit;
342
sh->corerev = shp->corerev;
343
344
sh->vid = shp->vid;
345
sh->did = shp->did;
346
sh->chip = shp->chip;
347
sh->chiprev = shp->chiprev;
348
sh->chippkg = shp->chippkg;
349
sh->sromrev = shp->sromrev;
350
sh->boardtype = shp->boardtype;
351
sh->boardrev = shp->boardrev;
352
sh->boardflags = shp->boardflags;
353
sh->boardflags2 = shp->boardflags2;
354
355
sh->fast_timer = PHY_SW_TIMER_FAST;
356
sh->slow_timer = PHY_SW_TIMER_SLOW;
357
sh->glacial_timer = PHY_SW_TIMER_GLACIAL;
358
359
sh->rssi_mode = RSSI_ANT_MERGE_MAX;
360
361
return sh;
362
}
363
364
static void wlc_phy_timercb_phycal(void *ptr)
365
{
366
struct brcms_phy *pi = ptr;
367
uint delay = 5;
368
369
if (PHY_PERICAL_MPHASE_PENDING(pi)) {
370
if (!pi->sh->up) {
371
wlc_phy_cal_perical_mphase_reset(pi);
372
return;
373
}
374
375
if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
376
377
delay = 1000;
378
wlc_phy_cal_perical_mphase_restart(pi);
379
} else
380
wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
381
wlapi_add_timer(pi->phycal_timer, delay, 0);
382
return;
383
}
384
385
}
386
387
static u32 wlc_phy_get_radio_ver(struct brcms_phy *pi)
388
{
389
u32 ver;
390
391
ver = read_radio_id(pi);
392
393
return ver;
394
}
395
396
struct brcms_phy_pub *
397
wlc_phy_attach(struct shared_phy *sh, struct bcma_device *d11core,
398
int bandtype, struct wiphy *wiphy)
399
{
400
struct brcms_phy *pi;
401
u32 sflags = 0;
402
uint phyversion;
403
u32 idcode;
404
int i;
405
406
if (D11REV_IS(sh->corerev, 4))
407
sflags = SISF_2G_PHY | SISF_5G_PHY;
408
else
409
sflags = bcma_aread32(d11core, BCMA_IOST);
410
411
if (bandtype == BRCM_BAND_5G) {
412
if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0)
413
return NULL;
414
}
415
416
pi = sh->phy_head;
417
if ((sflags & SISF_DB_PHY) && pi) {
418
wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
419
pi->refcnt++;
420
return &pi->pubpi_ro;
421
}
422
423
pi = kzalloc(sizeof(*pi), GFP_ATOMIC);
424
if (pi == NULL)
425
return NULL;
426
pi->wiphy = wiphy;
427
pi->d11core = d11core;
428
pi->sh = sh;
429
pi->phy_init_por = true;
430
pi->phy_wreg_limit = PHY_WREG_LIMIT;
431
432
pi->txpwr_percent = 100;
433
434
pi->do_initcal = true;
435
436
pi->phycal_tempdelta = 0;
437
438
if (bandtype == BRCM_BAND_2G && (sflags & SISF_2G_PHY))
439
pi->pubpi.coreflags = SICF_GMODE;
440
441
wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
442
phyversion = bcma_read16(pi->d11core, D11REGOFFS(phyversion));
443
444
pi->pubpi.phy_type = PHY_TYPE(phyversion);
445
pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
446
447
if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) {
448
pi->pubpi.phy_type = PHY_TYPE_N;
449
pi->pubpi.phy_rev += LCNXN_BASEREV;
450
}
451
pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
452
pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
453
454
if (pi->pubpi.phy_type != PHY_TYPE_N &&
455
pi->pubpi.phy_type != PHY_TYPE_LCN)
456
goto err;
457
458
if (bandtype == BRCM_BAND_5G) {
459
if (!ISNPHY(pi))
460
goto err;
461
} else if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
462
goto err;
463
}
464
465
wlc_phy_anacore((struct brcms_phy_pub *) pi, ON);
466
467
idcode = wlc_phy_get_radio_ver(pi);
468
pi->pubpi.radioid =
469
(idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
470
pi->pubpi.radiorev =
471
(idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
472
pi->pubpi.radiover =
473
(idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
474
if (!VALID_RADIO(pi, pi->pubpi.radioid))
475
goto err;
476
477
wlc_phy_switch_radio((struct brcms_phy_pub *) pi, OFF);
478
479
wlc_set_phy_uninitted(pi);
480
481
pi->bw = WL_CHANSPEC_BW_20;
482
pi->radio_chanspec = (bandtype == BRCM_BAND_2G) ?
483
ch20mhz_chspec(1) : ch20mhz_chspec(36);
484
485
pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
486
pi->rxiq_antsel = ANT_RX_DIV_DEF;
487
488
pi->watchdog_override = true;
489
490
pi->cal_type_override = PHY_PERICAL_AUTO;
491
492
pi->nphy_saved_noisevars.bufcount = 0;
493
494
if (ISNPHY(pi))
495
pi->min_txpower = PHY_TXPWR_MIN_NPHY;
496
else
497
pi->min_txpower = PHY_TXPWR_MIN;
498
499
pi->sh->phyrxchain = 0x3;
500
501
pi->rx2tx_biasentry = -1;
502
503
pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
504
pi->phy_txcore_enable_temp =
505
PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
506
pi->phy_tempsense_offset = 0;
507
pi->phy_txcore_heatedup = false;
508
509
pi->nphy_lastcal_temp = -50;
510
511
pi->phynoise_polling = true;
512
if (ISNPHY(pi) || ISLCNPHY(pi))
513
pi->phynoise_polling = false;
514
515
for (i = 0; i < TXP_NUM_RATES; i++) {
516
pi->txpwr_limit[i] = BRCMS_TXPWR_MAX;
517
pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
518
pi->tx_user_target[i] = BRCMS_TXPWR_MAX;
519
}
520
521
pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF;
522
523
pi->user_txpwr_at_rfport = false;
524
525
if (ISNPHY(pi)) {
526
527
pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
528
wlc_phy_timercb_phycal,
529
pi, "phycal");
530
if (!pi->phycal_timer)
531
goto err;
532
533
wlc_phy_attach_nphy(pi);
534
535
} else if (ISLCNPHY(pi)) {
536
if (!wlc_phy_attach_lcnphy(pi))
537
goto err;
538
539
}
540
541
pi->refcnt++;
542
pi->next = pi->sh->phy_head;
543
sh->phy_head = pi;
544
545
memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(struct brcms_phy_pub));
546
547
return &pi->pubpi_ro;
548
549
err:
550
kfree(pi);
551
return NULL;
552
}
553
554
void wlc_phy_detach(struct brcms_phy_pub *pih)
555
{
556
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
557
558
if (pih) {
559
if (--pi->refcnt)
560
return;
561
562
if (pi->phycal_timer) {
563
wlapi_free_timer(pi->phycal_timer);
564
pi->phycal_timer = NULL;
565
}
566
567
if (pi->sh->phy_head == pi)
568
pi->sh->phy_head = pi->next;
569
else if (pi->sh->phy_head->next == pi)
570
pi->sh->phy_head->next = NULL;
571
572
if (pi->pi_fptr.detach)
573
(pi->pi_fptr.detach)(pi);
574
575
kfree(pi);
576
}
577
}
578
579
bool
580
wlc_phy_get_phyversion(struct brcms_phy_pub *pih, u16 *phytype, u16 *phyrev,
581
u16 *radioid, u16 *radiover)
582
{
583
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
584
*phytype = (u16) pi->pubpi.phy_type;
585
*phyrev = (u16) pi->pubpi.phy_rev;
586
*radioid = pi->pubpi.radioid;
587
*radiover = pi->pubpi.radiorev;
588
589
return true;
590
}
591
592
bool wlc_phy_get_encore(struct brcms_phy_pub *pih)
593
{
594
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
595
return pi->pubpi.abgphy_encore;
596
}
597
598
u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih)
599
{
600
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
601
return pi->pubpi.coreflags;
602
}
603
604
void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on)
605
{
606
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
607
608
if (ISNPHY(pi)) {
609
if (on) {
610
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
611
write_phy_reg(pi, 0xa6, 0x0d);
612
write_phy_reg(pi, 0x8f, 0x0);
613
write_phy_reg(pi, 0xa7, 0x0d);
614
write_phy_reg(pi, 0xa5, 0x0);
615
} else {
616
write_phy_reg(pi, 0xa5, 0x0);
617
}
618
} else {
619
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
620
write_phy_reg(pi, 0x8f, 0x07ff);
621
write_phy_reg(pi, 0xa6, 0x0fd);
622
write_phy_reg(pi, 0xa5, 0x07ff);
623
write_phy_reg(pi, 0xa7, 0x0fd);
624
} else {
625
write_phy_reg(pi, 0xa5, 0x7fff);
626
}
627
}
628
} else if (ISLCNPHY(pi)) {
629
if (on) {
630
and_phy_reg(pi, 0x43b,
631
~((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
632
} else {
633
or_phy_reg(pi, 0x43c,
634
(0x1 << 0) | (0x1 << 1) | (0x1 << 2));
635
or_phy_reg(pi, 0x43b,
636
(0x1 << 0) | (0x1 << 1) | (0x1 << 2));
637
}
638
}
639
}
640
641
u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih)
642
{
643
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
644
645
u32 phy_bw_clkbits = 0;
646
647
if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) {
648
switch (pi->bw) {
649
case WL_CHANSPEC_BW_10:
650
phy_bw_clkbits = SICF_BW10;
651
break;
652
case WL_CHANSPEC_BW_20:
653
phy_bw_clkbits = SICF_BW20;
654
break;
655
case WL_CHANSPEC_BW_40:
656
phy_bw_clkbits = SICF_BW40;
657
break;
658
default:
659
break;
660
}
661
}
662
663
return phy_bw_clkbits;
664
}
665
666
void wlc_phy_por_inform(struct brcms_phy_pub *ppi)
667
{
668
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
669
670
pi->phy_init_por = true;
671
}
672
673
void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal)
674
{
675
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
676
677
pi->do_initcal = initcal;
678
}
679
680
void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *pih, bool newstate)
681
{
682
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
683
684
if (!pi || !pi->sh)
685
return;
686
687
pi->sh->clk = newstate;
688
}
689
690
void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate)
691
{
692
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
693
694
if (!pi || !pi->sh)
695
return;
696
697
pi->sh->up = newstate;
698
}
699
700
void wlc_phy_init(struct brcms_phy_pub *pih, u16 chanspec)
701
{
702
u32 mc;
703
void (*phy_init)(struct brcms_phy *) = NULL;
704
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
705
706
if (pi->init_in_progress)
707
return;
708
709
pi->init_in_progress = true;
710
711
pi->radio_chanspec = chanspec;
712
713
mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
714
if (WARN(mc & MCTL_EN_MAC, "HW error MAC running on init"))
715
return;
716
717
if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN))
718
pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
719
720
if (WARN(!(bcma_aread32(pi->d11core, BCMA_IOST) & SISF_FCLKA),
721
"HW error SISF_FCLKA\n"))
722
return;
723
724
phy_init = pi->pi_fptr.init;
725
726
if (phy_init == NULL)
727
return;
728
729
wlc_phy_anacore(pih, ON);
730
731
if (CHSPEC_BW(pi->radio_chanspec) != pi->bw)
732
wlapi_bmac_bw_set(pi->sh->physhim,
733
CHSPEC_BW(pi->radio_chanspec));
734
735
pi->nphy_gain_boost = true;
736
737
wlc_phy_switch_radio((struct brcms_phy_pub *) pi, ON);
738
739
(*phy_init)(pi);
740
741
pi->phy_init_por = false;
742
743
if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
744
wlc_phy_do_dummy_tx(pi, true, OFF);
745
746
if (!(ISNPHY(pi)))
747
wlc_phy_txpower_update_shm(pi);
748
749
wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, pi->sh->rx_antdiv);
750
751
pi->init_in_progress = false;
752
}
753
754
void wlc_phy_cal_init(struct brcms_phy_pub *pih)
755
{
756
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
757
void (*cal_init)(struct brcms_phy *) = NULL;
758
759
if (WARN((bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
760
MCTL_EN_MAC) != 0, "HW error: MAC enabled during phy cal\n"))
761
return;
762
763
if (!pi->initialized) {
764
cal_init = pi->pi_fptr.calinit;
765
if (cal_init)
766
(*cal_init)(pi);
767
768
pi->initialized = true;
769
}
770
}
771
772
int wlc_phy_down(struct brcms_phy_pub *pih)
773
{
774
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
775
int callbacks = 0;
776
777
if (pi->phycal_timer
778
&& !wlapi_del_timer(pi->phycal_timer))
779
callbacks++;
780
781
pi->nphy_iqcal_chanspec_2G = 0;
782
pi->nphy_iqcal_chanspec_5G = 0;
783
784
return callbacks;
785
}
786
787
void
788
wlc_phy_table_addr(struct brcms_phy *pi, uint tbl_id, uint tbl_offset,
789
u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
790
{
791
write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
792
793
pi->tbl_data_hi = tblDataHi;
794
pi->tbl_data_lo = tblDataLo;
795
796
if (pi->sh->chip == BCMA_CHIP_ID_BCM43224 &&
797
pi->sh->chiprev == 1) {
798
pi->tbl_addr = tblAddr;
799
pi->tbl_save_id = tbl_id;
800
pi->tbl_save_offset = tbl_offset;
801
}
802
}
803
804
void wlc_phy_table_data_write(struct brcms_phy *pi, uint width, u32 val)
805
{
806
if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
807
(pi->sh->chiprev == 1) &&
808
(pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
809
read_phy_reg(pi, pi->tbl_data_lo);
810
811
write_phy_reg(pi, pi->tbl_addr,
812
(pi->tbl_save_id << 10) | pi->tbl_save_offset);
813
pi->tbl_save_offset++;
814
}
815
816
if (width == 32) {
817
write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
818
write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
819
} else {
820
write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
821
}
822
}
823
824
void
825
wlc_phy_write_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
826
u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
827
{
828
uint idx;
829
uint tbl_id = ptbl_info->tbl_id;
830
uint tbl_offset = ptbl_info->tbl_offset;
831
uint tbl_width = ptbl_info->tbl_width;
832
const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr;
833
const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr;
834
const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr;
835
836
write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
837
838
for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
839
840
if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
841
(pi->sh->chiprev == 1) &&
842
(tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
843
read_phy_reg(pi, tblDataLo);
844
845
write_phy_reg(pi, tblAddr,
846
(tbl_id << 10) | (tbl_offset + idx));
847
}
848
849
if (tbl_width == 32) {
850
write_phy_reg(pi, tblDataHi,
851
(u16) (ptbl_32b[idx] >> 16));
852
write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
853
} else if (tbl_width == 16) {
854
write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
855
} else {
856
write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
857
}
858
}
859
}
860
861
void
862
wlc_phy_read_table(struct brcms_phy *pi, const struct phytbl_info *ptbl_info,
863
u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
864
{
865
uint idx;
866
uint tbl_id = ptbl_info->tbl_id;
867
uint tbl_offset = ptbl_info->tbl_offset;
868
uint tbl_width = ptbl_info->tbl_width;
869
u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr;
870
u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr;
871
u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr;
872
873
write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
874
875
for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
876
877
if ((pi->sh->chip == BCMA_CHIP_ID_BCM43224) &&
878
(pi->sh->chiprev == 1)) {
879
(void)read_phy_reg(pi, tblDataLo);
880
881
write_phy_reg(pi, tblAddr,
882
(tbl_id << 10) | (tbl_offset + idx));
883
}
884
885
if (tbl_width == 32) {
886
ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
887
ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
888
} else if (tbl_width == 16) {
889
ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
890
} else {
891
ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
892
}
893
}
894
}
895
896
uint
897
wlc_phy_init_radio_regs_allbands(struct brcms_phy *pi,
898
struct radio_20xx_regs *radioregs)
899
{
900
uint i = 0;
901
902
do {
903
if (radioregs[i].do_init)
904
write_radio_reg(pi, radioregs[i].address,
905
(u16) radioregs[i].init);
906
907
i++;
908
} while (radioregs[i].address != 0xffff);
909
910
return i;
911
}
912
913
uint
914
wlc_phy_init_radio_regs(struct brcms_phy *pi,
915
const struct radio_regs *radioregs,
916
u16 core_offset)
917
{
918
uint i = 0;
919
uint count = 0;
920
921
do {
922
if (CHSPEC_IS5G(pi->radio_chanspec)) {
923
if (radioregs[i].do_init_a) {
924
write_radio_reg(pi,
925
radioregs[i].
926
address | core_offset,
927
(u16) radioregs[i].init_a);
928
if (ISNPHY(pi) && (++count % 4 == 0))
929
BRCMS_PHY_WAR_PR51571(pi);
930
}
931
} else {
932
if (radioregs[i].do_init_g) {
933
write_radio_reg(pi,
934
radioregs[i].
935
address | core_offset,
936
(u16) radioregs[i].init_g);
937
if (ISNPHY(pi) && (++count % 4 == 0))
938
BRCMS_PHY_WAR_PR51571(pi);
939
}
940
}
941
942
i++;
943
} while (radioregs[i].address != 0xffff);
944
945
return i;
946
}
947
948
void wlc_phy_do_dummy_tx(struct brcms_phy *pi, bool ofdm, bool pa_on)
949
{
950
#define DUMMY_PKT_LEN 20
951
struct bcma_device *core = pi->d11core;
952
int i, count;
953
u8 ofdmpkt[DUMMY_PKT_LEN] = {
954
0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
955
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
956
};
957
u8 cckpkt[DUMMY_PKT_LEN] = {
958
0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
959
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
960
};
961
u32 *dummypkt;
962
963
dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt);
964
wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
965
dummypkt);
966
967
bcma_write16(core, D11REGOFFS(xmtsel), 0);
968
969
if (D11REV_GE(pi->sh->corerev, 11))
970
bcma_write16(core, D11REGOFFS(wepctl), 0x100);
971
else
972
bcma_write16(core, D11REGOFFS(wepctl), 0);
973
974
bcma_write16(core, D11REGOFFS(txe_phyctl),
975
(ofdm ? 1 : 0) | PHY_TXC_ANT_0);
976
if (ISNPHY(pi) || ISLCNPHY(pi))
977
bcma_write16(core, D11REGOFFS(txe_phyctl1), 0x1A02);
978
979
bcma_write16(core, D11REGOFFS(txe_wm_0), 0);
980
bcma_write16(core, D11REGOFFS(txe_wm_1), 0);
981
982
bcma_write16(core, D11REGOFFS(xmttplatetxptr), 0);
983
bcma_write16(core, D11REGOFFS(xmttxcnt), DUMMY_PKT_LEN);
984
985
bcma_write16(core, D11REGOFFS(xmtsel),
986
((8 << 8) | (1 << 5) | (1 << 2) | 2));
987
988
bcma_write16(core, D11REGOFFS(txe_ctl), 0);
989
990
if (!pa_on) {
991
if (ISNPHY(pi))
992
wlc_phy_pa_override_nphy(pi, OFF);
993
}
994
995
if (ISNPHY(pi) || ISLCNPHY(pi))
996
bcma_write16(core, D11REGOFFS(txe_aux), 0xD0);
997
else
998
bcma_write16(core, D11REGOFFS(txe_aux), ((1 << 5) | (1 << 4)));
999
1000
(void)bcma_read16(core, D11REGOFFS(txe_aux));
1001
1002
i = 0;
1003
count = ofdm ? 30 : 250;
1004
while ((i++ < count)
1005
&& (bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 7)))
1006
udelay(10);
1007
1008
i = 0;
1009
1010
while ((i++ < 10) &&
1011
((bcma_read16(core, D11REGOFFS(txe_status)) & (1 << 10)) == 0))
1012
udelay(10);
1013
1014
i = 0;
1015
1016
while ((i++ < 10) &&
1017
((bcma_read16(core, D11REGOFFS(ifsstat)) & (1 << 8))))
1018
udelay(10);
1019
1020
if (!pa_on) {
1021
if (ISNPHY(pi))
1022
wlc_phy_pa_override_nphy(pi, ON);
1023
}
1024
}
1025
1026
void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set)
1027
{
1028
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
1029
1030
if (set)
1031
mboolset(pi->measure_hold, id);
1032
else
1033
mboolclr(pi->measure_hold, id);
1034
1035
return;
1036
}
1037
1038
void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags)
1039
{
1040
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
1041
1042
if (mute)
1043
mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
1044
else
1045
mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
1046
1047
if (!mute && (flags & PHY_MUTE_FOR_PREISM))
1048
pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
1049
return;
1050
}
1051
1052
static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
1053
{
1054
return false;
1055
}
1056
1057
void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on)
1058
{
1059
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
1060
(void)bcma_read32(pi->d11core, D11REGOFFS(maccontrol));
1061
1062
if (ISNPHY(pi)) {
1063
wlc_phy_switch_radio_nphy(pi, on);
1064
} else if (ISLCNPHY(pi)) {
1065
if (on) {
1066
and_phy_reg(pi, 0x44c,
1067
~((0x1 << 8) |
1068
(0x1 << 9) |
1069
(0x1 << 10) | (0x1 << 11) | (0x1 << 12)));
1070
and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11)));
1071
and_phy_reg(pi, 0x4f9, ~(0x1 << 3));
1072
} else {
1073
and_phy_reg(pi, 0x44d,
1074
~((0x1 << 10) |
1075
(0x1 << 11) |
1076
(0x1 << 12) | (0x1 << 13) | (0x1 << 14)));
1077
or_phy_reg(pi, 0x44c,
1078
(0x1 << 8) |
1079
(0x1 << 9) |
1080
(0x1 << 10) | (0x1 << 11) | (0x1 << 12));
1081
1082
and_phy_reg(pi, 0x4b7, ~((0x7f << 8)));
1083
and_phy_reg(pi, 0x4b1, ~((0x1 << 13)));
1084
or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11));
1085
and_phy_reg(pi, 0x4fa, ~((0x1 << 3)));
1086
or_phy_reg(pi, 0x4f9, (0x1 << 3));
1087
}
1088
}
1089
}
1090
1091
void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw)
1092
{
1093
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1094
1095
pi->bw = bw;
1096
}
1097
1098
void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch)
1099
{
1100
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1101
pi->radio_chanspec = newch;
1102
1103
}
1104
1105
u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi)
1106
{
1107
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1108
1109
return pi->radio_chanspec;
1110
}
1111
1112
void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec)
1113
{
1114
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1115
u16 m_cur_channel;
1116
void (*chanspec_set)(struct brcms_phy *, u16) = NULL;
1117
m_cur_channel = CHSPEC_CHANNEL(chanspec);
1118
if (CHSPEC_IS5G(chanspec))
1119
m_cur_channel |= D11_CURCHANNEL_5G;
1120
if (CHSPEC_IS40(chanspec))
1121
m_cur_channel |= D11_CURCHANNEL_40;
1122
wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel);
1123
1124
chanspec_set = pi->pi_fptr.chanset;
1125
if (chanspec_set)
1126
(*chanspec_set)(pi, chanspec);
1127
1128
}
1129
1130
void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
1131
bool wide_filter)
1132
{
1133
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1134
1135
pi->channel_14_wide_filter = wide_filter;
1136
1137
}
1138
1139
int wlc_phy_channel2freq(uint channel)
1140
{
1141
uint i;
1142
1143
for (i = 0; i < ARRAY_SIZE(chan_info_all); i++)
1144
if (chan_info_all[i].chan == channel)
1145
return chan_info_all[i].freq;
1146
return 0;
1147
}
1148
1149
void
1150
wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
1151
struct brcms_chanvec *channels)
1152
{
1153
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1154
uint i;
1155
uint channel;
1156
1157
memset(channels, 0, sizeof(struct brcms_chanvec));
1158
1159
for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
1160
channel = chan_info_all[i].chan;
1161
1162
if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
1163
&& (channel <= LAST_REF5_CHANNUM))
1164
continue;
1165
1166
if ((band == BRCM_BAND_2G && channel <= CH_MAX_2G_CHANNEL) ||
1167
(band == BRCM_BAND_5G && channel > CH_MAX_2G_CHANNEL))
1168
setbit(channels->vec, channel);
1169
}
1170
}
1171
1172
int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override)
1173
{
1174
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1175
1176
*qdbm = pi->tx_user_target[0];
1177
if (override != NULL)
1178
*override = pi->txpwroverride;
1179
return 0;
1180
}
1181
1182
int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
1183
{
1184
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1185
int i;
1186
1187
if (qdbm > 127)
1188
return -EINVAL;
1189
1190
for (i = 0; i < TXP_NUM_RATES; i++)
1191
pi->tx_user_target[i] = (u8) qdbm;
1192
1193
pi->txpwroverride = false;
1194
1195
if (pi->sh->up) {
1196
if (!SCAN_INPROG_PHY(pi)) {
1197
bool suspend;
1198
1199
suspend = (0 == (bcma_read32(pi->d11core,
1200
D11REGOFFS(maccontrol)) &
1201
MCTL_EN_MAC));
1202
1203
if (!suspend)
1204
wlapi_suspend_mac_and_wait(pi->sh->physhim);
1205
1206
wlc_phy_txpower_recalc_target(pi);
1207
wlc_phy_cal_txpower_recalc_sw(pi);
1208
1209
if (!suspend)
1210
wlapi_enable_mac(pi->sh->physhim);
1211
}
1212
}
1213
return 0;
1214
}
1215
1216
void
1217
wlc_phy_txpower_sromlimit(struct brcms_phy_pub *ppi, uint channel, u8 *min_pwr,
1218
u8 *max_pwr, int txp_rate_idx)
1219
{
1220
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1221
uint i;
1222
1223
*min_pwr = pi->min_txpower * BRCMS_TXPWR_DB_FACTOR;
1224
1225
if (ISNPHY(pi)) {
1226
if (txp_rate_idx < 0)
1227
txp_rate_idx = TXP_FIRST_CCK;
1228
wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr,
1229
(u8) txp_rate_idx);
1230
1231
} else if ((channel <= CH_MAX_2G_CHANNEL)) {
1232
if (txp_rate_idx < 0)
1233
txp_rate_idx = TXP_FIRST_CCK;
1234
*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
1235
} else {
1236
1237
*max_pwr = BRCMS_TXPWR_MAX;
1238
1239
if (txp_rate_idx < 0)
1240
txp_rate_idx = TXP_FIRST_OFDM;
1241
1242
for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
1243
if (channel == chan_info_all[i].chan)
1244
break;
1245
}
1246
1247
if (pi->hwtxpwr) {
1248
*max_pwr = pi->hwtxpwr[i];
1249
} else {
1250
1251
if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN))
1252
*max_pwr =
1253
pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
1254
if ((i >= FIRST_HIGH_5G_CHAN)
1255
&& (i <= LAST_HIGH_5G_CHAN))
1256
*max_pwr =
1257
pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
1258
if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN))
1259
*max_pwr =
1260
pi->tx_srom_max_rate_5g_low[txp_rate_idx];
1261
}
1262
}
1263
}
1264
1265
static s8 wlc_phy_env_measure_vbat(struct brcms_phy *pi)
1266
{
1267
if (ISLCNPHY(pi))
1268
return wlc_lcnphy_vbatsense(pi, 0);
1269
else
1270
return 0;
1271
}
1272
1273
static s8 wlc_phy_env_measure_temperature(struct brcms_phy *pi)
1274
{
1275
if (ISLCNPHY(pi))
1276
return wlc_lcnphy_tempsense_degree(pi, 0);
1277
else
1278
return 0;
1279
}
1280
1281
static void wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy *pi, u32 band)
1282
{
1283
u8 i;
1284
1285
for (i = 0; i < TXP_NUM_RATES; i++)
1286
pi->txpwr_env_limit[i] = BRCMS_TXPWR_MAX;
1287
1288
wlc_phy_env_measure_vbat(pi);
1289
wlc_phy_env_measure_temperature(pi);
1290
}
1291
1292
static s8
1293
wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
1294
u8 rate)
1295
{
1296
return 0;
1297
}
1298
1299
void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
1300
{
1301
u8 maxtxpwr, mintxpwr, rate, pactrl;
1302
uint target_chan;
1303
u8 tx_pwr_target[TXP_NUM_RATES];
1304
u8 tx_pwr_max = 0;
1305
u8 tx_pwr_min = 255;
1306
u8 tx_pwr_max_rate_ind = 0;
1307
u8 max_num_rate;
1308
u8 start_rate = 0;
1309
u16 chspec;
1310
u32 band = CHSPEC2BAND(pi->radio_chanspec);
1311
void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL;
1312
1313
chspec = pi->radio_chanspec;
1314
if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
1315
target_chan = CHSPEC_CHANNEL(chspec);
1316
else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
1317
target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec));
1318
else
1319
target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec));
1320
1321
pactrl = 0;
1322
if (ISLCNPHY(pi)) {
1323
u32 offset_mcs, i;
1324
1325
if (CHSPEC_IS40(pi->radio_chanspec)) {
1326
offset_mcs = pi->mcs40_po;
1327
for (i = TXP_FIRST_SISO_MCS_20;
1328
i <= TXP_LAST_SISO_MCS_20; i++) {
1329
pi->tx_srom_max_rate_2g[i - 8] =
1330
pi->tx_srom_max_2g -
1331
((offset_mcs & 0xf) * 2);
1332
offset_mcs >>= 4;
1333
}
1334
} else {
1335
offset_mcs = pi->mcs20_po;
1336
for (i = TXP_FIRST_SISO_MCS_20;
1337
i <= TXP_LAST_SISO_MCS_20; i++) {
1338
pi->tx_srom_max_rate_2g[i - 8] =
1339
pi->tx_srom_max_2g -
1340
((offset_mcs & 0xf) * 2);
1341
offset_mcs >>= 4;
1342
}
1343
}
1344
}
1345
1346
max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
1347
((ISLCNPHY(pi)) ?
1348
(TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
1349
1350
wlc_phy_upd_env_txpwr_rate_limits(pi, band);
1351
1352
for (rate = start_rate; rate < max_num_rate; rate++) {
1353
1354
tx_pwr_target[rate] = pi->tx_user_target[rate];
1355
1356
if (pi->user_txpwr_at_rfport)
1357
tx_pwr_target[rate] +=
1358
wlc_user_txpwr_antport_to_rfport(pi,
1359
target_chan,
1360
band,
1361
rate);
1362
1363
wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi,
1364
target_chan,
1365
&mintxpwr, &maxtxpwr, rate);
1366
1367
maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
1368
1369
maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
1370
1371
maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
1372
1373
maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
1374
1375
if (pi->txpwr_percent <= 100)
1376
maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
1377
1378
tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
1379
1380
tx_pwr_target[rate] =
1381
min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
1382
1383
if (tx_pwr_target[rate] > tx_pwr_max)
1384
tx_pwr_max_rate_ind = rate;
1385
1386
tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]);
1387
tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]);
1388
}
1389
1390
memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset));
1391
pi->tx_power_max = tx_pwr_max;
1392
pi->tx_power_min = tx_pwr_min;
1393
pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind;
1394
for (rate = 0; rate < max_num_rate; rate++) {
1395
1396
pi->tx_power_target[rate] = tx_pwr_target[rate];
1397
1398
if (!pi->hwpwrctrl || ISNPHY(pi))
1399
pi->tx_power_offset[rate] =
1400
pi->tx_power_max - pi->tx_power_target[rate];
1401
else
1402
pi->tx_power_offset[rate] =
1403
pi->tx_power_target[rate] - pi->tx_power_min;
1404
}
1405
1406
txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
1407
if (txpwr_recalc_fn)
1408
(*txpwr_recalc_fn)(pi);
1409
}
1410
1411
static void
1412
wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
1413
u16 chanspec)
1414
{
1415
u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM];
1416
u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
1417
int rate_start_index = 0, rate1, rate2, k;
1418
1419
for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0;
1420
rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++)
1421
pi->txpwr_limit[rate1] = txpwr->cck[rate2];
1422
1423
for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0;
1424
rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++)
1425
pi->txpwr_limit[rate1] = txpwr->ofdm[rate2];
1426
1427
if (ISNPHY(pi)) {
1428
1429
for (k = 0; k < 4; k++) {
1430
switch (k) {
1431
case 0:
1432
1433
txpwr_ptr1 = txpwr->mcs_20_siso;
1434
txpwr_ptr2 = txpwr->ofdm;
1435
rate_start_index = WL_TX_POWER_OFDM_FIRST;
1436
break;
1437
case 1:
1438
1439
txpwr_ptr1 = txpwr->mcs_20_cdd;
1440
txpwr_ptr2 = txpwr->ofdm_cdd;
1441
rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST;
1442
break;
1443
case 2:
1444
1445
txpwr_ptr1 = txpwr->mcs_40_siso;
1446
txpwr_ptr2 = txpwr->ofdm_40_siso;
1447
rate_start_index =
1448
WL_TX_POWER_OFDM40_SISO_FIRST;
1449
break;
1450
case 3:
1451
1452
txpwr_ptr1 = txpwr->mcs_40_cdd;
1453
txpwr_ptr2 = txpwr->ofdm_40_cdd;
1454
rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST;
1455
break;
1456
}
1457
1458
for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
1459
rate2++) {
1460
tmp_txpwr_limit[rate2] = 0;
1461
tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
1462
txpwr_ptr1[rate2];
1463
}
1464
wlc_phy_mcs_to_ofdm_powers_nphy(
1465
tmp_txpwr_limit, 0,
1466
BRCMS_NUM_RATES_OFDM -
1467
1, BRCMS_NUM_RATES_OFDM);
1468
for (rate1 = rate_start_index, rate2 = 0;
1469
rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++)
1470
pi->txpwr_limit[rate1] =
1471
min(txpwr_ptr2[rate2],
1472
tmp_txpwr_limit[rate2]);
1473
}
1474
1475
for (k = 0; k < 4; k++) {
1476
switch (k) {
1477
case 0:
1478
1479
txpwr_ptr1 = txpwr->ofdm;
1480
txpwr_ptr2 = txpwr->mcs_20_siso;
1481
rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST;
1482
break;
1483
case 1:
1484
1485
txpwr_ptr1 = txpwr->ofdm_cdd;
1486
txpwr_ptr2 = txpwr->mcs_20_cdd;
1487
rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST;
1488
break;
1489
case 2:
1490
1491
txpwr_ptr1 = txpwr->ofdm_40_siso;
1492
txpwr_ptr2 = txpwr->mcs_40_siso;
1493
rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST;
1494
break;
1495
case 3:
1496
1497
txpwr_ptr1 = txpwr->ofdm_40_cdd;
1498
txpwr_ptr2 = txpwr->mcs_40_cdd;
1499
rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
1500
break;
1501
}
1502
for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
1503
rate2++) {
1504
tmp_txpwr_limit[rate2] = 0;
1505
tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
1506
txpwr_ptr1[rate2];
1507
}
1508
wlc_phy_ofdm_to_mcs_powers_nphy(
1509
tmp_txpwr_limit, 0,
1510
BRCMS_NUM_RATES_OFDM -
1511
1, BRCMS_NUM_RATES_OFDM);
1512
for (rate1 = rate_start_index, rate2 = 0;
1513
rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
1514
rate1++, rate2++)
1515
pi->txpwr_limit[rate1] =
1516
min(txpwr_ptr2[rate2],
1517
tmp_txpwr_limit[rate2]);
1518
}
1519
1520
for (k = 0; k < 2; k++) {
1521
switch (k) {
1522
case 0:
1523
1524
rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST;
1525
txpwr_ptr1 = txpwr->mcs_20_stbc;
1526
break;
1527
case 1:
1528
1529
rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST;
1530
txpwr_ptr1 = txpwr->mcs_40_stbc;
1531
break;
1532
}
1533
for (rate1 = rate_start_index, rate2 = 0;
1534
rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
1535
rate1++, rate2++)
1536
pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
1537
}
1538
1539
for (k = 0; k < 2; k++) {
1540
switch (k) {
1541
case 0:
1542
1543
rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST;
1544
txpwr_ptr1 = txpwr->mcs_20_mimo;
1545
break;
1546
case 1:
1547
1548
rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST;
1549
txpwr_ptr1 = txpwr->mcs_40_mimo;
1550
break;
1551
}
1552
for (rate1 = rate_start_index, rate2 = 0;
1553
rate2 < BRCMS_NUM_RATES_MCS_2_STREAM;
1554
rate1++, rate2++)
1555
pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
1556
}
1557
1558
pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
1559
1560
pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
1561
min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
1562
pi->txpwr_limit[WL_TX_POWER_MCS_32]);
1563
pi->txpwr_limit[WL_TX_POWER_MCS_32] =
1564
pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
1565
}
1566
}
1567
1568
void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap)
1569
{
1570
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1571
1572
pi->sh->machwcap = machwcap;
1573
}
1574
1575
void
1576
wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr,
1577
u16 chanspec)
1578
{
1579
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1580
1581
wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec);
1582
1583
if (ISLCNPHY(pi)) {
1584
int i, j;
1585
for (i = TXP_FIRST_OFDM_20_CDD, j = 0;
1586
j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) {
1587
if (txpwr->mcs_20_siso[j])
1588
pi->txpwr_limit[i] = txpwr->mcs_20_siso[j];
1589
else
1590
pi->txpwr_limit[i] = txpwr->ofdm[j];
1591
}
1592
}
1593
1594
wlapi_suspend_mac_and_wait(pi->sh->physhim);
1595
1596
wlc_phy_txpower_recalc_target(pi);
1597
wlc_phy_cal_txpower_recalc_sw(pi);
1598
wlapi_enable_mac(pi->sh->physhim);
1599
}
1600
1601
void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war)
1602
{
1603
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
1604
1605
pi->ofdm_rateset_war = war;
1606
}
1607
1608
void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt)
1609
{
1610
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
1611
1612
pi->bf_preempt_4306 = bf_preempt;
1613
}
1614
1615
void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
1616
{
1617
int j;
1618
if (ISNPHY(pi))
1619
return;
1620
1621
if (!pi->sh->clk)
1622
return;
1623
1624
if (pi->hwpwrctrl) {
1625
u16 offset;
1626
1627
wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63);
1628
wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N,
1629
1 << NUM_TSSI_FRAMES);
1630
1631
wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET,
1632
pi->tx_power_min << NUM_TSSI_FRAMES);
1633
1634
wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR,
1635
pi->hwpwr_txcur);
1636
1637
for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
1638
static const u8 ucode_ofdm_rates[] = {
1639
0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
1640
};
1641
offset = wlapi_bmac_rate_shm_offset(
1642
pi->sh->physhim,
1643
ucode_ofdm_rates[j - TXP_FIRST_OFDM]);
1644
wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
1645
pi->tx_power_offset[j]);
1646
wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
1647
-(pi->tx_power_offset[j] / 2));
1648
}
1649
1650
wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL,
1651
MHF2_HWPWRCTL, BRCM_BAND_ALL);
1652
} else {
1653
int i;
1654
1655
for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
1656
pi->tx_power_offset[i] =
1657
(u8) roundup(pi->tx_power_offset[i], 8);
1658
wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
1659
(u16)
1660
((pi->tx_power_offset[TXP_FIRST_OFDM]
1661
+ 7) >> 3));
1662
}
1663
}
1664
1665
bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi)
1666
{
1667
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1668
1669
if (ISNPHY(pi))
1670
return pi->nphy_txpwrctrl;
1671
else
1672
return pi->hwpwrctrl;
1673
}
1674
1675
void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi)
1676
{
1677
1678
if (NREV_GE(pi->pubpi.phy_rev, 3)) {
1679
pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2);
1680
pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2);
1681
} else {
1682
pi->ipa2g_on = false;
1683
pi->ipa5g_on = false;
1684
}
1685
}
1686
1687
static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi)
1688
{
1689
s16 tx0_status, tx1_status;
1690
u16 estPower1, estPower2;
1691
u8 pwr0, pwr1, adj_pwr0, adj_pwr1;
1692
u32 est_pwr;
1693
1694
estPower1 = read_phy_reg(pi, 0x118);
1695
estPower2 = read_phy_reg(pi, 0x119);
1696
1697
if ((estPower1 & (0x1 << 8)) == (0x1 << 8))
1698
pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0;
1699
else
1700
pwr0 = 0x80;
1701
1702
if ((estPower2 & (0x1 << 8)) == (0x1 << 8))
1703
pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0;
1704
else
1705
pwr1 = 0x80;
1706
1707
tx0_status = read_phy_reg(pi, 0x1ed);
1708
tx1_status = read_phy_reg(pi, 0x1ee);
1709
1710
if ((tx0_status & (0x1 << 15)) == (0x1 << 15))
1711
adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0;
1712
else
1713
adj_pwr0 = 0x80;
1714
if ((tx1_status & (0x1 << 15)) == (0x1 << 15))
1715
adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0;
1716
else
1717
adj_pwr1 = 0x80;
1718
1719
est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) |
1720
adj_pwr1);
1721
1722
return est_pwr;
1723
}
1724
1725
void
1726
wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power,
1727
uint channel)
1728
{
1729
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1730
uint rate, num_rates;
1731
u8 min_pwr, max_pwr;
1732
1733
#if WL_TX_POWER_RATES != TXP_NUM_RATES
1734
#error "struct tx_power out of sync with this fn"
1735
#endif
1736
1737
if (ISNPHY(pi)) {
1738
power->rf_cores = 2;
1739
power->flags |= (WL_TX_POWER_F_MIMO);
1740
if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
1741
power->flags |=
1742
(WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
1743
} else if (ISLCNPHY(pi)) {
1744
power->rf_cores = 1;
1745
power->flags |= (WL_TX_POWER_F_SISO);
1746
if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF)
1747
power->flags |= WL_TX_POWER_F_ENABLED;
1748
if (pi->hwpwrctrl)
1749
power->flags |= WL_TX_POWER_F_HW;
1750
}
1751
1752
num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
1753
((ISLCNPHY(pi)) ?
1754
(TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1)));
1755
1756
for (rate = 0; rate < num_rates; rate++) {
1757
power->user_limit[rate] = pi->tx_user_target[rate];
1758
wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr,
1759
rate);
1760
power->board_limit[rate] = (u8) max_pwr;
1761
power->target[rate] = pi->tx_power_target[rate];
1762
}
1763
1764
if (ISNPHY(pi)) {
1765
u32 est_pout;
1766
1767
wlapi_suspend_mac_and_wait(pi->sh->physhim);
1768
wlc_phyreg_enter((struct brcms_phy_pub *) pi);
1769
est_pout = wlc_phy_txpower_est_power_nphy(pi);
1770
wlc_phyreg_exit((struct brcms_phy_pub *) pi);
1771
wlapi_enable_mac(pi->sh->physhim);
1772
1773
power->est_Pout[0] = (est_pout >> 8) & 0xff;
1774
power->est_Pout[1] = est_pout & 0xff;
1775
1776
power->est_Pout_act[0] = est_pout >> 24;
1777
power->est_Pout_act[1] = (est_pout >> 16) & 0xff;
1778
1779
if (power->est_Pout[0] == 0x80)
1780
power->est_Pout[0] = 0;
1781
if (power->est_Pout[1] == 0x80)
1782
power->est_Pout[1] = 0;
1783
1784
if (power->est_Pout_act[0] == 0x80)
1785
power->est_Pout_act[0] = 0;
1786
if (power->est_Pout_act[1] == 0x80)
1787
power->est_Pout_act[1] = 0;
1788
1789
power->est_Pout_cck = 0;
1790
1791
power->tx_power_max[0] = pi->tx_power_max;
1792
power->tx_power_max[1] = pi->tx_power_max;
1793
1794
power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind;
1795
power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind;
1796
} else if (pi->hwpwrctrl && pi->sh->up) {
1797
1798
wlc_phyreg_enter(ppi);
1799
if (ISLCNPHY(pi)) {
1800
1801
power->tx_power_max[0] = pi->tx_power_max;
1802
power->tx_power_max[1] = pi->tx_power_max;
1803
1804
power->tx_power_max_rate_ind[0] =
1805
pi->tx_power_max_rate_ind;
1806
power->tx_power_max_rate_ind[1] =
1807
pi->tx_power_max_rate_ind;
1808
1809
if (wlc_phy_tpc_isenabled_lcnphy(pi))
1810
power->flags |=
1811
(WL_TX_POWER_F_HW |
1812
WL_TX_POWER_F_ENABLED);
1813
else
1814
power->flags &=
1815
~(WL_TX_POWER_F_HW |
1816
WL_TX_POWER_F_ENABLED);
1817
1818
wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
1819
(s8 *) &power->est_Pout_cck);
1820
}
1821
wlc_phyreg_exit(ppi);
1822
}
1823
}
1824
1825
void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type)
1826
{
1827
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1828
1829
pi->antsel_type = antsel_type;
1830
}
1831
1832
void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val)
1833
{
1834
struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1835
bool suspend;
1836
1837
pi->sh->rx_antdiv = val;
1838
1839
if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) {
1840
if (val > ANT_RX_DIV_FORCE_1)
1841
wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV,
1842
MHF1_ANTDIV, BRCM_BAND_ALL);
1843
else
1844
wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0,
1845
BRCM_BAND_ALL);
1846
}
1847
1848
if (ISNPHY(pi))
1849
return;
1850
1851
if (!pi->sh->clk)
1852
return;
1853
1854
suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
1855
MCTL_EN_MAC));
1856
if (!suspend)
1857
wlapi_suspend_mac_and_wait(pi->sh->physhim);
1858
1859
if (ISLCNPHY(pi)) {
1860
if (val > ANT_RX_DIV_FORCE_1) {
1861
mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1);
1862
mod_phy_reg(pi, 0x410,
1863
(0x1 << 0),
1864
((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0);
1865
} else {
1866
mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1);
1867
mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0);
1868
}
1869
}
1870
1871
if (!suspend)
1872
wlapi_enable_mac(pi->sh->physhim);
1873
1874
return;
1875
}
1876
1877
static bool
1878
wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant)
1879
{
1880
s8 cmplx_pwr_dbm[PHY_CORE_MAX];
1881
u8 i;
1882
1883
memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm));
1884
wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum);
1885
1886
for (i = 0; i < pi->pubpi.phy_corenum; i++) {
1887
if (NREV_GE(pi->pubpi.phy_rev, 3))
1888
cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322;
1889
else
1890
1891
cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70);
1892
}
1893
1894
for (i = 0; i < pi->pubpi.phy_corenum; i++) {
1895
pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i];
1896
pwr_ant[i] = cmplx_pwr_dbm[i];
1897
}
1898
pi->nphy_noise_index =
1899
MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
1900
return true;
1901
}
1902
1903
static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm)
1904
{
1905
if (!pi->phynoise_state)
1906
return;
1907
1908
if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
1909
if (pi->phynoise_chan_watchdog == channel) {
1910
pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
1911
noise_dbm;
1912
pi->sh->phy_noise_index =
1913
MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
1914
}
1915
pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
1916
}
1917
1918
if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL)
1919
pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
1920
1921
}
1922
1923
static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi)
1924
{
1925
u32 cmplx_pwr[PHY_CORE_MAX];
1926
s8 noise_dbm_ant[PHY_CORE_MAX];
1927
u16 lo, hi;
1928
u32 cmplx_pwr_tot = 0;
1929
s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
1930
u8 idx, core;
1931
1932
memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
1933
memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
1934
1935
for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2,
1936
core++) {
1937
lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
1938
hi = wlapi_bmac_read_shm(pi->sh->physhim,
1939
M_PWRIND_MAP(idx + 1));
1940
cmplx_pwr[core] = (hi << 16) + lo;
1941
cmplx_pwr_tot += cmplx_pwr[core];
1942
if (cmplx_pwr[core] == 0)
1943
noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
1944
else
1945
cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
1946
}
1947
1948
if (cmplx_pwr_tot != 0)
1949
wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
1950
1951
for (core = 0; core < pi->pubpi.phy_corenum; core++) {
1952
pi->nphy_noise_win[core][pi->nphy_noise_index] =
1953
noise_dbm_ant[core];
1954
1955
if (noise_dbm_ant[core] > noise_dbm)
1956
noise_dbm = noise_dbm_ant[core];
1957
}
1958
pi->nphy_noise_index =
1959
MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
1960
1961
return noise_dbm;
1962
1963
}
1964
1965
void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih)
1966
{
1967
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
1968
u16 jssi_aux;
1969
u8 channel = 0;
1970
s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
1971
1972
if (ISLCNPHY(pi)) {
1973
u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
1974
u16 lo, hi;
1975
s32 pwr_offset_dB, gain_dB;
1976
u16 status_0, status_1;
1977
1978
jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
1979
channel = jssi_aux & D11_CURCHANNEL_MAX;
1980
1981
lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
1982
hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
1983
cmplx_pwr0 = (hi << 16) + lo;
1984
1985
lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
1986
hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
1987
cmplx_pwr1 = (hi << 16) + lo;
1988
cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
1989
1990
status_0 = 0x44;
1991
status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
1992
if ((cmplx_pwr > 0 && cmplx_pwr < 500)
1993
&& ((status_1 & 0xc000) == 0x4000)) {
1994
1995
wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
1996
pi->pubpi.phy_corenum);
1997
pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
1998
if (pwr_offset_dB > 127)
1999
pwr_offset_dB -= 256;
2000
2001
noise_dbm += (s8) (pwr_offset_dB - 30);
2002
2003
gain_dB = (status_0 & 0x1ff);
2004
noise_dbm -= (s8) (gain_dB);
2005
} else {
2006
noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
2007
}
2008
} else if (ISNPHY(pi)) {
2009
2010
jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
2011
channel = jssi_aux & D11_CURCHANNEL_MAX;
2012
2013
noise_dbm = wlc_phy_noise_read_shmem(pi);
2014
}
2015
2016
wlc_phy_noise_cb(pi, channel, noise_dbm);
2017
2018
}
2019
2020
static void
2021
wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
2022
{
2023
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2024
s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2025
bool sampling_in_progress = (pi->phynoise_state != 0);
2026
bool wait_for_intr = true;
2027
2028
switch (reason) {
2029
case PHY_NOISE_SAMPLE_MON:
2030
pi->phynoise_chan_watchdog = ch;
2031
pi->phynoise_state |= PHY_NOISE_STATE_MON;
2032
break;
2033
2034
case PHY_NOISE_SAMPLE_EXTERNAL:
2035
pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
2036
break;
2037
2038
default:
2039
break;
2040
}
2041
2042
if (sampling_in_progress)
2043
return;
2044
2045
pi->phynoise_now = pi->sh->now;
2046
2047
if (pi->phy_fixed_noise) {
2048
if (ISNPHY(pi)) {
2049
pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
2050
PHY_NOISE_FIXED_VAL_NPHY;
2051
pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
2052
PHY_NOISE_FIXED_VAL_NPHY;
2053
pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
2054
PHY_NOISE_WINDOW_SZ);
2055
noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2056
} else {
2057
noise_dbm = PHY_NOISE_FIXED_VAL;
2058
}
2059
2060
wait_for_intr = false;
2061
goto done;
2062
}
2063
2064
if (ISLCNPHY(pi)) {
2065
if (!pi->phynoise_polling
2066
|| (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
2067
wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0);
2068
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
2069
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
2070
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
2071
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
2072
2073
bcma_set32(pi->d11core, D11REGOFFS(maccommand),
2074
MCMD_BG_NOISE);
2075
} else {
2076
wlapi_suspend_mac_and_wait(pi->sh->physhim);
2077
wlc_lcnphy_deaf_mode(pi, (bool) 0);
2078
noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20);
2079
wlc_lcnphy_deaf_mode(pi, (bool) 1);
2080
wlapi_enable_mac(pi->sh->physhim);
2081
wait_for_intr = false;
2082
}
2083
} else if (ISNPHY(pi)) {
2084
if (!pi->phynoise_polling
2085
|| (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
2086
2087
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
2088
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
2089
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
2090
wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
2091
2092
bcma_set32(pi->d11core, D11REGOFFS(maccommand),
2093
MCMD_BG_NOISE);
2094
} else {
2095
struct phy_iq_est est[PHY_CORE_MAX];
2096
u32 cmplx_pwr[PHY_CORE_MAX];
2097
s8 noise_dbm_ant[PHY_CORE_MAX];
2098
u16 log_num_samps, num_samps, classif_state = 0;
2099
u8 wait_time = 32;
2100
u8 wait_crs = 0;
2101
u8 i;
2102
2103
memset((u8 *) est, 0, sizeof(est));
2104
memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
2105
memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
2106
2107
log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
2108
num_samps = 1 << log_num_samps;
2109
2110
wlapi_suspend_mac_and_wait(pi->sh->physhim);
2111
classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
2112
wlc_phy_classifier_nphy(pi, 3, 0);
2113
wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time,
2114
wait_crs);
2115
wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
2116
wlapi_enable_mac(pi->sh->physhim);
2117
2118
for (i = 0; i < pi->pubpi.phy_corenum; i++)
2119
cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >>
2120
log_num_samps;
2121
2122
wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
2123
2124
for (i = 0; i < pi->pubpi.phy_corenum; i++) {
2125
pi->nphy_noise_win[i][pi->nphy_noise_index] =
2126
noise_dbm_ant[i];
2127
2128
if (noise_dbm_ant[i] > noise_dbm)
2129
noise_dbm = noise_dbm_ant[i];
2130
}
2131
pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
2132
PHY_NOISE_WINDOW_SZ);
2133
2134
wait_for_intr = false;
2135
}
2136
}
2137
2138
done:
2139
2140
if (!wait_for_intr)
2141
wlc_phy_noise_cb(pi, ch, noise_dbm);
2142
2143
}
2144
2145
static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
2146
8,
2147
8,
2148
8,
2149
8,
2150
8,
2151
8,
2152
8,
2153
9,
2154
10,
2155
8,
2156
8,
2157
7,
2158
7,
2159
1,
2160
2,
2161
2,
2162
2,
2163
2,
2164
2,
2165
2,
2166
2,
2167
2,
2168
2,
2169
2,
2170
2,
2171
2,
2172
2,
2173
2,
2174
2,
2175
2,
2176
2,
2177
2,
2178
1,
2179
1,
2180
0,
2181
0,
2182
0,
2183
0
2184
};
2185
2186
void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
2187
{
2188
u8 msb, secondmsb, i;
2189
u32 tmp;
2190
2191
for (i = 0; i < core; i++) {
2192
secondmsb = 0;
2193
tmp = cmplx_pwr[i];
2194
msb = fls(tmp);
2195
if (msb)
2196
secondmsb = (u8) ((tmp >> (--msb - 1)) & 1);
2197
p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb);
2198
}
2199
}
2200
2201
int wlc_phy_rssi_compute(struct brcms_phy_pub *pih,
2202
struct d11rxhdr *rxh)
2203
{
2204
int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK;
2205
uint radioid = pih->radioid;
2206
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2207
2208
if ((pi->sh->corerev >= 11)
2209
&& !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) {
2210
rssi = BRCMS_RSSI_INVALID;
2211
goto end;
2212
}
2213
2214
if (ISLCNPHY(pi)) {
2215
u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10;
2216
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2217
2218
if (rssi > 127)
2219
rssi -= 256;
2220
2221
rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx];
2222
if ((rssi > -46) && (gidx > 18))
2223
rssi = rssi + 7;
2224
2225
rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope;
2226
2227
rssi = rssi + 2;
2228
2229
}
2230
2231
if (ISLCNPHY(pi)) {
2232
if (rssi > 127)
2233
rssi -= 256;
2234
} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
2235
|| radioid == BCM2057_ID) {
2236
rssi = wlc_phy_rssi_compute_nphy(pi, rxh);
2237
}
2238
2239
end:
2240
return rssi;
2241
}
2242
2243
void wlc_phy_watchdog(struct brcms_phy_pub *pih)
2244
{
2245
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2246
bool delay_phy_cal = false;
2247
pi->sh->now++;
2248
2249
if (!pi->watchdog_override)
2250
return;
2251
2252
if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)))
2253
wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi,
2254
PHY_NOISE_SAMPLE_MON,
2255
CHSPEC_CHANNEL(pi->
2256
radio_chanspec));
2257
2258
if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5)
2259
pi->phynoise_state = 0;
2260
2261
if ((!pi->phycal_txpower) ||
2262
((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
2263
2264
if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi))
2265
pi->phycal_txpower = pi->sh->now;
2266
}
2267
2268
if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
2269
|| ASSOC_INPROG_PHY(pi)))
2270
return;
2271
2272
if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) {
2273
2274
if ((pi->nphy_perical != PHY_PERICAL_DISABLE) &&
2275
(pi->nphy_perical != PHY_PERICAL_MANUAL) &&
2276
((pi->sh->now - pi->nphy_perical_last) >=
2277
pi->sh->glacial_timer))
2278
wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
2279
PHY_PERICAL_WATCHDOG);
2280
2281
wlc_phy_txpwr_papd_cal_nphy(pi);
2282
}
2283
2284
if (ISLCNPHY(pi)) {
2285
if (pi->phy_forcecal ||
2286
((pi->sh->now - pi->phy_lastcal) >=
2287
pi->sh->glacial_timer)) {
2288
if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
2289
wlc_lcnphy_calib_modes(
2290
pi,
2291
LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
2292
if (!
2293
(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
2294
|| ASSOC_INPROG_PHY(pi)
2295
|| pi->carrier_suppr_disable
2296
|| pi->disable_percal))
2297
wlc_lcnphy_calib_modes(pi,
2298
PHY_PERICAL_WATCHDOG);
2299
}
2300
}
2301
}
2302
2303
void
2304
wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
2305
{
2306
*eps_imag = (epsilon >> 13);
2307
if (*eps_imag > 0xfff)
2308
*eps_imag -= 0x2000;
2309
2310
*eps_real = (epsilon & 0x1fff);
2311
if (*eps_real > 0xfff)
2312
*eps_real -= 0x2000;
2313
}
2314
2315
void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi)
2316
{
2317
wlapi_del_timer(pi->phycal_timer);
2318
2319
pi->cal_type_override = PHY_PERICAL_AUTO;
2320
pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
2321
pi->mphase_txcal_cmdidx = 0;
2322
}
2323
2324
static void
2325
wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay)
2326
{
2327
2328
if ((pi->nphy_perical != PHY_PERICAL_MPHASE) &&
2329
(pi->nphy_perical != PHY_PERICAL_MANUAL))
2330
return;
2331
2332
wlapi_del_timer(pi->phycal_timer);
2333
2334
pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
2335
wlapi_add_timer(pi->phycal_timer, delay, 0);
2336
}
2337
2338
void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
2339
{
2340
s16 nphy_currtemp = 0;
2341
s16 delta_temp = 0;
2342
bool do_periodic_cal = true;
2343
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2344
2345
if (!ISNPHY(pi))
2346
return;
2347
2348
if ((pi->nphy_perical == PHY_PERICAL_DISABLE) ||
2349
(pi->nphy_perical == PHY_PERICAL_MANUAL))
2350
return;
2351
2352
switch (reason) {
2353
case PHY_PERICAL_DRIVERUP:
2354
break;
2355
2356
case PHY_PERICAL_PHYINIT:
2357
if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
2358
if (PHY_PERICAL_MPHASE_PENDING(pi))
2359
wlc_phy_cal_perical_mphase_reset(pi);
2360
2361
wlc_phy_cal_perical_mphase_schedule(
2362
pi,
2363
PHY_PERICAL_INIT_DELAY);
2364
}
2365
break;
2366
2367
case PHY_PERICAL_JOIN_BSS:
2368
case PHY_PERICAL_START_IBSS:
2369
case PHY_PERICAL_UP_BSS:
2370
if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
2371
PHY_PERICAL_MPHASE_PENDING(pi))
2372
wlc_phy_cal_perical_mphase_reset(pi);
2373
2374
pi->first_cal_after_assoc = true;
2375
2376
pi->cal_type_override = PHY_PERICAL_FULL;
2377
2378
if (pi->phycal_tempdelta)
2379
pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
2380
2381
wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
2382
break;
2383
2384
case PHY_PERICAL_WATCHDOG:
2385
if (pi->phycal_tempdelta) {
2386
nphy_currtemp = wlc_phy_tempsense_nphy(pi);
2387
delta_temp =
2388
(nphy_currtemp > pi->nphy_lastcal_temp) ?
2389
nphy_currtemp - pi->nphy_lastcal_temp :
2390
pi->nphy_lastcal_temp - nphy_currtemp;
2391
2392
if ((delta_temp < (s16) pi->phycal_tempdelta) &&
2393
(pi->nphy_txiqlocal_chanspec ==
2394
pi->radio_chanspec))
2395
do_periodic_cal = false;
2396
else
2397
pi->nphy_lastcal_temp = nphy_currtemp;
2398
}
2399
2400
if (do_periodic_cal) {
2401
if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
2402
if (!PHY_PERICAL_MPHASE_PENDING(pi))
2403
wlc_phy_cal_perical_mphase_schedule(
2404
pi,
2405
PHY_PERICAL_WDOG_DELAY);
2406
} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
2407
wlc_phy_cal_perical_nphy_run(pi,
2408
PHY_PERICAL_AUTO);
2409
}
2410
break;
2411
default:
2412
break;
2413
}
2414
}
2415
2416
void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi)
2417
{
2418
pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
2419
pi->mphase_txcal_cmdidx = 0;
2420
}
2421
2422
u8 wlc_phy_nbits(s32 value)
2423
{
2424
s32 abs_val;
2425
u8 nbits = 0;
2426
2427
abs_val = abs(value);
2428
while ((abs_val >> nbits) > 0)
2429
nbits++;
2430
2431
return nbits;
2432
}
2433
2434
void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
2435
{
2436
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2437
2438
pi->sh->hw_phytxchain = txchain;
2439
pi->sh->hw_phyrxchain = rxchain;
2440
pi->sh->phytxchain = txchain;
2441
pi->sh->phyrxchain = rxchain;
2442
pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
2443
}
2444
2445
void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
2446
{
2447
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2448
2449
pi->sh->phytxchain = txchain;
2450
2451
if (ISNPHY(pi))
2452
wlc_phy_rxcore_setstate_nphy(pih, rxchain);
2453
2454
pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
2455
}
2456
2457
u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih)
2458
{
2459
s16 nphy_currtemp;
2460
u8 active_bitmap;
2461
struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2462
2463
active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33;
2464
2465
if (!pi->watchdog_override)
2466
return active_bitmap;
2467
2468
if (NREV_GE(pi->pubpi.phy_rev, 6)) {
2469
wlapi_suspend_mac_and_wait(pi->sh->physhim);
2470
nphy_currtemp = wlc_phy_tempsense_nphy(pi);
2471
wlapi_enable_mac(pi->sh->physhim);
2472
2473
if (!pi->phy_txcore_heatedup) {
2474
if (nphy_currtemp >= pi->phy_txcore_disable_temp) {
2475
active_bitmap &= 0xFD;
2476
pi->phy_txcore_heatedup = true;
2477
}
2478
} else {
2479
if (nphy_currtemp <= pi->phy_txcore_enable_temp) {
2480
active_bitmap |= 0x2;
2481
pi->phy_txcore_heatedup = false;
2482
}
2483
}
2484
}
2485
2486
return active_bitmap;
2487
}
2488
2489
const u8 *wlc_phy_get_ofdm_rate_lookup(void)
2490
{
2491
return ofdm_rate_lookup;
2492
}
2493
2494
void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc)
2495
{
2496
return;
2497
}
2498
2499