aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/phy_n.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43/phy_n.c')
-rw-r--r--drivers/net/wireless/b43/phy_n.c128
1 files changed, 63 insertions, 65 deletions
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index f575e757caeb..dfec5496055e 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -29,6 +29,8 @@
29#include "b43.h" 29#include "b43.h"
30#include "phy_n.h" 30#include "phy_n.h"
31#include "tables_nphy.h" 31#include "tables_nphy.h"
32#include "radio_2055.h"
33#include "radio_2056.h"
32#include "main.h" 34#include "main.h"
33 35
34struct nphy_txgains { 36struct nphy_txgains {
@@ -74,19 +76,11 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
74static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, 76static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
75 u16 value, u8 core); 77 u16 value, u8 core);
76 78
77static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec) 79static inline bool b43_channel_type_is_40mhz(
80 enum nl80211_channel_type channel_type)
78{ 81{
79 return !chanspec->channel && !chanspec->sideband && 82 return (channel_type == NL80211_CHAN_HT40MINUS ||
80 !chanspec->b_width && !chanspec->b_freq; 83 channel_type == NL80211_CHAN_HT40PLUS);
81}
82
83static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1,
84 struct b43_chanspec *chanspec2)
85{
86 return (chanspec1->channel == chanspec2->channel &&
87 chanspec1->sideband == chanspec2->sideband &&
88 chanspec1->b_width == chanspec2->b_width &&
89 chanspec1->b_freq == chanspec2->b_freq);
90} 84}
91 85
92void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) 86void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
@@ -781,7 +775,7 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev)
781{ 775{
782 struct b43_phy_n *nphy = dev->phy.n; 776 struct b43_phy_n *nphy = dev->phy.n;
783 777
784 u8 channel = nphy->radio_chanspec.channel; 778 u8 channel = dev->phy.channel;
785 int tone[2] = { 57, 58 }; 779 int tone[2] = { 57, 58 };
786 u32 noise[2] = { 0x3FF, 0x3FF }; 780 u32 noise[2] = { 0x3FF, 0x3FF };
787 781
@@ -855,9 +849,9 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
855 gain[0] = 6; 849 gain[0] = 6;
856 gain[1] = 6; 850 gain[1] = 6;
857 } else { 851 } else {
858 tmp = 40370 - 315 * nphy->radio_chanspec.channel; 852 tmp = 40370 - 315 * dev->phy.channel;
859 gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1)); 853 gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
860 tmp = 23242 - 224 * nphy->radio_chanspec.channel; 854 tmp = 23242 - 224 * dev->phy.channel;
861 gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1)); 855 gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
862 } 856 }
863 } else { 857 } else {
@@ -2083,12 +2077,12 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
2083 u16 *rssical_phy_regs = NULL; 2077 u16 *rssical_phy_regs = NULL;
2084 2078
2085 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 2079 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2086 if (b43_empty_chanspec(&nphy->rssical_chanspec_2G)) 2080 if (!nphy->rssical_chanspec_2G.center_freq)
2087 return; 2081 return;
2088 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; 2082 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
2089 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; 2083 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
2090 } else { 2084 } else {
2091 if (b43_empty_chanspec(&nphy->rssical_chanspec_5G)) 2085 if (!nphy->rssical_chanspec_5G.center_freq)
2092 return; 2086 return;
2093 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; 2087 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
2094 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; 2088 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
@@ -2544,8 +2538,9 @@ static void b43_nphy_save_cal(struct b43_wldev *dev)
2544 txcal_radio_regs[2] = b43_radio_read(dev, 0x8D); 2538 txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
2545 txcal_radio_regs[3] = b43_radio_read(dev, 0xBC); 2539 txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
2546 } 2540 }
2547 *iqcal_chanspec = nphy->radio_chanspec; 2541 iqcal_chanspec->center_freq = dev->phy.channel_freq;
2548 b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table); 2542 iqcal_chanspec->channel_type = dev->phy.channel_type;
2543 b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
2549 2544
2550 if (nphy->hang_avoid) 2545 if (nphy->hang_avoid)
2551 b43_nphy_stay_in_carrier_search(dev, 0); 2546 b43_nphy_stay_in_carrier_search(dev, 0);
@@ -2565,12 +2560,12 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev)
2565 struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; 2560 struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
2566 2561
2567 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 2562 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2568 if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G)) 2563 if (!nphy->iqcal_chanspec_2G.center_freq)
2569 return; 2564 return;
2570 table = nphy->cal_cache.txcal_coeffs_2G; 2565 table = nphy->cal_cache.txcal_coeffs_2G;
2571 loft = &nphy->cal_cache.txcal_coeffs_2G[5]; 2566 loft = &nphy->cal_cache.txcal_coeffs_2G[5];
2572 } else { 2567 } else {
2573 if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G)) 2568 if (!nphy->iqcal_chanspec_5G.center_freq)
2574 return; 2569 return;
2575 table = nphy->cal_cache.txcal_coeffs_5G; 2570 table = nphy->cal_cache.txcal_coeffs_5G;
2576 loft = &nphy->cal_cache.txcal_coeffs_5G[5]; 2571 loft = &nphy->cal_cache.txcal_coeffs_5G[5];
@@ -2815,7 +2810,10 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
2815 b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, 2810 b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
2816 nphy->txiqlocal_bestc); 2811 nphy->txiqlocal_bestc);
2817 nphy->txiqlocal_coeffsvalid = true; 2812 nphy->txiqlocal_coeffsvalid = true;
2818 nphy->txiqlocal_chanspec = nphy->radio_chanspec; 2813 nphy->txiqlocal_chanspec.center_freq =
2814 dev->phy.channel_freq;
2815 nphy->txiqlocal_chanspec.channel_type =
2816 dev->phy.channel_type;
2819 } else { 2817 } else {
2820 length = 11; 2818 length = 11;
2821 if (dev->phy.rev < 3) 2819 if (dev->phy.rev < 3)
@@ -2851,7 +2849,8 @@ static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
2851 bool equal = true; 2849 bool equal = true;
2852 2850
2853 if (!nphy->txiqlocal_coeffsvalid || 2851 if (!nphy->txiqlocal_coeffsvalid ||
2854 b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec)) 2852 nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq ||
2853 nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type)
2855 return; 2854 return;
2856 2855
2857 b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); 2856 b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
@@ -3257,11 +3256,9 @@ int b43_phy_initn(struct b43_wldev *dev)
3257 do_rssi_cal = false; 3256 do_rssi_cal = false;
3258 if (phy->rev >= 3) { 3257 if (phy->rev >= 3) {
3259 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 3258 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
3260 do_rssi_cal = 3259 do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
3261 b43_empty_chanspec(&nphy->rssical_chanspec_2G);
3262 else 3260 else
3263 do_rssi_cal = 3261 do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
3264 b43_empty_chanspec(&nphy->rssical_chanspec_5G);
3265 3262
3266 if (do_rssi_cal) 3263 if (do_rssi_cal)
3267 b43_nphy_rssi_cal(dev); 3264 b43_nphy_rssi_cal(dev);
@@ -3273,9 +3270,9 @@ int b43_phy_initn(struct b43_wldev *dev)
3273 3270
3274 if (!((nphy->measure_hold & 0x6) != 0)) { 3271 if (!((nphy->measure_hold & 0x6) != 0)) {
3275 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 3272 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
3276 do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G); 3273 do_cal = !nphy->iqcal_chanspec_2G.center_freq;
3277 else 3274 else
3278 do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G); 3275 do_cal = !nphy->iqcal_chanspec_5G.center_freq;
3279 3276
3280 if (nphy->mute) 3277 if (nphy->mute)
3281 do_cal = false; 3278 do_cal = false;
@@ -3323,24 +3320,25 @@ int b43_phy_initn(struct b43_wldev *dev)
3323} 3320}
3324 3321
3325/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ 3322/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
3326static void b43_nphy_chanspec_setup(struct b43_wldev *dev, 3323static void b43_nphy_channel_setup(struct b43_wldev *dev,
3327 const struct b43_phy_n_sfo_cfg *e, 3324 const struct b43_phy_n_sfo_cfg *e,
3328 struct b43_chanspec chanspec) 3325 struct ieee80211_channel *new_channel)
3329{ 3326{
3330 struct b43_phy *phy = &dev->phy; 3327 struct b43_phy *phy = &dev->phy;
3331 struct b43_phy_n *nphy = dev->phy.n; 3328 struct b43_phy_n *nphy = dev->phy.n;
3332 3329
3333 u16 tmp; 3330 u16 old_band_5ghz;
3334 u32 tmp32; 3331 u32 tmp32;
3335 3332
3336 tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; 3333 old_band_5ghz =
3337 if (chanspec.b_freq == 1 && tmp == 0) { 3334 b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
3335 if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
3338 tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); 3336 tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
3339 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); 3337 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
3340 b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); 3338 b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
3341 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); 3339 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
3342 b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); 3340 b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
3343 } else if (chanspec.b_freq == 1) { 3341 } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
3344 b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); 3342 b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
3345 tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); 3343 tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
3346 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); 3344 b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
@@ -3350,13 +3348,12 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
3350 3348
3351 b43_chantab_phy_upload(dev, e); 3349 b43_chantab_phy_upload(dev, e);
3352 3350
3353 3351 if (new_channel->hw_value == 14) {
3354 if (nphy->radio_chanspec.channel == 14) {
3355 b43_nphy_classifier(dev, 2, 0); 3352 b43_nphy_classifier(dev, 2, 0);
3356 b43_phy_set(dev, B43_PHY_B_TEST, 0x0800); 3353 b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
3357 } else { 3354 } else {
3358 b43_nphy_classifier(dev, 2, 2); 3355 b43_nphy_classifier(dev, 2, 2);
3359 if (chanspec.b_freq == 2) 3356 if (new_channel->band == IEEE80211_BAND_2GHZ)
3360 b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); 3357 b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
3361 } 3358 }
3362 3359
@@ -3379,53 +3376,57 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev,
3379} 3376}
3380 3377
3381/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ 3378/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
3382static int b43_nphy_set_chanspec(struct b43_wldev *dev, 3379static int b43_nphy_set_channel(struct b43_wldev *dev,
3383 struct b43_chanspec chanspec) 3380 struct ieee80211_channel *channel,
3381 enum nl80211_channel_type channel_type)
3384{ 3382{
3383 struct b43_phy *phy = &dev->phy;
3385 struct b43_phy_n *nphy = dev->phy.n; 3384 struct b43_phy_n *nphy = dev->phy.n;
3386 3385
3387 const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; 3386 const struct b43_nphy_channeltab_entry_rev2 *tabent_r2;
3388 const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; 3387 const struct b43_nphy_channeltab_entry_rev3 *tabent_r3;
3389 3388
3390 u8 tmp; 3389 u8 tmp;
3391 u8 channel = chanspec.channel;
3392 3390
3393 if (dev->phy.rev >= 3) { 3391 if (dev->phy.rev >= 3) {
3394 /* TODO */ 3392 tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
3393 channel->center_freq);
3395 tabent_r3 = NULL; 3394 tabent_r3 = NULL;
3396 if (!tabent_r3) 3395 if (!tabent_r3)
3397 return -ESRCH; 3396 return -ESRCH;
3398 } else { 3397 } else {
3399 tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel); 3398 tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
3399 channel->hw_value);
3400 if (!tabent_r2) 3400 if (!tabent_r2)
3401 return -ESRCH; 3401 return -ESRCH;
3402 } 3402 }
3403 3403
3404 nphy->radio_chanspec = chanspec; 3404 /* Channel is set later in common code, but we need to set it on our
3405 own to let this function's subcalls work properly. */
3406 phy->channel = channel->hw_value;
3407 phy->channel_freq = channel->center_freq;
3405 3408
3406 if (chanspec.b_width != nphy->b_width) 3409 if (b43_channel_type_is_40mhz(phy->channel_type) !=
3407 ; /* TODO: BMAC BW Set (chanspec.b_width) */ 3410 b43_channel_type_is_40mhz(channel_type))
3411 ; /* TODO: BMAC BW Set (channel_type) */
3408 3412
3409 /* TODO: use defines */ 3413 if (channel_type == NL80211_CHAN_HT40PLUS)
3410 if (chanspec.b_width == 3) { 3414 b43_phy_set(dev, B43_NPHY_RXCTL,
3411 if (chanspec.sideband == 2) 3415 B43_NPHY_RXCTL_BSELU20);
3412 b43_phy_set(dev, B43_NPHY_RXCTL, 3416 else if (channel_type == NL80211_CHAN_HT40MINUS)
3413 B43_NPHY_RXCTL_BSELU20); 3417 b43_phy_mask(dev, B43_NPHY_RXCTL,
3414 else 3418 ~B43_NPHY_RXCTL_BSELU20);
3415 b43_phy_mask(dev, B43_NPHY_RXCTL,
3416 ~B43_NPHY_RXCTL_BSELU20);
3417 }
3418 3419
3419 if (dev->phy.rev >= 3) { 3420 if (dev->phy.rev >= 3) {
3420 tmp = (chanspec.b_freq == 1) ? 4 : 0; 3421 tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
3421 b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); 3422 b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
3422 /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */ 3423 /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */
3423 b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec); 3424 b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
3424 } else { 3425 } else {
3425 tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; 3426 tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
3426 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); 3427 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
3427 b43_radio_2055_setup(dev, tabent_r2); 3428 b43_radio_2055_setup(dev, tabent_r2);
3428 b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec); 3429 b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
3429 } 3430 }
3430 3431
3431 return 0; 3432 return 0;
@@ -3567,8 +3568,8 @@ static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
3567static int b43_nphy_op_switch_channel(struct b43_wldev *dev, 3568static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
3568 unsigned int new_channel) 3569 unsigned int new_channel)
3569{ 3570{
3570 struct b43_phy_n *nphy = dev->phy.n; 3571 struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
3571 struct b43_chanspec chanspec; 3572 enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
3572 3573
3573 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 3574 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3574 if ((new_channel < 1) || (new_channel > 14)) 3575 if ((new_channel < 1) || (new_channel > 14))
@@ -3578,10 +3579,7 @@ static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
3578 return -EINVAL; 3579 return -EINVAL;
3579 } 3580 }
3580 3581
3581 chanspec = nphy->radio_chanspec; 3582 return b43_nphy_set_channel(dev, channel, channel_type);
3582 chanspec.channel = new_channel;
3583
3584 return b43_nphy_set_chanspec(dev, chanspec);
3585} 3583}
3586 3584
3587static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) 3585static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)