Commit 97fe6420 authored by Sujith Manoharan's avatar Sujith Manoharan Committed by John W. Linville

ath9k: Modify IQ calibration for AR955x

IQ calibration post-processing for AR955x is different
from other chips - instead of just doing it as part
of AGC calibration once, it is triggered 3 times and
a median is determined. This patch adds initial support
for changing the calibration behavior for AR955x.

Also, to simplify things, a helper routine to issue/poll
AGC calibration is used.

For non-AR955x chips, the iqcal_idx (which will be used
in subsequent patches) is set to zero.
Signed-off-by: default avatarSujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent adddc0d2
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
#define MAX_MAG_DELTA 11 #define MAX_MAG_DELTA 11
#define MAX_PHS_DELTA 10 #define MAX_PHS_DELTA 10
#define MAXIQCAL 3
struct coeff { struct coeff {
int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
...@@ -797,7 +798,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, ...@@ -797,7 +798,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
if (q_q_coff > 63) if (q_q_coff > 63)
q_q_coff = 63; q_q_coff = 63;
iqc_coeff[0] = (q_q_coff * 128) + q_i_coff; iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n", ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
chain_idx, iqc_coeff[0]); chain_idx, iqc_coeff[0]);
...@@ -828,7 +829,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, ...@@ -828,7 +829,7 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
if (q_q_coff > 63) if (q_q_coff > 63)
q_q_coff = 63; q_q_coff = 63;
iqc_coeff[1] = (q_q_coff * 128) + q_i_coff; iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n", ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
chain_idx, iqc_coeff[1]); chain_idx, iqc_coeff[1]);
...@@ -991,7 +992,9 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) ...@@ -991,7 +992,9 @@ static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
return true; return true;
} }
static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable) static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
int iqcal_idx,
bool is_reusable)
{ {
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
const u32 txiqcal_status[AR9300_MAX_CHAINS] = { const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
...@@ -1410,7 +1413,7 @@ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah, ...@@ -1410,7 +1413,7 @@ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
} }
if (txiqcal_done) if (txiqcal_done)
ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable); ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags)) else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
ar9003_hw_tx_iq_cal_reload(ah); ar9003_hw_tx_iq_cal_reload(ah);
...@@ -1456,6 +1459,29 @@ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah, ...@@ -1456,6 +1459,29 @@ static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
return true; return true;
} }
static bool do_ar9003_agc_cal(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
bool status;
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) |
AR_PHY_AGC_CONTROL_CAL);
status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
AR_PHY_AGC_CONTROL_CAL,
0, AH_WAIT_TIMEOUT);
if (!status) {
ath_dbg(common, CALIBRATE,
"offset calibration failed to complete in %d ms,"
"noisy environment?\n",
AH_WAIT_TIMEOUT / 1000);
return false;
}
return true;
}
static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
...@@ -1464,6 +1490,7 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, ...@@ -1464,6 +1490,7 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
bool txiqcal_done = false; bool txiqcal_done = false;
bool status = true; bool status = true;
bool run_agc_cal = false, sep_iq_cal = false; bool run_agc_cal = false, sep_iq_cal = false;
int i = 0;
/* Use chip chainmask only for calibration */ /* Use chip chainmask only for calibration */
ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
...@@ -1518,26 +1545,36 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, ...@@ -1518,26 +1545,36 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
if (AR_SREV_9330_11(ah)) if (AR_SREV_9330_11(ah))
ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan)); ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
/* Calibrate the AGC */ /*
REG_WRITE(ah, AR_PHY_AGC_CONTROL, * For non-AR9550 chips, we just trigger AGC calibration
REG_READ(ah, AR_PHY_AGC_CONTROL) | * in the HW, poll for completion and then process
AR_PHY_AGC_CONTROL_CAL); * the results.
*
/* Poll for offset calibration complete */ * For AR955x, we run it multiple times and use
status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, * median IQ correction.
AR_PHY_AGC_CONTROL_CAL, */
0, AH_WAIT_TIMEOUT); if (!AR_SREV_9550(ah)) {
} status = do_ar9003_agc_cal(ah);
if (!status)
if (!status) {
ath_dbg(common, CALIBRATE,
"offset calibration failed to complete in %d ms; noisy environment?\n",
AH_WAIT_TIMEOUT / 1000);
return false; return false;
}
if (txiqcal_done) if (txiqcal_done)
ar9003_hw_tx_iq_cal_post_proc(ah, false); ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
} else {
if (!txiqcal_done) {
status = do_ar9003_agc_cal(ah);
if (!status)
return false;
} else {
for (i = 0; i < MAXIQCAL; i++) {
status = do_ar9003_agc_cal(ah);
if (!status)
return false;
ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
}
}
}
}
/* Revert chainmask to runtime parameters */ /* Revert chainmask to runtime parameters */
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment