[go: nahoru, domu]

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
51struct chan_info_basic {
52	u16 chan;
53	u16 freq;
54};
55
56static 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
115static 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
129void 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
135void 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
141void 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
149void 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
158u16 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
199void 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
219static 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
245void 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
253void 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
261void 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
269void 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
277void write_phy_channel_reg(struct brcms_phy *pi, uint val)
278{
279	bcma_write16(pi->d11core, D11REGOFFS(phychannel), val);
280}
281
282u16 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
290void 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
307void 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
314void 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
321void 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
329static 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
365struct 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
397static 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
419static 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
428struct brcms_phy_pub *
429wlc_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
582err:
583	kfree(pi);
584	return NULL;
585}
586
587void 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
612bool
613wlc_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
625bool 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
631u32 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
637void 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
674u32 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
699void 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
706void 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
718void 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
725void 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
735void 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
745void 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
799void 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
817int 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
832void
833wlc_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
849void 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
869void
870wlc_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
906void
907wlc_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
941uint
942wlc_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
958uint
959wlc_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
993void 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
1071void 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
1083void 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
1097void 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
1111static bool wlc_phy_cal_txpower_recalc_sw(struct brcms_phy *pi)
1112{
1113	return false;
1114}
1115
1116void 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
1150u16 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
1157void 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
1164void 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
1171u16 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
1178void 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
1196int 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
1212int 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
1226void 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
1235int 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
1245void
1246wlc_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
1268u16 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
1312int 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
1322void 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
1372int 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
1406void
1407wlc_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
1455void
1456wlc_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
1487void
1488wlc_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
1494u8 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
1501u8 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
1508static 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
1516static 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
1524static 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
1537static s8
1538wlc_user_txpwr_antport_to_rfport(struct brcms_phy *pi, uint chan, u32 band,
1539				 u8 rate)
1540{
1541	return 0;
1542}
1543
1544void 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
1656static void
1657wlc_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
1813void 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
1820void 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
1827void 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
1856void
1857wlc_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
1882void 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
1889void 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
1896void 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			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
1946bool 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
1956void 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
1987void 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
1999static 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
2037void
2038wlc_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
2137void 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
2144bool 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
2151void 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
2196static bool
2197wlc_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
2222static 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
2242static 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
2284void 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
2339static void
2340wlc_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
2457done:
2458
2459	if (!wait_for_intr)
2460		wlc_phy_noise_cb(pi, ch, noise_dbm);
2461
2462}
2463
2464void 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
2473static 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
2514void 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
2529int 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
2567end:
2568	return rssi;
2569}
2570
2571void wlc_phy_freqtrack_start(struct brcms_phy_pub *pih)
2572{
2573	return;
2574}
2575
2576void wlc_phy_freqtrack_end(struct brcms_phy_pub *pih)
2577{
2578	return;
2579}
2580
2581void 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
2592void 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
2652void 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
2674void
2675wlc_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
2686void 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
2695static void
2696wlc_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
2709void 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
2787void 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
2793u8 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
2805void 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
2816void 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
2828void 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
2836u8 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
2868s8 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
2887const u8 *wlc_phy_get_ofdm_rate_lookup(void)
2888{
2889	return ofdm_rate_lookup;
2890}
2891
2892void 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
2927void wlc_phy_ldpc_override_set(struct brcms_phy_pub *ppi, bool ldpc)
2928{
2929	return;
2930}
2931
2932void
2933wlc_phy_get_pwrdet_offsets(struct brcms_phy *pi, s8 *cckoffset, s8 *ofdmoffset)
2934{
2935	*cckoffset = 0;
2936	*ofdmoffset = 0;
2937}
2938
2939s8 wlc_phy_upd_rssi_offset(struct brcms_phy *pi, s8 rssi, u16 chanspec)
2940{
2941
2942	return rssi;
2943}
2944
2945bool 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 0;
2953}
2954