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