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