Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 266798
b: refs/heads/master
c: 5f0c04e
h: refs/heads/master
v: v3
  • Loading branch information
Rajkumar Manoharan authored and John W. Linville committed Oct 14, 2011
1 parent 096373f commit b507857
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a240dc7b3c7463bd60cf0a9b2a90f52f78aae0fd
refs/heads/master: 5f0c04ea1e7394c2b28fa247c1722487f9a77523
72 changes: 67 additions & 5 deletions trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "hw-ops.h"
#include "ar9003_phy.h"

#define MAX_MEASUREMENT 8
#define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
#define MAX_MAG_DELTA 11
#define MAX_PHS_DELTA 10

Expand Down Expand Up @@ -663,6 +663,7 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
{
int i, im, nmeasurement;
u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
struct ath9k_hw_cal_data *caldata = ah->caldata;

memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
Expand Down Expand Up @@ -712,13 +713,21 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
coeff->iqc_coeff[0]);

if (caldata)
caldata->tx_corr_coeff[im][i] =
coeff->iqc_coeff[0];
}
if (caldata)
caldata->num_measures[i] = nmeasurement;
}

REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
if (caldata)
caldata->done_txiqcal_once = true;

return;

Expand Down Expand Up @@ -845,10 +854,55 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
return;
}

static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
{
struct ath9k_hw_cal_data *caldata = ah->caldata;
u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
int i, im;

memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
for (i = 0; i < MAX_MEASUREMENT / 2; i++) {
tx_corr_coeff[i * 2][0] = tx_corr_coeff[(i * 2) + 1][0] =
AR_PHY_TX_IQCAL_CORR_COEFF_B0(i);
if (!AR_SREV_9485(ah)) {
tx_corr_coeff[i * 2][1] =
tx_corr_coeff[(i * 2) + 1][1] =
AR_PHY_TX_IQCAL_CORR_COEFF_B1(i);

tx_corr_coeff[i * 2][2] =
tx_corr_coeff[(i * 2) + 1][2] =
AR_PHY_TX_IQCAL_CORR_COEFF_B2(i);
}
}

for (i = 0; i < AR9300_MAX_CHAINS; i++) {
if (!(ah->txchainmask & (1 << i)))
continue;

for (im = 0; im < caldata->num_measures[i]; im++) {
if ((im % 2) == 0)
REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
AR_PHY_TX_IQCAL_CORR_COEFF_00_COEFF_TABLE,
caldata->tx_corr_coeff[im][i]);
else
REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
caldata->tx_corr_coeff[im][i]);
}
}

REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
}

static bool ar9003_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_cal_data *caldata = ah->caldata;
bool txiqcal_done = false;

/* Do Tx IQ Calibration */
Expand All @@ -860,9 +914,15 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
* For AR9485 or later chips, TxIQ cal runs as part of
* AGC calibration
*/
if (AR_SREV_9485_OR_LATER(ah))
if (AR_SREV_9485_OR_LATER(ah) && !AR_SREV_9340(ah)) {
if (caldata && !caldata->done_txiqcal_once)
REG_SET_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
else
REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
txiqcal_done = true;
else {
} else {
txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
udelay(5);
Expand All @@ -884,6 +944,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,

if (txiqcal_done)
ar9003_hw_tx_iq_cal_post_proc(ah);
else if (caldata && caldata->done_txiqcal_once)
ar9003_hw_tx_iq_cal_reload(ah);

ath9k_hw_loadnf(ah, chan);
ath9k_hw_start_nfcal(ah, true);
Expand Down Expand Up @@ -912,8 +974,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
if (ah->cal_list_curr)
ath9k_hw_reset_calibration(ah, ah->cal_list_curr);

if (ah->caldata)
ah->caldata->CalValid = 0;
if (caldata)
caldata->CalValid = 0;

return true;
}
Expand Down
69 changes: 69 additions & 0 deletions trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
if (AR_SREV_9480(ah))
ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1);

ah->modes_index = modesIndex;
ar9003_hw_override_ini(ah);
ar9003_hw_set_channel_regs(ah, chan);
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
Expand Down Expand Up @@ -1247,6 +1248,73 @@ static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval);
}

static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 *ini_reloaded)
{
unsigned int regWrites = 0;
u32 modesIndex;

switch (chan->chanmode) {
case CHANNEL_A:
case CHANNEL_A_HT20:
modesIndex = 1;
break;
case CHANNEL_A_HT40PLUS:
case CHANNEL_A_HT40MINUS:
modesIndex = 2;
break;
case CHANNEL_G:
case CHANNEL_G_HT20:
case CHANNEL_B:
modesIndex = 4;
break;
case CHANNEL_G_HT40PLUS:
case CHANNEL_G_HT40MINUS:
modesIndex = 3;
break;

default:
return -EINVAL;
}

if (modesIndex == ah->modes_index) {
*ini_reloaded = false;
goto set_rfmode;
}

ar9003_hw_prog_ini(ah, &ah->iniSOC[ATH_INI_POST], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniMac[ATH_INI_POST], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniBB[ATH_INI_POST], modesIndex);
ar9003_hw_prog_ini(ah, &ah->iniRadio[ATH_INI_POST], modesIndex);
if (AR_SREV_9480_20(ah))
ar9003_hw_prog_ini(ah,
&ah->ini_radio_post_sys2ant,
modesIndex);

REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);

