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