Loading drivers/net/wireless/ath/ath5k/reset.c +5 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,11 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211); rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211); /* * Set default Tx frame to Tx data start delay */ txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; /* * 5210 initvals don't include usec settings * so we need to use magic values here for Loading drivers/net/wireless/ath/ath9k/ahb.c +5 −1 Original line number Diff line number Diff line Loading @@ -21,11 +21,15 @@ #include <linux/ath9k_platform.h> #include "ath9k.h" const struct platform_device_id ath9k_platform_id_table[] = { static const struct platform_device_id ath9k_platform_id_table[] = { { .name = "ath9k", .driver_data = AR5416_AR9100_DEVID, }, { .name = "ar934x_wmac", .driver_data = AR9300_DEVID_AR9340, }, {}, }; Loading drivers/net/wireless/ath/ath9k/ani.c +0 −6 Original line number Diff line number Diff line Loading @@ -899,12 +899,6 @@ void ath9k_hw_ani_init(struct ath_hw *ah) * check here default level should not modify INI setting. */ if (use_new_ani(ah)) { const struct ani_ofdm_level_entry *entry_ofdm; const struct ani_cck_level_entry *entry_cck; entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; ah->aniperiod = ATH9K_ANI_PERIOD_NEW; ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; } else { Loading drivers/net/wireless/ath/ath9k/ar9003_calib.c +146 −241 Original line number Diff line number Diff line Loading @@ -18,13 +18,13 @@ #include "hw-ops.h" #include "ar9003_phy.h" #define MPASS 3 #define MAX_MEASUREMENT 8 #define MAX_DIFFERENCE 10 #define MAX_MAG_DELTA 11 #define MAX_PHS_DELTA 10 struct coeff { int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; int iqc_coeff[2]; }; Loading Loading @@ -185,6 +185,7 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah) /* Accumulate IQ cal measures for active chains */ for (i = 0; i < AR5416_MAX_CHAINS; i++) { if (ah->txchainmask & BIT(i)) { ah->totalPowerMeasI[i] += REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); ah->totalPowerMeasQ[i] += Loading @@ -198,6 +199,7 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah) ah->totalIqCorrMeas[i]); } } } static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) { Loading Loading @@ -608,36 +610,48 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, return true; } static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg) static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, int max_delta) { int diff[MPASS]; diff[0] = abs(mp_coeff[0] - mp_coeff[1]); diff[1] = abs(mp_coeff[1] - mp_coeff[2]); diff[2] = abs(mp_coeff[2] - mp_coeff[0]); if (diff[0] > MAX_DIFFERENCE && diff[1] > MAX_DIFFERENCE && diff[2] > MAX_DIFFERENCE) return false; if (diff[0] <= diff[1] && diff[0] <= diff[2]) *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; else if (diff[1] <= diff[2]) *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; int mp_max = -64, max_idx = 0; int mp_min = 63, min_idx = 0; int mp_avg = 0, i, outlier_idx = 0; /* find min/max mismatch across all calibrated gains */ for (i = 0; i < nmeasurement; i++) { mp_avg += mp_coeff[i]; if (mp_coeff[i] > mp_max) { mp_max = mp_coeff[i]; max_idx = i; } else if (mp_coeff[i] < mp_min) { mp_min = mp_coeff[i]; min_idx = i; } } /* find average (exclude max abs value) */ for (i = 0; i < nmeasurement; i++) { if ((abs(mp_coeff[i]) < abs(mp_max)) || (abs(mp_coeff[i]) < abs(mp_min))) mp_avg += mp_coeff[i]; } mp_avg /= (nmeasurement - 1); /* detect outlier */ if (abs(mp_max - mp_min) > max_delta) { if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg)) outlier_idx = max_idx; else *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; return true; outlier_idx = min_idx; } mp_coeff[outlier_idx] = mp_avg; } static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, u8 num_chains, struct coeff *coeff) { struct ath_common *common = ath9k_hw_common(ah); int i, im, nmeasurement; int magnitude, phase; u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); Loading @@ -657,11 +671,6 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, /* Load the average of 2 passes */ for (i = 0; i < num_chains; i++) { if (AR_SREV_9485(ah)) nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0_9485, AR_PHY_CALIBRATED_GAINS_0); else nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_CALIBRATED_GAINS_0); Loading @@ -669,25 +678,21 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, if (nmeasurement > MAX_MEASUREMENT) nmeasurement = MAX_MEASUREMENT; for (im = 0; im < nmeasurement; im++) { /* * Determine which 2 passes are closest and compute avg * magnitude */ if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im], &magnitude)) goto disable_txiqcal; /* detect outlier only if nmeasurement > 1 */ if (nmeasurement > 1) { /* Detect magnitude outlier */ ar9003_hw_detect_outlier(coeff->mag_coeff[i], nmeasurement, MAX_MAG_DELTA); /* * Determine which 2 passes are closest and compute avg * phase */ if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im], &phase)) goto disable_txiqcal; /* Detect phase outlier */ ar9003_hw_detect_outlier(coeff->phs_coeff[i], nmeasurement, MAX_PHS_DELTA); } coeff->iqc_coeff[0] = (magnitude & 0x7f) | ((phase & 0x7f) << 7); for (im = 0; im < nmeasurement; im++) { coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | ((coeff->phs_coeff[i][im] & 0x7f) << 7); if ((im % 2) == 0) REG_RMW_FIELD(ah, tx_corr_coeff[im][i], Loading @@ -707,141 +712,37 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, return; disable_txiqcal: REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0); REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0); ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n"); } static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); static const u32 txiqcal_status[AR9300_MAX_CHAINS] = { AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, }; static const u32 chan_info_tab[] = { AR_PHY_CHAN_INFO_TAB_0, AR_PHY_CHAN_INFO_TAB_1, AR_PHY_CHAN_INFO_TAB_2, }; struct coeff coeff; s32 iq_res[6]; s32 i, j, ip, im, nmeasurement; u8 nchains = get_streams(common->tx_chainmask); for (ip = 0; ip < MPASS; ip++) { REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL, AR_PHY_TX_IQCAL_START_DO_CAL); if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL, 0, AH_WAIT_TIMEOUT)) { ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal not complete.\n"); goto TX_IQ_CAL_FAILED; } nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_CALIBRATED_GAINS_0); if (nmeasurement > MAX_MEASUREMENT) nmeasurement = MAX_MEASUREMENT; for (i = 0; i < nchains; i++) { ath_dbg(common, ATH_DBG_CALIBRATE, "Doing Tx IQ Cal for chain %d.\n", i); for (im = 0; im < nmeasurement; im++) { if (REG_READ(ah, txiqcal_status[i]) & AR_PHY_TX_IQCAL_STATUS_FAILED) { ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed for chain %d.\n", i); goto TX_IQ_CAL_FAILED; } for (j = 0; j < 3; j++) { u8 idx = 2 * j, offset = 4 * (3 * im + j); REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 0); /* 32 bits */ iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset); REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 1); /* 16 bits */ iq_res[idx+1] = 0xffff & REG_READ(ah, chan_info_tab[i] + offset); ath_dbg(common, ATH_DBG_CALIBRATE, "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", idx, iq_res[idx], idx+1, iq_res[idx+1]); } if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, coeff.iqc_coeff)) { ath_dbg(common, ATH_DBG_CALIBRATE, "Failed in calculation of IQ correction.\n"); goto TX_IQ_CAL_FAILED; } coeff.mag_coeff[i][im][ip] = coeff.iqc_coeff[0] & 0x7f; coeff.phs_coeff[i][im][ip] = (coeff.iqc_coeff[0] >> 7) & 0x7f; if (coeff.mag_coeff[i][im][ip] > 63) coeff.mag_coeff[i][im][ip] -= 128; if (coeff.phs_coeff[i][im][ip] > 63) coeff.phs_coeff[i][im][ip] -= 128; } } } ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff); return; TX_IQ_CAL_FAILED: ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); } static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) { u8 tx_gain_forced; REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485, AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE); if (tx_gain_forced) REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE, 0); REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1); REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL, 1); if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL, 0, AH_WAIT_TIMEOUT)) { ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal is not completed.\n"); return false; } return true; } static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); const u32 txiqcal_status[AR9300_MAX_CHAINS] = { AR_PHY_TX_IQCAL_STATUS_B0_9485, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, }; Loading @@ -853,7 +754,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) struct coeff coeff; s32 iq_res[6]; u8 num_chains = 0; int i, ip, im, j; int i, im, j; int nmeasurement; for (i = 0; i < AR9300_MAX_CHAINS; i++) { Loading @@ -861,10 +762,9 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) num_chains++; } for (ip = 0; ip < MPASS; ip++) { for (i = 0; i < num_chains; i++) { nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0_9485, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_CALIBRATED_GAINS_0); if (nmeasurement > MAX_MEASUREMENT) nmeasurement = MAX_MEASUREMENT; Loading Loading @@ -912,20 +812,19 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, coeff.iqc_coeff)) { ath_dbg(common, ATH_DBG_CALIBRATE, "Failed in calculation of IQ correction.\n"); "Failed in calculation of \ IQ correction.\n"); goto tx_iqcal_fail; } coeff.mag_coeff[i][im][ip] = coeff.iqc_coeff[0] & 0x7f; coeff.phs_coeff[i][im][ip] = coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; coeff.phs_coeff[i][im] = (coeff.iqc_coeff[0] >> 7) & 0x7f; if (coeff.mag_coeff[i][im][ip] > 63) coeff.mag_coeff[i][im][ip] -= 128; if (coeff.phs_coeff[i][im][ip] > 63) coeff.phs_coeff[i][im][ip] -= 128; } if (coeff.mag_coeff[i][im] > 63) coeff.mag_coeff[i][im] -= 128; if (coeff.phs_coeff[i][im] > 63) coeff.phs_coeff[i][im] -= 128; } } ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); Loading @@ -940,31 +839,37 @@ 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_capabilities *pCap = &ah->caps; int val; bool txiqcal_done = false; val = REG_READ(ah, AR_ENT_OTP); ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); if (AR_SREV_9485(ah)) ar9003_hw_set_chain_masks(ah, 0x1, 0x1); else if (val & AR_ENT_OTP_CHAIN2_DISABLE) /* Configure rx/tx chains before running AGC/TxiQ cals */ if (val & AR_ENT_OTP_CHAIN2_DISABLE) ar9003_hw_set_chain_masks(ah, 0x3, 0x3); else /* * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain * mode before running AGC/TxIQ cals */ ar9003_hw_set_chain_masks(ah, 0x7, 0x7); ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask, pCap->tx_chainmask); /* Do Tx IQ Calibration */ if (AR_SREV_9485(ah)) ar9003_hw_tx_iq_cal_run(ah); else ar9003_hw_tx_iq_cal(ah); REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); /* * For AR9485 or later chips, TxIQ cal runs as part of * AGC calibration */ if (AR_SREV_9485_OR_LATER(ah)) txiqcal_done = true; else { txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); udelay(5); REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); } /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, Loading @@ -979,7 +884,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, return false; } if (AR_SREV_9485(ah)) if (txiqcal_done) ar9003_hw_tx_iq_cal_post_proc(ah); /* Revert chainmasks to their original values before NF cal */ Loading drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +36 −25 Original line number Diff line number Diff line Loading @@ -3217,7 +3217,6 @@ static int ar9300_compress_decision(struct ath_hw *ah, u8 *word, int length, int mdata_size) { struct ath_common *common = ath9k_hw_common(ah); u8 *dptr; const struct ar9300_eeprom *eep = NULL; switch (code) { Loading @@ -3235,7 +3234,6 @@ static int ar9300_compress_decision(struct ath_hw *ah, break; case _CompressBlock: if (reference == 0) { dptr = mptr; } else { eep = ar9003_eeprom_struct_find_by_id(reference); if (eep == NULL) { Loading Loading @@ -3448,9 +3446,13 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); else { REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, if (!AR_SREV_9340(ah)) { REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, bias >> 2); REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1); REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1); } } } Loading Loading @@ -3497,23 +3499,28 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) { int chain; static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { AR_PHY_SWITCH_CHAIN_0, AR_PHY_SWITCH_CHAIN_1, AR_PHY_SWITCH_CHAIN_2, }; u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); if (!AR_SREV_9485(ah)) { value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value); value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value); for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { if ((ah->rxchainmask & BIT(chain)) || (ah->txchainmask & BIT(chain))) { value = ar9003_hw_ant_ctrl_chain_get(ah, chain, is2ghz); REG_RMW_FIELD(ah, switch_chain_reg[chain], AR_SWITCH_TABLE_ALL, value); } } if (AR_SREV_9485(ah)) { Loading Loading @@ -3634,13 +3641,16 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) /* Test value. if 0 then attenuation is unused. Don't load anything. */ for (i = 0; i < 3; i++) { if (ah->txchainmask & BIT(i)) { value = ar9003_hw_atten_chain_get(ah, i, chan); REG_RMW_FIELD(ah, ext_atten_reg[i], AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); value = ar9003_hw_atten_chain_get_margin(ah, i, chan); REG_RMW_FIELD(ah, ext_atten_reg[i], AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); } } } Loading Loading @@ -3749,8 +3759,9 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); ar9003_hw_drive_strength_apply(ah); ar9003_hw_atten_apply(ah, chan); if (!AR_SREV_9340(ah)) ar9003_hw_internal_regulator_apply(ah); if (AR_SREV_9485(ah)) if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) ar9003_hw_apply_tuning_caps(ah); } Loading Loading
drivers/net/wireless/ath/ath5k/reset.c +5 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,11 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211); rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211); /* * Set default Tx frame to Tx data start delay */ txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; /* * 5210 initvals don't include usec settings * so we need to use magic values here for Loading
drivers/net/wireless/ath/ath9k/ahb.c +5 −1 Original line number Diff line number Diff line Loading @@ -21,11 +21,15 @@ #include <linux/ath9k_platform.h> #include "ath9k.h" const struct platform_device_id ath9k_platform_id_table[] = { static const struct platform_device_id ath9k_platform_id_table[] = { { .name = "ath9k", .driver_data = AR5416_AR9100_DEVID, }, { .name = "ar934x_wmac", .driver_data = AR9300_DEVID_AR9340, }, {}, }; Loading
drivers/net/wireless/ath/ath9k/ani.c +0 −6 Original line number Diff line number Diff line Loading @@ -899,12 +899,6 @@ void ath9k_hw_ani_init(struct ath_hw *ah) * check here default level should not modify INI setting. */ if (use_new_ani(ah)) { const struct ani_ofdm_level_entry *entry_ofdm; const struct ani_cck_level_entry *entry_cck; entry_ofdm = &ofdm_level_table[ATH9K_ANI_OFDM_DEF_LEVEL]; entry_cck = &cck_level_table[ATH9K_ANI_CCK_DEF_LEVEL]; ah->aniperiod = ATH9K_ANI_PERIOD_NEW; ah->config.ani_poll_interval = ATH9K_ANI_POLLINTERVAL_NEW; } else { Loading
drivers/net/wireless/ath/ath9k/ar9003_calib.c +146 −241 Original line number Diff line number Diff line Loading @@ -18,13 +18,13 @@ #include "hw-ops.h" #include "ar9003_phy.h" #define MPASS 3 #define MAX_MEASUREMENT 8 #define MAX_DIFFERENCE 10 #define MAX_MAG_DELTA 11 #define MAX_PHS_DELTA 10 struct coeff { int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; int iqc_coeff[2]; }; Loading Loading @@ -185,6 +185,7 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah) /* Accumulate IQ cal measures for active chains */ for (i = 0; i < AR5416_MAX_CHAINS; i++) { if (ah->txchainmask & BIT(i)) { ah->totalPowerMeasI[i] += REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); ah->totalPowerMeasQ[i] += Loading @@ -198,6 +199,7 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah) ah->totalIqCorrMeas[i]); } } } static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) { Loading Loading @@ -608,36 +610,48 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah, return true; } static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg) static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, int max_delta) { int diff[MPASS]; diff[0] = abs(mp_coeff[0] - mp_coeff[1]); diff[1] = abs(mp_coeff[1] - mp_coeff[2]); diff[2] = abs(mp_coeff[2] - mp_coeff[0]); if (diff[0] > MAX_DIFFERENCE && diff[1] > MAX_DIFFERENCE && diff[2] > MAX_DIFFERENCE) return false; if (diff[0] <= diff[1] && diff[0] <= diff[2]) *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; else if (diff[1] <= diff[2]) *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; int mp_max = -64, max_idx = 0; int mp_min = 63, min_idx = 0; int mp_avg = 0, i, outlier_idx = 0; /* find min/max mismatch across all calibrated gains */ for (i = 0; i < nmeasurement; i++) { mp_avg += mp_coeff[i]; if (mp_coeff[i] > mp_max) { mp_max = mp_coeff[i]; max_idx = i; } else if (mp_coeff[i] < mp_min) { mp_min = mp_coeff[i]; min_idx = i; } } /* find average (exclude max abs value) */ for (i = 0; i < nmeasurement; i++) { if ((abs(mp_coeff[i]) < abs(mp_max)) || (abs(mp_coeff[i]) < abs(mp_min))) mp_avg += mp_coeff[i]; } mp_avg /= (nmeasurement - 1); /* detect outlier */ if (abs(mp_max - mp_min) > max_delta) { if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg)) outlier_idx = max_idx; else *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; return true; outlier_idx = min_idx; } mp_coeff[outlier_idx] = mp_avg; } static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, u8 num_chains, struct coeff *coeff) { struct ath_common *common = ath9k_hw_common(ah); int i, im, nmeasurement; int magnitude, phase; u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); Loading @@ -657,11 +671,6 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, /* Load the average of 2 passes */ for (i = 0; i < num_chains; i++) { if (AR_SREV_9485(ah)) nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0_9485, AR_PHY_CALIBRATED_GAINS_0); else nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_CALIBRATED_GAINS_0); Loading @@ -669,25 +678,21 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, if (nmeasurement > MAX_MEASUREMENT) nmeasurement = MAX_MEASUREMENT; for (im = 0; im < nmeasurement; im++) { /* * Determine which 2 passes are closest and compute avg * magnitude */ if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im], &magnitude)) goto disable_txiqcal; /* detect outlier only if nmeasurement > 1 */ if (nmeasurement > 1) { /* Detect magnitude outlier */ ar9003_hw_detect_outlier(coeff->mag_coeff[i], nmeasurement, MAX_MAG_DELTA); /* * Determine which 2 passes are closest and compute avg * phase */ if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im], &phase)) goto disable_txiqcal; /* Detect phase outlier */ ar9003_hw_detect_outlier(coeff->phs_coeff[i], nmeasurement, MAX_PHS_DELTA); } coeff->iqc_coeff[0] = (magnitude & 0x7f) | ((phase & 0x7f) << 7); for (im = 0; im < nmeasurement; im++) { coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | ((coeff->phs_coeff[i][im] & 0x7f) << 7); if ((im % 2) == 0) REG_RMW_FIELD(ah, tx_corr_coeff[im][i], Loading @@ -707,141 +712,37 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, return; disable_txiqcal: REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0); REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0); ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n"); } static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); static const u32 txiqcal_status[AR9300_MAX_CHAINS] = { AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, }; static const u32 chan_info_tab[] = { AR_PHY_CHAN_INFO_TAB_0, AR_PHY_CHAN_INFO_TAB_1, AR_PHY_CHAN_INFO_TAB_2, }; struct coeff coeff; s32 iq_res[6]; s32 i, j, ip, im, nmeasurement; u8 nchains = get_streams(common->tx_chainmask); for (ip = 0; ip < MPASS; ip++) { REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL, AR_PHY_TX_IQCAL_START_DO_CAL); if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL, 0, AH_WAIT_TIMEOUT)) { ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal not complete.\n"); goto TX_IQ_CAL_FAILED; } nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_CALIBRATED_GAINS_0); if (nmeasurement > MAX_MEASUREMENT) nmeasurement = MAX_MEASUREMENT; for (i = 0; i < nchains; i++) { ath_dbg(common, ATH_DBG_CALIBRATE, "Doing Tx IQ Cal for chain %d.\n", i); for (im = 0; im < nmeasurement; im++) { if (REG_READ(ah, txiqcal_status[i]) & AR_PHY_TX_IQCAL_STATUS_FAILED) { ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed for chain %d.\n", i); goto TX_IQ_CAL_FAILED; } for (j = 0; j < 3; j++) { u8 idx = 2 * j, offset = 4 * (3 * im + j); REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 0); /* 32 bits */ iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset); REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, AR_PHY_CHAN_INFO_TAB_S2_READ, 1); /* 16 bits */ iq_res[idx+1] = 0xffff & REG_READ(ah, chan_info_tab[i] + offset); ath_dbg(common, ATH_DBG_CALIBRATE, "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", idx, iq_res[idx], idx+1, iq_res[idx+1]); } if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, coeff.iqc_coeff)) { ath_dbg(common, ATH_DBG_CALIBRATE, "Failed in calculation of IQ correction.\n"); goto TX_IQ_CAL_FAILED; } coeff.mag_coeff[i][im][ip] = coeff.iqc_coeff[0] & 0x7f; coeff.phs_coeff[i][im][ip] = (coeff.iqc_coeff[0] >> 7) & 0x7f; if (coeff.mag_coeff[i][im][ip] > 63) coeff.mag_coeff[i][im][ip] -= 128; if (coeff.phs_coeff[i][im][ip] > 63) coeff.phs_coeff[i][im][ip] -= 128; } } } ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff); return; TX_IQ_CAL_FAILED: ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); } static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) { u8 tx_gain_forced; REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485, AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE); if (tx_gain_forced) REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, AR_PHY_TXGAIN_FORCE, 0); REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1); REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL, 1); if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, AR_PHY_TX_IQCAL_START_DO_CAL, 0, AH_WAIT_TIMEOUT)) { ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal is not completed.\n"); return false; } return true; } static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); const u32 txiqcal_status[AR9300_MAX_CHAINS] = { AR_PHY_TX_IQCAL_STATUS_B0_9485, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_TX_IQCAL_STATUS_B1, AR_PHY_TX_IQCAL_STATUS_B2, }; Loading @@ -853,7 +754,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) struct coeff coeff; s32 iq_res[6]; u8 num_chains = 0; int i, ip, im, j; int i, im, j; int nmeasurement; for (i = 0; i < AR9300_MAX_CHAINS; i++) { Loading @@ -861,10 +762,9 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) num_chains++; } for (ip = 0; ip < MPASS; ip++) { for (i = 0; i < num_chains; i++) { nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0_9485, AR_PHY_TX_IQCAL_STATUS_B0, AR_PHY_CALIBRATED_GAINS_0); if (nmeasurement > MAX_MEASUREMENT) nmeasurement = MAX_MEASUREMENT; Loading Loading @@ -912,20 +812,19 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, coeff.iqc_coeff)) { ath_dbg(common, ATH_DBG_CALIBRATE, "Failed in calculation of IQ correction.\n"); "Failed in calculation of \ IQ correction.\n"); goto tx_iqcal_fail; } coeff.mag_coeff[i][im][ip] = coeff.iqc_coeff[0] & 0x7f; coeff.phs_coeff[i][im][ip] = coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; coeff.phs_coeff[i][im] = (coeff.iqc_coeff[0] >> 7) & 0x7f; if (coeff.mag_coeff[i][im][ip] > 63) coeff.mag_coeff[i][im][ip] -= 128; if (coeff.phs_coeff[i][im][ip] > 63) coeff.phs_coeff[i][im][ip] -= 128; } if (coeff.mag_coeff[i][im] > 63) coeff.mag_coeff[i][im] -= 128; if (coeff.phs_coeff[i][im] > 63) coeff.phs_coeff[i][im] -= 128; } } ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); Loading @@ -940,31 +839,37 @@ 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_capabilities *pCap = &ah->caps; int val; bool txiqcal_done = false; val = REG_READ(ah, AR_ENT_OTP); ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); if (AR_SREV_9485(ah)) ar9003_hw_set_chain_masks(ah, 0x1, 0x1); else if (val & AR_ENT_OTP_CHAIN2_DISABLE) /* Configure rx/tx chains before running AGC/TxiQ cals */ if (val & AR_ENT_OTP_CHAIN2_DISABLE) ar9003_hw_set_chain_masks(ah, 0x3, 0x3); else /* * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain * mode before running AGC/TxIQ cals */ ar9003_hw_set_chain_masks(ah, 0x7, 0x7); ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask, pCap->tx_chainmask); /* Do Tx IQ Calibration */ if (AR_SREV_9485(ah)) ar9003_hw_tx_iq_cal_run(ah); else ar9003_hw_tx_iq_cal(ah); REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); /* * For AR9485 or later chips, TxIQ cal runs as part of * AGC calibration */ if (AR_SREV_9485_OR_LATER(ah)) txiqcal_done = true; else { txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); udelay(5); REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); } /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, Loading @@ -979,7 +884,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, return false; } if (AR_SREV_9485(ah)) if (txiqcal_done) ar9003_hw_tx_iq_cal_post_proc(ah); /* Revert chainmasks to their original values before NF cal */ Loading
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +36 −25 Original line number Diff line number Diff line Loading @@ -3217,7 +3217,6 @@ static int ar9300_compress_decision(struct ath_hw *ah, u8 *word, int length, int mdata_size) { struct ath_common *common = ath9k_hw_common(ah); u8 *dptr; const struct ar9300_eeprom *eep = NULL; switch (code) { Loading @@ -3235,7 +3234,6 @@ static int ar9300_compress_decision(struct ath_hw *ah, break; case _CompressBlock: if (reference == 0) { dptr = mptr; } else { eep = ar9003_eeprom_struct_find_by_id(reference); if (eep == NULL) { Loading Loading @@ -3448,9 +3446,13 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); else { REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, if (!AR_SREV_9340(ah)) { REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPABIASLVL_MSB, bias >> 2); REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1); REG_RMW_FIELD(ah, AR_CH0_THERM, AR_CH0_THERM_XPASHORT2GND, 1); } } } Loading Loading @@ -3497,23 +3499,28 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) { int chain; static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { AR_PHY_SWITCH_CHAIN_0, AR_PHY_SWITCH_CHAIN_1, AR_PHY_SWITCH_CHAIN_2, }; u32 value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM, AR_SWITCH_TABLE_COM_ALL, value); value = ar9003_hw_ant_ctrl_common_2_get(ah, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM_2, AR_SWITCH_TABLE_COM2_ALL, value); value = ar9003_hw_ant_ctrl_chain_get(ah, 0, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_0, AR_SWITCH_TABLE_ALL, value); if (!AR_SREV_9485(ah)) { value = ar9003_hw_ant_ctrl_chain_get(ah, 1, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_1, AR_SWITCH_TABLE_ALL, value); value = ar9003_hw_ant_ctrl_chain_get(ah, 2, is2ghz); REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN_2, AR_SWITCH_TABLE_ALL, value); for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { if ((ah->rxchainmask & BIT(chain)) || (ah->txchainmask & BIT(chain))) { value = ar9003_hw_ant_ctrl_chain_get(ah, chain, is2ghz); REG_RMW_FIELD(ah, switch_chain_reg[chain], AR_SWITCH_TABLE_ALL, value); } } if (AR_SREV_9485(ah)) { Loading Loading @@ -3634,13 +3641,16 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) /* Test value. if 0 then attenuation is unused. Don't load anything. */ for (i = 0; i < 3; i++) { if (ah->txchainmask & BIT(i)) { value = ar9003_hw_atten_chain_get(ah, i, chan); REG_RMW_FIELD(ah, ext_atten_reg[i], AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, value); value = ar9003_hw_atten_chain_get_margin(ah, i, chan); REG_RMW_FIELD(ah, ext_atten_reg[i], AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, value); } } } Loading Loading @@ -3749,8 +3759,9 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan)); ar9003_hw_drive_strength_apply(ah); ar9003_hw_atten_apply(ah, chan); if (!AR_SREV_9340(ah)) ar9003_hw_internal_regulator_apply(ah); if (AR_SREV_9485(ah)) if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) ar9003_hw_apply_tuning_caps(ah); } Loading