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