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