diff options
author | Nick Kossifidis <mickflemm@gmail.com> | 2010-11-23 22:39:28 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-30 21:53:43 +0300 |
commit | 8aec7af99b1e4594c4bb9e1c48005e6111f97e8e (patch) | |
tree | b89d4466afda78ba949d03f32d0efb8f3c75ecd6 /drivers/net/wireless/ath/ath5k/phy.c | |
parent | 4c57581d939fd0f8f244b9730812069f4dac308a (diff) | |
download | linux-8aec7af99b1e4594c4bb9e1c48005e6111f97e8e.tar.xz |
ath5k: Support synth-only channel change for AR2413/AR5413
* Add synth-only channel change for AR2413/5413. When we call
ath5k_reset with a channel ath5k_hw_reset will first try to
set channel on PHY while PHY is running instead of doing a normal
full reset. To do this phy_init has to change to implement this
functionality.
* Clean up change_channel flag, what it really did was skip PCU
registers when setting initvals. This is done because on reset
PCU registers are not affected (except the registers we set
in pcu init and -due to hw problems- TSF). Use a new skip_pcu
flag that's not misleading instead. In the future we might use
that to also skip PCU reset and save us the TSF etc problems
(needs testing because standard practice is to reset everything).
* Use fast channel change only when setting channel, and set skip_pcu
to false only on init. When we reset the card due to DMA or PHY
problems skip pcu but never do a fast channel change.
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/phy.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 64 |
1 files changed, 49 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 9392320eb301..1b6fcf9e097b 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -3223,7 +3223,7 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) \*************/ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, - u8 mode, u8 ee_mode, u8 freq) + u8 mode, u8 ee_mode, u8 freq, bool fast) { struct ieee80211_channel *curr_channel; int ret, i; @@ -3232,11 +3232,37 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, ret = 0; /* + * Sanity check for fast flag + * Don't try fast channel change when changing modulation + * mode/band. We check for chip compatibility on + * ath5k_hw_reset. + */ + curr_channel = ah->ah_current_channel; + if (fast && (channel->hw_value != curr_channel->hw_value)) + return -EINVAL; + + /* + * On fast channel change we only set the synth parameters + * while PHY is running, enable calibration and skip the rest. + */ + if (fast) { + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, + AR5K_PHY_RFBUS_REQ_REQUEST); + for (i = 0; i < 100; i++) { + if (ath5k_hw_reg_read(ah, AR5K_PHY_RFBUS_GRANT)) + break; + udelay(5); + } + /* Failed */ + if (i >= 100) + return -EIO; + } + + /* * If we don't change channel/mode skip * tx powertable calculation and use the * cached one. */ - curr_channel = ah->ah_current_channel; if ((channel->hw_value == curr_channel->hw_value) && (channel->center_freq == curr_channel->center_freq)) fast_txp = true; @@ -3262,7 +3288,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, * any settings (5210 also only supports * a/aturbo modes) */ - if (ah->ah_version != AR5K_AR5210) { + if ((ah->ah_version != AR5K_AR5210) && !fast) { /* * Write initial RF gain settings @@ -3308,7 +3334,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, AR5K_TXCFG_B_MODE); } - } else { + } else if (ah->ah_version == AR5K_AR5210) { mdelay(1); /* Disable phy and wait */ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); @@ -3345,18 +3371,26 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, mdelay(1); } - /* - * Perform ADC test to see if baseband is ready - * Set TX hold and check ADC test register - */ - phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); - ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); - for (i = 0; i <= 20; i++) { - if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) - break; - udelay(200); + if (fast) + /* + * Release RF Bus grant + */ + AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_RFBUS_REQ, + AR5K_PHY_RFBUS_REQ_REQUEST); + else { + /* + * Perform ADC test to see if baseband is ready + * Set tx hold and check adc test register + */ + phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); + ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); + for (i = 0; i <= 20; i++) { + if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) + break; + udelay(200); + } + ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); } - ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); /* * Start automatic gain control calibration |