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