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