diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/phy.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 106 |
1 files changed, 55 insertions, 51 deletions
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 492cbb15720d..219367884e64 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -115,7 +115,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, \**********************/ /* - * This code is used to optimize rf gain on different environments + * This code is used to optimize RF gain on different environments * (temperature mostly) based on feedback from a power detector. * * It's only used on RF5111 and RF5112, later RF chips seem to have @@ -302,7 +302,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) } /* Perform gain_F adjustment by choosing the right set - * of parameters from rf gain optimization ladder */ + * of parameters from RF gain optimization ladder */ static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) { const struct ath5k_gain_opt *go; @@ -367,7 +367,7 @@ done: return ret; } -/* Main callback for thermal rf gain calibration engine +/* Main callback for thermal RF gain calibration engine * Check for a new gain reading and schedule an adjustment * if needed. * @@ -378,8 +378,6 @@ enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) u32 data, type; struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - ATH5K_TRACE(ah->ah_sc); - if (ah->ah_rf_banks == NULL || ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE) return AR5K_RFGAIN_INACTIVE; @@ -435,7 +433,7 @@ done: return ah->ah_gain.g_state; } -/* Write initial rf gain table to set the RF sensitivity +/* Write initial RF gain table to set the RF sensitivity * this one works on all RF chips and has nothing to do * with gain_F calibration */ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) @@ -498,7 +496,7 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) /* - * Setup RF registers by writing rf buffer on hw + * Setup RF registers by writing RF buffer on hw */ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode) @@ -573,7 +571,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, return -EINVAL; } - /* If it's the first time we set rf buffer, allocate + /* If it's the first time we set RF buffer, allocate * ah->ah_rf_banks based on ah->ah_rf_banks_size * we set above */ if (ah->ah_rf_banks == NULL) { @@ -1095,6 +1093,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) ah->ah_current_channel = channel; ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; + ath5k_hw_set_clockrate(ah); return 0; } @@ -1167,7 +1166,7 @@ static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah) * The median of the values in the history is then loaded into the * hardware for its own use for RSSI and CCA measurements. */ -static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) +void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; u32 val; @@ -1248,7 +1247,6 @@ static void ath5k_hw_update_noise_floor(struct ath5k_hw *ah) /* * Perform a PHY calibration on RF5110 * -Fix BPSK/QAM Constellation (I/Q correction) - * -Calculate Noise Floor */ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel) @@ -1260,7 +1258,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, * Disable beacons and RX/TX queues, wait */ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, - AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); + AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); @@ -1335,35 +1333,31 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, return ret; } - ath5k_hw_update_noise_floor(ah); - /* * Re-enable RX/TX and beacons */ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, - AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); + AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); return 0; } /* - * Perform a PHY calibration on RF5111/5112 and newer chips + * Perform I/Q calibration on RF5111/5112 and newer chips */ -static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, - struct ieee80211_channel *channel) +static int +ath5k_hw_rf511x_iq_calibrate(struct ath5k_hw *ah) { u32 i_pwr, q_pwr; s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; int i; - ATH5K_TRACE(ah->ah_sc); if (!ah->ah_calibration || ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) - goto done; + return 0; /* Calibration has finished, get the results and re-run */ - /* work around empty results which can apparently happen on 5212 */ for (i = 0; i <= 10; i++) { iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); @@ -1384,7 +1378,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, /* protect against divide by 0 and loss of sign bits */ if (i_coffd == 0 || q_coffd < 2) - goto done; + return 0; i_coff = (-iq_corr) / i_coffd; i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ @@ -1410,17 +1404,6 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN); -done: - - /* TODO: Separate noise floor calibration from I/Q calibration - * since noise floor calibration interrupts rx path while I/Q - * calibration doesn't. We don't need to run noise floor calibration - * as often as I/Q calibration.*/ - ath5k_hw_update_noise_floor(ah); - - /* Initiate a gain_F calibration */ - ath5k_hw_request_rfgain_probe(ah); - return 0; } @@ -1434,8 +1417,10 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, if (ah->ah_radio == AR5K_RF5110) ret = ath5k_hw_rf5110_calibrate(ah, channel); - else - ret = ath5k_hw_rf511x_calibrate(ah, channel); + else { + ret = ath5k_hw_rf511x_iq_calibrate(ah); + ath5k_hw_request_rfgain_probe(ah); + } return ret; } @@ -1598,7 +1583,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, else if (curr_sym_off >= 31 && curr_sym_off <= 46) mag_mask[2] |= plt_mag_map << (curr_sym_off - 31) * 2; - else if (curr_sym_off >= 46 && curr_sym_off <= 53) + else if (curr_sym_off >= 47 && curr_sym_off <= 53) mag_mask[3] |= plt_mag_map << (curr_sym_off - 47) * 2; @@ -1693,7 +1678,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, int ath5k_hw_phy_disable(struct ath5k_hw *ah) { - ATH5K_TRACE(ah->ah_sc); /*Just a try M.F.*/ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); @@ -1709,8 +1693,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) u32 srev; u16 ret; - ATH5K_TRACE(ah->ah_sc); - /* * Set the radio chip access register */ @@ -1755,8 +1737,6 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) static void /*TODO:Boundary check*/ ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) { - ATH5K_TRACE(ah->ah_sc); - if (ah->ah_version != AR5K_AR5210) ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); } @@ -1789,19 +1769,50 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) if (enable) { AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, - AR5K_PHY_RESTART_DIV_GC, 0xc); + AR5K_PHY_RESTART_DIV_GC, 4); AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, AR5K_PHY_FAST_ANT_DIV_EN); } else { AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, - AR5K_PHY_RESTART_DIV_GC, 0x8); + AR5K_PHY_RESTART_DIV_GC, 0); AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, AR5K_PHY_FAST_ANT_DIV_EN); } } +void +ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode) +{ + u8 ant0, ant1; + + /* + * In case a fixed antenna was set as default + * use the same switch table twice. + */ + if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) + ant0 = ant1 = AR5K_ANT_SWTABLE_A; + else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) + ant0 = ant1 = AR5K_ANT_SWTABLE_B; + else { + ant0 = AR5K_ANT_SWTABLE_A; + ant1 = AR5K_ANT_SWTABLE_B; + } + + /* Set antenna idle switch table */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, + AR5K_PHY_ANT_CTL_SWTABLE_IDLE, + (ah->ah_ant_ctl[ee_mode][AR5K_ANT_CTL] | + AR5K_PHY_ANT_CTL_TXRX_EN)); + + /* Set antenna switch tables */ + ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant0], + AR5K_PHY_ANT_SWITCH_TABLE_0); + ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant1], + AR5K_PHY_ANT_SWITCH_TABLE_1); +} + /* * Set antenna operating mode */ @@ -1823,8 +1834,6 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) def_ant = ah->ah_def_ant; - ATH5K_TRACE(ah->ah_sc); - switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: case CHANNEL_T: @@ -1923,6 +1932,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) if (sta_id1) AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1); + ath5k_hw_set_antenna_switch(ah, ee_mode); /* Note: set diversity before default antenna * because it won't work correctly */ ath5k_hw_set_fast_div(ah, ee_mode, fast_div); @@ -2978,7 +2988,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, /* - * Set transmition power + * Set transmission power */ int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, @@ -2988,7 +2998,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 type; int ret; - ATH5K_TRACE(ah->ah_sc); if (txpower > AR5K_TUNE_MAX_TXPOWER) { ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); return -EINVAL; @@ -3027,9 +3036,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, /* Limit max power if we have a CTL available */ ath5k_get_max_ctl_power(ah, channel); - /* FIXME: Tx power limit for this regdomain - * XXX: Mac80211/CRDA will do that anyway ? */ - /* FIXME: Antenna reduction stuff */ /* FIXME: Limit power on turbo modes */ @@ -3084,8 +3090,6 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) struct ieee80211_channel *channel = ah->ah_current_channel; u8 ee_mode; - ATH5K_TRACE(ah->ah_sc); - switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: case CHANNEL_T: |