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