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