diff options
author | Rafał Miłecki <zajec5@gmail.com> | 2014-07-19 12:52:43 +0200 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-07-22 13:53:18 -0400 |
commit | 49083b47a380b086c3c92ffe5ae7125a16ad4671 (patch) | |
tree | 3bba3dc9b26e7689819cbc8afeb7ed26d02a270f | |
parent | 6b346e54bf94f65b756ad32902e663785da9eda6 (diff) | |
download | op-kernel-dev-49083b47a380b086c3c92ffe5ae7125a16ad4671.zip op-kernel-dev-49083b47a380b086c3c92ffe5ae7125a16ad4671.tar.gz |
b43: N-PHY: update generic rev7+ workarounds
Add some missing ops and prepare for new devices support. This patch is
a great stability improvement for BCM43217. Earlier Tenda W322E used to
disconnect every 2 minutes (16 times over 30 minutes). With this fix I
got it running for 4 hours (with iperf) without any disconnection.
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 120 |
1 files changed, 79 insertions, 41 deletions
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 1293f51..448c676 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -2708,15 +2708,19 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) struct ssb_sprom *sprom = dev->dev->bus_sprom; struct b43_phy *phy = &dev->phy; + /* TX to RX */ + u8 tx2rx_events[7] = { 4, 3, 5, 2, 1, 8, 31, }; + u8 tx2rx_delays[7] = { 8, 4, 4, 4, 4, 6, 1, }; + /* RX to TX */ u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3, 0x1F }; u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; - u16 ntab7_15e_16e[] = { 0x10f, 0x10f }; + static const u16 ntab7_15e_16e[] = { 0, 0x10f, 0x10f }; u8 ntab7_138_146[] = { 0x11, 0x11 }; u8 ntab7_133[] = { 0x77, 0x11, 0x11 }; - u16 lpf_20, lpf_40, lpf_11b; + u16 lpf_ofdm_20mhz, lpf_ofdm_40mhz, lpf_11b; u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40; u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40; bool rccal_ovrd = false; @@ -2727,6 +2731,13 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) u32 tmp32; u8 core; + b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125); + b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01b3); + b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105); + b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016e); + b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00cd); + b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020); + if (phy->rev == 7) { b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10); b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020); @@ -2746,11 +2757,18 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040); b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000); } - if (phy->rev <= 8) { + + if (phy->rev >= 16) { + b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x7ff); + b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x7ff); + } else if (phy->rev <= 8) { b43_phy_write(dev, B43_NPHY_FORCEFRONT0, 0x1B0); b43_phy_write(dev, B43_NPHY_FORCEFRONT1, 0x1B0); } - if (phy->rev >= 8) + + if (phy->rev >= 16) + b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0xa0); + else if (phy->rev >= 8) b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72); b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2); @@ -2758,9 +2776,11 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0)); tmp32 &= 0xffffff; b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32); - b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e); - b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e); + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15d), 3, ntab7_15e_16e); + b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16d), 3, ntab7_15e_16e); + b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays, + ARRAY_SIZE(tx2rx_events)); if (b43_nphy_ipa(dev)) b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa, rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa)); @@ -2768,44 +2788,53 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_0, 0x3FFF, 0x4000); b43_phy_maskset(dev, B43_NPHY_EPS_OVERRIDEI_1, 0x3FFF, 0x4000); - lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154); - lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159); + lpf_ofdm_20mhz = b43_nphy_read_lpf_ctl(dev, 0x154); + lpf_ofdm_40mhz = b43_nphy_read_lpf_ctl(dev, 0x159); lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152); + + bcap_val = b43_radio_read(dev, R2057_RCCAL_BCAP_VAL); + scap_val = b43_radio_read(dev, R2057_RCCAL_SCAP_VAL); + if (b43_nphy_ipa(dev)) { - if ((phy->radio_rev == 5 && b43_is_40mhz(dev)) || - phy->radio_rev == 7 || phy->radio_rev == 8) { - bcap_val = b43_radio_read(dev, 0x16b); - scap_val = b43_radio_read(dev, 0x16a); - scap_val_11b = scap_val; - bcap_val_11b = bcap_val; - if (phy->radio_rev == 5 && b43_is_40mhz(dev)) { + switch (phy->radio_rev) { + case 5: + /* Check radio version (to be 0) by PHY rev for now */ + if (phy->rev == 8 && b43_is_40mhz(dev)) { + scap_val_11b = scap_val; + bcap_val_11b = bcap_val; scap_val_11n_20 = scap_val; bcap_val_11n_20 = bcap_val; scap_val_11n_40 = bcap_val_11n_40 = 0xc; rccal_ovrd = true; - } else { /* Rev 7/8 */ - lpf_20 = 4; - lpf_11b = 1; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - scap_val_11n_20 = 0xc; - bcap_val_11n_20 = 0xc; - scap_val_11n_40 = 0xa; - bcap_val_11n_40 = 0xa; - } else { - scap_val_11n_20 = 0x14; - bcap_val_11n_20 = 0x14; - scap_val_11n_40 = 0xf; - bcap_val_11n_40 = 0xf; - } - rccal_ovrd = true; } + if (phy->rev == 9) { + /* TODO: Radio version 1 (e.g. BCM5357B0) */ + } + break; + case 7: + case 8: + scap_val_11b = scap_val; + bcap_val_11b = bcap_val; + lpf_ofdm_20mhz = 4; + lpf_11b = 1; + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { + scap_val_11n_20 = 0xc; + bcap_val_11n_20 = 0xc; + scap_val_11n_40 = 0xa; + bcap_val_11n_40 = 0xa; + } else { + scap_val_11n_20 = 0x14; + bcap_val_11n_20 = 0x14; + scap_val_11n_40 = 0xf; + bcap_val_11n_40 = 0xf; + } + rccal_ovrd = true; + break; } } else { if (phy->radio_rev == 5) { - lpf_20 = 1; - lpf_40 = 3; - bcap_val = b43_radio_read(dev, 0x16b); - scap_val = b43_radio_read(dev, 0x16a); + lpf_ofdm_20mhz = 1; + lpf_ofdm_40mhz = 3; scap_val_11b = scap_val; bcap_val_11b = bcap_val; scap_val_11n_20 = 0x11; @@ -2816,15 +2845,20 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) } } if (rccal_ovrd) { - rx2tx_lut_20_11b = (bcap_val_11b << 8) | + u8 rx2tx_lut_extra = 1; + + rx2tx_lut_20_11b = (rx2tx_lut_extra << 13) | + (bcap_val_11b << 8) | (scap_val_11b << 3) | lpf_11b; - rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) | + rx2tx_lut_20_11n = (rx2tx_lut_extra << 13) | + (bcap_val_11n_20 << 8) | (scap_val_11n_20 << 3) | - lpf_20; - rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) | + lpf_ofdm_20mhz; + rx2tx_lut_40_11n = (rx2tx_lut_extra << 13) | + (bcap_val_11n_40 << 8) | (scap_val_11n_40 << 3) | - lpf_40; + lpf_ofdm_40mhz; for (core = 0; core < 2; core++) { b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16), rx2tx_lut_20_11b); @@ -2893,7 +2927,8 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) 0x7f); } } - if (phy->radio_rev == 3) { + switch (phy->radio_rev) { + case 3: for (core = 0; core < 2; core++) { if (core == 0) { b43_radio_write(dev, 0x64, @@ -2919,7 +2954,9 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) 0x3E); } } - } else if (phy->radio_rev == 7 || phy->radio_rev == 8) { + break; + case 7: + case 8: if (!b43_is_40mhz(dev)) { b43_radio_write(dev, 0x5F, 0x14); b43_radio_write(dev, 0xE8, 0x12); @@ -2927,6 +2964,7 @@ static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev) b43_radio_write(dev, 0x5F, 0x16); b43_radio_write(dev, 0xE8, 0x16); } + break; } } else { u16 freq = phy->chandef->chan->center_freq; |