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 void b43_nphy_set_rxantenna(struct b43_wldev
*dev
, int antenna
)
62 static void b43_nphy_op_adjust_txpower(struct b43_wldev
*dev
)
66 static enum b43_txpwr_result
b43_nphy_op_recalc_txpower(struct b43_wldev
*dev
,
69 return B43_TXPWR_RES_DONE
;
72 static void b43_chantab_radio_upload(struct b43_wldev
*dev
,
73 const struct b43_nphy_channeltab_entry
*e
)
75 b43_radio_write16(dev
, B2055_PLL_REF
, e
->radio_pll_ref
);
76 b43_radio_write16(dev
, B2055_RF_PLLMOD0
, e
->radio_rf_pllmod0
);
77 b43_radio_write16(dev
, B2055_RF_PLLMOD1
, e
->radio_rf_pllmod1
);
78 b43_radio_write16(dev
, B2055_VCO_CAPTAIL
, e
->radio_vco_captail
);
79 b43_radio_write16(dev
, B2055_VCO_CAL1
, e
->radio_vco_cal1
);
80 b43_radio_write16(dev
, B2055_VCO_CAL2
, e
->radio_vco_cal2
);
81 b43_radio_write16(dev
, B2055_PLL_LFC1
, e
->radio_pll_lfc1
);
82 b43_radio_write16(dev
, B2055_PLL_LFR1
, e
->radio_pll_lfr1
);
83 b43_radio_write16(dev
, B2055_PLL_LFC2
, e
->radio_pll_lfc2
);
84 b43_radio_write16(dev
, B2055_LGBUF_CENBUF
, e
->radio_lgbuf_cenbuf
);
85 b43_radio_write16(dev
, B2055_LGEN_TUNE1
, e
->radio_lgen_tune1
);
86 b43_radio_write16(dev
, B2055_LGEN_TUNE2
, e
->radio_lgen_tune2
);
87 b43_radio_write16(dev
, B2055_C1_LGBUF_ATUNE
, e
->radio_c1_lgbuf_atune
);
88 b43_radio_write16(dev
, B2055_C1_LGBUF_GTUNE
, e
->radio_c1_lgbuf_gtune
);
89 b43_radio_write16(dev
, B2055_C1_RX_RFR1
, e
->radio_c1_rx_rfr1
);
90 b43_radio_write16(dev
, B2055_C1_TX_PGAPADTN
, e
->radio_c1_tx_pgapadtn
);
91 b43_radio_write16(dev
, B2055_C1_TX_MXBGTRIM
, e
->radio_c1_tx_mxbgtrim
);
92 b43_radio_write16(dev
, B2055_C2_LGBUF_ATUNE
, e
->radio_c2_lgbuf_atune
);
93 b43_radio_write16(dev
, B2055_C2_LGBUF_GTUNE
, e
->radio_c2_lgbuf_gtune
);
94 b43_radio_write16(dev
, B2055_C2_RX_RFR1
, e
->radio_c2_rx_rfr1
);
95 b43_radio_write16(dev
, B2055_C2_TX_PGAPADTN
, e
->radio_c2_tx_pgapadtn
);
96 b43_radio_write16(dev
, B2055_C2_TX_MXBGTRIM
, e
->radio_c2_tx_mxbgtrim
);
99 static void b43_chantab_phy_upload(struct b43_wldev
*dev
,
100 const struct b43_nphy_channeltab_entry
*e
)
102 b43_phy_write(dev
, B43_NPHY_BW1A
, e
->phy_bw1a
);
103 b43_phy_write(dev
, B43_NPHY_BW2
, e
->phy_bw2
);
104 b43_phy_write(dev
, B43_NPHY_BW3
, e
->phy_bw3
);
105 b43_phy_write(dev
, B43_NPHY_BW4
, e
->phy_bw4
);
106 b43_phy_write(dev
, B43_NPHY_BW5
, e
->phy_bw5
);
107 b43_phy_write(dev
, B43_NPHY_BW6
, e
->phy_bw6
);
110 static void b43_nphy_tx_power_fix(struct b43_wldev
*dev
)
115 /* Tune the hardware to a new channel. */
116 static int nphy_channel_switch(struct b43_wldev
*dev
, unsigned int channel
)
118 const struct b43_nphy_channeltab_entry
*tabent
;
120 tabent
= b43_nphy_get_chantabent(dev
, channel
);
124 //FIXME enable/disable band select upper20 in RXCTL
125 if (0 /*FIXME 5Ghz*/)
126 b43_radio_maskset(dev
, B2055_MASTER1
, 0xFF8F, 0x20);
128 b43_radio_maskset(dev
, B2055_MASTER1
, 0xFF8F, 0x50);
129 b43_chantab_radio_upload(dev
, tabent
);
131 b43_radio_write16(dev
, B2055_VCO_CAL10
, 5);
132 b43_radio_write16(dev
, B2055_VCO_CAL10
, 45);
133 b43_radio_write16(dev
, B2055_VCO_CAL10
, 65);
135 if (0 /*FIXME 5Ghz*/)
136 b43_phy_set(dev
, B43_NPHY_BANDCTL
, B43_NPHY_BANDCTL_5GHZ
);
138 b43_phy_mask(dev
, B43_NPHY_BANDCTL
, ~B43_NPHY_BANDCTL_5GHZ
);
139 b43_chantab_phy_upload(dev
, tabent
);
140 b43_nphy_tx_power_fix(dev
);
145 static void b43_radio_init2055_pre(struct b43_wldev
*dev
)
147 b43_phy_mask(dev
, B43_NPHY_RFCTL_CMD
,
148 ~B43_NPHY_RFCTL_CMD_PORFORCE
);
149 b43_phy_set(dev
, B43_NPHY_RFCTL_CMD
,
150 B43_NPHY_RFCTL_CMD_CHIP0PU
|
151 B43_NPHY_RFCTL_CMD_OEPORFORCE
);
152 b43_phy_set(dev
, B43_NPHY_RFCTL_CMD
,
153 B43_NPHY_RFCTL_CMD_PORFORCE
);
156 static void b43_radio_init2055_post(struct b43_wldev
*dev
)
158 struct ssb_sprom
*sprom
= &(dev
->dev
->bus
->sprom
);
159 struct ssb_boardinfo
*binfo
= &(dev
->dev
->bus
->boardinfo
);
163 b43_radio_mask(dev
, B2055_MASTER1
, 0xFFF3);
165 if ((sprom
->revision
!= 4) ||
166 !(sprom
->boardflags_hi
& B43_BFH_RSSIINV
)) {
167 if ((binfo
->vendor
!= PCI_VENDOR_ID_BROADCOM
) ||
168 (binfo
->type
!= 0x46D) ||
169 (binfo
->rev
< 0x41)) {
170 b43_radio_mask(dev
, B2055_C1_RX_BB_REG
, 0x7F);
171 b43_radio_mask(dev
, B2055_C1_RX_BB_REG
, 0x7F);
175 b43_radio_maskset(dev
, B2055_RRCCAL_NOPTSEL
, 0x3F, 0x2C);
177 b43_radio_write16(dev
, B2055_CAL_MISC
, 0x3C);
179 b43_radio_mask(dev
, B2055_CAL_MISC
, 0xFFBE);
181 b43_radio_set(dev
, B2055_CAL_LPOCTL
, 0x80);
183 b43_radio_set(dev
, B2055_CAL_MISC
, 0x1);
185 b43_radio_set(dev
, B2055_CAL_MISC
, 0x40);
187 for (i
= 0; i
< 100; i
++) {
188 val
= b43_radio_read16(dev
, B2055_CAL_COUT2
);
194 b43_radio_mask(dev
, B2055_CAL_LPOCTL
, 0xFF7F);
196 nphy_channel_switch(dev
, dev
->phy
.channel
);
197 b43_radio_write16(dev
, B2055_C1_RX_BB_LPF
, 0x9);
198 b43_radio_write16(dev
, B2055_C2_RX_BB_LPF
, 0x9);
199 b43_radio_write16(dev
, B2055_C1_RX_BB_MIDACHP
, 0x83);
200 b43_radio_write16(dev
, B2055_C2_RX_BB_MIDACHP
, 0x83);
203 /* Initialize a Broadcom 2055 N-radio */
204 static void b43_radio_init2055(struct b43_wldev
*dev
)
206 b43_radio_init2055_pre(dev
);
207 if (b43_status(dev
) < B43_STAT_INITIALIZED
)
208 b2055_upload_inittab(dev
, 0, 1);
210 b2055_upload_inittab(dev
, 0/*FIXME on 5ghz band*/, 0);
211 b43_radio_init2055_post(dev
);
214 void b43_nphy_radio_turn_on(struct b43_wldev
*dev
)
216 b43_radio_init2055(dev
);
219 void b43_nphy_radio_turn_off(struct b43_wldev
*dev
)
221 b43_phy_mask(dev
, B43_NPHY_RFCTL_CMD
,
222 ~B43_NPHY_RFCTL_CMD_EN
);
225 #define ntab_upload(dev, offset, data) do { \
227 for (i = 0; i < (offset##_SIZE); i++) \
228 b43_ntab_write(dev, (offset) + i, (data)[i]); \
232 * Upload the N-PHY tables.
233 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
235 static void b43_nphy_tables_init(struct b43_wldev
*dev
)
237 if (dev
->phy
.rev
< 3)
238 b43_nphy_rev0_1_2_tables_init(dev
);
240 b43_nphy_rev3plus_tables_init(dev
);
243 static void b43_nphy_workarounds(struct b43_wldev
*dev
)
245 struct b43_phy
*phy
= &dev
->phy
;
248 b43_phy_set(dev
, B43_NPHY_IQFLIP
,
249 B43_NPHY_IQFLIP_ADC1
| B43_NPHY_IQFLIP_ADC2
);
250 if (1 /* FIXME band is 2.4GHz */) {
251 b43_phy_set(dev
, B43_NPHY_CLASSCTL
,
252 B43_NPHY_CLASSCTL_CCKEN
);
254 b43_phy_mask(dev
, B43_NPHY_CLASSCTL
,
255 ~B43_NPHY_CLASSCTL_CCKEN
);
257 b43_radio_set(dev
, B2055_C1_TX_RF_SPARE
, 0x8);
258 b43_phy_write(dev
, B43_NPHY_TXFRAMEDELAY
, 8);
260 /* Fixup some tables */
261 b43_ntab_write(dev
, B43_NTAB16(8, 0x00), 0xA);
262 b43_ntab_write(dev
, B43_NTAB16(8, 0x10), 0xA);
263 b43_ntab_write(dev
, B43_NTAB16(8, 0x02), 0xCDAA);
264 b43_ntab_write(dev
, B43_NTAB16(8, 0x12), 0xCDAA);
265 b43_ntab_write(dev
, B43_NTAB16(8, 0x08), 0);
266 b43_ntab_write(dev
, B43_NTAB16(8, 0x18), 0);
267 b43_ntab_write(dev
, B43_NTAB16(8, 0x07), 0x7AAB);
268 b43_ntab_write(dev
, B43_NTAB16(8, 0x17), 0x7AAB);
269 b43_ntab_write(dev
, B43_NTAB16(8, 0x06), 0x800);
270 b43_ntab_write(dev
, B43_NTAB16(8, 0x16), 0x800);
272 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_LO1
, 0x2D8);
273 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_UP1
, 0x301);
274 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_LO2
, 0x2D8);
275 b43_phy_write(dev
, B43_NPHY_RFCTL_LUT_TRSW_UP2
, 0x301);
277 //TODO set RF sequence
279 /* Set narrowband clip threshold */
280 b43_phy_write(dev
, B43_NPHY_C1_NBCLIPTHRES
, 66);
281 b43_phy_write(dev
, B43_NPHY_C2_NBCLIPTHRES
, 66);
283 /* Set wideband clip 2 threshold */
284 b43_phy_maskset(dev
, B43_NPHY_C1_CLIPWBTHRES
,
285 ~B43_NPHY_C1_CLIPWBTHRES_CLIP2
,
286 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT
);
287 b43_phy_maskset(dev
, B43_NPHY_C2_CLIPWBTHRES
,
288 ~B43_NPHY_C2_CLIPWBTHRES_CLIP2
,
289 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT
);
291 /* Set Clip 2 detect */
292 b43_phy_set(dev
, B43_NPHY_C1_CGAINI
,
293 B43_NPHY_C1_CGAINI_CL2DETECT
);
294 b43_phy_set(dev
, B43_NPHY_C2_CGAINI
,
295 B43_NPHY_C2_CGAINI_CL2DETECT
);
298 /* Set dwell lengths */
299 b43_phy_write(dev
, B43_NPHY_CLIP1_NBDWELL_LEN
, 43);
300 b43_phy_write(dev
, B43_NPHY_CLIP2_NBDWELL_LEN
, 43);
301 b43_phy_write(dev
, B43_NPHY_W1CLIP1_DWELL_LEN
, 9);
302 b43_phy_write(dev
, B43_NPHY_W1CLIP2_DWELL_LEN
, 9);
304 /* Set gain backoff */
305 b43_phy_maskset(dev
, B43_NPHY_C1_CGAINI
,
306 ~B43_NPHY_C1_CGAINI_GAINBKOFF
,
307 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT
);
308 b43_phy_maskset(dev
, B43_NPHY_C2_CGAINI
,
309 ~B43_NPHY_C2_CGAINI_GAINBKOFF
,
310 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT
);
312 /* Set HPVGA2 index */
313 b43_phy_maskset(dev
, B43_NPHY_C1_INITGAIN
,
314 ~B43_NPHY_C1_INITGAIN_HPVGA2
,
315 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT
);
316 b43_phy_maskset(dev
, B43_NPHY_C2_INITGAIN
,
317 ~B43_NPHY_C2_INITGAIN_HPVGA2
,
318 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT
);
320 //FIXME verify that the specs really mean to use autoinc here.
321 for (i
= 0; i
< 3; i
++)
322 b43_ntab_write(dev
, B43_NTAB16(7, 0x106) + i
, 0x673);
325 /* Set minimum gain value */
326 b43_phy_maskset(dev
, B43_NPHY_C1_MINMAX_GAIN
,
327 ~B43_NPHY_C1_MINGAIN
,
328 23 << B43_NPHY_C1_MINGAIN_SHIFT
);
329 b43_phy_maskset(dev
, B43_NPHY_C2_MINMAX_GAIN
,
330 ~B43_NPHY_C2_MINGAIN
,
331 23 << B43_NPHY_C2_MINGAIN_SHIFT
);
334 b43_phy_mask(dev
, B43_NPHY_SCRAM_SIGCTL
,
335 ~B43_NPHY_SCRAM_SIGCTL_SCM
);
338 /* Set phase track alpha and beta */
339 b43_phy_write(dev
, B43_NPHY_PHASETR_A0
, 0x125);
340 b43_phy_write(dev
, B43_NPHY_PHASETR_A1
, 0x1B3);
341 b43_phy_write(dev
, B43_NPHY_PHASETR_A2
, 0x105);
342 b43_phy_write(dev
, B43_NPHY_PHASETR_B0
, 0x16E);
343 b43_phy_write(dev
, B43_NPHY_PHASETR_B1
, 0xCD);
344 b43_phy_write(dev
, B43_NPHY_PHASETR_B2
, 0x20);
347 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
348 static void b43_nphy_bmac_clock_fgc(struct b43_wldev
*dev
, bool force
)
352 if (dev
->phy
.type
!= B43_PHYTYPE_N
)
355 tmslow
= ssb_read32(dev
->dev
, SSB_TMSLOW
);
357 tmslow
|= SSB_TMSLOW_FGC
;
359 tmslow
&= ~SSB_TMSLOW_FGC
;
360 ssb_write32(dev
->dev
, SSB_TMSLOW
, tmslow
);
363 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
364 static void b43_nphy_reset_cca(struct b43_wldev
*dev
)
368 b43_nphy_bmac_clock_fgc(dev
, 1);
369 bbcfg
= b43_phy_read(dev
, B43_NPHY_BBCFG
);
370 b43_phy_write(dev
, B43_NPHY_BBCFG
, bbcfg
| B43_NPHY_BBCFG_RSTCCA
);
372 b43_phy_write(dev
, B43_NPHY_BBCFG
, bbcfg
& ~B43_NPHY_BBCFG_RSTCCA
);
373 b43_nphy_bmac_clock_fgc(dev
, 0);
374 /* TODO: N PHY Force RF Seq with argument 2 */
377 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
378 static void b43_nphy_write_clip_detection(struct b43_wldev
*dev
, u16
*clip_st
)
380 b43_phy_write(dev
, B43_NPHY_C1_CLIP1THRES
, clip_st
[0]);
381 b43_phy_write(dev
, B43_NPHY_C2_CLIP1THRES
, clip_st
[1]);
384 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
385 static void b43_nphy_read_clip_detection(struct b43_wldev
*dev
, u16
*clip_st
)
387 clip_st
[0] = b43_phy_read(dev
, B43_NPHY_C1_CLIP1THRES
);
388 clip_st
[1] = b43_phy_read(dev
, B43_NPHY_C2_CLIP1THRES
);
391 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
392 static u16
b43_nphy_classifier(struct b43_wldev
*dev
, u16 mask
, u16 val
)
396 if (dev
->dev
->id
.revision
== 16)
397 b43_mac_suspend(dev
);
399 tmp
= b43_phy_read(dev
, B43_NPHY_CLASSCTL
);
400 tmp
&= (B43_NPHY_CLASSCTL_CCKEN
| B43_NPHY_CLASSCTL_OFDMEN
|
401 B43_NPHY_CLASSCTL_WAITEDEN
);
404 b43_phy_maskset(dev
, B43_NPHY_CLASSCTL
, 0xFFF8, tmp
);
406 if (dev
->dev
->id
.revision
== 16)
412 enum b43_nphy_rf_sequence
{
416 B43_RFSEQ_UPDATE_GAINH
,
417 B43_RFSEQ_UPDATE_GAINL
,
418 B43_RFSEQ_UPDATE_GAINU
,
421 static void b43_nphy_force_rf_sequence(struct b43_wldev
*dev
,
422 enum b43_nphy_rf_sequence seq
)
424 static const u16 trigger
[] = {
425 [B43_RFSEQ_RX2TX
] = B43_NPHY_RFSEQTR_RX2TX
,
426 [B43_RFSEQ_TX2RX
] = B43_NPHY_RFSEQTR_TX2RX
,
427 [B43_RFSEQ_RESET2RX
] = B43_NPHY_RFSEQTR_RST2RX
,
428 [B43_RFSEQ_UPDATE_GAINH
] = B43_NPHY_RFSEQTR_UPGH
,
429 [B43_RFSEQ_UPDATE_GAINL
] = B43_NPHY_RFSEQTR_UPGL
,
430 [B43_RFSEQ_UPDATE_GAINU
] = B43_NPHY_RFSEQTR_UPGU
,
434 B43_WARN_ON(seq
>= ARRAY_SIZE(trigger
));
436 b43_phy_set(dev
, B43_NPHY_RFSEQMODE
,
437 B43_NPHY_RFSEQMODE_CAOVER
| B43_NPHY_RFSEQMODE_TROVER
);
438 b43_phy_set(dev
, B43_NPHY_RFSEQTR
, trigger
[seq
]);
439 for (i
= 0; i
< 200; i
++) {
440 if (!(b43_phy_read(dev
, B43_NPHY_RFSEQST
) & trigger
[seq
]))
444 b43err(dev
->wl
, "RF sequence status timeout\n");
446 b43_phy_mask(dev
, B43_NPHY_RFSEQMODE
,
447 ~(B43_NPHY_RFSEQMODE_CAOVER
| B43_NPHY_RFSEQMODE_TROVER
));
450 static void b43_nphy_bphy_init(struct b43_wldev
*dev
)
456 for (i
= 0; i
< 14; i
++) {
457 b43_phy_write(dev
, B43_PHY_N_BMODE(0x88 + i
), val
);
461 for (i
= 0; i
< 16; i
++) {
462 b43_phy_write(dev
, B43_PHY_N_BMODE(0x97 + i
), val
);
465 b43_phy_write(dev
, B43_PHY_N_BMODE(0x38), 0x668);
468 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
469 static void b43_nphy_scale_offset_rssi(struct b43_wldev
*dev
, u16 scale
,
470 s8 offset
, u8 core
, u8 rail
, u8 type
)
473 bool core1or5
= (core
== 1) || (core
== 5);
474 bool core2or5
= (core
== 2) || (core
== 5);
476 offset
= clamp_val(offset
, -32, 31);
477 tmp
= ((scale
& 0x3F) << 8) | (offset
& 0x3F);
479 if (core1or5
&& (rail
== 0) && (type
== 2))
480 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_RSSI_Z
, tmp
);
481 if (core1or5
&& (rail
== 1) && (type
== 2))
482 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_RSSI_Z
, tmp
);
483 if (core2or5
&& (rail
== 0) && (type
== 2))
484 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_RSSI_Z
, tmp
);
485 if (core2or5
&& (rail
== 1) && (type
== 2))
486 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_RSSI_Z
, tmp
);
487 if (core1or5
&& (rail
== 0) && (type
== 0))
488 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_RSSI_X
, tmp
);
489 if (core1or5
&& (rail
== 1) && (type
== 0))
490 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_RSSI_X
, tmp
);
491 if (core2or5
&& (rail
== 0) && (type
== 0))
492 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_RSSI_X
, tmp
);
493 if (core2or5
&& (rail
== 1) && (type
== 0))
494 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_RSSI_X
, tmp
);
495 if (core1or5
&& (rail
== 0) && (type
== 1))
496 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_RSSI_Y
, tmp
);
497 if (core1or5
&& (rail
== 1) && (type
== 1))
498 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_RSSI_Y
, tmp
);
499 if (core2or5
&& (rail
== 0) && (type
== 1))
500 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_RSSI_Y
, tmp
);
501 if (core2or5
&& (rail
== 1) && (type
== 1))
502 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_RSSI_Y
, tmp
);
503 if (core1or5
&& (rail
== 0) && (type
== 6))
504 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_TBD
, tmp
);
505 if (core1or5
&& (rail
== 1) && (type
== 6))
506 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_TBD
, tmp
);
507 if (core2or5
&& (rail
== 0) && (type
== 6))
508 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_TBD
, tmp
);
509 if (core2or5
&& (rail
== 1) && (type
== 6))
510 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_TBD
, tmp
);
511 if (core1or5
&& (rail
== 0) && (type
== 3))
512 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_PWRDET
, tmp
);
513 if (core1or5
&& (rail
== 1) && (type
== 3))
514 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_PWRDET
, tmp
);
515 if (core2or5
&& (rail
== 0) && (type
== 3))
516 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_PWRDET
, tmp
);
517 if (core2or5
&& (rail
== 1) && (type
== 3))
518 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_PWRDET
, tmp
);
519 if (core1or5
&& (type
== 4))
520 b43_phy_write(dev
, B43_NPHY_RSSIMC_0I_TSSI
, tmp
);
521 if (core2or5
&& (type
== 4))
522 b43_phy_write(dev
, B43_NPHY_RSSIMC_1I_TSSI
, tmp
);
523 if (core1or5
&& (type
== 5))
524 b43_phy_write(dev
, B43_NPHY_RSSIMC_0Q_TSSI
, tmp
);
525 if (core2or5
&& (type
== 5))
526 b43_phy_write(dev
, B43_NPHY_RSSIMC_1Q_TSSI
, tmp
);
529 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
530 static void b43_nphy_rssi_select(struct b43_wldev
*dev
, u8 code
, u8 type
)
534 if (dev
->phy
.rev
>= 3) {
546 val
= (val
<< 12) | (val
<< 14);
547 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C1
, 0x0FFF, val
);
548 b43_phy_maskset(dev
, B43_NPHY_AFECTL_C2
, 0x0FFF, val
);
551 b43_phy_maskset(dev
, B43_NPHY_RFCTL_RSSIO1
, 0xFFCF,
553 b43_phy_maskset(dev
, B43_NPHY_RFCTL_RSSIO2
, 0xFFCF,
557 /* TODO use some definitions */
559 b43_phy_maskset(dev
, B43_NPHY_AFECTL_OVER
, 0xCFFF, 0);
561 b43_phy_maskset(dev
, B43_NPHY_RFCTL_CMD
,
563 b43_phy_maskset(dev
, B43_NPHY_RFCTL_OVER
,
565 b43_phy_maskset(dev
, B43_NPHY_RFCTL_CMD
,
568 b43_phy_maskset(dev
, B43_NPHY_RFCTL_OVER
,
572 b43_phy_maskset(dev
, B43_NPHY_AFECTL_OVER
, 0xCFFF,
575 b43_phy_maskset(dev
, B43_NPHY_RFCTL_CMD
,
577 b43_phy_maskset(dev
, B43_NPHY_RFCTL_OVER
,
578 0xEFDC, (code
<< 1 | 0x1021));
579 b43_phy_maskset(dev
, B43_NPHY_RFCTL_CMD
,
582 b43_phy_maskset(dev
, B43_NPHY_RFCTL_OVER
,
589 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
590 static void b43_nphy_rev2_rssi_cal(struct b43_wldev
*dev
, u8 type
)
595 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
596 static void b43_nphy_rev3_rssi_cal(struct b43_wldev
*dev
)
603 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
605 static void b43_nphy_rssi_cal(struct b43_wldev
*dev
)
607 if (dev
->phy
.rev
>= 3) {
608 b43_nphy_rev3_rssi_cal(dev
);
610 b43_nphy_rev2_rssi_cal(dev
, 2);
611 b43_nphy_rev2_rssi_cal(dev
, 0);
612 b43_nphy_rev2_rssi_cal(dev
, 1);
618 * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
620 int b43_phy_initn(struct b43_wldev
*dev
)
622 struct ssb_bus
*bus
= dev
->dev
->bus
;
623 struct b43_phy
*phy
= &dev
->phy
;
624 struct b43_phy_n
*nphy
= phy
->n
;
626 struct nphy_txgains target
;
628 enum ieee80211_band tmp2
;
634 if ((dev
->phy
.rev
>= 3) &&
635 (bus
->sprom
.boardflags_lo
& B43_BFL_EXTLNA
) &&
636 (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
)) {
637 chipco_set32(&dev
->dev
->bus
->chipco
, SSB_CHIPCO_CHIPCTL
, 0x40);
639 nphy
->deaf_count
= 0;
640 b43_nphy_tables_init(dev
);
641 nphy
->crsminpwr_adjusted
= false;
642 nphy
->noisevars_adjusted
= false;
644 /* Clear all overrides */
645 if (dev
->phy
.rev
>= 3) {
646 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B1S1
, 0);
647 b43_phy_write(dev
, B43_NPHY_RFCTL_OVER
, 0);
648 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B1S0
, 0);
649 b43_phy_write(dev
, B43_NPHY_TXF_40CO_B32S1
, 0);
651 b43_phy_write(dev
, B43_NPHY_RFCTL_OVER
, 0);
653 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC1
, 0);
654 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC2
, 0);
655 if (dev
->phy
.rev
< 6) {
656 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC3
, 0);
657 b43_phy_write(dev
, B43_NPHY_RFCTL_INTC4
, 0);
659 b43_phy_mask(dev
, B43_NPHY_RFSEQMODE
,
660 ~(B43_NPHY_RFSEQMODE_CAOVER
|
661 B43_NPHY_RFSEQMODE_TROVER
));
662 if (dev
->phy
.rev
>= 3)
663 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER1
, 0);
664 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
, 0);
666 if (dev
->phy
.rev
<= 2) {
667 tmp
= (dev
->phy
.rev
== 2) ? 0x3B : 0x40;
668 b43_phy_maskset(dev
, B43_NPHY_BPHY_CTL3
,
669 ~B43_NPHY_BPHY_CTL3_SCALE
,
670 tmp
<< B43_NPHY_BPHY_CTL3_SCALE_SHIFT
);
672 b43_phy_write(dev
, B43_NPHY_AFESEQ_TX2RX_PUD_20M
, 0x20);
673 b43_phy_write(dev
, B43_NPHY_AFESEQ_TX2RX_PUD_40M
, 0x20);
675 if (bus
->sprom
.boardflags2_lo
& 0x100 ||
676 (bus
->boardinfo
.vendor
== PCI_VENDOR_ID_APPLE
&&
677 bus
->boardinfo
.type
== 0x8B))
678 b43_phy_write(dev
, B43_NPHY_TXREALFD
, 0xA0);
680 b43_phy_write(dev
, B43_NPHY_TXREALFD
, 0xB8);
681 b43_phy_write(dev
, B43_NPHY_MIMO_CRSTXEXT
, 0xC8);
682 b43_phy_write(dev
, B43_NPHY_PLOAD_CSENSE_EXTLEN
, 0x50);
683 b43_phy_write(dev
, B43_NPHY_TXRIFS_FRDEL
, 0x30);
685 /* TODO MIMO-Config */
686 /* TODO Update TX/RX chain */
689 b43_phy_write(dev
, B43_NPHY_DUP40_GFBL
, 0xAA8);
690 b43_phy_write(dev
, B43_NPHY_DUP40_BL
, 0x9A4);
693 tmp2
= b43_current_band(dev
->wl
);
694 if ((nphy
->ipa2g_on
&& tmp2
== IEEE80211_BAND_2GHZ
) ||
695 (nphy
->ipa5g_on
&& tmp2
== IEEE80211_BAND_5GHZ
)) {
696 b43_phy_set(dev
, B43_NPHY_PAPD_EN0
, 0x1);
697 b43_phy_maskset(dev
, B43_NPHY_EPS_TABLE_ADJ0
, 0x007F,
698 nphy
->papd_epsilon_offset
[0] << 7);
699 b43_phy_set(dev
, B43_NPHY_PAPD_EN1
, 0x1);
700 b43_phy_maskset(dev
, B43_NPHY_EPS_TABLE_ADJ1
, 0x007F,
701 nphy
->papd_epsilon_offset
[1] << 7);
702 /* TODO N PHY IPA Set TX Dig Filters */
703 } else if (phy
->rev
>= 5) {
704 /* TODO N PHY Ext PA Set TX Dig Filters */
707 b43_nphy_workarounds(dev
);
709 /* Reset CCA, in init code it differs a little from standard way */
710 /* b43_nphy_bmac_clock_fgc(dev, 1); */
711 tmp
= b43_phy_read(dev
, B43_NPHY_BBCFG
);
712 b43_phy_write(dev
, B43_NPHY_BBCFG
, tmp
| B43_NPHY_BBCFG_RSTCCA
);
713 b43_phy_write(dev
, B43_NPHY_BBCFG
, tmp
& ~B43_NPHY_BBCFG_RSTCCA
);
714 /* b43_nphy_bmac_clock_fgc(dev, 0); */
716 /* TODO N PHY MAC PHY Clock Set with argument 1 */
718 /* b43_nphy_pa_override(dev, false); */
719 b43_nphy_force_rf_sequence(dev
, B43_RFSEQ_RX2TX
);
720 b43_nphy_force_rf_sequence(dev
, B43_RFSEQ_RESET2RX
);
721 /* b43_nphy_pa_override(dev, true); */
723 b43_nphy_classifier(dev
, 0, 0);
724 b43_nphy_read_clip_detection(dev
, clip
);
725 tx_pwr_state
= nphy
->txpwrctrl
;
726 /* TODO N PHY TX power control with argument 0
727 (turning off power control) */
728 /* TODO Fix the TX Power Settings */
729 /* TODO N PHY TX Power Control Idle TSSI */
730 /* TODO N PHY TX Power Control Setup */
735 /* TODO Write an N PHY table with ID 26, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */
736 /* TODO Write an N PHY table with ID 27, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */
739 if (nphy
->phyrxchain
!= 3)
740 ;/* TODO N PHY RX Core Set State with phyrxchain as argument */
741 if (nphy
->mphase_cal_phase_id
> 0)
742 ;/* TODO PHY Periodic Calibration Multi-Phase Restart */
746 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
)
747 do_rssi_cal
= (nphy
->rssical_chanspec_2G
== 0);
749 do_rssi_cal
= (nphy
->rssical_chanspec_5G
== 0);
752 b43_nphy_rssi_cal(dev
);
754 ;/* b43_nphy_restore_rssi_cal(dev); */
756 b43_nphy_rssi_cal(dev
);
759 if (!((nphy
->measure_hold
& 0x6) != 0)) {
760 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
)
761 do_cal
= (nphy
->iqcal_chanspec_2G
== 0);
763 do_cal
= (nphy
->iqcal_chanspec_5G
== 0);
769 /* target = b43_nphy_get_tx_gains(dev); */
771 if (nphy
->antsel_type
== 2)
772 ;/*TODO NPHY Superswitch Init with argument 1*/
773 if (nphy
->perical
!= 2) {
774 /* b43_nphy_rssi_cal(dev); */
776 nphy
->cal_orig_pwr_idx
[0] =
777 nphy
->txpwrindex
[0].index_internal
;
778 nphy
->cal_orig_pwr_idx
[1] =
779 nphy
->txpwrindex
[1].index_internal
;
780 /* TODO N PHY Pre Calibrate TX Gain */
781 /*target = b43_nphy_get_tx_gains(dev)*/
788 if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) {
789 if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
791 else if (nphy->mphase_cal_phase_id == 0)
792 N PHY Periodic Calibration with argument 3
794 b43_nphy_restore_cal(dev);
798 /* b43_nphy_tx_pwr_ctrl_coef_setup(dev); */
799 /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */
800 b43_phy_write(dev
, B43_NPHY_TXMACIF_HOLDOFF
, 0x0015);
801 b43_phy_write(dev
, B43_NPHY_TXMACDELAY
, 0x0320);
802 if (phy
->rev
>= 3 && phy
->rev
<= 6)
803 b43_phy_write(dev
, B43_NPHY_PLOAD_CSENSE_EXTLEN
, 0x0014);
804 /* b43_nphy_tx_lp_fbw(dev); */
805 /* TODO N PHY Spur Workaround */
807 b43err(dev
->wl
, "IEEE 802.11n devices are not supported, yet.\n");
811 static int b43_nphy_op_allocate(struct b43_wldev
*dev
)
813 struct b43_phy_n
*nphy
;
815 nphy
= kzalloc(sizeof(*nphy
), GFP_KERNEL
);
823 static void b43_nphy_op_prepare_structs(struct b43_wldev
*dev
)
825 struct b43_phy
*phy
= &dev
->phy
;
826 struct b43_phy_n
*nphy
= phy
->n
;
828 memset(nphy
, 0, sizeof(*nphy
));
830 //TODO init struct b43_phy_n
833 static void b43_nphy_op_free(struct b43_wldev
*dev
)
835 struct b43_phy
*phy
= &dev
->phy
;
836 struct b43_phy_n
*nphy
= phy
->n
;
842 static int b43_nphy_op_init(struct b43_wldev
*dev
)
844 return b43_phy_initn(dev
);
847 static inline void check_phyreg(struct b43_wldev
*dev
, u16 offset
)
850 if ((offset
& B43_PHYROUTE
) == B43_PHYROUTE_OFDM_GPHY
) {
851 /* OFDM registers are onnly available on A/G-PHYs */
852 b43err(dev
->wl
, "Invalid OFDM PHY access at "
853 "0x%04X on N-PHY\n", offset
);
856 if ((offset
& B43_PHYROUTE
) == B43_PHYROUTE_EXT_GPHY
) {
857 /* Ext-G registers are only available on G-PHYs */
858 b43err(dev
->wl
, "Invalid EXT-G PHY access at "
859 "0x%04X on N-PHY\n", offset
);
862 #endif /* B43_DEBUG */
865 static u16
b43_nphy_op_read(struct b43_wldev
*dev
, u16 reg
)
867 check_phyreg(dev
, reg
);
868 b43_write16(dev
, B43_MMIO_PHY_CONTROL
, reg
);
869 return b43_read16(dev
, B43_MMIO_PHY_DATA
);
872 static void b43_nphy_op_write(struct b43_wldev
*dev
, u16 reg
, u16 value
)
874 check_phyreg(dev
, reg
);
875 b43_write16(dev
, B43_MMIO_PHY_CONTROL
, reg
);
876 b43_write16(dev
, B43_MMIO_PHY_DATA
, value
);
879 static u16
b43_nphy_op_radio_read(struct b43_wldev
*dev
, u16 reg
)
881 /* Register 1 is a 32-bit register. */
882 B43_WARN_ON(reg
== 1);
883 /* N-PHY needs 0x100 for read access */
886 b43_write16(dev
, B43_MMIO_RADIO_CONTROL
, reg
);
887 return b43_read16(dev
, B43_MMIO_RADIO_DATA_LOW
);
890 static void b43_nphy_op_radio_write(struct b43_wldev
*dev
, u16 reg
, u16 value
)
892 /* Register 1 is a 32-bit register. */
893 B43_WARN_ON(reg
== 1);
895 b43_write16(dev
, B43_MMIO_RADIO_CONTROL
, reg
);
896 b43_write16(dev
, B43_MMIO_RADIO_DATA_LOW
, value
);
899 static void b43_nphy_op_software_rfkill(struct b43_wldev
*dev
,
904 static void b43_nphy_op_switch_analog(struct b43_wldev
*dev
, bool on
)
906 b43_phy_write(dev
, B43_NPHY_AFECTL_OVER
,
910 static int b43_nphy_op_switch_channel(struct b43_wldev
*dev
,
911 unsigned int new_channel
)
913 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
) {
914 if ((new_channel
< 1) || (new_channel
> 14))
917 if (new_channel
> 200)
921 return nphy_channel_switch(dev
, new_channel
);
924 static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev
*dev
)
926 if (b43_current_band(dev
->wl
) == IEEE80211_BAND_2GHZ
)
931 const struct b43_phy_operations b43_phyops_n
= {
932 .allocate
= b43_nphy_op_allocate
,
933 .free
= b43_nphy_op_free
,
934 .prepare_structs
= b43_nphy_op_prepare_structs
,
935 .init
= b43_nphy_op_init
,
936 .phy_read
= b43_nphy_op_read
,
937 .phy_write
= b43_nphy_op_write
,
938 .radio_read
= b43_nphy_op_radio_read
,
939 .radio_write
= b43_nphy_op_radio_write
,
940 .software_rfkill
= b43_nphy_op_software_rfkill
,
941 .switch_analog
= b43_nphy_op_switch_analog
,
942 .switch_channel
= b43_nphy_op_switch_channel
,
943 .get_default_chan
= b43_nphy_op_get_default_chan
,
944 .recalc_txpower
= b43_nphy_op_recalc_txpower
,
945 .adjust_txpower
= b43_nphy_op_adjust_txpower
,