/*
* For 5GHz channels requiring Fast Clock, apply
* different modal values.
*/
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites);

if (AR_SREV_9330(ah))
REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);

if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);

ah->modes_index = modesIndex;
*ini_reloaded = true;

set_rfmode:
ar9003_hw_set_rfmode(ah, chan);
return 0;
}

void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
Expand Down Expand Up @@ -1275,6 +1343,7 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->do_getnf = ar9003_hw_do_getnf;
priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
priv_ops->set_radar_params = ar9003_hw_set_radar_params;
priv_ops->fast_chan_change = ar9003_hw_fast_chan_change;

ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,8 @@

#define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300)

#define AR_PHY_TX_IQCAL_CONTROL_0 (AR_SM_BASE + AR_SREV_9485(ah) ? \
0x3c4 : 0x444)
#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \
0x3c8 : 0x448)
#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \
Expand Down Expand Up @@ -823,6 +825,7 @@
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24
#define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004
#define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL 0x80000000
#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000
#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18
#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001
Expand Down
7 changes: 7 additions & 0 deletions trunk/drivers/net/wireless/ath/ath9k/hw-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,4 +205,11 @@ static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
}

static inline int ath9k_hw_fast_chan_change(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 *ini_reloaded)
{
return ath9k_hw_private_ops(ah)->fast_chan_change(ah, chan,
ini_reloaded);
}
#endif /* ATH9K_HW_OPS_H */
32 changes: 32 additions & 0 deletions trunk/drivers/net/wireless/ath/ath9k/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,14 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
struct ath_common *common = ath9k_hw_common(ah);
u32 qnum;
int r;
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
bool band_switch, mode_diff;
u8 ini_reloaded;

band_switch = (chan->channelFlags & (CHANNEL_2GHZ | CHANNEL_5GHZ)) !=
(ah->curchan->channelFlags & (CHANNEL_2GHZ |
CHANNEL_5GHZ));
mode_diff = (chan->chanmode != ah->curchan->chanmode);

for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
if (ath9k_hw_numtxpending(ah, qnum)) {
Expand All @@ -1408,6 +1416,18 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
return false;
}

if (edma && (band_switch || mode_diff)) {
ath9k_hw_mark_phy_inactive(ah);
udelay(5);

ath9k_hw_init_pll(ah, NULL);

if (ath9k_hw_fast_chan_change(ah, chan, &ini_reloaded)) {
ath_err(common, "Failed to do fast channel change\n");
return false;
}
}

ath9k_hw_set_channel_regs(ah, chan);

r = ath9k_hw_rf_set_freq(ah, chan);
Expand All @@ -1424,6 +1444,16 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,

ath9k_hw_spur_mitigate_freq(ah, chan);

if (edma && (band_switch || mode_diff)) {
if (band_switch || ini_reloaded)
ah->eep_ops->set_board_values(ah, chan);

ath9k_hw_init_bb(ah, chan);

if (band_switch || ini_reloaded)
ath9k_hw_init_cal(ah, chan);
}

return true;
}

Expand Down Expand Up @@ -1677,6 +1707,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,

ath9k_hw_init_bb(ah, chan);

if (caldata)
caldata->done_txiqcal_once = false;
if (!ath9k_hw_init_cal(ah, chan))
return -EIO;

Expand Down
8 changes: 8 additions & 0 deletions trunk/drivers/net/wireless/ath/ath9k/hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,8 @@ enum ath9k_int {
CHANNEL_HT40PLUS | \
CHANNEL_HT40MINUS)

#define MAX_IQCAL_MEASUREMENT 8

struct ath9k_hw_cal_data {
u16 channel;
u32 channelFlags;
Expand All @@ -346,8 +348,11 @@ struct ath9k_hw_cal_data {
bool paprd_done;
bool nfcal_pending;
bool nfcal_interference;
bool done_txiqcal_once;
u16 small_signal_gain[AR9300_MAX_CHAINS];
u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
u32 num_measures[AR9300_MAX_CHAINS];
int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS];
struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
};

Expand Down Expand Up @@ -583,6 +588,8 @@ struct ath_hw_private_ops {
void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
void (*set_radar_params)(struct ath_hw *ah,
struct ath_hw_radar_conf *conf);
int (*fast_chan_change)(struct ath_hw *ah, struct ath9k_channel *chan,
u8 *ini_reloaded);

/* ANI */
void (*ani_cache_ini_regs)(struct ath_hw *ah);
Expand Down Expand Up @@ -684,6 +691,7 @@ struct ath_hw {
atomic_t intr_ref_cnt;
bool chip_fullsleep;
u32 atim_window;
u32 modes_index;

/* Calibration */
u32 supp_cals;
Expand Down

0 comments on commit b507857

Please sign in to comment.