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