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