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