ath9k: Fix PeakDetect calibration for AR9462

Since HW PeakDetect calibration is turned on for AR9462,
various conditions have to be handled in the driver:

* Enable agc_cal when loading RTT fails.
* Disable SW PeakDetect calibration when RTT calibration is not enabled.
* Keep SW PeakDetect calibration result in driver.
* Update RTT table according to the saved value.
* Write RTT back after modifying SW RTT table.
* Enable local mode for PeakDetect calibration and restore values.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Sujith Manoharan 2013-09-11 16:36:32 +05:30 committed by John W. Linville
parent 4b9b42bfe0
commit 3001f0d00b
3 changed files with 99 additions and 12 deletions

View File

@ -965,18 +965,44 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
}
static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
struct ath9k_channel *chan,
bool run_rtt_cal)
{
struct ath9k_hw_cal_data *caldata = ah->caldata;
int i;
if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah))
return;
if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && !run_rtt_cal)
return;
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
if (!(ah->rxchainmask & (1 << i)))
continue;
ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan));
}
if (caldata)
set_bit(SW_PKDET_DONE, &caldata->cal_flags);
if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && caldata) {
if (IS_CHAN_2GHZ(chan)){
caldata->caldac[0] = REG_READ_FIELD(ah,
AR_PHY_65NM_RXRF_AGC(0),
AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR);
caldata->caldac[1] = REG_READ_FIELD(ah,
AR_PHY_65NM_RXRF_AGC(1),
AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR);
} else {
caldata->caldac[0] = REG_READ_FIELD(ah,
AR_PHY_65NM_RXRF_AGC(0),
AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR);
caldata->caldac[1] = REG_READ_FIELD(ah,
AR_PHY_65NM_RXRF_AGC(1),
AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR);
}
}
}
static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
@ -1047,13 +1073,18 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
ar9003_hw_rtt_clear_hist(ah);
}
if (rtt && !run_rtt_cal) {
agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
agc_supp_cals &= agc_ctrl;
agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
AR_PHY_AGC_CONTROL_FLTR_CAL |
AR_PHY_AGC_CONTROL_PKDET_CAL);
REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
if (rtt) {
if (!run_rtt_cal) {
agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL);
agc_supp_cals &= agc_ctrl;
agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL |
AR_PHY_AGC_CONTROL_FLTR_CAL |
AR_PHY_AGC_CONTROL_PKDET_CAL);
REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl);
} else {
if (ah->ah_flags & AH_FASTCC)
run_agc_cal = true;
}
}
if (ah->enabled_cals & TX_CL_CAL) {
@ -1124,7 +1155,7 @@ skip_tx_iqcal:
AR_PHY_AGC_CONTROL_CAL,
0, AH_WAIT_TIMEOUT);
ar9003_hw_do_manual_peak_cal(ah, chan);
ar9003_hw_do_manual_peak_cal(ah, chan, run_rtt_cal);
}
if (REG_READ(ah, AR_PHY_CL_CAL_CTL) & AR_PHY_CL_CAL_ENABLE) {
@ -1159,12 +1190,16 @@ skip_tx_iqcal:
if (run_rtt_cal && caldata) {
if (is_reusable) {
if (!ath9k_hw_rfbus_req(ah))
if (!ath9k_hw_rfbus_req(ah)) {
ath_err(ath9k_hw_common(ah),
"Could not stop baseband\n");
else
} else {
ar9003_hw_rtt_fill_hist(ah);
if (test_bit(SW_PKDET_DONE, &caldata->cal_flags))
ar9003_hw_rtt_load_hist(ah);
}
ath9k_hw_rfbus_done(ah);
}

View File

@ -118,6 +118,27 @@ void ar9003_hw_rtt_load_hist(struct ath_hw *ah)
}
}
static void ar9003_hw_patch_rtt(struct ath_hw *ah, int index, int chain)
{
int agc, caldac;
if (!test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags))
return;
if ((index != 5) || (chain >= 2))
return;
agc = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE);
if (!agc)
return;
caldac = ah->caldata->caldac[chain];
ah->caldata->rtt_table[chain][index] &= 0xFFFF05FF;
caldac = (caldac & 0x20) | ((caldac & 0x1F) << 7);
ah->caldata->rtt_table[chain][index] |= (caldac << 4);
}
static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index)
{
u32 val;
@ -155,6 +176,9 @@ void ar9003_hw_rtt_fill_hist(struct ath_hw *ah)
for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) {
ah->caldata->rtt_table[chain][i] =
ar9003_hw_rtt_fill_hist_entry(ah, chain, i);
ar9003_hw_patch_rtt(ah, i, chain);
ath_dbg(ath9k_hw_common(ah), CALIBRATE,
"RTT value at idx %d, chain %d is: 0x%x\n",
i, chain, ah->caldata->rtt_table[chain][i]);
@ -186,11 +210,37 @@ bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
if (!ah->caldata)
return false;
if (test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags)) {
if (IS_CHAN_2GHZ(chan)){
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0),
AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
ah->caldata->caldac[0]);
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1),
AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR,
ah->caldata->caldac[1]);
} else {
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0),
AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
ah->caldata->caldac[0]);
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1),
AR_PHY_65NM_RXRF_AGC_AGC5G_CALDAC_OVR,
ah->caldata->caldac[1]);
}
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(1),
AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(0),
AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE, 0x1);
}
if (!test_bit(RTT_DONE, &ah->caldata->cal_flags))
return false;
ar9003_hw_rtt_enable(ah);
ar9003_hw_rtt_set_mask(ah, 0x10);
if (test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags))
ar9003_hw_rtt_set_mask(ah, 0x30);
else
ar9003_hw_rtt_set_mask(ah, 0x10);
if (!ath9k_hw_rfbus_req(ah)) {
ath_err(ath9k_hw_common(ah), "Could not stop baseband\n");

View File

@ -412,6 +412,7 @@ enum ath9k_cal_flags {
NFCAL_INTF,
TXIQCAL_DONE,
TXCLCAL_DONE,
SW_PKDET_DONE,
};
struct ath9k_hw_cal_data {
@ -422,6 +423,7 @@ struct ath9k_hw_cal_data {
int32_t CalValid;
int8_t iCoff;
int8_t qCoff;
u8 caldac[2];
u16 small_signal_gain[AR9300_MAX_CHAINS];
u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
u32 num_measures[AR9300_MAX_CHAINS];