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