186
186
/* Accumulate IQ cal measures for active chains */
187
187
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
188
ah->totalPowerMeasI[i] +=
189
REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
190
ah->totalPowerMeasQ[i] +=
191
REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
192
ah->totalIqCorrMeas[i] +=
193
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
194
ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
195
"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
196
ah->cal_samples, i, ah->totalPowerMeasI[i],
197
ah->totalPowerMeasQ[i],
198
ah->totalIqCorrMeas[i]);
188
if (ah->txchainmask & BIT(i)) {
189
ah->totalPowerMeasI[i] +=
190
REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
191
ah->totalPowerMeasQ[i] +=
192
REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
193
ah->totalIqCorrMeas[i] +=
194
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
195
ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
196
"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
197
ah->cal_samples, i, ah->totalPowerMeasI[i],
198
ah->totalPowerMeasQ[i],
199
ah->totalIqCorrMeas[i]);
611
static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg)
613
static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
615
diff[0] = abs(mp_coeff[0] - mp_coeff[1]);
616
diff[1] = abs(mp_coeff[1] - mp_coeff[2]);
617
diff[2] = abs(mp_coeff[2] - mp_coeff[0]);
619
if (diff[0] > MAX_DIFFERENCE &&
620
diff[1] > MAX_DIFFERENCE &&
621
diff[2] > MAX_DIFFERENCE)
624
if (diff[0] <= diff[1] && diff[0] <= diff[2])
625
*mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2;
626
else if (diff[1] <= diff[2])
627
*mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2;
629
*mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2;
616
int mp_max = -64, max_idx = 0;
617
int mp_min = 63, min_idx = 0;
618
int mp_avg = 0, i, outlier_idx = 0;
620
/* find min/max mismatch across all calibrated gains */
621
for (i = 0; i < nmeasurement; i++) {
622
mp_avg += mp_coeff[i];
623
if (mp_coeff[i] > mp_max) {
624
mp_max = mp_coeff[i];
626
} else if (mp_coeff[i] < mp_min) {
627
mp_min = mp_coeff[i];
632
/* find average (exclude max abs value) */
633
for (i = 0; i < nmeasurement; i++) {
634
if ((abs(mp_coeff[i]) < abs(mp_max)) ||
635
(abs(mp_coeff[i]) < abs(mp_min)))
636
mp_avg += mp_coeff[i];
638
mp_avg /= (nmeasurement - 1);
641
if (abs(mp_max - mp_min) > max_delta) {
642
if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg))
643
outlier_idx = max_idx;
645
outlier_idx = min_idx;
647
mp_coeff[outlier_idx] = mp_avg;
634
650
static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
636
652
struct coeff *coeff)
638
struct ath_common *common = ath9k_hw_common(ah);
639
654
int i, im, nmeasurement;
640
int magnitude, phase;
641
655
u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
643
657
memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
658
672
/* Load the average of 2 passes */
659
673
for (i = 0; i < num_chains; i++) {
660
if (AR_SREV_9485(ah))
661
nmeasurement = REG_READ_FIELD(ah,
662
AR_PHY_TX_IQCAL_STATUS_B0_9485,
663
AR_PHY_CALIBRATED_GAINS_0);
665
nmeasurement = REG_READ_FIELD(ah,
666
AR_PHY_TX_IQCAL_STATUS_B0,
667
AR_PHY_CALIBRATED_GAINS_0);
674
nmeasurement = REG_READ_FIELD(ah,
675
AR_PHY_TX_IQCAL_STATUS_B0,
676
AR_PHY_CALIBRATED_GAINS_0);
669
678
if (nmeasurement > MAX_MEASUREMENT)
670
679
nmeasurement = MAX_MEASUREMENT;
681
/* detect outlier only if nmeasurement > 1 */
682
if (nmeasurement > 1) {
683
/* Detect magnitude outlier */
684
ar9003_hw_detect_outlier(coeff->mag_coeff[i],
685
nmeasurement, MAX_MAG_DELTA);
687
/* Detect phase outlier */
688
ar9003_hw_detect_outlier(coeff->phs_coeff[i],
689
nmeasurement, MAX_PHS_DELTA);
672
692
for (im = 0; im < nmeasurement; im++) {
674
* Determine which 2 passes are closest and compute avg
677
if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im],
679
goto disable_txiqcal;
682
* Determine which 2 passes are closest and compute avg
685
if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im],
687
goto disable_txiqcal;
689
coeff->iqc_coeff[0] = (magnitude & 0x7f) |
690
((phase & 0x7f) << 7);
694
coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
695
((coeff->phs_coeff[i][im] & 0x7f) << 7);
692
697
if ((im % 2) == 0)
693
698
REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
711
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
712
AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0);
713
REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
714
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0);
716
ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n");
719
static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
717
static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
721
719
struct ath_common *common = ath9k_hw_common(ah);
722
static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
723
AR_PHY_TX_IQCAL_STATUS_B0,
724
AR_PHY_TX_IQCAL_STATUS_B1,
725
AR_PHY_TX_IQCAL_STATUS_B2,
727
static const u32 chan_info_tab[] = {
728
AR_PHY_CHAN_INFO_TAB_0,
729
AR_PHY_CHAN_INFO_TAB_1,
730
AR_PHY_CHAN_INFO_TAB_2,
734
s32 i, j, ip, im, nmeasurement;
735
u8 nchains = get_streams(common->tx_chainmask);
737
for (ip = 0; ip < MPASS; ip++) {
738
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
739
AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
741
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
742
AR_PHY_TX_IQCAL_START_DO_CAL,
743
AR_PHY_TX_IQCAL_START_DO_CAL);
745
if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
746
AR_PHY_TX_IQCAL_START_DO_CAL,
747
0, AH_WAIT_TIMEOUT)) {
748
ath_dbg(common, ATH_DBG_CALIBRATE,
749
"Tx IQ Cal not complete.\n");
750
goto TX_IQ_CAL_FAILED;
753
nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0,
754
AR_PHY_CALIBRATED_GAINS_0);
755
if (nmeasurement > MAX_MEASUREMENT)
756
nmeasurement = MAX_MEASUREMENT;
758
for (i = 0; i < nchains; i++) {
759
ath_dbg(common, ATH_DBG_CALIBRATE,
760
"Doing Tx IQ Cal for chain %d.\n", i);
761
for (im = 0; im < nmeasurement; im++) {
762
if (REG_READ(ah, txiqcal_status[i]) &
763
AR_PHY_TX_IQCAL_STATUS_FAILED) {
764
ath_dbg(common, ATH_DBG_CALIBRATE,
765
"Tx IQ Cal failed for chain %d.\n", i);
766
goto TX_IQ_CAL_FAILED;
769
for (j = 0; j < 3; j++) {
771
offset = 4 * (3 * im + j);
773
REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
774
AR_PHY_CHAN_INFO_TAB_S2_READ,
778
iq_res[idx] = REG_READ(ah,
782
REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
783
AR_PHY_CHAN_INFO_TAB_S2_READ,
787
iq_res[idx+1] = 0xffff & REG_READ(ah,
791
ath_dbg(common, ATH_DBG_CALIBRATE,
792
"IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
793
idx, iq_res[idx], idx+1, iq_res[idx+1]);
796
if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
798
ath_dbg(common, ATH_DBG_CALIBRATE,
799
"Failed in calculation of IQ correction.\n");
800
goto TX_IQ_CAL_FAILED;
802
coeff.mag_coeff[i][im][ip] =
803
coeff.iqc_coeff[0] & 0x7f;
804
coeff.phs_coeff[i][im][ip] =
805
(coeff.iqc_coeff[0] >> 7) & 0x7f;
807
if (coeff.mag_coeff[i][im][ip] > 63)
808
coeff.mag_coeff[i][im][ip] -= 128;
809
if (coeff.phs_coeff[i][im][ip] > 63)
810
coeff.phs_coeff[i][im][ip] -= 128;
816
ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff);
821
ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
824
static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
826
720
u8 tx_gain_forced;
828
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485,
829
AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT);
830
722
tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
831
723
AR_PHY_TXGAIN_FORCE);
832
724
if (tx_gain_forced)
833
725
REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
834
726
AR_PHY_TXGAIN_FORCE, 0);
836
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485,
837
AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1);
728
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
729
AR_PHY_TX_IQCAL_START_DO_CAL, 1);
731
if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
732
AR_PHY_TX_IQCAL_START_DO_CAL, 0,
734
ath_dbg(common, ATH_DBG_CALIBRATE,
735
"Tx IQ Cal is not completed.\n");
840
741
static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
842
743
struct ath_common *common = ath9k_hw_common(ah);
843
744
const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
844
AR_PHY_TX_IQCAL_STATUS_B0_9485,
745
AR_PHY_TX_IQCAL_STATUS_B0,
845
746
AR_PHY_TX_IQCAL_STATUS_B1,
846
747
AR_PHY_TX_IQCAL_STATUS_B2,
864
for (ip = 0; ip < MPASS; ip++) {
865
for (i = 0; i < num_chains; i++) {
866
nmeasurement = REG_READ_FIELD(ah,
867
AR_PHY_TX_IQCAL_STATUS_B0_9485,
868
AR_PHY_CALIBRATED_GAINS_0);
869
if (nmeasurement > MAX_MEASUREMENT)
870
nmeasurement = MAX_MEASUREMENT;
872
for (im = 0; im < nmeasurement; im++) {
765
for (i = 0; i < num_chains; i++) {
766
nmeasurement = REG_READ_FIELD(ah,
767
AR_PHY_TX_IQCAL_STATUS_B0,
768
AR_PHY_CALIBRATED_GAINS_0);
769
if (nmeasurement > MAX_MEASUREMENT)
770
nmeasurement = MAX_MEASUREMENT;
772
for (im = 0; im < nmeasurement; im++) {
773
ath_dbg(common, ATH_DBG_CALIBRATE,
774
"Doing Tx IQ Cal for chain %d.\n", i);
776
if (REG_READ(ah, txiqcal_status[i]) &
777
AR_PHY_TX_IQCAL_STATUS_FAILED) {
873
778
ath_dbg(common, ATH_DBG_CALIBRATE,
874
"Doing Tx IQ Cal for chain %d.\n", i);
876
if (REG_READ(ah, txiqcal_status[i]) &
877
AR_PHY_TX_IQCAL_STATUS_FAILED) {
878
ath_dbg(common, ATH_DBG_CALIBRATE,
879
779
"Tx IQ Cal failed for chain %d.\n", i);
883
for (j = 0; j < 3; j++) {
884
u32 idx = 2 * j, offset = 4 * (3 * im + j);
783
for (j = 0; j < 3; j++) {
784
u32 idx = 2 * j, offset = 4 * (3 * im + j);
887
787
AR_PHY_CHAN_INFO_MEMORY,
888
788
AR_PHY_CHAN_INFO_TAB_S2_READ,
892
iq_res[idx] = REG_READ(ah,
792
iq_res[idx] = REG_READ(ah,
897
797
AR_PHY_CHAN_INFO_MEMORY,
898
798
AR_PHY_CHAN_INFO_TAB_S2_READ,
902
iq_res[idx + 1] = 0xffff & REG_READ(ah,
903
chan_info_tab[i] + offset);
905
ath_dbg(common, ATH_DBG_CALIBRATE,
908
idx, iq_res[idx], idx + 1,
912
if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
914
ath_dbg(common, ATH_DBG_CALIBRATE,
915
"Failed in calculation of IQ correction.\n");
919
coeff.mag_coeff[i][im][ip] =
920
coeff.iqc_coeff[0] & 0x7f;
921
coeff.phs_coeff[i][im][ip] =
922
(coeff.iqc_coeff[0] >> 7) & 0x7f;
924
if (coeff.mag_coeff[i][im][ip] > 63)
925
coeff.mag_coeff[i][im][ip] -= 128;
926
if (coeff.phs_coeff[i][im][ip] > 63)
927
coeff.phs_coeff[i][im][ip] -= 128;
802
iq_res[idx + 1] = 0xffff & REG_READ(ah,
803
chan_info_tab[i] + offset);
805
ath_dbg(common, ATH_DBG_CALIBRATE,
808
idx, iq_res[idx], idx + 1,
812
if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
814
ath_dbg(common, ATH_DBG_CALIBRATE,
815
"Failed in calculation of \
820
coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
821
coeff.phs_coeff[i][im] =
822
(coeff.iqc_coeff[0] >> 7) & 0x7f;
824
if (coeff.mag_coeff[i][im] > 63)
825
coeff.mag_coeff[i][im] -= 128;
826
if (coeff.phs_coeff[i][im] > 63)
827
coeff.phs_coeff[i][im] -= 128;
931
830
ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
940
839
struct ath9k_channel *chan)
942
841
struct ath_common *common = ath9k_hw_common(ah);
842
struct ath9k_hw_capabilities *pCap = &ah->caps;
844
bool txiqcal_done = false;
945
846
val = REG_READ(ah, AR_ENT_OTP);
946
847
ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
948
if (AR_SREV_9485(ah))
949
ar9003_hw_set_chain_masks(ah, 0x1, 0x1);
950
else if (val & AR_ENT_OTP_CHAIN2_DISABLE)
849
/* Configure rx/tx chains before running AGC/TxiQ cals */
850
if (val & AR_ENT_OTP_CHAIN2_DISABLE)
951
851
ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
954
* 0x7 = 0b111 , AR9003 needs to be configured for 3-chain
955
* mode before running AGC/TxIQ cals
957
ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
853
ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
959
856
/* Do Tx IQ Calibration */
960
if (AR_SREV_9485(ah))
961
ar9003_hw_tx_iq_cal_run(ah);
963
ar9003_hw_tx_iq_cal(ah);
857
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
858
AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
965
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
967
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
862
* For AR9485 or later chips, TxIQ cal runs as part of
865
if (AR_SREV_9485_OR_LATER(ah))
868
txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
869
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
871
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
969
874
/* Calibrate the AGC */
970
875
REG_WRITE(ah, AR_PHY_AGC_CONTROL,