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