+--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+@@ -1040,8 +1040,8 @@ static void ar9003_hw_cl_cal_post_proc(s
+ }
+ }
+
+-static bool ar9003_hw_init_cal(struct ath_hw *ah,
+- struct ath9k_channel *chan)
++static bool ar9003_hw_init_cal_pcoem(struct ath_hw *ah,
++ struct ath9k_channel *chan)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+@@ -1228,13 +1228,109 @@ skip_tx_iqcal:
+ return true;
+ }
+
++static bool ar9003_hw_init_cal_soc(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;
++ bool is_reusable = true, status = true;
++ bool run_agc_cal = false, sep_iq_cal = false;
++
++ /* Use chip chainmask only for calibration */
++ ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
++
++ if (ah->enabled_cals & TX_CL_CAL) {
++ REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
++ run_agc_cal = true;
++ }
++
++ if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))
++ goto skip_tx_iqcal;
++
++ /* Do Tx IQ Calibration */
++ 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. Specifically, AR9550 in SoC chips.
++ */
++ if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
++ txiqcal_done = true;
++ run_agc_cal = true;
++ } else {
++ sep_iq_cal = true;
++ run_agc_cal = true;
++ }
++
++ /*
++ * In the SoC family, this will run for AR9300, AR9331 and AR9340.
++ */
++ if (sep_iq_cal) {
++ 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);
++ }
++
++skip_tx_iqcal:
++ if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
++ /* Calibrate the AGC */
++ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
++ REG_READ(ah, AR_PHY_AGC_CONTROL) |
++ AR_PHY_AGC_CONTROL_CAL);
++
++ /* Poll for offset calibration complete */
++ 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;
++ }
++
++ if (txiqcal_done)
++ ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
++
++ /* Revert chainmask to runtime parameters */
++ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
++
++ /* Initialize list pointers */
++ ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
++
++ INIT_CAL(&ah->iq_caldata);
++ INSERT_CAL(ah, &ah->iq_caldata);
++ ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
++
++ /* Initialize current pointer to first element in list */
++ ah->cal_list_curr = ah->cal_list;
++
++ if (ah->cal_list_curr)
++ ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
++
++ if (caldata)
++ caldata->CalValid = 0;
++
++ return true;
++}
++
+ void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
+ {
+ struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
+ struct ath_hw_ops *ops = ath9k_hw_ops(ah);
+
++ if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9565(ah))
++ priv_ops->init_cal = ar9003_hw_init_cal_pcoem;
++ else
++ priv_ops->init_cal = ar9003_hw_init_cal_soc;
++
+ priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
+- priv_ops->init_cal = ar9003_hw_init_cal;
+ priv_ops->setup_calibration = ar9003_hw_setup_calibration;
+
+ ops->calibrate = ar9003_hw_calibrate;
+--- a/drivers/net/wireless/ath/ath9k/common.c
++++ b/drivers/net/wireless/ath/ath9k/common.c
+@@ -98,10 +98,8 @@ struct ath9k_channel *ath9k_cmn_get_chan
+ {
+ struct ieee80211_channel *curchan = chandef->chan;
+ struct ath9k_channel *channel;
+- u8 chan_idx;
+
+- chan_idx = curchan->hw_value;
+- channel = &ah->channels[chan_idx];
++ channel = &ah->channels[curchan->hw_value];
+ ath9k_cmn_update_ichannel(channel, chandef);
+
+ return channel;