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