3 Broadcom B43 wireless driver
4 IEEE 802.11n PHY support
6 Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
21 Boston, MA 02110-1301, USA.
25 #include <linux/delay.h>
26 #include <linux/types.h>
30 #include "tables_nphy.h"
40 struct nphy_iqcal_params
{
58 enum b43_nphy_rf_sequence
{
62 B43_RFSEQ_UPDATE_GAINH
,
63 B43_RFSEQ_UPDATE_GAINL
,
64 B43_RFSEQ_UPDATE_GAINU
,
67 static void b43_nphy_force_rf_sequence(struct b43_wldev
*dev
,
68 enum b43_nphy_rf_sequence seq
);
70 void b43_nphy_set_rxantenna(struct b43_wldev
*dev
, int antenna
)
74 static void b43_nphy_op_adjust_txpower(struct b43_wldev
*dev
)
78 static enum b43_txpwr_result
b43_nphy_op_recalc_txpower(struct b43_wldev
*dev
,
81 return B43_TXPWR_RES_DONE
;
84 static void b43_chantab_radio_upload(struct b43_wldev
*dev
,
85 const struct b43_nphy_channeltab_entry
*e
)
87 b43_radio_write16(dev
, B2055_PLL_REF
, e
->radio_pll_ref
);
88 b43_radio_write16(dev
, B2055_RF_PLLMOD0
, e
->radio_rf_pllmod0
);
89 b43_radio_write16(dev
, B2055_RF_PLLMOD1
, e
->radio_rf_pllmod1
);
90 b43_radio_write16(dev
, B2055_VCO_CAPTAIL
, e
->radio_vco_captail
);
91 b43_radio_write16(dev
, B2055_VCO_CAL1
, e
->radio_vco_cal1
);
92 b43_radio_write16(dev
, B2055_VCO_CAL2
, e
->radio_vco_cal2
);
93 b43_radio_write16(dev
, B2055_PLL_LFC1
, e
->radio_pll_lfc1
);
94 b43_radio_write16(dev
, B2055_PLL_LFR1
, e
->radio_pll_lfr1
);
95 b43_radio_write16(dev
, B2055_PLL_LFC2
, e
->radio_pll_lfc2
);
96 b43_radio_write16(dev
, B2055_LGBUF_CENBUF
, e
->radio_lgbuf_cenbuf
);
97 b43_radio_write16(dev
, B2055_LGEN_TUNE1
, e
->radio_lgen_tune1
);
98 b43_radio_write16(dev
, B2055_LGEN_TUNE2
, e
->radio_lgen_tune2
);
99 b43_radio_write16(dev
, B2055_C1_LGBUF_ATUNE
, e
->radio_c1_lgbuf_atune
);
100 b43_radio_write16(dev
, B2055_C1_LGBUF_GTUNE
, e
->radio_c1_lgbuf_gtune
);
101 b43_radio_write16(dev
, B2055_C1_RX_RFR1
, e
->radio_c1_rx_rfr1
);
102 b43_radio_write16(dev
, B2055_C1_TX_PGAPADTN
, e
->radio_c1_tx_pgapadtn
);
103 b43_radio_write16(dev
, B2055_C1_TX_MXBGTRIM
, e
->radio_c1_tx_mxbgtrim
);
104 b43_radio_write16(dev
, B2055_C2_LGBUF_ATUNE
, e
->radio_c2_lgbuf_atune
);
105 b43_radio_write16(dev
, B2055_C2_LGBUF_GTUNE
, e
->radio_c2_lgbuf_gtune
);
106 b43_radio_write16(dev
, B2055_C2_RX_RFR1
, e
->radio_c2_rx_rfr1
);
107 b43_radio_write16(dev
, B2055_C2_TX_PGAPADTN
, e
->radio_c2_tx_pgapadtn
);
108 b43_radio_write16(dev
, B2055_C2_TX_MXBGTRIM
, e
->radio_c2_tx_mxbgtrim
);
111 static void b43_chantab_phy_upload(struct b43_wldev
*dev
,
112 const struct b43_nphy_channeltab_entry
*e
)
114 b43_phy_write(dev
, B43_NPHY_BW1A
, e
->phy_bw1a
);
115 b43_phy_write(dev
, B43_NPHY_BW2
, e
->phy_bw2
);
116 b43_phy_write(dev
, B43_NPHY_BW3
, e
->phy_bw3
);
117 b43_phy_write(dev
, B43_NPHY_BW4
, e
->phy_bw4
);
118 b43_phy_write(dev
, B43_NPHY_BW5
, e
->phy_bw5
);
119 b43_phy_write(dev
, B43_NPHY_BW6
, e
->phy_bw6
);
122 static void b43_nphy_tx_power_fix(struct b43_wldev
*dev
)
127 /* Tune the hardware to a new channel. */
128 static int nphy_channel_switch(struct b43_wldev
*dev
, unsigned int channel
)
130 const struct b43_nphy_channeltab_entry
*tabent
;
132 tabent
= b43_nphy_get_chantabent(dev
, channel
);
136 //FIXME enable/disable band select upper20 in RXCTL
137 if (0 /*FIXME 5Ghz*/)
138 b43_radio_maskset(dev
, B2055_MASTER1
, 0xFF8F, 0x20);
140 b43_radio_maskset(dev
, B2055_MASTER1
, 0xFF8F, 0x50);
141 b43_chantab_radio_upload(dev
, tabent
);
143 b43_radio_write16(dev
, B2055_VCO_CAL10
, 5);
144 b43_radio_write16(dev
, B2055_VCO_CAL10
, 45);
145 b43_radio_write16(dev
, B2055_VCO_CAL10
, 65);
147 if (0 /*FIXME 5Ghz*/)
148 b43_phy_set(dev
, B43_NPHY_BANDCTL
, B43_NPHY_BANDCTL_5GHZ
);
150 b43_phy_mask(dev
, B43_NPHY_BANDCTL
, ~B43_NPHY_BANDCTL_5GHZ
);
151 b43_chantab_phy_upload(dev
, tabent
);
152 b43_nphy_tx_power_fix(dev
);
157 static void b43_radio_init2055_pre(struct b43_wldev
*dev
)
159 b43_phy_mask(dev
, B43_NPHY_RFCTL_CMD
,
160 ~B43_NPHY_RFCTL_CMD_PORFORCE
);
161 b43_phy_set(dev
, B43_NPHY_RFCTL_CMD
,
162 B43_NPHY_RFCTL_CMD_CHIP0PU
|
163 B43_NPHY_RFCTL_CMD_OEPORFORCE
);
164 b43_phy_set(dev
, B43_NPHY_RFCTL_CMD
,
165 B43_NPHY_RFCTL_CMD_PORFORCE
);
168 static void b43_radio_init2055_post(struct b43_wldev
*dev
)
170 struct ssb_sprom
*sprom
= &(dev
->dev
->bus
->sprom
);
171 struct ssb_boardinfo
*binfo
= &(dev
->dev
->bus
->boardinfo
);
175 b43_radio_mask(dev
, B2055_MASTER1
, 0xFFF3);
177 if ((sprom
->revision
!= 4) ||
178 !(sprom
->boardflags_hi
& B43_BFH_RSSIINV
)) {
179 if ((binfo
->vendor
!= PCI_VENDOR_ID_BROADCOM
) ||
180 (binfo
->type
!= 0x46D) ||
181 (binfo
->rev
< 0x41)) {
182 b43_radio_mask(dev
, B2055_C1_RX_BB_REG
, 0x7F);
183 b43_radio_mask(dev
, B2055_C1_RX_BB_REG
, 0x7F);
187 b43_radio_maskset(dev
, B2055_RRCCAL_NOPTSEL
, 0x3F, 0x2C);
189 b43_radio_write16(dev
, B2055_CAL_MISC
, 0x3C);
191 b43_radio_mask(dev
, B2055_CAL_MISC
, 0xFFBE);
193 b43_radio_set(dev
, B2055_CAL_LPOCTL
, 0x80);
195 b43_radio_set(dev
, B2055_CAL_MISC
, 0x1);
197 b43_radio_set(dev
, B2055_CAL_MISC
, 0x40);
199 for (i
= 0; i
< 100; i
++) {
200 val
= b43_radio_read16(dev
, B2055_CAL_COUT2
);
206 b43_radio_mask(dev
, B2055_CAL_LPOCTL
, 0xFF7F);
208 nphy_channel_switch(dev
, dev
->phy
.channel
);
209 b43_radio_write16(dev
, B2055_C1_RX_BB_LPF
, 0x9);
210 b43_radio_write16(dev
, B2055_C2_RX_BB_LPF
, 0x9);
211 b43_radio_write16(dev
, B2055_C1_RX_BB_MIDACHP
, 0x83);
212 b43_radio_write16(dev
, B2055_C2_RX_BB_MIDACHP
, 0x83);
215 /* Initialize a Broadcom 2055 N-radio */
216 static void b43_radio_init2055(struct b43_wldev
*dev
)
218 b43_radio_init2055_pre(dev
);
219 if (b43_status(dev
) < B43_STAT_INITIALIZED
)
220 b2055_upload_inittab(dev
, 0, 1);
222 b2055_upload_inittab(dev
, 0/*FIXME on 5ghz band*/, 0);
223 b43_radio_init2055_post(dev
);
226 void b43_nphy_radio_turn_on(struct b43_wldev
*dev
)
228 b43_radio_init2055(dev
);
231 void b43_nphy_radio_turn_off(struct b43_wldev
*dev
)
233 b43_phy_mask(dev
, B43_NPHY_RFCTL_CMD
,
234 ~B43_NPHY_RFCTL_CMD_EN
);
238 * Upload the N-PHY tables.
239 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
241 static void b43_nphy_tables_init(struct b43_wldev
*dev
)
243 if (dev
->phy
.rev
< 3)
244 b43_nphy_rev0_1_2_tables_init(dev
);
246 b43_nphy_rev3plus_tables_init(dev
);
249 static void b43_nphy_workarounds(struct b43_wldev
*dev
)
251 struct b43_phy
*phy
= &dev
->phy
;
254 b43_phy_set(dev
, B43_NPHY_IQFLIP
,
255 B43_NPHY_IQFLIP_ADC1
| B43_NPHY_IQFLIP_ADC2
);
256 if (1 /* FIXME band is 2.4GHz */) {
257 b43_phy_set(dev
, B43_NPHY_CLASSCTL
,
258 B43_NPHY_CLASSCTL_CCKEN
);
260 b43_phy_mask(dev
, B43_NPHY_CLASSCTL
,
261 ~B43_NPHY_CLASSCTL_CCKEN
);
263 b43_radio_set(dev
, B2055_C1_TX_RF_SPARE
, 0x8);
264 b43_phy_write(dev
, B43_NPHY_TXFRAMEDELAY
, 8);
266 /* Fixup some tables */
267 b43_ntab_write(dev
, B43_NTAB16(8, 0x00), 0xA);
268 b43_ntab_write(dev
, B43_NTAB16(8, 0x10), 0xA);
269 b43_ntab_write(dev
, B43_NTAB16(8, 0x02), 0xCDAA);
270 b43_ntab_write(dev
, B43_NTAB16(8, 0x12), 0xCDAA);
271 b43_ntab_write(dev
, B43_NTAB16(8, 0x08), 0);
272 b43_ntab_write(dev
, B43_NTAB16(8, 0x18), 0);
273 b43_ntab_write(dev
, B43_NTAB16(8, 0x07), 0x7AAB);
274 b43_ntab_write(dev
, B43_NTAB16(8, 0x17), 0x7AAB);
275 b43_ntab_write(dev
, B43_NTAB16(8, 0x06), 0x800);
276 b43_ntab_write(dev
, B43_NTAB16(8, 0x16), 0x800);
278 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_LO1
, 0x2D8);
279 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_UP1
, 0x301);
280 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_LO2
, 0x2D8);
281 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_UP2
, 0x301);
283 //TODO set RF sequence
285 /* Set narrowband clip threshold */
286 b43_phy_write(dev
, B43_NPHY_C1_NBCLIPTHRES
, 66);
287 b43_phy_write(dev
, B43_NPHY_C2_NBCLIPTHRES
, 66);
289 /* Set wideband clip 2 threshold */
290 b43_phy_maskset(dev
, B43_NPHY_C1_CLIPWBTHRES
,
291 ~B43_NPHY_C1_CLIPWBTHRES_CLIP2
,
292 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT
);
293 b43_phy_maskset(dev
, B43_NPHY_C2_CLIPWBTHRES
,
294 ~B43_NPHY_C2_CLIPWBTHRES_CLIP2
,
295 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT
);
297 /* Set Clip 2 detect */
298 b43_phy_set(dev
, B43_NPHY_C1_CGAINI
,
299 B43_NPHY_C1_CGAINI_CL2DETECT
);
300 b43_phy_set(dev
, B43_NPHY_C2_CGAINI
,
301 B43_NPHY_C2_CGAINI_CL2DETECT
);
304 /* Set dwell lengths */
305 b43_phy_write(dev
, B43_NPHY_CLIP1_NBDWELL_LEN
, 43);
306 b43_phy_write(dev
, B43_NPHY_CLIP2_NBDWELL_LEN
, 43);
307 b43_phy_write(dev
, B43_NPHY_W1CLIP1_DWELL_LEN
, 9);
308 b43_phy_write(dev
, B43_NPHY_W1CLIP2_DWELL_LEN
, 9);
310 /* Set gain backoff */
311 b43_phy_maskset(dev
, B43_NPHY_C1_CGAINI
,
312 ~B43_NPHY_C1_CGAINI_GAINBKOFF
,
313 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT
);
314 b43_phy_maskset(dev
, B43_NPHY_C2_CGAINI
,
315 ~B43_NPHY_C2_CGAINI_GAINBKOFF
,
316 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT
);
318 /* Set HPVGA2 index */
319 b43_phy_maskset(dev
, B43_NPHY_C1_INITGAIN
,
320 ~B43_NPHY_C1_INITGAIN_HPVGA2
,
321 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT
);
322 b43_phy_maskset(dev
, B43_NPHY_C2_INITGAIN
,
323 ~B43_NPHY_C2_INITGAIN_HPVGA2
,
324 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT
);
326 //FIXME verify that the specs really mean to use autoinc here.
327 for (i
= 0; i
< 3; i
++)
328 b43_ntab_write(dev
, B43_NTAB16(7, 0x106) + i
, 0x673);
331 /* Set minimum gain value */
332 b43_phy_maskset(dev
, B43_NPHY_C1_MINMAX_GAIN
,
333 ~B43_NPHY_C1_MINGAIN
,
334 23 << B43_NPHY_C1_MINGAIN_SHIFT
);
335 b43_phy_maskset(dev
, B43_NPHY_C2_MINMAX_GAIN
,
336 ~B43_NPHY_C2_MINGAIN
,
337 23 << B43_NPHY_C2_MINGAIN_SHIFT
);
340 b43_phy_mask(dev
, B43_NPHY_SCRAM_SIGCTL
,
341 ~B43_NPHY_SCRAM_SIGCTL_SCM
);
344 /* Set phase track alpha and beta */
345 b43_phy_write(dev
, B43_NPHY_PHASETR_A0
, 0x125);
346 b43_phy_write(dev
, B43_NPHY_PHASETR_A1
, 0x1B3);
347 b43_phy_write(dev
, B43_NPHY_PHASETR_A2
, 0x105);
348 b43_phy_write(dev
, B43_NPHY_PHASETR_B0
, 0x16E);
349 b43_phy_write(dev
, B43_NPHY_PHASETR_B1
, 0xCD);
350 b43_phy_write(dev
, B43_NPHY_PHASETR_B2
, 0x20);
353 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
354 static void b43_nphy_pa_override(struct b43_wldev
*dev
, bool enable
)
356 struct b43_phy_n
*nphy
= dev
->phy
.n
;
357 enum ieee80211_band band
;
361 nphy
->rfctrl_intc1_save
= b43_phy_read(dev
,
362 B43_NPHY_RFCTL_INTC1
);
363 nphy
->rfctrl_intc2_save
= b43_phy_read(dev
,
364 B43_NPHY_RFCTL_INTC2
);
365 band
= b43_current_band(dev
->wl
);
366 if (dev
->phy
.rev
>= 3) {
367 if (band
== IEEE80211_BAND_5GHZ
)
372 if (band
== IEEE80211_BAND_5GHZ
)
377 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
, tmp
);
378 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
, tmp
);
380 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
,
381 nphy
->rfctrl_intc1_save
);
382 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
,
383 nphy
->rfctrl_intc2_save
);
387 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
388 static void b43_nphy_tx_lp_fbw(struct b43_wldev
*dev
)
390 struct b43_phy_n
*nphy
= dev
->phy
.n
;
392 enum ieee80211_band band
= b43_current_band(dev
->wl
);
393 bool ipa
= (nphy
->ipa2g_on
&& band
== IEEE80211_BAND_2GHZ
) ||
394 (nphy
->ipa5g_on
&& band
== IEEE80211_BAND_5GHZ
);
396 if (dev
->phy
.rev
>= 3) {
399 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B32S2
,
400 (((((tmp
<< 3) | tmp
) << 3) | tmp
) << 3) | tmp
);
404 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B1S2
,
405 (((((tmp
<< 3) | tmp
) << 3) | tmp
) << 3) | tmp
);
409 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
410 static void b43_nphy_bmac_clock_fgc(struct b43_wldev
*dev
, bool force
)
414 if (dev
->phy
.type
!= B43_PHYTYPE_N
)
417 tmslow
= ssb_read32(dev
->dev
, SSB_TMSLOW
);
419 tmslow
|= SSB_TMSLOW_FGC
;
421 tmslow
&= ~SSB_TMSLOW_FGC
;
422 ssb_write32(dev
->dev
, SSB_TMSLOW
, tmslow
);
425 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
426 static void b43_nphy_reset_cca(struct b43_wldev
*dev
)
430 b43_nphy_bmac_clock_fgc(dev
, 1);
431 bbcfg
= b43_phy_read(dev
, B43_NPHY_BBCFG
);
432 b43_phy_write(dev
, B43_NPHY_BBCFG
, bbcfg
| B43_NPHY_BBCFG_RSTCCA
);
434 b43_phy_write(dev
, B43_NPHY_BBCFG
, bbcfg
& ~B43_NPHY_BBCFG_RSTCCA
);
435 b43_nphy_bmac_clock_fgc(dev
, 0);
436 b43_nphy_force_rf_sequence(dev
, B43_RFSEQ_RESET2RX
);
439 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
440 static void b43_nphy_update_mimo_config(struct b43_wldev
*dev
, s32 preamble
)
442 u16 mimocfg
= b43_phy_read(dev
, B43_NPHY_MIMOCFG
);
444 mimocfg
|= B43_NPHY_MIMOCFG_AUTO
;
446 mimocfg
|= B43_NPHY_MIMOCFG_GFMIX
;
448 mimocfg
&= ~B43_NPHY_MIMOCFG_GFMIX
;
450 b43_phy_write(dev
, B43_NPHY_MIMOCFG
, mimocfg
);
453 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
454 static void b43_nphy_update_txrx_chain(struct b43_wldev
*dev
)
456 struct b43_phy_n
*nphy
= dev
->phy
.n
;
458 bool override
= false;
461 if (nphy
->txrx_chain
== 0) {
464 } else if (nphy
->txrx_chain
== 1) {
469 b43_phy_maskset(dev
, B43_NPHY_RFSEQCA
,
470 ~(B43_NPHY_RFSEQCA_TXEN
| B43_NPHY_RFSEQCA_RXEN
),
474 b43_phy_set(dev
, B43_NPHY_RFSEQMODE
,
475 B43_NPHY_RFSEQMODE_CAOVER
);
477 b43_phy_mask(dev
, B43_NPHY_RFSEQMODE
,
478 ~B43_NPHY_RFSEQMODE_CAOVER
);
481 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
482 static void b43_nphy_rx_iq_est(struct b43_wldev
*dev
, struct nphy_iq_est
*est
,
483 u16 samps
, u8 time
, bool wait
)
488 b43_phy_write(dev
, B43_NPHY_IQEST_SAMCNT
, samps
);
489 b43_phy_maskset(dev
, B43_NPHY_IQEST_WT
, ~B43_NPHY_IQEST_WT_VAL
, time
);
491 b43_phy_set(dev
, B43_NPHY_IQEST_CMD
, B43_NPHY_IQEST_CMD_MODE
);
493 b43_phy_mask(dev
, B43_NPHY_IQEST_CMD
, ~B43_NPHY_IQEST_CMD_MODE
);
495 b43_phy_set(dev
, B43_NPHY_IQEST_CMD
, B43_NPHY_IQEST_CMD_START
);
497 for (i
= 1000; i
; i
--) {
498 tmp
= b43_phy_read(dev
, B43_NPHY_IQEST_CMD
);
499 if (!(tmp
& B43_NPHY_IQEST_CMD_START
)) {
500 est
->i0_pwr
= (b43_phy_read(dev
, B43_NPHY_IQEST_IPACC_HI0
) << 16) |
501 b43_phy_read(dev
, B43_NPHY_IQEST_IPACC_LO0
);
502 est
->q0_pwr
= (b43_phy_read(dev
, B43_NPHY_IQEST_QPACC_HI0
) << 16) |
503 b43_phy_read(dev
, B43_NPHY_IQEST_QPACC_LO0
);
504 est
->iq0_prod
= (b43_phy_read(dev
, B43_NPHY_IQEST_IQACC_HI0
) << 16) |
505 b43_phy_read(dev
, B43_NPHY_IQEST_IQACC_LO0
);
507 est
->i1_pwr
= (b43_phy_read(dev
, B43_NPHY_IQEST_IPACC_HI1
) << 16) |
508 b43_phy_read(dev
, B43_NPHY_IQEST_IPACC_LO1
);
509 est
->q1_pwr
= (b43_phy_read(dev
, B43_NPHY_IQEST_QPACC_HI1
) << 16) |
510 b43_phy_read(dev
, B43_NPHY_IQEST_QPACC_LO1
);
511 est
->iq1_prod
= (b43_phy_read(dev
, B43_NPHY_IQEST_IQACC_HI1
) << 16) |
512 b43_phy_read(dev
, B43_NPHY_IQEST_IQACC_LO1
);
517 memset(est
, 0, sizeof(*est
));
520 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
521 static void b43_nphy_rx_iq_coeffs(struct b43_wldev
*dev
, bool write
,
522 struct b43_phy_n_iq_comp
*pcomp
)
525 b43_phy_write(dev
, B43_NPHY_C1_RXIQ_COMPA0
, pcomp
->a0
);
526 b43_phy_write(dev
, B43_NPHY_C1_RXIQ_COMPB0
, pcomp
->b0
);
527 b43_phy_write(dev
, B43_NPHY_C2_RXIQ_COMPA1
, pcomp
->a1
);
528 b43_phy_write(dev
, B43_NPHY_C2_RXIQ_COMPB1
, pcomp
->b1
);
530 pcomp
->a0
= b43_phy_read(dev
, B43_NPHY_C1_RXIQ_COMPA0
);
531 pcomp
->b0
= b43_phy_read(dev
, B43_NPHY_C1_RXIQ_COMPB0
);
532 pcomp
->a1
= b43_phy_read(dev
, B43_NPHY_C2_RXIQ_COMPA1
);
533 pcomp
->b1
= b43_phy_read(dev
, B43_NPHY_C2_RXIQ_COMPB1
);
537 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
538 static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev
*dev
, u8 core
)
540 u16
*regs
= dev
->phy
.n
->tx_rx_cal_phy_saveregs
;
542 b43_phy_write(dev
, B43_NPHY_RFSEQCA
, regs
[0]);
544 b43_phy_write(dev
, B43_NPHY_AFECTL_C1
, regs
[1]);
545 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER1
, regs
[2]);
547 b43_phy_write(dev
, B43_NPHY_AFECTL_C2
, regs
[1]);
548 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
, regs
[2]);
550 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
, regs
[3]);
551 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
, regs
[4]);
552 b43_phy_write(dev
, B43_NPHY_RFCTL_RSSIO1
, regs
[5]);
553 b43_phy_write(dev
, B43_NPHY_RFCTL_RSSIO2
, regs
[6]);
554 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B1S1
, regs
[7]);
555 b43_phy_write(dev
, B43_NPHY_RFCTL_OVER
, regs
[8]);
556 b43_phy_write(dev
, B43_NPHY_PAPD_EN0
, regs
[9]);
557 b43_phy_write(dev
, B43_NPHY_PAPD_EN1
, regs
[10]);
560 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
561 static void b43_nphy_rx_cal_phy_setup(struct b43_wldev
*dev
, u8 core
)
564 u16
*regs
= dev
->phy
.n
->tx_rx_cal_phy_saveregs
;
566 regs
[0] = b43_phy_read(dev
, B43_NPHY_RFSEQCA
);
568 regs
[1] = b43_phy_read(dev
, B43_NPHY_AFECTL_C1
);
569 regs
[2] = b43_phy_read(dev
, B43_NPHY_AFECTL_OVER1
);
571 regs
[1] = b43_phy_read(dev
, B43_NPHY_AFECTL_C2
);
572 regs
[2] = b43_phy_read(dev
, B43_NPHY_AFECTL_OVER
);
574 regs
[3] = b43_phy_read(dev
, B43_NPHY_RFCTL_INTC1
);
575 regs
[4] = b43_phy_read(dev
, B43_NPHY_RFCTL_INTC2
);
576 regs
[5] = b43_phy_read(dev
, B43_NPHY_RFCTL_RSSIO1
);
577 regs
[6] = b43_phy_read(dev
, B43_NPHY_RFCTL_RSSIO2
);
578 regs
[7] = b43_phy_read(dev
, B43_NPHY_TXF_40CO_B1S1
);
579 regs
[8] = b43_phy_read(dev
, B43_NPHY_RFCTL_OVER
);
580 regs
[9] = b43_phy_read(dev
, B43_NPHY_PAPD_EN0
);
581 regs
[10] = b43_phy_read(dev
, B43_NPHY_PAPD_EN1
);
583 b43_phy_mask(dev
, B43_NPHY_PAPD_EN0
, ~0x0001);
584 b43_phy_mask(dev
, B43_NPHY_PAPD_EN1
, ~0x0001);
586 b43_phy_maskset(dev
, B43_NPHY_RFSEQCA
, (u16
)~B43_NPHY_RFSEQCA_RXDIS
,
587 ((1 - core
) << B43_NPHY_RFSEQCA_RXDIS_SHIFT
));
588 b43_phy_maskset(dev
, B43_NPHY_RFSEQCA
, ~B43_NPHY_RFSEQCA_TXEN
,
589 ((1 - core
) << B43_NPHY_RFSEQCA_TXEN_SHIFT
));
590 b43_phy_maskset(dev
, B43_NPHY_RFSEQCA
, ~B43_NPHY_RFSEQCA_RXEN
,
591 (core
<< B43_NPHY_RFSEQCA_RXEN_SHIFT
));
592 b43_phy_maskset(dev
, B43_NPHY_RFSEQCA
, ~B43_NPHY_RFSEQCA_TXDIS
,
593 (core
<< B43_NPHY_RFSEQCA_TXDIS_SHIFT
));
596 b43_phy_mask(dev
, B43_NPHY_AFECTL_C1
, ~0x0007);
597 b43_phy_set(dev
, B43_NPHY_AFECTL_OVER1
, 0x0007);
599 b43_phy_mask(dev
, B43_NPHY_AFECTL_C2
, ~0x0007);
600 b43_phy_set(dev
, B43_NPHY_AFECTL_OVER
, 0x0007);
603 /* TODO: Call N PHY RF Ctrl Intc Override with 2, 0, 3 as arguments */
604 /* TODO: Call N PHY RF Intc Override with 8, 0, 3, 0 as arguments */
605 b43_nphy_force_rf_sequence(dev
, B43_RFSEQ_RX2TX
);
615 /* TODO: Call N PHY RF Ctrl Intc Override with 1, rxval, (core + 1) */
616 /* TODO: Call N PHY RF Ctrl Intc Override with 1, txval, (2 - core) */
619 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
620 static void b43_nphy_calc_rx_iq_comp(struct b43_wldev
*dev
, u8 mask
)
626 int iq_nbits
, qq_nbits
;
630 struct nphy_iq_est est
;
631 struct b43_phy_n_iq_comp old
;
632 struct b43_phy_n_iq_comp
new = { };
638 b43_nphy_rx_iq_coeffs(dev
, false, &old
);
639 b43_nphy_rx_iq_coeffs(dev
, true, &new);
640 b43_nphy_rx_iq_est(dev
, &est
, 0x4000, 32, false);
643 for (i
= 0; i
< 2; i
++) {
644 if (i
== 0 && (mask
& 1)) {
648 } else if (i
== 1 && (mask
& 2)) {
662 iq_nbits
= fls(abs(iq
));
665 arsh
= iq_nbits
- 20;
667 a
= -((iq
<< (30 - iq_nbits
)) + (ii
>> (1 + arsh
)));
670 a
= -((iq
<< (30 - iq_nbits
)) + (ii
<< (-1 - arsh
)));
679 brsh
= qq_nbits
- 11;
681 b
= (qq
<< (31 - qq_nbits
));
684 b
= (qq
<< (31 - qq_nbits
));
691 b
= int_sqrt(b
/ tmp
- a
* a
) - (1 << 10);
693 if (i
== 0 && (mask
& 0x1)) {
694 if (dev
->phy
.rev
>= 3) {
701 } else if (i
== 1 && (mask
& 0x2)) {
702 if (dev
->phy
.rev
>= 3) {
715 b43_nphy_rx_iq_coeffs(dev
, true, &new);
718 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
719 static void b43_nphy_tx_iq_workaround(struct b43_wldev
*dev
)
724 b43_phy_write(dev
, B43_NPHY_TABLE_ADDR
, 0x3C50);
725 for (i
= 0; i
< 4; i
++)
726 array
[i
] = b43_phy_read(dev
, B43_NPHY_TABLE_DATALO
);
728 b43_shm_write16(dev
, B43_SHM_SHARED
, B43_SHM_SH_NPHY_TXIQW0
, array
[0]);
729 b43_shm_write16(dev
, B43_SHM_SHARED
, B43_SHM_SH_NPHY_TXIQW1
, array
[1]);
730 b43_shm_write16(dev
, B43_SHM_SHARED
, B43_SHM_SH_NPHY_TXIQW2
, array
[2]);
731 b43_shm_write16(dev
, B43_SHM_SHARED
, B43_SHM_SH_NPHY_TXIQW3
, array
[3]);
734 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
735 static void b43_nphy_write_clip_detection(struct b43_wldev
*dev
, u16
*clip_st
)
737 b43_phy_write(dev
, B43_NPHY_C1_CLIP1THRES
, clip_st
[0]);
738 b43_phy_write(dev
, B43_NPHY_C2_CLIP1THRES
, clip_st
[1]);
741 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
742 static void b43_nphy_read_clip_detection(struct b43_wldev
*dev
, u16
*clip_st
)
744 clip_st
[0] = b43_phy_read(dev
, B43_NPHY_C1_CLIP1THRES
);
745 clip_st
[1] = b43_phy_read(dev
, B43_NPHY_C2_CLIP1THRES
);
748 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
749 static u16
b43_nphy_classifier(struct b43_wldev
*dev
, u16 mask
, u16 val
)
753 if (dev
->dev
->id
.revision
== 16)
754 b43_mac_suspend(dev
);
756 tmp
= b43_phy_read(dev
, B43_NPHY_CLASSCTL
);
757 tmp
&= (B43_NPHY_CLASSCTL_CCKEN
| B43_NPHY_CLASSCTL_OFDMEN
|
758 B43_NPHY_CLASSCTL_WAITEDEN
);
761 b43_phy_maskset(dev
, B43_NPHY_CLASSCTL
, 0xFFF8, tmp
);
763 if (dev
->dev
->id
.revision
== 16)
769 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
770 static void b43_nphy_stay_in_carrier_search(struct b43_wldev
*dev
, bool enable
)
772 struct b43_phy
*phy
= &dev
->phy
;
773 struct b43_phy_n
*nphy
= phy
->n
;
776 u16 clip
[] = { 0xFFFF, 0xFFFF };
777 if (nphy
->deaf_count
++ == 0) {
778 nphy
->classifier_state
= b43_nphy_classifier(dev
, 0, 0);
779 b43_nphy_classifier(dev
, 0x7, 0);
780 b43_nphy_read_clip_detection(dev
, nphy
->clip_state
);
781 b43_nphy_write_clip_detection(dev
, clip
);
783 b43_nphy_reset_cca(dev
);
785 if (--nphy
->deaf_count
== 0) {
786 b43_nphy_classifier(dev
, 0x7, nphy
->classifier_state
);
787 b43_nphy_write_clip_detection(dev
, nphy
->clip_state
);
792 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
793 static void b43_nphy_stop_playback(struct b43_wldev
*dev
)
795 struct b43_phy_n
*nphy
= dev
->phy
.n
;
798 if (nphy
->hang_avoid
)
799 b43_nphy_stay_in_carrier_search(dev
, 1);
801 tmp
= b43_phy_read(dev
, B43_NPHY_SAMP_STAT
);
803 b43_phy_set(dev
, B43_NPHY_SAMP_CMD
, B43_NPHY_SAMP_CMD_STOP
);
805 b43_phy_mask(dev
, B43_NPHY_IQLOCAL_CMDGCTL
, (u16
)~0x8000);
807 b43_phy_mask(dev
, B43_NPHY_SAMP_CMD
, ~0x0004);
809 if (nphy
->bb_mult_save
& 0x80000000) {
810 tmp
= nphy
->bb_mult_save
& 0xFFFF;
811 b43_ntab_write(dev
, B43_NTAB16(15, 87), tmp
);
812 nphy
->bb_mult_save
= 0;
815 if (nphy
->hang_avoid
)
816 b43_nphy_stay_in_carrier_search(dev
, 0);
819 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
820 static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev
*dev
)
822 struct b43_phy_n
*nphy
= dev
->phy
.n
;
825 u32 cur_real
, cur_imag
, real_part
, imag_part
;
829 if (nphy
->hang_avoid
)
830 b43_nphy_stay_in_carrier_search(dev
, true);
832 b43_ntab_read_bulk(dev
, B43_NTAB16(15, 80), 7, buffer
);
834 for (i
= 0; i
< 2; i
++) {
835 tmp
= ((buffer
[i
* 2] & 0x3FF) << 10) |
836 (buffer
[i
* 2 + 1] & 0x3FF);
837 b43_phy_write(dev
, B43_NPHY_TABLE_ADDR
,
838 (((i
+ 26) << 10) | 320));
839 for (j
= 0; j
< 128; j
++) {
840 b43_phy_write(dev
, B43_NPHY_TABLE_DATAHI
,
841 ((tmp
>> 16) & 0xFFFF));
842 b43_phy_write(dev
, B43_NPHY_TABLE_DATALO
,
847 for (i
= 0; i
< 2; i
++) {
849 real_part
= (tmp
>> 8) & 0xFF;
850 imag_part
= (tmp
& 0xFF);
851 b43_phy_write(dev
, B43_NPHY_TABLE_ADDR
,
852 (((i
+ 26) << 10) | 448));
854 if (dev
->phy
.rev
>= 3) {
855 cur_real
= real_part
;
856 cur_imag
= imag_part
;
857 tmp
= ((cur_real
& 0xFF) << 8) | (cur_imag
& 0xFF);
860 for (j
= 0; j
< 128; j
++) {
861 if (dev
->phy
.rev
< 3) {
862 cur_real
= (real_part
* loscale
[j
] + 128) >> 8;
863 cur_imag
= (imag_part
* loscale
[j
] + 128) >> 8;
864 tmp
= ((cur_real
& 0xFF) << 8) |
867 b43_phy_write(dev
, B43_NPHY_TABLE_DATAHI
,
868 ((tmp
>> 16) & 0xFFFF));
869 b43_phy_write(dev
, B43_NPHY_TABLE_DATALO
,
874 if (dev
->phy
.rev
>= 3) {
875 b43_shm_write16(dev
, B43_SHM_SHARED
,
876 B43_SHM_SH_NPHY_TXPWR_INDX0
, 0xFFFF);
877 b43_shm_write16(dev
, B43_SHM_SHARED
,
878 B43_SHM_SH_NPHY_TXPWR_INDX1
, 0xFFFF);
881 if (nphy
->hang_avoid
)
882 b43_nphy_stay_in_carrier_search(dev
, false);
885 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
886 static void b43_nphy_force_rf_sequence(struct b43_wldev
*dev
,
887 enum b43_nphy_rf_sequence seq
)
889 static const u16 trigger
[] = {
890 [B43_RFSEQ_RX2TX
] = B43_NPHY_RFSEQTR_RX2TX
,
891 [B43_RFSEQ_TX2RX
] = B43_NPHY_RFSEQTR_TX2RX
,
892 [B43_RFSEQ_RESET2RX
] = B43_NPHY_RFSEQTR_RST2RX
,
893 [B43_RFSEQ_UPDATE_GAINH
] = B43_NPHY_RFSEQTR_UPGH
,
894 [B43_RFSEQ_UPDATE_GAINL
] = B43_NPHY_RFSEQTR_UPGL
,
895 [B43_RFSEQ_UPDATE_GAINU
] = B43_NPHY_RFSEQTR_UPGU
,
898 u16 seq_mode
= b43_phy_read(dev
, B43_NPHY_RFSEQMODE
);
900 B43_WARN_ON(seq
>= ARRAY_SIZE(trigger
));
902 b43_phy_set(dev
, B43_NPHY_RFSEQMODE
,
903 B43_NPHY_RFSEQMODE_CAOVER
| B43_NPHY_RFSEQMODE_TROVER
);
904 b43_phy_set(dev
, B43_NPHY_RFSEQTR
, trigger
[seq
]);
905 for (i
= 0; i
< 200; i
++) {
906 if (!(b43_phy_read(dev
, B43_NPHY_RFSEQST
) & trigger
[seq
]))
910 b43err(dev
->wl
, "RF sequence status timeout\n");
912 b43_phy_write(dev
, B43_NPHY_RFSEQMODE
, seq_mode
);
915 static void b43_nphy_bphy_init(struct b43_wldev
*dev
)
921 for (i
= 0; i
< 14; i
++) {
922 b43_phy_write(dev
, B43_PHY_N_BMODE(0x88 + i
), val
);
926 for (i
= 0; i
< 16; i
++) {
927 b43_phy_write(dev
, B43_PHY_N_BMODE(0x97 + i
), val
);
930 b43_phy_write(dev
, B43_PHY_N_BMODE(0x38), 0x668);
933 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
934 static void b43_nphy_scale_offset_rssi(struct b43_wldev
*dev
, u16 scale
,
935 s8 offset
, u8 core
, u8 rail
, u8 type
)
938 bool core1or5
= (core
== 1) || (core
== 5);
939 bool core2or5
= (core
== 2) || (core
== 5);
941 offset
= clamp_val(offset
, -32, 31);
942 tmp
= ((scale
& 0x3F) << 8) | (offset
& 0x3F);
944 if (core1or5
&& (rail
== 0) && (type
== 2))
945 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_RSSI_Z
, tmp
);
946 if (core1or5
&& (rail
== 1) && (type
== 2))
947 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_RSSI_Z
, tmp
);
948 if (core2or5
&& (rail
== 0) && (type
== 2))
949 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_RSSI_Z
, tmp
);
950 if (core2or5
&& (rail
== 1) && (type
== 2))
951 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_RSSI_Z
, tmp
);
952 if (core1or5
&& (rail
== 0) && (type
== 0))
953 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_RSSI_X
, tmp
);
954 if (core1or5
&& (rail
== 1) && (type
== 0))
955 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_RSSI_X
, tmp
);
956 if (core2or5
&& (rail
== 0) && (type
== 0))
957 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_RSSI_X
, tmp
);
958 if (core2or5
&& (rail
== 1) && (type
== 0))
959 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_RSSI_X
, tmp
);
960 if (core1or5
&& (rail
== 0) && (type
== 1))
961 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_RSSI_Y
, tmp
);
962 if (core1or5
&& (rail
== 1) && (type
== 1))
963 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_RSSI_Y
, tmp
);
964 if (core2or5
&& (rail
== 0) && (type
== 1))
965 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_RSSI_Y
, tmp
);
966 if (core2or5
&& (rail
== 1) && (type
== 1))
967 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_RSSI_Y
, tmp
);
968 if (core1or5
&& (rail
== 0) && (type
== 6))
969 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_TBD
, tmp
);
970 if (core1or5
&& (rail
== 1) && (type
== 6))
971 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_TBD
, tmp
);
972 if (core2or5
&& (rail
== 0) && (type
== 6))
973 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_TBD
, tmp
);
974 if (core2or5
&& (rail
== 1) && (type
== 6))
975 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_TBD
, tmp
);
976 if (core1or5
&& (rail
== 0) && (type
== 3))
977 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_PWRDET
, tmp
);
978 if (core1or5
&& (rail
== 1) && (type
== 3))
979 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_PWRDET
, tmp
);
980 if (core2or5
&& (rail
== 0) && (type
== 3))
981 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_PWRDET
, tmp
);
982 if (core2or5
&& (rail
== 1) && (type
== 3))
983 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_PWRDET
, tmp
);
984 if (core1or5
&& (type
== 4))
985 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_TSSI
, tmp
);
986 if (core2or5
&& (type
== 4))
987 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_TSSI
, tmp
);
988 if (core1or5
&& (type
== 5))
989 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_TSSI
, tmp
);
990 if (core2or5
&& (type
== 5))
991 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_TSSI
, tmp
);
994 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
995 static void b43_nphy_rssi_select(struct b43_wldev
*dev
, u8 code
, u8 type
)
999 if (dev
->phy
.rev
>= 3) {
1011 val
= (val
<< 12) | (val
<< 14);
1012 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C1
, 0x0FFF, val
);
1013 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C2
, 0x0FFF, val
);
1016 b43_phy_maskset(dev
, B43_NPHY_RFCTL_RSSIO1
, 0xFFCF,
1018 b43_phy_maskset(dev
, B43_NPHY_RFCTL_RSSIO2
, 0xFFCF,
1022 /* TODO use some definitions */
1024 b43_phy_maskset(dev
, B43_NPHY_AFECTL_OVER
, 0xCFFF, 0);
1026 b43_phy_maskset(dev
, B43_NPHY_RFCTL_CMD
,
1028 b43_phy_maskset(dev
, B43_NPHY_RFCTL_OVER
,
1030 b43_phy_maskset(dev
, B43_NPHY_RFCTL_CMD
,
1033 b43_phy_maskset(dev
, B43_NPHY_RFCTL_OVER
,
1037 b43_phy_maskset(dev
, B43_NPHY_AFECTL_OVER
, 0xCFFF,
1040 b43_phy_maskset(dev
, B43_NPHY_RFCTL_CMD
,
1042 b43_phy_maskset(dev
, B43_NPHY_RFCTL_OVER
,
1043 0xEFDC, (code
<< 1 | 0x1021));
1044 b43_phy_maskset(dev
, B43_NPHY_RFCTL_CMD
,
1047 b43_phy_maskset(dev
, B43_NPHY_RFCTL_OVER
,
1054 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
1055 static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev
*dev
, u8 type
, u8
*buf
)
1058 for (i
= 0; i
< 2; i
++) {
1061 b43_radio_maskset(dev
, B2055_C1_B0NB_RSSIVCM
,
1063 b43_radio_maskset(dev
, B2055_C1_RX_BB_RSSICTL5
,
1066 b43_radio_maskset(dev
, B2055_C2_B0NB_RSSIVCM
,
1068 b43_radio_maskset(dev
, B2055_C2_RX_BB_RSSICTL5
,
1069 0xFC, buf
[2 * i
+ 1]);
1073 b43_radio_maskset(dev
, B2055_C1_RX_BB_RSSICTL5
,
1076 b43_radio_maskset(dev
, B2055_C2_RX_BB_RSSICTL5
,
1077 0xF3, buf
[2 * i
+ 1] << 2);
1082 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
1083 static int b43_nphy_poll_rssi(struct b43_wldev
*dev
, u8 type
, s32
*buf
,
1088 u16 save_regs_phy
[9];
1091 if (dev
->phy
.rev
>= 3) {
1092 save_regs_phy
[0] = b43_phy_read(dev
,
1093 B43_NPHY_RFCTL_LUT_TRSW_UP1
);
1094 save_regs_phy
[1] = b43_phy_read(dev
,
1095 B43_NPHY_RFCTL_LUT_TRSW_UP2
);
1096 save_regs_phy
[2] = b43_phy_read(dev
, B43_NPHY_AFECTL_C1
);
1097 save_regs_phy
[3] = b43_phy_read(dev
, B43_NPHY_AFECTL_C2
);
1098 save_regs_phy
[4] = b43_phy_read(dev
, B43_NPHY_AFECTL_OVER1
);
1099 save_regs_phy
[5] = b43_phy_read(dev
, B43_NPHY_AFECTL_OVER
);
1100 save_regs_phy
[6] = b43_phy_read(dev
, B43_NPHY_TXF_40CO_B1S0
);
1101 save_regs_phy
[7] = b43_phy_read(dev
, B43_NPHY_TXF_40CO_B32S1
);
1104 b43_nphy_rssi_select(dev
, 5, type
);
1106 if (dev
->phy
.rev
< 2) {
1107 save_regs_phy
[8] = b43_phy_read(dev
, B43_NPHY_GPIO_SEL
);
1108 b43_phy_write(dev
, B43_NPHY_GPIO_SEL
, 5);
1111 for (i
= 0; i
< 4; i
++)
1114 for (i
= 0; i
< nsamp
; i
++) {
1115 if (dev
->phy
.rev
< 2) {
1116 s
[0] = b43_phy_read(dev
, B43_NPHY_GPIO_LOOUT
);
1117 s
[1] = b43_phy_read(dev
, B43_NPHY_GPIO_HIOUT
);
1119 s
[0] = b43_phy_read(dev
, B43_NPHY_RSSI1
);
1120 s
[1] = b43_phy_read(dev
, B43_NPHY_RSSI2
);
1123 buf
[0] += ((s8
)((s
[0] & 0x3F) << 2)) >> 2;
1124 buf
[1] += ((s8
)(((s
[0] >> 8) & 0x3F) << 2)) >> 2;
1125 buf
[2] += ((s8
)((s
[1] & 0x3F) << 2)) >> 2;
1126 buf
[3] += ((s8
)(((s
[1] >> 8) & 0x3F) << 2)) >> 2;
1128 out
= (buf
[0] & 0xFF) << 24 | (buf
[1] & 0xFF) << 16 |
1129 (buf
[2] & 0xFF) << 8 | (buf
[3] & 0xFF);
1131 if (dev
->phy
.rev
< 2)
1132 b43_phy_write(dev
, B43_NPHY_GPIO_SEL
, save_regs_phy
[8]);
1134 if (dev
->phy
.rev
>= 3) {
1135 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_UP1
,
1137 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_UP2
,
1139 b43_phy_write(dev
, B43_NPHY_AFECTL_C1
, save_regs_phy
[2]);
1140 b43_phy_write(dev
, B43_NPHY_AFECTL_C2
, save_regs_phy
[3]);
1141 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER1
, save_regs_phy
[4]);
1142 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
, save_regs_phy
[5]);
1143 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B1S0
, save_regs_phy
[6]);
1144 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B32S1
, save_regs_phy
[7]);
1150 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
1151 static void b43_nphy_rev2_rssi_cal(struct b43_wldev
*dev
, u8 type
)
1156 u16
class, override
;
1157 u8 regs_save_radio
[2];
1158 u16 regs_save_phy
[2];
1162 u16 clip_off
[2] = { 0xFFFF, 0xFFFF };
1163 s32 results_min
[4] = { };
1164 u8 vcm_final
[4] = { };
1165 s32 results
[4][4] = { };
1166 s32 miniq
[4][2] = { };
1171 } else if (type
< 2) {
1179 class = b43_nphy_classifier(dev
, 0, 0);
1180 b43_nphy_classifier(dev
, 7, 4);
1181 b43_nphy_read_clip_detection(dev
, clip_state
);
1182 b43_nphy_write_clip_detection(dev
, clip_off
);
1184 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_5GHZ
)
1189 regs_save_phy
[0] = b43_phy_read(dev
, B43_NPHY_RFCTL_INTC1
);
1190 regs_save_radio
[0] = b43_radio_read16(dev
, B2055_C1_PD_RXTX
);
1191 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
, override
);
1192 b43_radio_write16(dev
, B2055_C1_PD_RXTX
, val
);
1194 regs_save_phy
[1] = b43_phy_read(dev
, B43_NPHY_RFCTL_INTC2
);
1195 regs_save_radio
[1] = b43_radio_read16(dev
, B2055_C2_PD_RXTX
);
1196 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
, override
);
1197 b43_radio_write16(dev
, B2055_C2_PD_RXTX
, val
);
1199 state
[0] = b43_radio_read16(dev
, B2055_C1_PD_RSSIMISC
) & 0x07;
1200 state
[1] = b43_radio_read16(dev
, B2055_C2_PD_RSSIMISC
) & 0x07;
1201 b43_radio_mask(dev
, B2055_C1_PD_RSSIMISC
, 0xF8);
1202 b43_radio_mask(dev
, B2055_C2_PD_RSSIMISC
, 0xF8);
1203 state
[2] = b43_radio_read16(dev
, B2055_C1_SP_RSSI
) & 0x07;
1204 state
[3] = b43_radio_read16(dev
, B2055_C2_SP_RSSI
) & 0x07;
1206 b43_nphy_rssi_select(dev
, 5, type
);
1207 b43_nphy_scale_offset_rssi(dev
, 0, 0, 5, 0, type
);
1208 b43_nphy_scale_offset_rssi(dev
, 0, 0, 5, 1, type
);
1210 for (i
= 0; i
< 4; i
++) {
1212 for (j
= 0; j
< 4; j
++)
1215 b43_nphy_set_rssi_2055_vcm(dev
, type
, tmp
);
1216 b43_nphy_poll_rssi(dev
, type
, results
[i
], 8);
1218 for (j
= 0; j
< 2; j
++)
1219 miniq
[i
][j
] = min(results
[i
][2 * j
],
1220 results
[i
][2 * j
+ 1]);
1223 for (i
= 0; i
< 4; i
++) {
1228 for (j
= 0; j
< 4; j
++) {
1230 curr
= abs(results
[j
][i
]);
1232 curr
= abs(miniq
[j
][i
/ 2] - code
* 8);
1239 if (results
[j
][i
] < minpoll
)
1240 minpoll
= results
[j
][i
];
1242 results_min
[i
] = minpoll
;
1243 vcm_final
[i
] = minvcm
;
1247 b43_nphy_set_rssi_2055_vcm(dev
, type
, vcm_final
);
1249 for (i
= 0; i
< 4; i
++) {
1250 offset
[i
] = (code
* 8) - results
[vcm_final
[i
]][i
];
1253 offset
[i
] = -((abs(offset
[i
]) + 4) / 8);
1255 offset
[i
] = (offset
[i
] + 4) / 8;
1257 if (results_min
[i
] == 248)
1258 offset
[i
] = code
- 32;
1261 b43_nphy_scale_offset_rssi(dev
, 0, offset
[i
], 1, 0,
1264 b43_nphy_scale_offset_rssi(dev
, 0, offset
[i
], 2, 1,
1268 b43_radio_maskset(dev
, B2055_C1_PD_RSSIMISC
, 0xF8, state
[0]);
1269 b43_radio_maskset(dev
, B2055_C1_PD_RSSIMISC
, 0xF8, state
[1]);
1273 b43_nphy_rssi_select(dev
, 1, 2);
1276 b43_nphy_rssi_select(dev
, 1, 0);
1279 b43_nphy_rssi_select(dev
, 1, 1);
1282 b43_nphy_rssi_select(dev
, 1, 1);
1288 b43_nphy_rssi_select(dev
, 2, 2);
1291 b43_nphy_rssi_select(dev
, 2, 0);
1294 b43_nphy_rssi_select(dev
, 2, 1);
1298 b43_nphy_rssi_select(dev
, 0, type
);
1300 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
, regs_save_phy
[0]);
1301 b43_radio_write16(dev
, B2055_C1_PD_RXTX
, regs_save_radio
[0]);
1302 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
, regs_save_phy
[1]);
1303 b43_radio_write16(dev
, B2055_C2_PD_RXTX
, regs_save_radio
[1]);
1305 b43_nphy_classifier(dev
, 7, class);
1306 b43_nphy_write_clip_detection(dev
, clip_state
);
1309 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
1310 static void b43_nphy_rev3_rssi_cal(struct b43_wldev
*dev
)
1317 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
1319 static void b43_nphy_rssi_cal(struct b43_wldev
*dev
)
1321 if (dev
->phy
.rev
>= 3) {
1322 b43_nphy_rev3_rssi_cal(dev
);
1324 b43_nphy_rev2_rssi_cal(dev
, 2);
1325 b43_nphy_rev2_rssi_cal(dev
, 0);
1326 b43_nphy_rev2_rssi_cal(dev
, 1);
1331 * Restore RSSI Calibration
1332 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
1334 static void b43_nphy_restore_rssi_cal(struct b43_wldev
*dev
)
1336 struct b43_phy_n
*nphy
= dev
->phy
.n
;
1338 u16
*rssical_radio_regs
= NULL
;
1339 u16
*rssical_phy_regs
= NULL
;
1341 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
) {
1342 if (!nphy
->rssical_chanspec_2G
)
1344 rssical_radio_regs
= nphy
->rssical_cache
.rssical_radio_regs_2G
;
1345 rssical_phy_regs
= nphy
->rssical_cache
.rssical_phy_regs_2G
;
1347 if (!nphy
->rssical_chanspec_5G
)
1349 rssical_radio_regs
= nphy
->rssical_cache
.rssical_radio_regs_5G
;
1350 rssical_phy_regs
= nphy
->rssical_cache
.rssical_phy_regs_5G
;
1353 /* TODO use some definitions */
1354 b43_radio_maskset(dev
, 0x602B, 0xE3, rssical_radio_regs
[0]);
1355 b43_radio_maskset(dev
, 0x702B, 0xE3, rssical_radio_regs
[1]);
1357 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_RSSI_Z
, rssical_phy_regs
[0]);
1358 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_RSSI_Z
, rssical_phy_regs
[1]);
1359 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_RSSI_Z
, rssical_phy_regs
[2]);
1360 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_RSSI_Z
, rssical_phy_regs
[3]);
1362 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_RSSI_X
, rssical_phy_regs
[4]);
1363 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_RSSI_X
, rssical_phy_regs
[5]);
1364 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_RSSI_X
, rssical_phy_regs
[6]);
1365 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_RSSI_X
, rssical_phy_regs
[7]);
1367 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_RSSI_Y
, rssical_phy_regs
[8]);
1368 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_RSSI_Y
, rssical_phy_regs
[9]);
1369 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_RSSI_Y
, rssical_phy_regs
[10]);
1370 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_RSSI_Y
, rssical_phy_regs
[11]);
1373 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
1374 static const u32
*b43_nphy_get_ipa_gain_table(struct b43_wldev
*dev
)
1376 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
) {
1377 if (dev
->phy
.rev
>= 6) {
1378 /* TODO If the chip is 47162
1379 return txpwrctrl_tx_gain_ipa_rev5 */
1380 return txpwrctrl_tx_gain_ipa_rev6
;
1381 } else if (dev
->phy
.rev
>= 5) {
1382 return txpwrctrl_tx_gain_ipa_rev5
;
1384 return txpwrctrl_tx_gain_ipa
;
1387 return txpwrctrl_tx_gain_ipa_5g
;
1391 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
1392 static void b43_nphy_tx_cal_radio_setup(struct b43_wldev
*dev
)
1394 struct b43_phy_n
*nphy
= dev
->phy
.n
;
1395 u16
*save
= nphy
->tx_rx_cal_radio_saveregs
;
1397 if (dev
->phy
.rev
>= 3) {
1400 save
[0] = b43_radio_read16(dev
, B2055_C1_TX_RF_IQCAL1
);
1401 b43_radio_write16(dev
, B2055_C1_TX_RF_IQCAL1
, 0x29);
1403 save
[1] = b43_radio_read16(dev
, B2055_C1_TX_RF_IQCAL2
);
1404 b43_radio_write16(dev
, B2055_C1_TX_RF_IQCAL2
, 0x54);
1406 save
[2] = b43_radio_read16(dev
, B2055_C2_TX_RF_IQCAL1
);
1407 b43_radio_write16(dev
, B2055_C2_TX_RF_IQCAL1
, 0x29);
1409 save
[3] = b43_radio_read16(dev
, B2055_C2_TX_RF_IQCAL2
);
1410 b43_radio_write16(dev
, B2055_C2_TX_RF_IQCAL2
, 0x54);
1412 save
[3] = b43_radio_read16(dev
, B2055_C1_PWRDET_RXTX
);
1413 save
[4] = b43_radio_read16(dev
, B2055_C2_PWRDET_RXTX
);
1415 if (!(b43_phy_read(dev
, B43_NPHY_BANDCTL
) &
1416 B43_NPHY_BANDCTL_5GHZ
)) {
1417 b43_radio_write16(dev
, B2055_C1_PWRDET_RXTX
, 0x04);
1418 b43_radio_write16(dev
, B2055_C2_PWRDET_RXTX
, 0x04);
1420 b43_radio_write16(dev
, B2055_C1_PWRDET_RXTX
, 0x20);
1421 b43_radio_write16(dev
, B2055_C2_PWRDET_RXTX
, 0x20);
1424 if (dev
->phy
.rev
< 2) {
1425 b43_radio_set(dev
, B2055_C1_TX_BB_MXGM
, 0x20);
1426 b43_radio_set(dev
, B2055_C2_TX_BB_MXGM
, 0x20);
1428 b43_radio_mask(dev
, B2055_C1_TX_BB_MXGM
, ~0x20);
1429 b43_radio_mask(dev
, B2055_C2_TX_BB_MXGM
, ~0x20);
1434 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
1435 static void b43_nphy_iq_cal_gain_params(struct b43_wldev
*dev
, u16 core
,
1436 struct nphy_txgains target
,
1437 struct nphy_iqcal_params
*params
)
1442 if (dev
->phy
.rev
>= 3) {
1443 params
->txgm
= target
.txgm
[core
];
1444 params
->pga
= target
.pga
[core
];
1445 params
->pad
= target
.pad
[core
];
1446 params
->ipa
= target
.ipa
[core
];
1447 params
->cal_gain
= (params
->txgm
<< 12) | (params
->pga
<< 8) |
1448 (params
->pad
<< 4) | (params
->ipa
);
1449 for (j
= 0; j
< 5; j
++)
1450 params
->ncorr
[j
] = 0x79;
1452 gain
= (target
.pad
[core
]) | (target
.pga
[core
] << 4) |
1453 (target
.txgm
[core
] << 8);
1455 indx
= (b43_current_band(dev
->wl
) == IEEE80211_BAND_5GHZ
) ?
1457 for (i
= 0; i
< 9; i
++)
1458 if (tbl_iqcal_gainparams
[indx
][i
][0] == gain
)
1462 params
->txgm
= tbl_iqcal_gainparams
[indx
][i
][1];
1463 params
->pga
= tbl_iqcal_gainparams
[indx
][i
][2];
1464 params
->pad
= tbl_iqcal_gainparams
[indx
][i
][3];
1465 params
->cal_gain
= (params
->txgm
<< 7) | (params
->pga
<< 4) |
1467 for (j
= 0; j
< 4; j
++)
1468 params
->ncorr
[j
] = tbl_iqcal_gainparams
[indx
][i
][4 + j
];
1472 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
1473 static void b43_nphy_update_tx_cal_ladder(struct b43_wldev
*dev
, u16 core
)
1475 struct b43_phy_n
*nphy
= dev
->phy
.n
;
1479 u16 tmp
= nphy
->txcal_bbmult
;
1484 for (i
= 0; i
< 18; i
++) {
1485 scale
= (ladder_lo
[i
].percent
* tmp
) / 100;
1486 entry
= ((scale
& 0xFF) << 8) | ladder_lo
[i
].g_env
;
1487 b43_ntab_write(dev
, B43_NTAB16(15, i
), entry
);
1489 scale
= (ladder_iq
[i
].percent
* tmp
) / 100;
1490 entry
= ((scale
& 0xFF) << 8) | ladder_iq
[i
].g_env
;
1491 b43_ntab_write(dev
, B43_NTAB16(15, i
+ 32), entry
);
1495 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
1496 static struct nphy_txgains
b43_nphy_get_tx_gains(struct b43_wldev
*dev
)
1498 struct b43_phy_n
*nphy
= dev
->phy
.n
;
1501 struct nphy_txgains target
;
1502 const u32
*table
= NULL
;
1504 if (nphy
->txpwrctrl
== 0) {
1507 if (nphy
->hang_avoid
)
1508 b43_nphy_stay_in_carrier_search(dev
, true);
1509 b43_ntab_read_bulk(dev
, B43_NTAB16(7, 0x110), 2, curr_gain
);
1510 if (nphy
->hang_avoid
)
1511 b43_nphy_stay_in_carrier_search(dev
, false);
1513 for (i
= 0; i
< 2; ++i
) {
1514 if (dev
->phy
.rev
>= 3) {
1515 target
.ipa
[i
] = curr_gain
[i
] & 0x000F;
1516 target
.pad
[i
] = (curr_gain
[i
] & 0x00F0) >> 4;
1517 target
.pga
[i
] = (curr_gain
[i
] & 0x0F00) >> 8;
1518 target
.txgm
[i
] = (curr_gain
[i
] & 0x7000) >> 12;
1520 target
.ipa
[i
] = curr_gain
[i
] & 0x0003;
1521 target
.pad
[i
] = (curr_gain
[i
] & 0x000C) >> 2;
1522 target
.pga
[i
] = (curr_gain
[i
] & 0x0070) >> 4;
1523 target
.txgm
[i
] = (curr_gain
[i
] & 0x0380) >> 7;
1529 index
[0] = (b43_phy_read(dev
, B43_NPHY_C1_TXPCTL_STAT
) &
1530 B43_NPHY_TXPCTL_STAT_BIDX
) >>
1531 B43_NPHY_TXPCTL_STAT_BIDX_SHIFT
;
1532 index
[1] = (b43_phy_read(dev
, B43_NPHY_C2_TXPCTL_STAT
) &
1533 B43_NPHY_TXPCTL_STAT_BIDX
) >>
1534 B43_NPHY_TXPCTL_STAT_BIDX_SHIFT
;
1536 for (i
= 0; i
< 2; ++i
) {
1537 if (dev
->phy
.rev
>= 3) {
1538 enum ieee80211_band band
=
1539 b43_current_band(dev
->wl
);
1541 if ((nphy
->ipa2g_on
&&
1542 band
== IEEE80211_BAND_2GHZ
) ||
1544 band
== IEEE80211_BAND_5GHZ
)) {
1545 table
= b43_nphy_get_ipa_gain_table(dev
);
1547 if (band
== IEEE80211_BAND_5GHZ
) {
1548 if (dev
->phy
.rev
== 3)
1549 table
= b43_ntab_tx_gain_rev3_5ghz
;
1550 else if (dev
->phy
.rev
== 4)
1551 table
= b43_ntab_tx_gain_rev4_5ghz
;
1553 table
= b43_ntab_tx_gain_rev5plus_5ghz
;
1555 table
= b43_ntab_tx_gain_rev3plus_2ghz
;
1559 target
.ipa
[i
] = (table
[index
[i
]] >> 16) & 0xF;
1560 target
.pad
[i
] = (table
[index
[i
]] >> 20) & 0xF;
1561 target
.pga
[i
] = (table
[index
[i
]] >> 24) & 0xF;
1562 target
.txgm
[i
] = (table
[index
[i
]] >> 28) & 0xF;
1564 table
= b43_ntab_tx_gain_rev0_1_2
;
1566 target
.ipa
[i
] = (table
[index
[i
]] >> 16) & 0x3;
1567 target
.pad
[i
] = (table
[index
[i
]] >> 18) & 0x3;
1568 target
.pga
[i
] = (table
[index
[i
]] >> 20) & 0x7;
1569 target
.txgm
[i
] = (table
[index
[i
]] >> 23) & 0x7;
1577 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
1578 static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev
*dev
)
1580 u16
*regs
= dev
->phy
.n
->tx_rx_cal_phy_saveregs
;
1582 if (dev
->phy
.rev
>= 3) {
1583 b43_phy_write(dev
, B43_NPHY_AFECTL_C1
, regs
[0]);
1584 b43_phy_write(dev
, B43_NPHY_AFECTL_C2
, regs
[1]);
1585 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER1
, regs
[2]);
1586 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
, regs
[3]);
1587 b43_phy_write(dev
, B43_NPHY_BBCFG
, regs
[4]);
1588 b43_ntab_write(dev
, B43_NTAB16(8, 3), regs
[5]);
1589 b43_ntab_write(dev
, B43_NTAB16(8, 19), regs
[6]);
1590 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
, regs
[7]);
1591 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
, regs
[8]);
1592 b43_phy_write(dev
, B43_NPHY_PAPD_EN0
, regs
[9]);
1593 b43_phy_write(dev
, B43_NPHY_PAPD_EN1
, regs
[10]);
1594 b43_nphy_reset_cca(dev
);
1596 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C1
, 0x0FFF, regs
[0]);
1597 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C2
, 0x0FFF, regs
[1]);
1598 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
, regs
[2]);
1599 b43_ntab_write(dev
, B43_NTAB16(8, 2), regs
[3]);
1600 b43_ntab_write(dev
, B43_NTAB16(8, 18), regs
[4]);
1601 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
, regs
[5]);
1602 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
, regs
[6]);
1606 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
1607 static void b43_nphy_tx_cal_phy_setup(struct b43_wldev
*dev
)
1609 u16
*regs
= dev
->phy
.n
->tx_rx_cal_phy_saveregs
;
1612 regs
[0] = b43_phy_read(dev
, B43_NPHY_AFECTL_C1
);
1613 regs
[1] = b43_phy_read(dev
, B43_NPHY_AFECTL_C2
);
1614 if (dev
->phy
.rev
>= 3) {
1615 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C1
, 0xF0FF, 0x0A00);
1616 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C2
, 0xF0FF, 0x0A00);
1618 tmp
= b43_phy_read(dev
, B43_NPHY_AFECTL_OVER1
);
1620 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER1
, tmp
| 0x0600);
1622 tmp
= b43_phy_read(dev
, B43_NPHY_AFECTL_OVER
);
1624 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
, tmp
| 0x0600);
1626 regs
[4] = b43_phy_read(dev
, B43_NPHY_BBCFG
);
1627 b43_phy_mask(dev
, B43_NPHY_BBCFG
, (u16
)~B43_NPHY_BBCFG_RSTRX
);
1629 tmp
= b43_ntab_read(dev
, B43_NTAB16(8, 3));
1631 b43_ntab_write(dev
, B43_NTAB16(8, 3), 0);
1633 tmp
= b43_ntab_read(dev
, B43_NTAB16(8, 19));
1635 b43_ntab_write(dev
, B43_NTAB16(8, 19), 0);
1636 regs
[7] = b43_phy_read(dev
, B43_NPHY_RFCTL_INTC1
);
1637 regs
[8] = b43_phy_read(dev
, B43_NPHY_RFCTL_INTC2
);
1639 /* TODO: Call N PHY RF Ctrl Intc Override with 2, 1, 3 */
1640 /* TODO: Call N PHY RF Ctrl Intc Override with 1, 2, 1 */
1641 /* TODO: Call N PHY RF Ctrl Intc Override with 1, 8, 2 */
1643 regs
[9] = b43_phy_read(dev
, B43_NPHY_PAPD_EN0
);
1644 regs
[10] = b43_phy_read(dev
, B43_NPHY_PAPD_EN1
);
1645 b43_phy_mask(dev
, B43_NPHY_PAPD_EN0
, ~0x0001);
1646 b43_phy_mask(dev
, B43_NPHY_PAPD_EN1
, ~0x0001);
1648 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C1
, 0x0FFF, 0xA000);
1649 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C2
, 0x0FFF, 0xA000);
1650 tmp
= b43_phy_read(dev
, B43_NPHY_AFECTL_OVER
);
1652 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
, tmp
| 0x3000);
1653 tmp
= b43_ntab_read(dev
, B43_NTAB16(8, 2));
1656 b43_ntab_write(dev
, B43_NTAB16(8, 2), tmp
);
1657 tmp
= b43_ntab_read(dev
, B43_NTAB16(8, 18));
1660 b43_ntab_write(dev
, B43_NTAB16(8, 18), tmp
);
1661 regs
[5] = b43_phy_read(dev
, B43_NPHY_RFCTL_INTC1
);
1662 regs
[6] = b43_phy_read(dev
, B43_NPHY_RFCTL_INTC2
);
1663 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_5GHZ
)
1667 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
, tmp
);
1668 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
, tmp
);
1672 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
1673 static void b43_nphy_restore_cal(struct b43_wldev
*dev
)
1675 struct b43_phy_n
*nphy
= dev
->phy
.n
;
1682 u16
*txcal_radio_regs
= NULL
;
1683 struct b43_phy_n_iq_comp
*rxcal_coeffs
= NULL
;
1685 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
) {
1686 if (nphy
->iqcal_chanspec_2G
== 0)
1688 table
= nphy
->cal_cache
.txcal_coeffs_2G
;
1689 loft
= &nphy
->cal_cache
.txcal_coeffs_2G
[5];
1691 if (nphy
->iqcal_chanspec_5G
== 0)
1693 table
= nphy
->cal_cache
.txcal_coeffs_5G
;
1694 loft
= &nphy
->cal_cache
.txcal_coeffs_5G
[5];
1697 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 80), 4, table
);
1699 for (i
= 0; i
< 4; i
++) {
1700 if (dev
->phy
.rev
>= 3)
1706 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 88), 4, coef
);
1707 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 85), 2, loft
);
1708 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 93), 2, loft
);
1710 if (dev
->phy
.rev
< 2)
1711 b43_nphy_tx_iq_workaround(dev
);
1713 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
) {
1714 txcal_radio_regs
= nphy
->cal_cache
.txcal_radio_regs_2G
;
1715 rxcal_coeffs
= &nphy
->cal_cache
.rxcal_coeffs_2G
;
1717 txcal_radio_regs
= nphy
->cal_cache
.txcal_radio_regs_5G
;
1718 rxcal_coeffs
= &nphy
->cal_cache
.rxcal_coeffs_5G
;
1721 /* TODO use some definitions */
1722 if (dev
->phy
.rev
>= 3) {
1723 b43_radio_write(dev
, 0x2021, txcal_radio_regs
[0]);
1724 b43_radio_write(dev
, 0x2022, txcal_radio_regs
[1]);
1725 b43_radio_write(dev
, 0x3021, txcal_radio_regs
[2]);
1726 b43_radio_write(dev
, 0x3022, txcal_radio_regs
[3]);
1727 b43_radio_write(dev
, 0x2023, txcal_radio_regs
[4]);
1728 b43_radio_write(dev
, 0x2024, txcal_radio_regs
[5]);
1729 b43_radio_write(dev
, 0x3023, txcal_radio_regs
[6]);
1730 b43_radio_write(dev
, 0x3024, txcal_radio_regs
[7]);
1732 b43_radio_write(dev
, 0x8B, txcal_radio_regs
[0]);
1733 b43_radio_write(dev
, 0xBA, txcal_radio_regs
[1]);
1734 b43_radio_write(dev
, 0x8D, txcal_radio_regs
[2]);
1735 b43_radio_write(dev
, 0xBC, txcal_radio_regs
[3]);
1737 b43_nphy_rx_iq_coeffs(dev
, true, rxcal_coeffs
);
1740 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
1741 static int b43_nphy_cal_tx_iq_lo(struct b43_wldev
*dev
,
1742 struct nphy_txgains target
,
1743 bool full
, bool mphase
)
1745 struct b43_phy_n
*nphy
= dev
->phy
.n
;
1751 u16 tmp
, core
, type
, count
, max
, numb
, last
, cmd
;
1759 struct nphy_iqcal_params params
[2];
1760 bool updated
[2] = { };
1762 b43_nphy_stay_in_carrier_search(dev
, true);
1764 if (dev
->phy
.rev
>= 4) {
1765 avoid
= nphy
->hang_avoid
;
1766 nphy
->hang_avoid
= 0;
1769 b43_ntab_read_bulk(dev
, B43_NTAB16(7, 0x110), 2, save
);
1771 for (i
= 0; i
< 2; i
++) {
1772 b43_nphy_iq_cal_gain_params(dev
, i
, target
, ¶ms
[i
]);
1773 gain
[i
] = params
[i
].cal_gain
;
1776 b43_ntab_write_bulk(dev
, B43_NTAB16(7, 0x110), 2, gain
);
1778 b43_nphy_tx_cal_radio_setup(dev
);
1779 b43_nphy_tx_cal_phy_setup(dev
);
1781 phy6or5x
= dev
->phy
.rev
>= 6 ||
1782 (dev
->phy
.rev
== 5 && nphy
->ipa2g_on
&&
1783 b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
);
1788 b43_phy_write(dev
, B43_NPHY_IQLOCAL_CMDGCTL
, 0x8AA9);
1790 if (1 /* FIXME: the band width is 20 MHz */)
1795 if (nphy
->mphase_cal_phase_id
> 2)
1796 ;/* TODO: Call N PHY Run Samples with (band width * 8),
1797 0xFFFF, 0, 1, 0 as arguments */
1799 ;/* TODO: Call N PHY TX Tone with freq, 250, 1, 0 as arguments
1800 and save result as error */
1803 if (nphy
->mphase_cal_phase_id
> 2) {
1804 table
= nphy
->mphase_txcal_bestcoeffs
;
1806 if (dev
->phy
.rev
< 3)
1809 if (!full
&& nphy
->txiqlocal_coeffsvalid
) {
1810 table
= nphy
->txiqlocal_bestc
;
1812 if (dev
->phy
.rev
< 3)
1816 if (dev
->phy
.rev
>= 3) {
1817 table
= tbl_tx_iqlo_cal_startcoefs_nphyrev3
;
1818 length
= B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3
;
1820 table
= tbl_tx_iqlo_cal_startcoefs
;
1821 length
= B43_NTAB_TX_IQLO_CAL_STARTCOEFS
;
1826 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 64), length
, table
);
1829 if (dev
->phy
.rev
>= 3)
1830 max
= B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3
;
1832 max
= B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL
;
1834 if (dev
->phy
.rev
>= 3)
1835 max
= B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3
;
1837 max
= B43_NTAB_TX_IQLO_CAL_CMDS_RECAL
;
1841 count
= nphy
->mphase_txcal_cmdidx
;
1843 (u16
)(count
+ nphy
->mphase_txcal_numcmds
));
1849 for (; count
< numb
; count
++) {
1851 if (dev
->phy
.rev
>= 3)
1852 cmd
= tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
[count
];
1854 cmd
= tbl_tx_iqlo_cal_cmds_fullcal
[count
];
1856 if (dev
->phy
.rev
>= 3)
1857 cmd
= tbl_tx_iqlo_cal_cmds_recal_nphyrev3
[count
];
1859 cmd
= tbl_tx_iqlo_cal_cmds_recal
[count
];
1862 core
= (cmd
& 0x3000) >> 12;
1863 type
= (cmd
& 0x0F00) >> 8;
1865 if (phy6or5x
&& updated
[core
] == 0) {
1866 b43_nphy_update_tx_cal_ladder(dev
, core
);
1870 tmp
= (params
[core
].ncorr
[type
] << 8) | 0x66;
1871 b43_phy_write(dev
, B43_NPHY_IQLOCAL_CMDNNUM
, tmp
);
1873 if (type
== 1 || type
== 3 || type
== 4) {
1874 buffer
[0] = b43_ntab_read(dev
,
1875 B43_NTAB16(15, 69 + core
));
1876 diq_start
= buffer
[0];
1878 b43_ntab_write(dev
, B43_NTAB16(15, 69 + core
),
1882 b43_phy_write(dev
, B43_NPHY_IQLOCAL_CMD
, cmd
);
1883 for (i
= 0; i
< 2000; i
++) {
1884 tmp
= b43_phy_read(dev
, B43_NPHY_IQLOCAL_CMD
);
1890 b43_ntab_read_bulk(dev
, B43_NTAB16(15, 96), length
,
1892 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 64), length
,
1895 if (type
== 1 || type
== 3 || type
== 4)
1896 buffer
[0] = diq_start
;
1900 nphy
->mphase_txcal_cmdidx
= (numb
>= max
) ? 0 : numb
;
1902 last
= (dev
->phy
.rev
< 3) ? 6 : 7;
1904 if (!mphase
|| nphy
->mphase_cal_phase_id
== last
) {
1905 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 96), 4, buffer
);
1906 b43_ntab_read_bulk(dev
, B43_NTAB16(15, 80), 4, buffer
);
1907 if (dev
->phy
.rev
< 3) {
1913 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 88), 4,
1915 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 101), 2,
1917 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 85), 2,
1919 b43_ntab_write_bulk(dev
, B43_NTAB16(15, 93), 2,
1922 if (dev
->phy
.rev
< 3)
1924 b43_ntab_read_bulk(dev
, B43_NTAB16(15, 96), length
,
1925 nphy
->txiqlocal_bestc
);
1926 nphy
->txiqlocal_coeffsvalid
= true;
1927 /* TODO: Set nphy->txiqlocal_chanspec to
1928 the current channel */
1931 if (dev
->phy
.rev
< 3)
1933 b43_ntab_read_bulk(dev
, B43_NTAB16(15, 96), length
,
1934 nphy
->mphase_txcal_bestcoeffs
);
1937 b43_nphy_stop_playback(dev
);
1938 b43_phy_write(dev
, B43_NPHY_IQLOCAL_CMDGCTL
, 0);
1941 b43_nphy_tx_cal_phy_cleanup(dev
);
1942 b43_ntab_write_bulk(dev
, B43_NTAB16(7, 0x110), 2, save
);
1944 if (dev
->phy
.rev
< 2 && (!mphase
|| nphy
->mphase_cal_phase_id
== last
))
1945 b43_nphy_tx_iq_workaround(dev
);
1947 if (dev
->phy
.rev
>= 4)
1948 nphy
->hang_avoid
= avoid
;
1950 b43_nphy_stay_in_carrier_search(dev
, false);
1955 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
1956 static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev
*dev
,
1957 struct nphy_txgains target
, u8 type
, bool debug
)
1959 struct b43_phy_n
*nphy
= dev
->phy
.n
;
1964 u16 cur_hpf1
, cur_hpf2
, cur_lna
;
1966 enum ieee80211_band band
;
1970 u16 lna
[3] = { 3, 3, 1 };
1971 u16 hpf1
[3] = { 7, 2, 0 };
1972 u16 hpf2
[3] = { 2, 0, 0 };
1976 struct nphy_iqcal_params cal_params
[2];
1977 struct nphy_iq_est est
;
1979 bool playtone
= true;
1982 b43_nphy_stay_in_carrier_search(dev
, 1);
1984 if (dev
->phy
.rev
< 2)
1985 ;/* TODO: Call N PHY Reapply TX Cal Coeffs */
1986 b43_ntab_read_bulk(dev
, B43_NTAB16(7, 0x110), 2, gain_save
);
1987 for (i
= 0; i
< 2; i
++) {
1988 b43_nphy_iq_cal_gain_params(dev
, i
, target
, &cal_params
[i
]);
1989 cal_gain
[i
] = cal_params
[i
].cal_gain
;
1991 b43_ntab_write_bulk(dev
, B43_NTAB16(7, 0x110), 2, cal_gain
);
1993 for (i
= 0; i
< 2; i
++) {
1995 rfctl
[0] = B43_NPHY_RFCTL_INTC1
;
1996 rfctl
[1] = B43_NPHY_RFCTL_INTC2
;
1997 afectl_core
= B43_NPHY_AFECTL_C1
;
1999 rfctl
[0] = B43_NPHY_RFCTL_INTC2
;
2000 rfctl
[1] = B43_NPHY_RFCTL_INTC1
;
2001 afectl_core
= B43_NPHY_AFECTL_C2
;
2004 tmp
[1] = b43_phy_read(dev
, B43_NPHY_RFSEQCA
);
2005 tmp
[2] = b43_phy_read(dev
, afectl_core
);
2006 tmp
[3] = b43_phy_read(dev
, B43_NPHY_AFECTL_OVER
);
2007 tmp
[4] = b43_phy_read(dev
, rfctl
[0]);
2008 tmp
[5] = b43_phy_read(dev
, rfctl
[1]);
2010 b43_phy_maskset(dev
, B43_NPHY_RFSEQCA
,
2011 (u16
)~B43_NPHY_RFSEQCA_RXDIS
,
2012 ((1 - i
) << B43_NPHY_RFSEQCA_RXDIS_SHIFT
));
2013 b43_phy_maskset(dev
, B43_NPHY_RFSEQCA
, ~B43_NPHY_RFSEQCA_TXEN
,
2015 b43_phy_set(dev
, afectl_core
, 0x0006);
2016 b43_phy_set(dev
, B43_NPHY_AFECTL_OVER
, 0x0006);
2018 band
= b43_current_band(dev
->wl
);
2020 if (nphy
->rxcalparams
& 0xFF000000) {
2021 if (band
== IEEE80211_BAND_5GHZ
)
2022 b43_phy_write(dev
, rfctl
[0], 0x140);
2024 b43_phy_write(dev
, rfctl
[0], 0x110);
2026 if (band
== IEEE80211_BAND_5GHZ
)
2027 b43_phy_write(dev
, rfctl
[0], 0x180);
2029 b43_phy_write(dev
, rfctl
[0], 0x120);
2032 if (band
== IEEE80211_BAND_5GHZ
)
2033 b43_phy_write(dev
, rfctl
[1], 0x148);
2035 b43_phy_write(dev
, rfctl
[1], 0x114);
2037 if (nphy
->rxcalparams
& 0x10000) {
2038 b43_radio_maskset(dev
, B2055_C1_GENSPARE2
, 0xFC,
2040 b43_radio_maskset(dev
, B2055_C2_GENSPARE2
, 0xFC,
2044 for (j
= 0; i
< 4; j
++) {
2050 if (power
[1] > 10000) {
2055 if (power
[0] > 10000) {
2065 cur_lna
= lna
[index
];
2066 cur_hpf1
= hpf1
[index
];
2067 cur_hpf2
= hpf2
[index
];
2068 cur_hpf
+= desired
- hweight32(power
[index
]);
2069 cur_hpf
= clamp_val(cur_hpf
, 0, 10);
2076 tmp
[0] = ((cur_hpf2
<< 8) | (cur_hpf1
<< 4) |
2078 /* TODO:Call N PHY RF Ctrl Override with 0x400, tmp[0],
2079 3, 0 as arguments */
2080 b43_nphy_force_rf_sequence(dev
, B43_RFSEQ_RESET2RX
);
2081 b43_nphy_stop_playback(dev
);
2084 /* TODO: Call N PHY TX Tone with 4000,
2085 (nphy_rxcalparams & 0xffff), 0, 0
2086 as arguments and save result as ret */
2089 /* TODO: Call N PHY Run Samples with 160,
2090 0xFFFF, 0, 0, 0 as arguments */
2095 b43_nphy_rx_iq_est(dev
, &est
, 1024, 32,
2104 power
[i
] = ((real
+ imag
) / 1024) + 1;
2106 b43_nphy_calc_rx_iq_comp(dev
, 1 << i
);
2108 b43_nphy_stop_playback(dev
);
2115 b43_radio_mask(dev
, B2055_C1_GENSPARE2
, 0xFC);
2116 b43_radio_mask(dev
, B2055_C2_GENSPARE2
, 0xFC);
2117 b43_phy_write(dev
, rfctl
[1], tmp
[5]);
2118 b43_phy_write(dev
, rfctl
[0], tmp
[4]);
2119 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
, tmp
[3]);
2120 b43_phy_write(dev
, afectl_core
, tmp
[2]);
2121 b43_phy_write(dev
, B43_NPHY_RFSEQCA
, tmp
[1]);
2127 /* TODO: Call N PHY RF Ctrl Override with 0x400, 0, 3, 1 as arguments*/
2128 b43_nphy_force_rf_sequence(dev
, B43_RFSEQ_RESET2RX
);
2129 b43_ntab_write_bulk(dev
, B43_NTAB16(7, 0x110), 2, gain_save
);
2131 b43_nphy_stay_in_carrier_search(dev
, 0);
2136 static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev
*dev
,
2137 struct nphy_txgains target
, u8 type
, bool debug
)
2142 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
2143 static int b43_nphy_cal_rx_iq(struct b43_wldev
*dev
,
2144 struct nphy_txgains target
, u8 type
, bool debug
)
2146 if (dev
->phy
.rev
>= 3)
2147 return b43_nphy_rev3_cal_rx_iq(dev
, target
, type
, debug
);
2149 return b43_nphy_rev2_cal_rx_iq(dev
, target
, type
, debug
);
2154 * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
2156 int b43_phy_initn(struct b43_wldev
*dev
)
2158 struct ssb_bus
*bus
= dev
->dev
->bus
;
2159 struct b43_phy
*phy
= &dev
->phy
;
2160 struct b43_phy_n
*nphy
= phy
->n
;
2162 struct nphy_txgains target
;
2164 enum ieee80211_band tmp2
;
2168 bool do_cal
= false;
2170 if ((dev
->phy
.rev
>= 3) &&
2171 (bus
->sprom
.boardflags_lo
& B43_BFL_EXTLNA
) &&
2172 (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
)) {
2173 chipco_set32(&dev
->dev
->bus
->chipco
, SSB_CHIPCO_CHIPCTL
, 0x40);
2175 nphy
->deaf_count
= 0;
2176 b43_nphy_tables_init(dev
);
2177 nphy
->crsminpwr_adjusted
= false;
2178 nphy
->noisevars_adjusted
= false;
2180 /* Clear all overrides */
2181 if (dev
->phy
.rev
>= 3) {
2182 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B1S1
, 0);
2183 b43_phy_write(dev
, B43_NPHY_RFCTL_OVER
, 0);
2184 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B1S0
, 0);
2185 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B32S1
, 0);
2187 b43_phy_write(dev
, B43_NPHY_RFCTL_OVER
, 0);
2189 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
, 0);
2190 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
, 0);
2191 if (dev
->phy
.rev
< 6) {
2192 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC3
, 0);
2193 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC4
, 0);
2195 b43_phy_mask(dev
, B43_NPHY_RFSEQMODE
,
2196 ~(B43_NPHY_RFSEQMODE_CAOVER
|
2197 B43_NPHY_RFSEQMODE_TROVER
));
2198 if (dev
->phy
.rev
>= 3)
2199 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER1
, 0);
2200 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
, 0);
2202 if (dev
->phy
.rev
<= 2) {
2203 tmp
= (dev
->phy
.rev
== 2) ? 0x3B : 0x40;
2204 b43_phy_maskset(dev
, B43_NPHY_BPHY_CTL3
,
2205 ~B43_NPHY_BPHY_CTL3_SCALE
,
2206 tmp
<< B43_NPHY_BPHY_CTL3_SCALE_SHIFT
);
2208 b43_phy_write(dev
, B43_NPHY_AFESEQ_TX2RX_PUD_20M
, 0x20);
2209 b43_phy_write(dev
, B43_NPHY_AFESEQ_TX2RX_PUD_40M
, 0x20);
2211 if (bus
->sprom
.boardflags2_lo
& 0x100 ||
2212 (bus
->boardinfo
.vendor
== PCI_VENDOR_ID_APPLE
&&
2213 bus
->boardinfo
.type
== 0x8B))
2214 b43_phy_write(dev
, B43_NPHY_TXREALFD
, 0xA0);
2216 b43_phy_write(dev
, B43_NPHY_TXREALFD
, 0xB8);
2217 b43_phy_write(dev
, B43_NPHY_MIMO_CRSTXEXT
, 0xC8);
2218 b43_phy_write(dev
, B43_NPHY_PLOAD_CSENSE_EXTLEN
, 0x50);
2219 b43_phy_write(dev
, B43_NPHY_TXRIFS_FRDEL
, 0x30);
2221 b43_nphy_update_mimo_config(dev
, nphy
->preamble_override
);
2222 b43_nphy_update_txrx_chain(dev
);
2225 b43_phy_write(dev
, B43_NPHY_DUP40_GFBL
, 0xAA8);
2226 b43_phy_write(dev
, B43_NPHY_DUP40_BL
, 0x9A4);
2229 tmp2
= b43_current_band(dev
->wl
);
2230 if ((nphy
->ipa2g_on
&& tmp2
== IEEE80211_BAND_2GHZ
) ||
2231 (nphy
->ipa5g_on
&& tmp2
== IEEE80211_BAND_5GHZ
)) {
2232 b43_phy_set(dev
, B43_NPHY_PAPD_EN0
, 0x1);
2233 b43_phy_maskset(dev
, B43_NPHY_EPS_TABLE_ADJ0
, 0x007F,
2234 nphy
->papd_epsilon_offset
[0] << 7);
2235 b43_phy_set(dev
, B43_NPHY_PAPD_EN1
, 0x1);
2236 b43_phy_maskset(dev
, B43_NPHY_EPS_TABLE_ADJ1
, 0x007F,
2237 nphy
->papd_epsilon_offset
[1] << 7);
2238 /* TODO N PHY IPA Set TX Dig Filters */
2239 } else if (phy
->rev
>= 5) {
2240 /* TODO N PHY Ext PA Set TX Dig Filters */
2243 b43_nphy_workarounds(dev
);
2245 /* Reset CCA, in init code it differs a little from standard way */
2246 b43_nphy_bmac_clock_fgc(dev
, 1);
2247 tmp
= b43_phy_read(dev
, B43_NPHY_BBCFG
);
2248 b43_phy_write(dev
, B43_NPHY_BBCFG
, tmp
| B43_NPHY_BBCFG_RSTCCA
);
2249 b43_phy_write(dev
, B43_NPHY_BBCFG
, tmp
& ~B43_NPHY_BBCFG_RSTCCA
);
2250 b43_nphy_bmac_clock_fgc(dev
, 0);
2252 /* TODO N PHY MAC PHY Clock Set with argument 1 */
2254 b43_nphy_pa_override(dev
, false);
2255 b43_nphy_force_rf_sequence(dev
, B43_RFSEQ_RX2TX
);
2256 b43_nphy_force_rf_sequence(dev
, B43_RFSEQ_RESET2RX
);
2257 b43_nphy_pa_override(dev
, true);
2259 b43_nphy_classifier(dev
, 0, 0);
2260 b43_nphy_read_clip_detection(dev
, clip
);
2261 tx_pwr_state
= nphy
->txpwrctrl
;
2262 /* TODO N PHY TX power control with argument 0
2263 (turning off power control) */
2264 /* TODO Fix the TX Power Settings */
2265 /* TODO N PHY TX Power Control Idle TSSI */
2266 /* TODO N PHY TX Power Control Setup */
2268 if (phy
->rev
>= 3) {
2271 b43_ntab_write_bulk(dev
, B43_NTAB32(26, 192), 128,
2272 b43_ntab_tx_gain_rev0_1_2
);
2273 b43_ntab_write_bulk(dev
, B43_NTAB32(27, 192), 128,
2274 b43_ntab_tx_gain_rev0_1_2
);
2277 if (nphy
->phyrxchain
!= 3)
2278 ;/* TODO N PHY RX Core Set State with phyrxchain as argument */
2279 if (nphy
->mphase_cal_phase_id
> 0)
2280 ;/* TODO PHY Periodic Calibration Multi-Phase Restart */
2282 do_rssi_cal
= false;
2283 if (phy
->rev
>= 3) {
2284 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
)
2285 do_rssi_cal
= (nphy
->rssical_chanspec_2G
== 0);
2287 do_rssi_cal
= (nphy
->rssical_chanspec_5G
== 0);
2290 b43_nphy_rssi_cal(dev
);
2292 b43_nphy_restore_rssi_cal(dev
);
2294 b43_nphy_rssi_cal(dev
);
2297 if (!((nphy
->measure_hold
& 0x6) != 0)) {
2298 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
)
2299 do_cal
= (nphy
->iqcal_chanspec_2G
== 0);
2301 do_cal
= (nphy
->iqcal_chanspec_5G
== 0);
2307 target
= b43_nphy_get_tx_gains(dev
);
2309 if (nphy
->antsel_type
== 2)
2310 ;/*TODO NPHY Superswitch Init with argument 1*/
2311 if (nphy
->perical
!= 2) {
2312 b43_nphy_rssi_cal(dev
);
2313 if (phy
->rev
>= 3) {
2314 nphy
->cal_orig_pwr_idx
[0] =
2315 nphy
->txpwrindex
[0].index_internal
;
2316 nphy
->cal_orig_pwr_idx
[1] =
2317 nphy
->txpwrindex
[1].index_internal
;
2318 /* TODO N PHY Pre Calibrate TX Gain */
2319 target
= b43_nphy_get_tx_gains(dev
);
2325 if (!b43_nphy_cal_tx_iq_lo(dev
, target
, true, false)) {
2326 if (b43_nphy_cal_rx_iq(dev
, target
, 2, 0) == 0)
2327 ;/* Call N PHY Save Cal */
2328 else if (nphy
->mphase_cal_phase_id
== 0)
2329 ;/* N PHY Periodic Calibration with argument 3 */
2331 b43_nphy_restore_cal(dev
);
2334 b43_nphy_tx_pwr_ctrl_coef_setup(dev
);
2335 /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */
2336 b43_phy_write(dev
, B43_NPHY_TXMACIF_HOLDOFF
, 0x0015);
2337 b43_phy_write(dev
, B43_NPHY_TXMACDELAY
, 0x0320);
2338 if (phy
->rev
>= 3 && phy
->rev
<= 6)
2339 b43_phy_write(dev
, B43_NPHY_PLOAD_CSENSE_EXTLEN
, 0x0014);
2340 b43_nphy_tx_lp_fbw(dev
);
2341 /* TODO N PHY Spur Workaround */
2343 b43err(dev
->wl
, "IEEE 802.11n devices are not supported, yet.\n");
2347 static int b43_nphy_op_allocate(struct b43_wldev
*dev
)
2349 struct b43_phy_n
*nphy
;
2351 nphy
= kzalloc(sizeof(*nphy
), GFP_KERNEL
);
2359 static void b43_nphy_op_prepare_structs(struct b43_wldev
*dev
)
2361 struct b43_phy
*phy
= &dev
->phy
;
2362 struct b43_phy_n
*nphy
= phy
->n
;
2364 memset(nphy
, 0, sizeof(*nphy
));
2366 //TODO init struct b43_phy_n
2369 static void b43_nphy_op_free(struct b43_wldev
*dev
)
2371 struct b43_phy
*phy
= &dev
->phy
;
2372 struct b43_phy_n
*nphy
= phy
->n
;
2378 static int b43_nphy_op_init(struct b43_wldev
*dev
)
2380 return b43_phy_initn(dev
);
2383 static inline void check_phyreg(struct b43_wldev
*dev
, u16 offset
)
2386 if ((offset
& B43_PHYROUTE
) == B43_PHYROUTE_OFDM_GPHY
) {
2387 /* OFDM registers are onnly available on A/G-PHYs */
2388 b43err(dev
->wl
, "Invalid OFDM PHY access at "
2389 "0x%04X on N-PHY\n", offset
);
2392 if ((offset
& B43_PHYROUTE
) == B43_PHYROUTE_EXT_GPHY
) {
2393 /* Ext-G registers are only available on G-PHYs */
2394 b43err(dev
->wl
, "Invalid EXT-G PHY access at "
2395 "0x%04X on N-PHY\n", offset
);
2398 #endif /* B43_DEBUG */
2401 static u16
b43_nphy_op_read(struct b43_wldev
*dev
, u16 reg
)
2403 check_phyreg(dev
, reg
);
2404 b43_write16(dev
, B43_MMIO_PHY_CONTROL
, reg
);
2405 return b43_read16(dev
, B43_MMIO_PHY_DATA
);
2408 static void b43_nphy_op_write(struct b43_wldev
*dev
, u16 reg
, u16 value
)
2410 check_phyreg(dev
, reg
);
2411 b43_write16(dev
, B43_MMIO_PHY_CONTROL
, reg
);
2412 b43_write16(dev
, B43_MMIO_PHY_DATA
, value
);
2415 static u16
b43_nphy_op_radio_read(struct b43_wldev
*dev
, u16 reg
)
2417 /* Register 1 is a 32-bit register. */
2418 B43_WARN_ON(reg
== 1);
2419 /* N-PHY needs 0x100 for read access */
2422 b43_write16(dev
, B43_MMIO_RADIO_CONTROL
, reg
);
2423 return b43_read16(dev
, B43_MMIO_RADIO_DATA_LOW
);
2426 static void b43_nphy_op_radio_write(struct b43_wldev
*dev
, u16 reg
, u16 value
)
2428 /* Register 1 is a 32-bit register. */
2429 B43_WARN_ON(reg
== 1);
2431 b43_write16(dev
, B43_MMIO_RADIO_CONTROL
, reg
);
2432 b43_write16(dev
, B43_MMIO_RADIO_DATA_LOW
, value
);
2435 static void b43_nphy_op_software_rfkill(struct b43_wldev
*dev
,
2440 static void b43_nphy_op_switch_analog(struct b43_wldev
*dev
, bool on
)
2442 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
,
2446 static int b43_nphy_op_switch_channel(struct b43_wldev
*dev
,
2447 unsigned int new_channel
)
2449 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
) {
2450 if ((new_channel
< 1) || (new_channel
> 14))
2453 if (new_channel
> 200)
2457 return nphy_channel_switch(dev
, new_channel
);
2460 static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev
*dev
)
2462 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
)
2467 const struct b43_phy_operations b43_phyops_n
= {
2468 .allocate
= b43_nphy_op_allocate
,
2469 .free
= b43_nphy_op_free
,
2470 .prepare_structs
= b43_nphy_op_prepare_structs
,
2471 .init
= b43_nphy_op_init
,
2472 .phy_read
= b43_nphy_op_read
,
2473 .phy_write
= b43_nphy_op_write
,
2474 .radio_read
= b43_nphy_op_radio_read
,
2475 .radio_write
= b43_nphy_op_radio_write
,
2476 .software_rfkill
= b43_nphy_op_software_rfkill
,
2477 .switch_analog
= b43_nphy_op_switch_analog
,
2478 .switch_channel
= b43_nphy_op_switch_channel
,
2479 .get_default_chan
= b43_nphy_op_get_default_chan
,
2480 .recalc_txpower
= b43_nphy_op_recalc_txpower
,
2481 .adjust_txpower
= b43_nphy_op_adjust_txpower
,