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