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
wlc_phyreg_enter(struct brcms_phy_pub * pih)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
wlc_phyreg_exit(struct brcms_phy_pub * pih)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
read_radio_reg(struct brcms_phy * pi,u16 addr)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
write_radio_reg(struct brcms_phy * pi,u16 addr,u16 val)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
read_radio_id(struct brcms_phy * pi)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
and_radio_reg(struct brcms_phy * pi,u16 addr,u16 val)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
or_radio_reg(struct brcms_phy * pi,u16 addr,u16 val)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
xor_radio_reg(struct brcms_phy * pi,u16 addr,u16 mask)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
mod_radio_reg(struct brcms_phy * pi,u16 addr,u16 mask,u16 val)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
read_phy_reg(struct brcms_phy * pi,u16 addr)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
write_phy_reg(struct brcms_phy * pi,u16 addr,u16 val)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
and_phy_reg(struct brcms_phy * pi,u16 addr,u16 val)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
or_phy_reg(struct brcms_phy * pi,u16 addr,u16 val)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
mod_phy_reg(struct brcms_phy * pi,u16 addr,u16 mask,u16 val)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
wlc_set_phy_uninitted(struct brcms_phy * pi)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
wlc_phy_shared_attach(struct shared_phy_params * shp)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
wlc_phy_timercb_phycal(void * ptr)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
wlc_phy_get_radio_ver(struct brcms_phy * pi)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 *
wlc_phy_attach(struct shared_phy * sh,struct bcma_device * d11core,int bandtype,struct wiphy * wiphy)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
wlc_phy_detach(struct brcms_phy_pub * pih)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
wlc_phy_get_phyversion(struct brcms_phy_pub * pih,u16 * phytype,u16 * phyrev,u16 * radioid,u16 * radiover)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
wlc_phy_get_encore(struct brcms_phy_pub * pih)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
wlc_phy_get_coreflags(struct brcms_phy_pub * pih)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
wlc_phy_anacore(struct brcms_phy_pub * pih,bool on)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
wlc_phy_clk_bwbits(struct brcms_phy_pub * pih)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
wlc_phy_por_inform(struct brcms_phy_pub * ppi)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
wlc_phy_initcal_enable(struct brcms_phy_pub * pih,bool initcal)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
wlc_phy_hw_clk_state_upd(struct brcms_phy_pub * pih,bool newstate)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
wlc_phy_hw_state_upd(struct brcms_phy_pub * pih,bool newstate)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
wlc_phy_init(struct brcms_phy_pub * pih,u16 chanspec)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
wlc_phy_cal_init(struct brcms_phy_pub * pih)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
wlc_phy_down(struct brcms_phy_pub * pih)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
wlc_phy_table_addr(struct brcms_phy * pi,uint tbl_id,uint tbl_offset,u16 tblAddr,u16 tblDataHi,u16 tblDataLo)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
wlc_phy_table_data_write(struct brcms_phy * pi,uint width,u32 val)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
wlc_phy_write_table(struct brcms_phy * pi,const struct phytbl_info * ptbl_info,u16 tblAddr,u16 tblDataHi,u16 tblDataLo)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
wlc_phy_read_table(struct brcms_phy * pi,const struct phytbl_info * ptbl_info,u16 tblAddr,u16 tblDataHi,u16 tblDataLo)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
wlc_phy_init_radio_regs_allbands(struct brcms_phy * pi,struct radio_20xx_regs * radioregs)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
wlc_phy_init_radio_regs(struct brcms_phy * pi,const struct radio_regs * radioregs,u16 core_offset)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
wlc_phy_do_dummy_tx(struct brcms_phy * pi,bool ofdm,bool pa_on)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
wlc_phy_hold_upd(struct brcms_phy_pub * pih,u32 id,bool set)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
wlc_phy_mute_upd(struct brcms_phy_pub * pih,bool mute,u32 flags)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
wlc_phy_cal_txpower_recalc_sw(struct brcms_phy * pi)1052 static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
1053 {
1054 return false;
1055 }
1056
wlc_phy_switch_radio(struct brcms_phy_pub * pih,bool on)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
wlc_phy_bw_state_set(struct brcms_phy_pub * ppi,u16 bw)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
wlc_phy_chanspec_radio_set(struct brcms_phy_pub * ppi,u16 newch)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
wlc_phy_chanspec_get(struct brcms_phy_pub * ppi)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
wlc_phy_chanspec_set(struct brcms_phy_pub * ppi,u16 chanspec)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
wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub * ppi,bool wide_filter)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
wlc_phy_channel2freq(uint channel)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
wlc_phy_chanspec_band_validch(struct brcms_phy_pub * ppi,uint band,struct brcms_chanvec * channels)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
wlc_phy_txpower_get(struct brcms_phy_pub * ppi,uint * qdbm,bool * override)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
wlc_phy_txpower_set(struct brcms_phy_pub * ppi,uint qdbm,bool override)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
wlc_phy_txpower_sromlimit(struct brcms_phy_pub * ppi,uint channel,u8 * min_pwr,u8 * max_pwr,int txp_rate_idx)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
wlc_phy_env_measure_vbat(struct brcms_phy * pi)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
wlc_phy_env_measure_temperature(struct brcms_phy * pi)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
wlc_phy_upd_env_txpwr_rate_limits(struct brcms_phy * pi,u32 band)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
wlc_user_txpwr_antport_to_rfport(struct brcms_phy * pi,uint chan,u32 band,u8 rate)1293 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
1294 u8 rate)
1295 {
1296 return 0;
1297 }
1298
wlc_phy_txpower_recalc_target(struct brcms_phy * pi)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
wlc_phy_txpower_reg_limit_calc(struct brcms_phy * pi,struct txpwr_limits * txpwr,u16 chanspec)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
wlc_phy_machwcap_set(struct brcms_phy_pub * ppi,u32 machwcap)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
wlc_phy_txpower_limit_set(struct brcms_phy_pub * ppi,struct txpwr_limits * txpwr,u16 chanspec)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
wlc_phy_ofdm_rateset_war(struct brcms_phy_pub * pih,bool war)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
wlc_phy_bf_preempt_enable(struct brcms_phy_pub * pih,bool bf_preempt)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
wlc_phy_txpower_update_shm(struct brcms_phy * pi)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
wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub * ppi)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
wlc_phy_txpower_ipa_upd(struct brcms_phy * pi)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
wlc_phy_txpower_est_power_nphy(struct brcms_phy * pi)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
wlc_phy_txpower_get_current(struct brcms_phy_pub * ppi,struct tx_power * power,uint channel)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
wlc_phy_antsel_type_set(struct brcms_phy_pub * ppi,u8 antsel_type)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
wlc_phy_ant_rxdiv_set(struct brcms_phy_pub * ppi,u8 val)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
wlc_phy_noise_calc_phy(struct brcms_phy * pi,u32 * cmplx_pwr,s8 * pwr_ant)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
wlc_phy_noise_cb(struct brcms_phy * pi,u8 channel,s8 noise_dbm)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
wlc_phy_noise_read_shmem(struct brcms_phy * pi)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
wlc_phy_noise_sample_intr(struct brcms_phy_pub * pih)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
wlc_phy_noise_sample_request(struct brcms_phy_pub * pih,u8 reason,u8 ch)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
wlc_phy_compute_dB(u32 * cmplx_pwr,s8 * p_cmplx_pwr_dB,u8 core)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
wlc_phy_rssi_compute(struct brcms_phy_pub * pih,struct d11rxhdr * rxh)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
wlc_phy_watchdog(struct brcms_phy_pub * pih)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
wlc_phy_papd_decode_epsilon(u32 epsilon,s32 * eps_real,s32 * eps_imag)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
wlc_phy_cal_perical_mphase_reset(struct brcms_phy * pi)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
wlc_phy_cal_perical_mphase_schedule(struct brcms_phy * pi,uint delay)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
wlc_phy_cal_perical(struct brcms_phy_pub * pih,u8 reason)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
wlc_phy_cal_perical_mphase_restart(struct brcms_phy * pi)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
wlc_phy_nbits(s32 value)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
wlc_phy_stf_chain_init(struct brcms_phy_pub * pih,u8 txchain,u8 rxchain)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
wlc_phy_stf_chain_set(struct brcms_phy_pub * pih,u8 txchain,u8 rxchain)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
wlc_phy_stf_chain_active_get(struct brcms_phy_pub * pih)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
wlc_phy_get_ofdm_rate_lookup(void)2489 const u8 *wlc_phy_get_ofdm_rate_lookup(void)
2490 {
2491 return ofdm_rate_lookup;
2492 }
2493
wlc_phy_ldpc_override_set(struct brcms_phy_pub * ppi,bool ldpc)2494 void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc)
2495 {
2496 return;
2497 }
2498