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