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 
129 void wlc_phyreg_enter(struct brcms_phy_pub *pih)
130 {
131 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
132 	wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim);
133 }
134 
135 void wlc_phyreg_exit(struct brcms_phy_pub *pih)
136 {
137 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
138 	wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim);
139 }
140 
141 void wlc_radioreg_enter(struct brcms_phy_pub *pih)
142 {
143 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
144 	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO);
145 
146 	udelay(10);
147 }
148 
149 void wlc_radioreg_exit(struct brcms_phy_pub *pih)
150 {
151 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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 
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 
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 
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 
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 
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 
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 
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 
277 void write_phy_channel_reg(struct brcms_phy *pi, uint val)
278 {
279 	bcma_write16(pi->d11core, D11REGOFFS(phychannel), val);
280 }
281 
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 
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 
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 
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 
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 
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 
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 
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 
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 *
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 
587 void wlc_phy_detach(struct brcms_phy_pub *pih)
588 {
589 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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
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 = container_of(pih, struct brcms_phy, pubpi_ro);
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 
625 bool wlc_phy_get_encore(struct brcms_phy_pub *pih)
626 {
627 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
628 	return pi->pubpi.abgphy_encore;
629 }
630 
631 u32 wlc_phy_get_coreflags(struct brcms_phy_pub *pih)
632 {
633 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
634 	return pi->pubpi.coreflags;
635 }
636 
637 void wlc_phy_anacore(struct brcms_phy_pub *pih, bool on)
638 {
639 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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 
674 u32 wlc_phy_clk_bwbits(struct brcms_phy_pub *pih)
675 {
676 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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 
699 void wlc_phy_por_inform(struct brcms_phy_pub *ppi)
700 {
701 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
702 
703 	pi->phy_init_por = true;
704 }
705 
706 void wlc_phy_edcrs_lock(struct brcms_phy_pub *pih, bool lock)
707 {
708 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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 
718 void wlc_phy_initcal_enable(struct brcms_phy_pub *pih, bool initcal)
719 {
720 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
721 
722 	pi->do_initcal = initcal;
723 }
724 
725 void wlc_phy_hw_clk_state_upd(struct brcms_phy_pub *pih, bool newstate)
726 {
727 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
728 
729 	if (!pi || !pi->sh)
730 		return;
731 
732 	pi->sh->clk = newstate;
733 }
734 
735 void wlc_phy_hw_state_upd(struct brcms_phy_pub *pih, bool newstate)
736 {
737 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
738 
739 	if (!pi || !pi->sh)
740 		return;
741 
742 	pi->sh->up = newstate;
743 }
744 
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 = container_of(pih, struct brcms_phy, pubpi_ro);
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 
799 void wlc_phy_cal_init(struct brcms_phy_pub *pih)
800 {
801 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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 
817 int wlc_phy_down(struct brcms_phy_pub *pih)
818 {
819 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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
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 
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
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
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
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
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 
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 
1071 void wlc_phy_hold_upd(struct brcms_phy_pub *pih, u32 id, bool set)
1072 {
1073 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
1074 
1075 	if (set)
1076 		mboolset(pi->measure_hold, id);
1077 	else
1078 		mboolclr(pi->measure_hold, id);
1079 
1080 	return;
1081 }
1082 
1083 void wlc_phy_mute_upd(struct brcms_phy_pub *pih, bool mute, u32 flags)
1084 {
1085 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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 
1097 void wlc_phy_clear_tssi(struct brcms_phy_pub *pih)
1098 {
1099 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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 
1111 static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
1112 {
1113 	return false;
1114 }
1115 
1116 void wlc_phy_switch_radio(struct brcms_phy_pub *pih, bool on)
1117 {
1118 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
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 
1150 u16 wlc_phy_bw_state_get(struct brcms_phy_pub *ppi)
1151 {
1152 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1153 
1154 	return pi->bw;
1155 }
1156 
1157 void wlc_phy_bw_state_set(struct brcms_phy_pub *ppi, u16 bw)
1158 {
1159 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1160 
1161 	pi->bw = bw;
1162 }
1163 
1164 void wlc_phy_chanspec_radio_set(struct brcms_phy_pub *ppi, u16 newch)
1165 {
1166 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1167 	pi->radio_chanspec = newch;
1168 
1169 }
1170 
1171 u16 wlc_phy_chanspec_get(struct brcms_phy_pub *ppi)
1172 {
1173 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1174 
1175 	return pi->radio_chanspec;
1176 }
1177 
1178 void wlc_phy_chanspec_set(struct brcms_phy_pub *ppi, u16 chanspec)
1179 {
1180 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
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 
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 
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 
1226 void wlc_phy_chanspec_ch14_widefilter_set(struct brcms_phy_pub *ppi,
1227 					  bool wide_filter)
1228 {
1229 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1230 
1231 	pi->channel_14_wide_filter = wide_filter;
1232 
1233 }
1234 
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
1246 wlc_phy_chanspec_band_validch(struct brcms_phy_pub *ppi, uint band,
1247 			      struct brcms_chanvec *channels)
1248 {
1249 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
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 
1268 u16 wlc_phy_chanspec_band_firstch(struct brcms_phy_pub *ppi, uint band)
1269 {
1270 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
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 
1312 int wlc_phy_txpower_get(struct brcms_phy_pub *ppi, uint *qdbm, bool *override)
1313 {
1314 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1315 
1316 	*qdbm = pi->tx_user_target[0];
1317 	if (override != NULL)
1318 		*override = pi->txpwroverride;
1319 	return 0;
1320 }
1321 
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 = container_of(ppi, struct brcms_phy, pubpi_ro);
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 
1372 int wlc_phy_txpower_set(struct brcms_phy_pub *ppi, uint qdbm, bool override)
1373 {
1374 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
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
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 = container_of(ppi, struct brcms_phy, pubpi_ro);
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
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 = container_of(ppi, struct brcms_phy, pubpi_ro);
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
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 
1494 u8 wlc_phy_txpower_get_target_min(struct brcms_phy_pub *ppi)
1495 {
1496 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1497 
1498 	return pi->tx_power_min;
1499 }
1500 
1501 u8 wlc_phy_txpower_get_target_max(struct brcms_phy_pub *ppi)
1502 {
1503 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1504 
1505 	return pi->tx_power_max;
1506 }
1507 
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 
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 
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
1538 wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
1539 				 u8 rate)
1540 {
1541 	return 0;
1542 }
1543 
1544 void wlc_phy_txpower_recalc_target(struct brcms_phy *pi)
1545 {
1546 	u8 maxtxpwr, mintxpwr, rate, pactrl;
1547 	uint target_chan;
1548 	u8 tx_pwr_target[TXP_NUM_RATES];
1549 	u8 tx_pwr_max = 0;
1550 	u8 tx_pwr_min = 255;
1551 	u8 tx_pwr_max_rate_ind = 0;
1552 	u8 max_num_rate;
1553 	u8 start_rate = 0;
1554 	u16 chspec;
1555 	u32 band = CHSPEC2BAND(pi->radio_chanspec);
1556 	void (*txpwr_recalc_fn)(struct brcms_phy *) = NULL;
1557 
1558 	chspec = pi->radio_chanspec;
1559 	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
1560 		target_chan = CHSPEC_CHANNEL(chspec);
1561 	else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
1562 		target_chan = upper_20_sb(CHSPEC_CHANNEL(chspec));
1563 	else
1564 		target_chan = lower_20_sb(CHSPEC_CHANNEL(chspec));
1565 
1566 	pactrl = 0;
1567 	if (ISLCNPHY(pi)) {
1568 		u32 offset_mcs, i;
1569 
1570 		if (CHSPEC_IS40(pi->radio_chanspec)) {
1571 			offset_mcs = pi->mcs40_po;
1572 			for (i = TXP_FIRST_SISO_MCS_20;
1573 			     i <= TXP_LAST_SISO_MCS_20; i++) {
1574 				pi->tx_srom_max_rate_2g[i - 8] =
1575 					pi->tx_srom_max_2g -
1576 					((offset_mcs & 0xf) * 2);
1577 				offset_mcs >>= 4;
1578 			}
1579 		} else {
1580 			offset_mcs = pi->mcs20_po;
1581 			for (i = TXP_FIRST_SISO_MCS_20;
1582 			     i <= TXP_LAST_SISO_MCS_20; i++) {
1583 				pi->tx_srom_max_rate_2g[i - 8] =
1584 					pi->tx_srom_max_2g -
1585 					((offset_mcs & 0xf) * 2);
1586 				offset_mcs >>= 4;
1587 			}
1588 		}
1589 	}
1590 
1591 	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
1592 			((ISLCNPHY(pi)) ?
1593 			 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
1594 
1595 	wlc_phy_upd_env_txpwr_rate_limits(pi, band);
1596 
1597 	for (rate = start_rate; rate < max_num_rate; rate++) {
1598 
1599 		tx_pwr_target[rate] = pi->tx_user_target[rate];
1600 
1601 		if (pi->user_txpwr_at_rfport)
1602 			tx_pwr_target[rate] +=
1603 				wlc_user_txpwr_antport_to_rfport(pi,
1604 								 target_chan,
1605 								 band,
1606 								 rate);
1607 
1608 		wlc_phy_txpower_sromlimit((struct brcms_phy_pub *) pi,
1609 					  target_chan,
1610 					  &mintxpwr, &maxtxpwr, rate);
1611 
1612 		maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
1613 
1614 		maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
1615 
1616 		maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
1617 
1618 		maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
1619 
1620 		if (pi->txpwr_percent <= 100)
1621 			maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
1622 
1623 		tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
1624 
1625 		tx_pwr_target[rate] =
1626 			min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
1627 
1628 		if (tx_pwr_target[rate] > tx_pwr_max)
1629 			tx_pwr_max_rate_ind = rate;
1630 
1631 		tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]);
1632 		tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]);
1633 	}
1634 
1635 	memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset));
1636 	pi->tx_power_max = tx_pwr_max;
1637 	pi->tx_power_min = tx_pwr_min;
1638 	pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind;
1639 	for (rate = 0; rate < max_num_rate; rate++) {
1640 
1641 		pi->tx_power_target[rate] = tx_pwr_target[rate];
1642 
1643 		if (!pi->hwpwrctrl || ISNPHY(pi))
1644 			pi->tx_power_offset[rate] =
1645 				pi->tx_power_max - pi->tx_power_target[rate];
1646 		else
1647 			pi->tx_power_offset[rate] =
1648 				pi->tx_power_target[rate] - pi->tx_power_min;
1649 	}
1650 
1651 	txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
1652 	if (txpwr_recalc_fn)
1653 		(*txpwr_recalc_fn)(pi);
1654 }
1655 
1656 static void
1657 wlc_phy_txpower_reg_limit_calc(struct brcms_phy *pi, struct txpwr_limits *txpwr,
1658 			       u16 chanspec)
1659 {
1660 	u8 tmp_txpwr_limit[2 * BRCMS_NUM_RATES_OFDM];
1661 	u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
1662 	int rate_start_index = 0, rate1, rate2, k;
1663 
1664 	for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0;
1665 	     rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++)
1666 		pi->txpwr_limit[rate1] = txpwr->cck[rate2];
1667 
1668 	for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0;
1669 	     rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++)
1670 		pi->txpwr_limit[rate1] = txpwr->ofdm[rate2];
1671 
1672 	if (ISNPHY(pi)) {
1673 
1674 		for (k = 0; k < 4; k++) {
1675 			switch (k) {
1676 			case 0:
1677 
1678 				txpwr_ptr1 = txpwr->mcs_20_siso;
1679 				txpwr_ptr2 = txpwr->ofdm;
1680 				rate_start_index = WL_TX_POWER_OFDM_FIRST;
1681 				break;
1682 			case 1:
1683 
1684 				txpwr_ptr1 = txpwr->mcs_20_cdd;
1685 				txpwr_ptr2 = txpwr->ofdm_cdd;
1686 				rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST;
1687 				break;
1688 			case 2:
1689 
1690 				txpwr_ptr1 = txpwr->mcs_40_siso;
1691 				txpwr_ptr2 = txpwr->ofdm_40_siso;
1692 				rate_start_index =
1693 					WL_TX_POWER_OFDM40_SISO_FIRST;
1694 				break;
1695 			case 3:
1696 
1697 				txpwr_ptr1 = txpwr->mcs_40_cdd;
1698 				txpwr_ptr2 = txpwr->ofdm_40_cdd;
1699 				rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST;
1700 				break;
1701 			}
1702 
1703 			for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
1704 			     rate2++) {
1705 				tmp_txpwr_limit[rate2] = 0;
1706 				tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
1707 					txpwr_ptr1[rate2];
1708 			}
1709 			wlc_phy_mcs_to_ofdm_powers_nphy(
1710 				tmp_txpwr_limit, 0,
1711 				BRCMS_NUM_RATES_OFDM -
1712 				1, BRCMS_NUM_RATES_OFDM);
1713 			for (rate1 = rate_start_index, rate2 = 0;
1714 			     rate2 < BRCMS_NUM_RATES_OFDM; rate1++, rate2++)
1715 				pi->txpwr_limit[rate1] =
1716 					min(txpwr_ptr2[rate2],
1717 					    tmp_txpwr_limit[rate2]);
1718 		}
1719 
1720 		for (k = 0; k < 4; k++) {
1721 			switch (k) {
1722 			case 0:
1723 
1724 				txpwr_ptr1 = txpwr->ofdm;
1725 				txpwr_ptr2 = txpwr->mcs_20_siso;
1726 				rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST;
1727 				break;
1728 			case 1:
1729 
1730 				txpwr_ptr1 = txpwr->ofdm_cdd;
1731 				txpwr_ptr2 = txpwr->mcs_20_cdd;
1732 				rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST;
1733 				break;
1734 			case 2:
1735 
1736 				txpwr_ptr1 = txpwr->ofdm_40_siso;
1737 				txpwr_ptr2 = txpwr->mcs_40_siso;
1738 				rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST;
1739 				break;
1740 			case 3:
1741 
1742 				txpwr_ptr1 = txpwr->ofdm_40_cdd;
1743 				txpwr_ptr2 = txpwr->mcs_40_cdd;
1744 				rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
1745 				break;
1746 			}
1747 			for (rate2 = 0; rate2 < BRCMS_NUM_RATES_OFDM;
1748 			     rate2++) {
1749 				tmp_txpwr_limit[rate2] = 0;
1750 				tmp_txpwr_limit[BRCMS_NUM_RATES_OFDM + rate2] =
1751 					txpwr_ptr1[rate2];
1752 			}
1753 			wlc_phy_ofdm_to_mcs_powers_nphy(
1754 				tmp_txpwr_limit, 0,
1755 				BRCMS_NUM_RATES_OFDM -
1756 				1, BRCMS_NUM_RATES_OFDM);
1757 			for (rate1 = rate_start_index, rate2 = 0;
1758 			     rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
1759 			     rate1++, rate2++)
1760 				pi->txpwr_limit[rate1] =
1761 					min(txpwr_ptr2[rate2],
1762 					    tmp_txpwr_limit[rate2]);
1763 		}
1764 
1765 		for (k = 0; k < 2; k++) {
1766 			switch (k) {
1767 			case 0:
1768 
1769 				rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST;
1770 				txpwr_ptr1 = txpwr->mcs_20_stbc;
1771 				break;
1772 			case 1:
1773 
1774 				rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST;
1775 				txpwr_ptr1 = txpwr->mcs_40_stbc;
1776 				break;
1777 			}
1778 			for (rate1 = rate_start_index, rate2 = 0;
1779 			     rate2 < BRCMS_NUM_RATES_MCS_1_STREAM;
1780 			     rate1++, rate2++)
1781 				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
1782 		}
1783 
1784 		for (k = 0; k < 2; k++) {
1785 			switch (k) {
1786 			case 0:
1787 
1788 				rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST;
1789 				txpwr_ptr1 = txpwr->mcs_20_mimo;
1790 				break;
1791 			case 1:
1792 
1793 				rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST;
1794 				txpwr_ptr1 = txpwr->mcs_40_mimo;
1795 				break;
1796 			}
1797 			for (rate1 = rate_start_index, rate2 = 0;
1798 			     rate2 < BRCMS_NUM_RATES_MCS_2_STREAM;
1799 			     rate1++, rate2++)
1800 				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
1801 		}
1802 
1803 		pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
1804 
1805 		pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
1806 			min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
1807 			    pi->txpwr_limit[WL_TX_POWER_MCS_32]);
1808 		pi->txpwr_limit[WL_TX_POWER_MCS_32] =
1809 			pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
1810 	}
1811 }
1812 
1813 void wlc_phy_txpwr_percent_set(struct brcms_phy_pub *ppi, u8 txpwr_percent)
1814 {
1815 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1816 
1817 	pi->txpwr_percent = txpwr_percent;
1818 }
1819 
1820 void wlc_phy_machwcap_set(struct brcms_phy_pub *ppi, u32 machwcap)
1821 {
1822 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1823 
1824 	pi->sh->machwcap = machwcap;
1825 }
1826 
1827 void wlc_phy_runbist_config(struct brcms_phy_pub *ppi, bool start_end)
1828 {
1829 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1830 	u16 rxc;
1831 	rxc = 0;
1832 
1833 	if (start_end == ON) {
1834 		if (!ISNPHY(pi))
1835 			return;
1836 
1837 		if (NREV_IS(pi->pubpi.phy_rev, 3)
1838 		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
1839 			bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr),
1840 				      0xa0);
1841 			bcma_set16(pi->d11core, D11REGOFFS(phyregdata),
1842 				   0x1 << 15);
1843 		}
1844 	} else {
1845 		if (NREV_IS(pi->pubpi.phy_rev, 3)
1846 		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
1847 			bcma_wflush16(pi->d11core, D11REGOFFS(phyregaddr),
1848 				      0xa0);
1849 			bcma_write16(pi->d11core, D11REGOFFS(phyregdata), rxc);
1850 		}
1851 
1852 		wlc_phy_por_inform(ppi);
1853 	}
1854 }
1855 
1856 void
1857 wlc_phy_txpower_limit_set(struct brcms_phy_pub *ppi, struct txpwr_limits *txpwr,
1858 			  u16 chanspec)
1859 {
1860 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1861 
1862 	wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec);
1863 
1864 	if (ISLCNPHY(pi)) {
1865 		int i, j;
1866 		for (i = TXP_FIRST_OFDM_20_CDD, j = 0;
1867 		     j < BRCMS_NUM_RATES_MCS_1_STREAM; i++, j++) {
1868 			if (txpwr->mcs_20_siso[j])
1869 				pi->txpwr_limit[i] = txpwr->mcs_20_siso[j];
1870 			else
1871 				pi->txpwr_limit[i] = txpwr->ofdm[j];
1872 		}
1873 	}
1874 
1875 	wlapi_suspend_mac_and_wait(pi->sh->physhim);
1876 
1877 	wlc_phy_txpower_recalc_target(pi);
1878 	wlc_phy_cal_txpower_recalc_sw(pi);
1879 	wlapi_enable_mac(pi->sh->physhim);
1880 }
1881 
1882 void wlc_phy_ofdm_rateset_war(struct brcms_phy_pub *pih, bool war)
1883 {
1884 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
1885 
1886 	pi->ofdm_rateset_war = war;
1887 }
1888 
1889 void wlc_phy_bf_preempt_enable(struct brcms_phy_pub *pih, bool bf_preempt)
1890 {
1891 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
1892 
1893 	pi->bf_preempt_4306 = bf_preempt;
1894 }
1895 
1896 void wlc_phy_txpower_update_shm(struct brcms_phy *pi)
1897 {
1898 	int j;
1899 	if (ISNPHY(pi))
1900 		return;
1901 
1902 	if (!pi->sh->clk)
1903 		return;
1904 
1905 	if (pi->hwpwrctrl) {
1906 		u16 offset;
1907 
1908 		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63);
1909 		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N,
1910 				     1 << NUM_TSSI_FRAMES);
1911 
1912 		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET,
1913 				     pi->tx_power_min << NUM_TSSI_FRAMES);
1914 
1915 		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR,
1916 				     pi->hwpwr_txcur);
1917 
1918 		for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
1919 			static const u8 ucode_ofdm_rates[] = {
1920 				0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
1921 			};
1922 			offset = wlapi_bmac_rate_shm_offset(
1923 				pi->sh->physhim,
1924 				ucode_ofdm_rates[j - TXP_FIRST_OFDM]);
1925 			wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
1926 					     pi->tx_power_offset[j]);
1927 			wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
1928 					     -(pi->tx_power_offset[j] / 2));
1929 		}
1930 
1931 		wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL,
1932 			       MHF2_HWPWRCTL, BRCM_BAND_ALL);
1933 	} else {
1934 		int i;
1935 
1936 		for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
1937 			pi->tx_power_offset[i] =
1938 				(u8) roundup(pi->tx_power_offset[i], 8);
1939 		wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
1940 				     (u16)
1941 				     ((pi->tx_power_offset[TXP_FIRST_OFDM]
1942 				       + 7) >> 3));
1943 	}
1944 }
1945 
1946 bool wlc_phy_txpower_hw_ctrl_get(struct brcms_phy_pub *ppi)
1947 {
1948 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1949 
1950 	if (ISNPHY(pi))
1951 		return pi->nphy_txpwrctrl;
1952 	else
1953 		return pi->hwpwrctrl;
1954 }
1955 
1956 void wlc_phy_txpower_hw_ctrl_set(struct brcms_phy_pub *ppi, bool hwpwrctrl)
1957 {
1958 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
1959 	bool suspend;
1960 
1961 	if (!pi->hwpwrctrl_capable)
1962 		return;
1963 
1964 	pi->hwpwrctrl = hwpwrctrl;
1965 	pi->nphy_txpwrctrl = hwpwrctrl;
1966 	pi->txpwrctrl = hwpwrctrl;
1967 
1968 	if (ISNPHY(pi)) {
1969 		suspend = (0 == (bcma_read32(pi->d11core,
1970 					     D11REGOFFS(maccontrol)) &
1971 				 MCTL_EN_MAC));
1972 		if (!suspend)
1973 			wlapi_suspend_mac_and_wait(pi->sh->physhim);
1974 
1975 		wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
1976 		if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF)
1977 			wlc_phy_txpwr_fixpower_nphy(pi);
1978 		else
1979 			mod_phy_reg(pi, 0x1e7, (0x7f << 0),
1980 				    pi->saved_txpwr_idx);
1981 
1982 		if (!suspend)
1983 			wlapi_enable_mac(pi->sh->physhim);
1984 	}
1985 }
1986 
1987 void wlc_phy_txpower_ipa_upd(struct brcms_phy *pi)
1988 {
1989 
1990 	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
1991 		pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2);
1992 		pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2);
1993 	} else {
1994 		pi->ipa2g_on = false;
1995 		pi->ipa5g_on = false;
1996 	}
1997 }
1998 
1999 static u32 wlc_phy_txpower_est_power_nphy(struct brcms_phy *pi)
2000 {
2001 	s16 tx0_status, tx1_status;
2002 	u16 estPower1, estPower2;
2003 	u8 pwr0, pwr1, adj_pwr0, adj_pwr1;
2004 	u32 est_pwr;
2005 
2006 	estPower1 = read_phy_reg(pi, 0x118);
2007 	estPower2 = read_phy_reg(pi, 0x119);
2008 
2009 	if ((estPower1 & (0x1 << 8)) == (0x1 << 8))
2010 		pwr0 = (u8) (estPower1 & (0xff << 0)) >> 0;
2011 	else
2012 		pwr0 = 0x80;
2013 
2014 	if ((estPower2 & (0x1 << 8)) == (0x1 << 8))
2015 		pwr1 = (u8) (estPower2 & (0xff << 0)) >> 0;
2016 	else
2017 		pwr1 = 0x80;
2018 
2019 	tx0_status = read_phy_reg(pi, 0x1ed);
2020 	tx1_status = read_phy_reg(pi, 0x1ee);
2021 
2022 	if ((tx0_status & (0x1 << 15)) == (0x1 << 15))
2023 		adj_pwr0 = (u8) (tx0_status & (0xff << 0)) >> 0;
2024 	else
2025 		adj_pwr0 = 0x80;
2026 	if ((tx1_status & (0x1 << 15)) == (0x1 << 15))
2027 		adj_pwr1 = (u8) (tx1_status & (0xff << 0)) >> 0;
2028 	else
2029 		adj_pwr1 = 0x80;
2030 
2031 	est_pwr = (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) |
2032 			 adj_pwr1);
2033 
2034 	return est_pwr;
2035 }
2036 
2037 void
2038 wlc_phy_txpower_get_current(struct brcms_phy_pub *ppi, struct tx_power *power,
2039 			    uint channel)
2040 {
2041 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
2042 	uint rate, num_rates;
2043 	u8 min_pwr, max_pwr;
2044 
2045 #if WL_TX_POWER_RATES != TXP_NUM_RATES
2046 #error "struct tx_power out of sync with this fn"
2047 #endif
2048 
2049 	if (ISNPHY(pi)) {
2050 		power->rf_cores = 2;
2051 		power->flags |= (WL_TX_POWER_F_MIMO);
2052 		if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
2053 			power->flags |=
2054 				(WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
2055 	} else if (ISLCNPHY(pi)) {
2056 		power->rf_cores = 1;
2057 		power->flags |= (WL_TX_POWER_F_SISO);
2058 		if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF)
2059 			power->flags |= WL_TX_POWER_F_ENABLED;
2060 		if (pi->hwpwrctrl)
2061 			power->flags |= WL_TX_POWER_F_HW;
2062 	}
2063 
2064 	num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
2065 		     ((ISLCNPHY(pi)) ?
2066 		      (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1)));
2067 
2068 	for (rate = 0; rate < num_rates; rate++) {
2069 		power->user_limit[rate] = pi->tx_user_target[rate];
2070 		wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr,
2071 					  rate);
2072 		power->board_limit[rate] = (u8) max_pwr;
2073 		power->target[rate] = pi->tx_power_target[rate];
2074 	}
2075 
2076 	if (ISNPHY(pi)) {
2077 		u32 est_pout;
2078 
2079 		wlapi_suspend_mac_and_wait(pi->sh->physhim);
2080 		wlc_phyreg_enter((struct brcms_phy_pub *) pi);
2081 		est_pout = wlc_phy_txpower_est_power_nphy(pi);
2082 		wlc_phyreg_exit((struct brcms_phy_pub *) pi);
2083 		wlapi_enable_mac(pi->sh->physhim);
2084 
2085 		power->est_Pout[0] = (est_pout >> 8) & 0xff;
2086 		power->est_Pout[1] = est_pout & 0xff;
2087 
2088 		power->est_Pout_act[0] = est_pout >> 24;
2089 		power->est_Pout_act[1] = (est_pout >> 16) & 0xff;
2090 
2091 		if (power->est_Pout[0] == 0x80)
2092 			power->est_Pout[0] = 0;
2093 		if (power->est_Pout[1] == 0x80)
2094 			power->est_Pout[1] = 0;
2095 
2096 		if (power->est_Pout_act[0] == 0x80)
2097 			power->est_Pout_act[0] = 0;
2098 		if (power->est_Pout_act[1] == 0x80)
2099 			power->est_Pout_act[1] = 0;
2100 
2101 		power->est_Pout_cck = 0;
2102 
2103 		power->tx_power_max[0] = pi->tx_power_max;
2104 		power->tx_power_max[1] = pi->tx_power_max;
2105 
2106 		power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind;
2107 		power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind;
2108 	} else if (pi->hwpwrctrl && pi->sh->up) {
2109 
2110 		wlc_phyreg_enter(ppi);
2111 		if (ISLCNPHY(pi)) {
2112 
2113 			power->tx_power_max[0] = pi->tx_power_max;
2114 			power->tx_power_max[1] = pi->tx_power_max;
2115 
2116 			power->tx_power_max_rate_ind[0] =
2117 				pi->tx_power_max_rate_ind;
2118 			power->tx_power_max_rate_ind[1] =
2119 				pi->tx_power_max_rate_ind;
2120 
2121 			if (wlc_phy_tpc_isenabled_lcnphy(pi))
2122 				power->flags |=
2123 					(WL_TX_POWER_F_HW |
2124 					 WL_TX_POWER_F_ENABLED);
2125 			else
2126 				power->flags &=
2127 					~(WL_TX_POWER_F_HW |
2128 					  WL_TX_POWER_F_ENABLED);
2129 
2130 			wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
2131 					    (s8 *) &power->est_Pout_cck);
2132 		}
2133 		wlc_phyreg_exit(ppi);
2134 	}
2135 }
2136 
2137 void wlc_phy_antsel_type_set(struct brcms_phy_pub *ppi, u8 antsel_type)
2138 {
2139 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
2140 
2141 	pi->antsel_type = antsel_type;
2142 }
2143 
2144 bool wlc_phy_test_ison(struct brcms_phy_pub *ppi)
2145 {
2146 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
2147 
2148 	return pi->phytest_on;
2149 }
2150 
2151 void wlc_phy_ant_rxdiv_set(struct brcms_phy_pub *ppi, u8 val)
2152 {
2153 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
2154 	bool suspend;
2155 
2156 	pi->sh->rx_antdiv = val;
2157 
2158 	if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) {
2159 		if (val > ANT_RX_DIV_FORCE_1)
2160 			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV,
2161 				       MHF1_ANTDIV, BRCM_BAND_ALL);
2162 		else
2163 			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0,
2164 				       BRCM_BAND_ALL);
2165 	}
2166 
2167 	if (ISNPHY(pi))
2168 		return;
2169 
2170 	if (!pi->sh->clk)
2171 		return;
2172 
2173 	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
2174 			 MCTL_EN_MAC));
2175 	if (!suspend)
2176 		wlapi_suspend_mac_and_wait(pi->sh->physhim);
2177 
2178 	if (ISLCNPHY(pi)) {
2179 		if (val > ANT_RX_DIV_FORCE_1) {
2180 			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1);
2181 			mod_phy_reg(pi, 0x410,
2182 				    (0x1 << 0),
2183 				    ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0);
2184 		} else {
2185 			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1);
2186 			mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0);
2187 		}
2188 	}
2189 
2190 	if (!suspend)
2191 		wlapi_enable_mac(pi->sh->physhim);
2192 
2193 	return;
2194 }
2195 
2196 static bool
2197 wlc_phy_noise_calc_phy(struct brcms_phy *pi, u32 *cmplx_pwr, s8 *pwr_ant)
2198 {
2199 	s8 cmplx_pwr_dbm[PHY_CORE_MAX];
2200 	u8 i;
2201 
2202 	memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm));
2203 	wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum);
2204 
2205 	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
2206 		if (NREV_GE(pi->pubpi.phy_rev, 3))
2207 			cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322;
2208 		else
2209 
2210 			cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70);
2211 	}
2212 
2213 	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
2214 		pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i];
2215 		pwr_ant[i] = cmplx_pwr_dbm[i];
2216 	}
2217 	pi->nphy_noise_index =
2218 		MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
2219 	return true;
2220 }
2221 
2222 static void wlc_phy_noise_cb(struct brcms_phy *pi, u8 channel, s8 noise_dbm)
2223 {
2224 	if (!pi->phynoise_state)
2225 		return;
2226 
2227 	if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
2228 		if (pi->phynoise_chan_watchdog == channel) {
2229 			pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
2230 				noise_dbm;
2231 			pi->sh->phy_noise_index =
2232 				MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
2233 		}
2234 		pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
2235 	}
2236 
2237 	if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL)
2238 		pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
2239 
2240 }
2241 
2242 static s8 wlc_phy_noise_read_shmem(struct brcms_phy *pi)
2243 {
2244 	u32 cmplx_pwr[PHY_CORE_MAX];
2245 	s8 noise_dbm_ant[PHY_CORE_MAX];
2246 	u16 lo, hi;
2247 	u32 cmplx_pwr_tot = 0;
2248 	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2249 	u8 idx, core;
2250 
2251 	memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
2252 	memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
2253 
2254 	for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2,
2255 	     core++) {
2256 		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
2257 		hi = wlapi_bmac_read_shm(pi->sh->physhim,
2258 					 M_PWRIND_MAP(idx + 1));
2259 		cmplx_pwr[core] = (hi << 16) + lo;
2260 		cmplx_pwr_tot += cmplx_pwr[core];
2261 		if (cmplx_pwr[core] == 0)
2262 			noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
2263 		else
2264 			cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
2265 	}
2266 
2267 	if (cmplx_pwr_tot != 0)
2268 		wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
2269 
2270 	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
2271 		pi->nphy_noise_win[core][pi->nphy_noise_index] =
2272 			noise_dbm_ant[core];
2273 
2274 		if (noise_dbm_ant[core] > noise_dbm)
2275 			noise_dbm = noise_dbm_ant[core];
2276 	}
2277 	pi->nphy_noise_index =
2278 		MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
2279 
2280 	return noise_dbm;
2281 
2282 }
2283 
2284 void wlc_phy_noise_sample_intr(struct brcms_phy_pub *pih)
2285 {
2286 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2287 	u16 jssi_aux;
2288 	u8 channel = 0;
2289 	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2290 
2291 	if (ISLCNPHY(pi)) {
2292 		u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
2293 		u16 lo, hi;
2294 		s32 pwr_offset_dB, gain_dB;
2295 		u16 status_0, status_1;
2296 
2297 		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
2298 		channel = jssi_aux & D11_CURCHANNEL_MAX;
2299 
2300 		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
2301 		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
2302 		cmplx_pwr0 = (hi << 16) + lo;
2303 
2304 		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
2305 		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
2306 		cmplx_pwr1 = (hi << 16) + lo;
2307 		cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
2308 
2309 		status_0 = 0x44;
2310 		status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
2311 		if ((cmplx_pwr > 0 && cmplx_pwr < 500)
2312 		    && ((status_1 & 0xc000) == 0x4000)) {
2313 
2314 			wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
2315 					   pi->pubpi.phy_corenum);
2316 			pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
2317 			if (pwr_offset_dB > 127)
2318 				pwr_offset_dB -= 256;
2319 
2320 			noise_dbm += (s8) (pwr_offset_dB - 30);
2321 
2322 			gain_dB = (status_0 & 0x1ff);
2323 			noise_dbm -= (s8) (gain_dB);
2324 		} else {
2325 			noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
2326 		}
2327 	} else if (ISNPHY(pi)) {
2328 
2329 		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
2330 		channel = jssi_aux & D11_CURCHANNEL_MAX;
2331 
2332 		noise_dbm = wlc_phy_noise_read_shmem(pi);
2333 	}
2334 
2335 	wlc_phy_noise_cb(pi, channel, noise_dbm);
2336 
2337 }
2338 
2339 static void
2340 wlc_phy_noise_sample_request(struct brcms_phy_pub *pih, u8 reason, u8 ch)
2341 {
2342 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2343 	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2344 	bool sampling_in_progress = (pi->phynoise_state != 0);
2345 	bool wait_for_intr = true;
2346 
2347 	switch (reason) {
2348 	case PHY_NOISE_SAMPLE_MON:
2349 		pi->phynoise_chan_watchdog = ch;
2350 		pi->phynoise_state |= PHY_NOISE_STATE_MON;
2351 		break;
2352 
2353 	case PHY_NOISE_SAMPLE_EXTERNAL:
2354 		pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
2355 		break;
2356 
2357 	default:
2358 		break;
2359 	}
2360 
2361 	if (sampling_in_progress)
2362 		return;
2363 
2364 	pi->phynoise_now = pi->sh->now;
2365 
2366 	if (pi->phy_fixed_noise) {
2367 		if (ISNPHY(pi)) {
2368 			pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
2369 				PHY_NOISE_FIXED_VAL_NPHY;
2370 			pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
2371 				PHY_NOISE_FIXED_VAL_NPHY;
2372 			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
2373 							   PHY_NOISE_WINDOW_SZ);
2374 			noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
2375 		} else {
2376 			noise_dbm = PHY_NOISE_FIXED_VAL;
2377 		}
2378 
2379 		wait_for_intr = false;
2380 		goto done;
2381 	}
2382 
2383 	if (ISLCNPHY(pi)) {
2384 		if (!pi->phynoise_polling
2385 		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
2386 			wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0);
2387 			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
2388 			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
2389 			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
2390 			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
2391 
2392 			bcma_set32(pi->d11core, D11REGOFFS(maccommand),
2393 				   MCMD_BG_NOISE);
2394 		} else {
2395 			wlapi_suspend_mac_and_wait(pi->sh->physhim);
2396 			wlc_lcnphy_deaf_mode(pi, (bool) 0);
2397 			noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20);
2398 			wlc_lcnphy_deaf_mode(pi, (bool) 1);
2399 			wlapi_enable_mac(pi->sh->physhim);
2400 			wait_for_intr = false;
2401 		}
2402 	} else if (ISNPHY(pi)) {
2403 		if (!pi->phynoise_polling
2404 		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
2405 
2406 			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
2407 			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
2408 			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
2409 			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
2410 
2411 			bcma_set32(pi->d11core, D11REGOFFS(maccommand),
2412 				   MCMD_BG_NOISE);
2413 		} else {
2414 			struct phy_iq_est est[PHY_CORE_MAX];
2415 			u32 cmplx_pwr[PHY_CORE_MAX];
2416 			s8 noise_dbm_ant[PHY_CORE_MAX];
2417 			u16 log_num_samps, num_samps, classif_state = 0;
2418 			u8 wait_time = 32;
2419 			u8 wait_crs = 0;
2420 			u8 i;
2421 
2422 			memset((u8 *) est, 0, sizeof(est));
2423 			memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
2424 			memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
2425 
2426 			log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
2427 			num_samps = 1 << log_num_samps;
2428 
2429 			wlapi_suspend_mac_and_wait(pi->sh->physhim);
2430 			classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
2431 			wlc_phy_classifier_nphy(pi, 3, 0);
2432 			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time,
2433 					       wait_crs);
2434 			wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
2435 			wlapi_enable_mac(pi->sh->physhim);
2436 
2437 			for (i = 0; i < pi->pubpi.phy_corenum; i++)
2438 				cmplx_pwr[i] = (est[i].i_pwr + est[i].q_pwr) >>
2439 					       log_num_samps;
2440 
2441 			wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
2442 
2443 			for (i = 0; i < pi->pubpi.phy_corenum; i++) {
2444 				pi->nphy_noise_win[i][pi->nphy_noise_index] =
2445 					noise_dbm_ant[i];
2446 
2447 				if (noise_dbm_ant[i] > noise_dbm)
2448 					noise_dbm = noise_dbm_ant[i];
2449 			}
2450 			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
2451 							   PHY_NOISE_WINDOW_SZ);
2452 
2453 			wait_for_intr = false;
2454 		}
2455 	}
2456 
2457 done:
2458 
2459 	if (!wait_for_intr)
2460 		wlc_phy_noise_cb(pi, ch, noise_dbm);
2461 
2462 }
2463 
2464 void wlc_phy_noise_sample_request_external(struct brcms_phy_pub *pih)
2465 {
2466 	u8 channel;
2467 
2468 	channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih));
2469 
2470 	wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
2471 }
2472 
2473 static const s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
2474 	8,
2475 	8,
2476 	8,
2477 	8,
2478 	8,
2479 	8,
2480 	8,
2481 	9,
2482 	10,
2483 	8,
2484 	8,
2485 	7,
2486 	7,
2487 	1,
2488 	2,
2489 	2,
2490 	2,
2491 	2,
2492 	2,
2493 	2,
2494 	2,
2495 	2,
2496 	2,
2497 	2,
2498 	2,
2499 	2,
2500 	2,
2501 	2,
2502 	2,
2503 	2,
2504 	2,
2505 	2,
2506 	1,
2507 	1,
2508 	0,
2509 	0,
2510 	0,
2511 	0
2512 };
2513 
2514 void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
2515 {
2516 	u8 msb, secondmsb, i;
2517 	u32 tmp;
2518 
2519 	for (i = 0; i < core; i++) {
2520 		secondmsb = 0;
2521 		tmp = cmplx_pwr[i];
2522 		msb = fls(tmp);
2523 		if (msb)
2524 			secondmsb = (u8) ((tmp >> (--msb - 1)) & 1);
2525 		p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb);
2526 	}
2527 }
2528 
2529 int wlc_phy_rssi_compute(struct brcms_phy_pub *pih,
2530 			 struct d11rxhdr *rxh)
2531 {
2532 	int rssi = rxh->PhyRxStatus_1 & PRXS1_JSSI_MASK;
2533 	uint radioid = pih->radioid;
2534 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2535 
2536 	if ((pi->sh->corerev >= 11)
2537 	    && !(rxh->RxStatus2 & RXS_PHYRXST_VALID)) {
2538 		rssi = BRCMS_RSSI_INVALID;
2539 		goto end;
2540 	}
2541 
2542 	if (ISLCNPHY(pi)) {
2543 		u8 gidx = (rxh->PhyRxStatus_2 & 0xFC00) >> 10;
2544 		struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
2545 
2546 		if (rssi > 127)
2547 			rssi -= 256;
2548 
2549 		rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx];
2550 		if ((rssi > -46) && (gidx > 18))
2551 			rssi = rssi + 7;
2552 
2553 		rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope;
2554 
2555 		rssi = rssi + 2;
2556 
2557 	}
2558 
2559 	if (ISLCNPHY(pi)) {
2560 		if (rssi > 127)
2561 			rssi -= 256;
2562 	} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
2563 		   || radioid == BCM2057_ID) {
2564 		rssi = wlc_phy_rssi_compute_nphy(pi, rxh);
2565 	}
2566 
2567 end:
2568 	return rssi;
2569 }
2570 
2571 void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih)
2572 {
2573 	return;
2574 }
2575 
2576 void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih)
2577 {
2578 	return;
2579 }
2580 
2581 void wlc_phy_set_deaf(struct brcms_phy_pub *ppi, bool user_flag)
2582 {
2583 	struct brcms_phy *pi;
2584 	pi = (struct brcms_phy *) ppi;
2585 
2586 	if (ISLCNPHY(pi))
2587 		wlc_lcnphy_deaf_mode(pi, true);
2588 	else if (ISNPHY(pi))
2589 		wlc_nphy_deaf_mode(pi, true);
2590 }
2591 
2592 void wlc_phy_watchdog(struct brcms_phy_pub *pih)
2593 {
2594 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2595 	bool delay_phy_cal = false;
2596 	pi->sh->now++;
2597 
2598 	if (!pi->watchdog_override)
2599 		return;
2600 
2601 	if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)))
2602 		wlc_phy_noise_sample_request((struct brcms_phy_pub *) pi,
2603 					     PHY_NOISE_SAMPLE_MON,
2604 					     CHSPEC_CHANNEL(pi->
2605 							    radio_chanspec));
2606 
2607 	if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5)
2608 		pi->phynoise_state = 0;
2609 
2610 	if ((!pi->phycal_txpower) ||
2611 	    ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
2612 
2613 		if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi))
2614 			pi->phycal_txpower = pi->sh->now;
2615 	}
2616 
2617 	if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
2618 	     || ASSOC_INPROG_PHY(pi)))
2619 		return;
2620 
2621 	if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) {
2622 
2623 		if ((pi->nphy_perical != PHY_PERICAL_DISABLE) &&
2624 		    (pi->nphy_perical != PHY_PERICAL_MANUAL) &&
2625 		    ((pi->sh->now - pi->nphy_perical_last) >=
2626 		     pi->sh->glacial_timer))
2627 			wlc_phy_cal_perical((struct brcms_phy_pub *) pi,
2628 					    PHY_PERICAL_WATCHDOG);
2629 
2630 		wlc_phy_txpwr_papd_cal_nphy(pi);
2631 	}
2632 
2633 	if (ISLCNPHY(pi)) {
2634 		if (pi->phy_forcecal ||
2635 		    ((pi->sh->now - pi->phy_lastcal) >=
2636 		     pi->sh->glacial_timer)) {
2637 			if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
2638 				wlc_lcnphy_calib_modes(
2639 					pi,
2640 					LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
2641 			if (!
2642 			    (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
2643 			     || ASSOC_INPROG_PHY(pi)
2644 			     || pi->carrier_suppr_disable
2645 			     || pi->disable_percal))
2646 				wlc_lcnphy_calib_modes(pi,
2647 						       PHY_PERICAL_WATCHDOG);
2648 		}
2649 	}
2650 }
2651 
2652 void wlc_phy_BSSinit(struct brcms_phy_pub *pih, bool bonlyap, int rssi)
2653 {
2654 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2655 	uint i;
2656 	uint k;
2657 
2658 	for (i = 0; i < MA_WINDOW_SZ; i++)
2659 		pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
2660 	if (ISLCNPHY(pi)) {
2661 		for (i = 0; i < MA_WINDOW_SZ; i++)
2662 			pi->sh->phy_noise_window[i] =
2663 				PHY_NOISE_FIXED_VAL_LCNPHY;
2664 	}
2665 	pi->sh->phy_noise_index = 0;
2666 
2667 	for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) {
2668 		for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++)
2669 			pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY;
2670 	}
2671 	pi->nphy_noise_index = 0;
2672 }
2673 
2674 void
2675 wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
2676 {
2677 	*eps_imag = (epsilon >> 13);
2678 	if (*eps_imag > 0xfff)
2679 		*eps_imag -= 0x2000;
2680 
2681 	*eps_real = (epsilon & 0x1fff);
2682 	if (*eps_real > 0xfff)
2683 		*eps_real -= 0x2000;
2684 }
2685 
2686 void wlc_phy_cal_perical_mphase_reset(struct brcms_phy *pi)
2687 {
2688 	wlapi_del_timer(pi->phycal_timer);
2689 
2690 	pi->cal_type_override = PHY_PERICAL_AUTO;
2691 	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
2692 	pi->mphase_txcal_cmdidx = 0;
2693 }
2694 
2695 static void
2696 wlc_phy_cal_perical_mphase_schedule(struct brcms_phy *pi, uint delay)
2697 {
2698 
2699 	if ((pi->nphy_perical != PHY_PERICAL_MPHASE) &&
2700 	    (pi->nphy_perical != PHY_PERICAL_MANUAL))
2701 		return;
2702 
2703 	wlapi_del_timer(pi->phycal_timer);
2704 
2705 	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
2706 	wlapi_add_timer(pi->phycal_timer, delay, 0);
2707 }
2708 
2709 void wlc_phy_cal_perical(struct brcms_phy_pub *pih, u8 reason)
2710 {
2711 	s16 nphy_currtemp = 0;
2712 	s16 delta_temp = 0;
2713 	bool do_periodic_cal = true;
2714 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2715 
2716 	if (!ISNPHY(pi))
2717 		return;
2718 
2719 	if ((pi->nphy_perical == PHY_PERICAL_DISABLE) ||
2720 	    (pi->nphy_perical == PHY_PERICAL_MANUAL))
2721 		return;
2722 
2723 	switch (reason) {
2724 	case PHY_PERICAL_DRIVERUP:
2725 		break;
2726 
2727 	case PHY_PERICAL_PHYINIT:
2728 		if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
2729 			if (PHY_PERICAL_MPHASE_PENDING(pi))
2730 				wlc_phy_cal_perical_mphase_reset(pi);
2731 
2732 			wlc_phy_cal_perical_mphase_schedule(
2733 				pi,
2734 				PHY_PERICAL_INIT_DELAY);
2735 		}
2736 		break;
2737 
2738 	case PHY_PERICAL_JOIN_BSS:
2739 	case PHY_PERICAL_START_IBSS:
2740 	case PHY_PERICAL_UP_BSS:
2741 		if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
2742 		    PHY_PERICAL_MPHASE_PENDING(pi))
2743 			wlc_phy_cal_perical_mphase_reset(pi);
2744 
2745 		pi->first_cal_after_assoc = true;
2746 
2747 		pi->cal_type_override = PHY_PERICAL_FULL;
2748 
2749 		if (pi->phycal_tempdelta)
2750 			pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
2751 
2752 		wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
2753 		break;
2754 
2755 	case PHY_PERICAL_WATCHDOG:
2756 		if (pi->phycal_tempdelta) {
2757 			nphy_currtemp = wlc_phy_tempsense_nphy(pi);
2758 			delta_temp =
2759 				(nphy_currtemp > pi->nphy_lastcal_temp) ?
2760 				nphy_currtemp - pi->nphy_lastcal_temp :
2761 				pi->nphy_lastcal_temp - nphy_currtemp;
2762 
2763 			if ((delta_temp < (s16) pi->phycal_tempdelta) &&
2764 			    (pi->nphy_txiqlocal_chanspec ==
2765 			     pi->radio_chanspec))
2766 				do_periodic_cal = false;
2767 			else
2768 				pi->nphy_lastcal_temp = nphy_currtemp;
2769 		}
2770 
2771 		if (do_periodic_cal) {
2772 			if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
2773 				if (!PHY_PERICAL_MPHASE_PENDING(pi))
2774 					wlc_phy_cal_perical_mphase_schedule(
2775 						pi,
2776 						PHY_PERICAL_WDOG_DELAY);
2777 			} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
2778 				wlc_phy_cal_perical_nphy_run(pi,
2779 							     PHY_PERICAL_AUTO);
2780 		}
2781 		break;
2782 	default:
2783 		break;
2784 	}
2785 }
2786 
2787 void wlc_phy_cal_perical_mphase_restart(struct brcms_phy *pi)
2788 {
2789 	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
2790 	pi->mphase_txcal_cmdidx = 0;
2791 }
2792 
2793 u8 wlc_phy_nbits(s32 value)
2794 {
2795 	s32 abs_val;
2796 	u8 nbits = 0;
2797 
2798 	abs_val = abs(value);
2799 	while ((abs_val >> nbits) > 0)
2800 		nbits++;
2801 
2802 	return nbits;
2803 }
2804 
2805 void wlc_phy_stf_chain_init(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
2806 {
2807 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2808 
2809 	pi->sh->hw_phytxchain = txchain;
2810 	pi->sh->hw_phyrxchain = rxchain;
2811 	pi->sh->phytxchain = txchain;
2812 	pi->sh->phyrxchain = rxchain;
2813 	pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
2814 }
2815 
2816 void wlc_phy_stf_chain_set(struct brcms_phy_pub *pih, u8 txchain, u8 rxchain)
2817 {
2818 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2819 
2820 	pi->sh->phytxchain = txchain;
2821 
2822 	if (ISNPHY(pi))
2823 		wlc_phy_rxcore_setstate_nphy(pih, rxchain);
2824 
2825 	pi->pubpi.phy_corenum = (u8)hweight8(pi->sh->phyrxchain);
2826 }
2827 
2828 void wlc_phy_stf_chain_get(struct brcms_phy_pub *pih, u8 *txchain, u8 *rxchain)
2829 {
2830 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2831 
2832 	*txchain = pi->sh->phytxchain;
2833 	*rxchain = pi->sh->phyrxchain;
2834 }
2835 
2836 u8 wlc_phy_stf_chain_active_get(struct brcms_phy_pub *pih)
2837 {
2838 	s16 nphy_currtemp;
2839 	u8 active_bitmap;
2840 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2841 
2842 	active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33;
2843 
2844 	if (!pi->watchdog_override)
2845 		return active_bitmap;
2846 
2847 	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
2848 		wlapi_suspend_mac_and_wait(pi->sh->physhim);
2849 		nphy_currtemp = wlc_phy_tempsense_nphy(pi);
2850 		wlapi_enable_mac(pi->sh->physhim);
2851 
2852 		if (!pi->phy_txcore_heatedup) {
2853 			if (nphy_currtemp >= pi->phy_txcore_disable_temp) {
2854 				active_bitmap &= 0xFD;
2855 				pi->phy_txcore_heatedup = true;
2856 			}
2857 		} else {
2858 			if (nphy_currtemp <= pi->phy_txcore_enable_temp) {
2859 				active_bitmap |= 0x2;
2860 				pi->phy_txcore_heatedup = false;
2861 			}
2862 		}
2863 	}
2864 
2865 	return active_bitmap;
2866 }
2867 
2868 s8 wlc_phy_stf_ssmode_get(struct brcms_phy_pub *pih, u16 chanspec)
2869 {
2870 	struct brcms_phy *pi = container_of(pih, struct brcms_phy, pubpi_ro);
2871 	u8 siso_mcs_id, cdd_mcs_id;
2872 
2873 	siso_mcs_id =
2874 		(CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
2875 		TXP_FIRST_MCS_20_SISO;
2876 	cdd_mcs_id =
2877 		(CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
2878 		TXP_FIRST_MCS_20_CDD;
2879 
2880 	if (pi->tx_power_target[siso_mcs_id] >
2881 	    (pi->tx_power_target[cdd_mcs_id] + 12))
2882 		return PHY_TXC1_MODE_SISO;
2883 	else
2884 		return PHY_TXC1_MODE_CDD;
2885 }
2886 
2887 const u8 *wlc_phy_get_ofdm_rate_lookup(void)
2888 {
2889 	return ofdm_rate_lookup;
2890 }
2891 
2892 void wlc_lcnphy_epa_switch(struct brcms_phy *pi, bool mode)
2893 {
2894 	if ((pi->sh->chip == BCMA_CHIP_ID_BCM4313) &&
2895 	    (pi->sh->boardflags & BFL_FEM)) {
2896 		if (mode) {
2897 			u16 txant = 0;
2898 			txant = wlapi_bmac_get_txant(pi->sh->physhim);
2899 			if (txant == 1) {
2900 				mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
2901 
2902 				mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
2903 
2904 			}
2905 
2906 			bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
2907 						 0x0, 0x0);
2908 			bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
2909 					     ~0x40, 0x40);
2910 			bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
2911 					       ~0x40, 0x40);
2912 		} else {
2913 			mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
2914 
2915 			mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
2916 
2917 			bcma_chipco_gpio_out(&pi->d11core->bus->drv_cc,
2918 					     ~0x40, 0x00);
2919 			bcma_chipco_gpio_outen(&pi->d11core->bus->drv_cc,
2920 					       ~0x40, 0x00);
2921 			bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc,
2922 						 0x0, 0x40);
2923 		}
2924 	}
2925 }
2926 
2927 void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc)
2928 {
2929 	return;
2930 }
2931 
2932 void
2933 wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset)
2934 {
2935 	*cckoffset = 0;
2936 	*ofdmoffset = 0;
2937 }
2938 
2939 s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec)
2940 {
2941 
2942 	return rssi;
2943 }
2944 
2945 bool wlc_phy_txpower_ipa_ison(struct brcms_phy_pub *ppi)
2946 {
2947 	struct brcms_phy *pi = container_of(ppi, struct brcms_phy, pubpi_ro);
2948 
2949 	if (ISNPHY(pi))
2950 		return wlc_phy_n_txpower_ipa_ison(pi);
2951 	else
2952 		return false;
2953 }
2954