aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/ar9003_calib.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_calib.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c387
1 files changed, 146 insertions, 241 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 4a4cd88429c0..f276cb922b4d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -18,13 +18,13 @@
18#include "hw-ops.h" 18#include "hw-ops.h"
19#include "ar9003_phy.h" 19#include "ar9003_phy.h"
20 20
21#define MPASS 3
22#define MAX_MEASUREMENT 8 21#define MAX_MEASUREMENT 8
23#define MAX_DIFFERENCE 10 22#define MAX_MAG_DELTA 11
23#define MAX_PHS_DELTA 10
24 24
25struct coeff { 25struct coeff {
26 int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; 26 int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
27 int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; 27 int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
28 int iqc_coeff[2]; 28 int iqc_coeff[2];
29}; 29};
30 30
@@ -185,17 +185,19 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
185 185
186 /* Accumulate IQ cal measures for active chains */ 186 /* Accumulate IQ cal measures for active chains */
187 for (i = 0; i < AR5416_MAX_CHAINS; i++) { 187 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
188 ah->totalPowerMeasI[i] += 188 if (ah->txchainmask & BIT(i)) {
189 REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); 189 ah->totalPowerMeasI[i] +=
190 ah->totalPowerMeasQ[i] += 190 REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
191 REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); 191 ah->totalPowerMeasQ[i] +=
192 ah->totalIqCorrMeas[i] += 192 REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
193 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); 193 ah->totalIqCorrMeas[i] +=
194 ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, 194 (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
195 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", 195 ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
196 ah->cal_samples, i, ah->totalPowerMeasI[i], 196 "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
197 ah->totalPowerMeasQ[i], 197 ah->cal_samples, i, ah->totalPowerMeasI[i],
198 ah->totalIqCorrMeas[i]); 198 ah->totalPowerMeasQ[i],
199 ah->totalIqCorrMeas[i]);
200 }
199 } 201 }
200} 202}
201 203
@@ -608,36 +610,48 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
608 return true; 610 return true;
609} 611}
610 612
611static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg) 613static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
614 int max_delta)
612{ 615{
613 int diff[MPASS]; 616 int mp_max = -64, max_idx = 0;
614 617 int mp_min = 63, min_idx = 0;
615 diff[0] = abs(mp_coeff[0] - mp_coeff[1]); 618 int mp_avg = 0, i, outlier_idx = 0;
616 diff[1] = abs(mp_coeff[1] - mp_coeff[2]); 619
617 diff[2] = abs(mp_coeff[2] - mp_coeff[0]); 620 /* find min/max mismatch across all calibrated gains */
618 621 for (i = 0; i < nmeasurement; i++) {
619 if (diff[0] > MAX_DIFFERENCE && 622 mp_avg += mp_coeff[i];
620 diff[1] > MAX_DIFFERENCE && 623 if (mp_coeff[i] > mp_max) {
621 diff[2] > MAX_DIFFERENCE) 624 mp_max = mp_coeff[i];
622 return false; 625 max_idx = i;
626 } else if (mp_coeff[i] < mp_min) {
627 mp_min = mp_coeff[i];
628 min_idx = i;
629 }
630 }
623 631
624 if (diff[0] <= diff[1] && diff[0] <= diff[2]) 632 /* find average (exclude max abs value) */
625 *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; 633 for (i = 0; i < nmeasurement; i++) {
626 else if (diff[1] <= diff[2]) 634 if ((abs(mp_coeff[i]) < abs(mp_max)) ||
627 *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; 635 (abs(mp_coeff[i]) < abs(mp_min)))
628 else 636 mp_avg += mp_coeff[i];
629 *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; 637 }
638 mp_avg /= (nmeasurement - 1);
630 639
631 return true; 640 /* detect outlier */
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;
644 else
645 outlier_idx = min_idx;
646 }
647 mp_coeff[outlier_idx] = mp_avg;
632} 648}
633 649
634static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, 650static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
635 u8 num_chains, 651 u8 num_chains,
636 struct coeff *coeff) 652 struct coeff *coeff)
637{ 653{
638 struct ath_common *common = ath9k_hw_common(ah);
639 int i, im, nmeasurement; 654 int i, im, nmeasurement;
640 int magnitude, phase;
641 u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; 655 u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
642 656
643 memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); 657 memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
@@ -657,37 +671,28 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
657 671
658 /* Load the average of 2 passes */ 672 /* Load the average of 2 passes */
659 for (i = 0; i < num_chains; i++) { 673 for (i = 0; i < num_chains; i++) {
660 if (AR_SREV_9485(ah)) 674 nmeasurement = REG_READ_FIELD(ah,
661 nmeasurement = REG_READ_FIELD(ah, 675 AR_PHY_TX_IQCAL_STATUS_B0,
662 AR_PHY_TX_IQCAL_STATUS_B0_9485, 676 AR_PHY_CALIBRATED_GAINS_0);
663 AR_PHY_CALIBRATED_GAINS_0);
664 else
665 nmeasurement = REG_READ_FIELD(ah,
666 AR_PHY_TX_IQCAL_STATUS_B0,
667 AR_PHY_CALIBRATED_GAINS_0);
668 677
669 if (nmeasurement > MAX_MEASUREMENT) 678 if (nmeasurement > MAX_MEASUREMENT)
670 nmeasurement = MAX_MEASUREMENT; 679 nmeasurement = MAX_MEASUREMENT;
671 680
672 for (im = 0; im < nmeasurement; im++) { 681 /* detect outlier only if nmeasurement > 1 */
673 /* 682 if (nmeasurement > 1) {
674 * Determine which 2 passes are closest and compute avg 683 /* Detect magnitude outlier */
675 * magnitude 684 ar9003_hw_detect_outlier(coeff->mag_coeff[i],
676 */ 685 nmeasurement, MAX_MAG_DELTA);
677 if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im],
678 &magnitude))
679 goto disable_txiqcal;
680 686
681 /* 687 /* Detect phase outlier */
682 * Determine which 2 passes are closest and compute avg 688 ar9003_hw_detect_outlier(coeff->phs_coeff[i],
683 * phase 689 nmeasurement, MAX_PHS_DELTA);
684 */ 690 }
685 if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im], 691
686 &phase)) 692 for (im = 0; im < nmeasurement; im++) {
687 goto disable_txiqcal;
688 693
689 coeff->iqc_coeff[0] = (magnitude & 0x7f) | 694 coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
690 ((phase & 0x7f) << 7); 695 ((coeff->phs_coeff[i][im] & 0x7f) << 7);
691 696
692 if ((im % 2) == 0) 697 if ((im % 2) == 0)
693 REG_RMW_FIELD(ah, tx_corr_coeff[im][i], 698 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
@@ -707,141 +712,37 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
707 712
708 return; 713 return;
709 714
710disable_txiqcal:
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);
715
716 ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n");
717} 715}
718 716
719static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) 717static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
720{ 718{
721 struct ath_common *common = ath9k_hw_common(ah); 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,
726 };
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,
731 };
732 struct coeff coeff;
733 s32 iq_res[6];
734 s32 i, j, ip, im, nmeasurement;
735 u8 nchains = get_streams(common->tx_chainmask);
736
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,
740 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);
744
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;
751 }
752
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;
757
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;
767 }
768
769 for (j = 0; j < 3; j++) {
770 u8 idx = 2 * j,
771 offset = 4 * (3 * im + j);
772
773 REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
774 AR_PHY_CHAN_INFO_TAB_S2_READ,
775 0);
776
777 /* 32 bits */
778 iq_res[idx] = REG_READ(ah,
779 chan_info_tab[i] +
780 offset);
781
782 REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
783 AR_PHY_CHAN_INFO_TAB_S2_READ,
784 1);
785
786 /* 16 bits */
787 iq_res[idx+1] = 0xffff & REG_READ(ah,
788 chan_info_tab[i] +
789 offset);
790
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]);
794 }
795
796 if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
797 coeff.iqc_coeff)) {
798 ath_dbg(common, ATH_DBG_CALIBRATE,
799 "Failed in calculation of IQ correction.\n");
800 goto TX_IQ_CAL_FAILED;
801 }
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;
806
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;
811
812 }
813 }
814 }
815
816 ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff);
817
818 return;
819
820TX_IQ_CAL_FAILED:
821 ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
822}
823
824static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
825{
826 u8 tx_gain_forced; 720 u8 tx_gain_forced;
827 721
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 tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, 722 tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
831 AR_PHY_TXGAIN_FORCE); 723 AR_PHY_TXGAIN_FORCE);
832 if (tx_gain_forced) 724 if (tx_gain_forced)
833 REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, 725 REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
834 AR_PHY_TXGAIN_FORCE, 0); 726 AR_PHY_TXGAIN_FORCE, 0);
835 727
836 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, 728 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
837 AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1); 729 AR_PHY_TX_IQCAL_START_DO_CAL, 1);
730
731 if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
732 AR_PHY_TX_IQCAL_START_DO_CAL, 0,
733 AH_WAIT_TIMEOUT)) {
734 ath_dbg(common, ATH_DBG_CALIBRATE,
735 "Tx IQ Cal is not completed.\n");
736 return false;
737 }
738 return true;
838} 739}
839 740
840static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) 741static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
841{ 742{
842 struct ath_common *common = ath9k_hw_common(ah); 743 struct ath_common *common = ath9k_hw_common(ah);
843 const u32 txiqcal_status[AR9300_MAX_CHAINS] = { 744 const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
844 AR_PHY_TX_IQCAL_STATUS_B0_9485, 745 AR_PHY_TX_IQCAL_STATUS_B0,
845 AR_PHY_TX_IQCAL_STATUS_B1, 746 AR_PHY_TX_IQCAL_STATUS_B1,
846 AR_PHY_TX_IQCAL_STATUS_B2, 747 AR_PHY_TX_IQCAL_STATUS_B2,
847 }; 748 };
@@ -853,7 +754,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
853 struct coeff coeff; 754 struct coeff coeff;
854 s32 iq_res[6]; 755 s32 iq_res[6];
855 u8 num_chains = 0; 756 u8 num_chains = 0;
856 int i, ip, im, j; 757 int i, im, j;
857 int nmeasurement; 758 int nmeasurement;
858 759
859 for (i = 0; i < AR9300_MAX_CHAINS; i++) { 760 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
@@ -861,71 +762,69 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
861 num_chains++; 762 num_chains++;
862 } 763 }
863 764
864 for (ip = 0; ip < MPASS; ip++) { 765 for (i = 0; i < num_chains; i++) {
865 for (i = 0; i < num_chains; i++) { 766 nmeasurement = REG_READ_FIELD(ah,
866 nmeasurement = REG_READ_FIELD(ah, 767 AR_PHY_TX_IQCAL_STATUS_B0,
867 AR_PHY_TX_IQCAL_STATUS_B0_9485, 768 AR_PHY_CALIBRATED_GAINS_0);
868 AR_PHY_CALIBRATED_GAINS_0); 769 if (nmeasurement > MAX_MEASUREMENT)
869 if (nmeasurement > MAX_MEASUREMENT) 770 nmeasurement = MAX_MEASUREMENT;
870 nmeasurement = MAX_MEASUREMENT;
871 771
872 for (im = 0; im < nmeasurement; im++) { 772 for (im = 0; im < nmeasurement; im++) {
873 ath_dbg(common, ATH_DBG_CALIBRATE, 773 ath_dbg(common, ATH_DBG_CALIBRATE,
874 "Doing Tx IQ Cal for chain %d.\n", i); 774 "Doing Tx IQ Cal for chain %d.\n", i);
875 775
876 if (REG_READ(ah, txiqcal_status[i]) & 776 if (REG_READ(ah, txiqcal_status[i]) &
877 AR_PHY_TX_IQCAL_STATUS_FAILED) { 777 AR_PHY_TX_IQCAL_STATUS_FAILED) {
878 ath_dbg(common, ATH_DBG_CALIBRATE, 778 ath_dbg(common, ATH_DBG_CALIBRATE,
879 "Tx IQ Cal failed for chain %d.\n", i); 779 "Tx IQ Cal failed for chain %d.\n", i);
880 goto tx_iqcal_fail; 780 goto tx_iqcal_fail;
881 } 781 }
882 782
883 for (j = 0; j < 3; j++) { 783 for (j = 0; j < 3; j++) {
884 u32 idx = 2 * j, offset = 4 * (3 * im + j); 784 u32 idx = 2 * j, offset = 4 * (3 * im + j);
885 785
886 REG_RMW_FIELD(ah, 786 REG_RMW_FIELD(ah,
887 AR_PHY_CHAN_INFO_MEMORY, 787 AR_PHY_CHAN_INFO_MEMORY,
888 AR_PHY_CHAN_INFO_TAB_S2_READ, 788 AR_PHY_CHAN_INFO_TAB_S2_READ,
889 0); 789 0);
890 790
891 /* 32 bits */ 791 /* 32 bits */
892 iq_res[idx] = REG_READ(ah, 792 iq_res[idx] = REG_READ(ah,
893 chan_info_tab[i] + 793 chan_info_tab[i] +
894 offset); 794 offset);
895 795
896 REG_RMW_FIELD(ah, 796 REG_RMW_FIELD(ah,
897 AR_PHY_CHAN_INFO_MEMORY, 797 AR_PHY_CHAN_INFO_MEMORY,
898 AR_PHY_CHAN_INFO_TAB_S2_READ, 798 AR_PHY_CHAN_INFO_TAB_S2_READ,
899 1); 799 1);
900 800
901 /* 16 bits */ 801 /* 16 bits */
902 iq_res[idx + 1] = 0xffff & REG_READ(ah, 802 iq_res[idx + 1] = 0xffff & REG_READ(ah,
903 chan_info_tab[i] + offset); 803 chan_info_tab[i] + offset);
904 804
905 ath_dbg(common, ATH_DBG_CALIBRATE, 805 ath_dbg(common, ATH_DBG_CALIBRATE,
906 "IQ RES[%d]=0x%x" 806 "IQ RES[%d]=0x%x"
907 "IQ_RES[%d]=0x%x\n", 807 "IQ_RES[%d]=0x%x\n",
908 idx, iq_res[idx], idx + 1, 808 idx, iq_res[idx], idx + 1,
909 iq_res[idx + 1]); 809 iq_res[idx + 1]);
910 } 810 }
911 811
912 if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, 812 if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
913 coeff.iqc_coeff)) { 813 coeff.iqc_coeff)) {
914 ath_dbg(common, ATH_DBG_CALIBRATE, 814 ath_dbg(common, ATH_DBG_CALIBRATE,
915 "Failed in calculation of IQ correction.\n"); 815 "Failed in calculation of \
916 goto tx_iqcal_fail; 816 IQ correction.\n");
917 } 817 goto tx_iqcal_fail;
818 }
918 819
919 coeff.mag_coeff[i][im][ip] = 820 coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
920 coeff.iqc_coeff[0] & 0x7f; 821 coeff.phs_coeff[i][im] =
921 coeff.phs_coeff[i][im][ip] = 822 (coeff.iqc_coeff[0] >> 7) & 0x7f;
922 (coeff.iqc_coeff[0] >> 7) & 0x7f;
923 823
924 if (coeff.mag_coeff[i][im][ip] > 63) 824 if (coeff.mag_coeff[i][im] > 63)
925 coeff.mag_coeff[i][im][ip] -= 128; 825 coeff.mag_coeff[i][im] -= 128;
926 if (coeff.phs_coeff[i][im][ip] > 63) 826 if (coeff.phs_coeff[i][im] > 63)
927 coeff.phs_coeff[i][im][ip] -= 128; 827 coeff.phs_coeff[i][im] -= 128;
928 }
929 } 828 }
930 } 829 }
931 ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); 830 ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff);
@@ -940,31 +839,37 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
940 struct ath9k_channel *chan) 839 struct ath9k_channel *chan)
941{ 840{
942 struct ath_common *common = ath9k_hw_common(ah); 841 struct ath_common *common = ath9k_hw_common(ah);
842 struct ath9k_hw_capabilities *pCap = &ah->caps;
943 int val; 843 int val;
844 bool txiqcal_done = false;
944 845
945 val = REG_READ(ah, AR_ENT_OTP); 846 val = REG_READ(ah, AR_ENT_OTP);
946 ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); 847 ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
947 848
948 if (AR_SREV_9485(ah)) 849 /* Configure rx/tx chains before running AGC/TxiQ cals */
949 ar9003_hw_set_chain_masks(ah, 0x1, 0x1); 850 if (val & AR_ENT_OTP_CHAIN2_DISABLE)
950 else if (val & AR_ENT_OTP_CHAIN2_DISABLE)
951 ar9003_hw_set_chain_masks(ah, 0x3, 0x3); 851 ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
952 else 852 else
953 /* 853 ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
954 * 0x7 = 0b111 , AR9003 needs to be configured for 3-chain 854 pCap->tx_chainmask);
955 * mode before running AGC/TxIQ cals
956 */
957 ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
958 855
959 /* Do Tx IQ Calibration */ 856 /* Do Tx IQ Calibration */
960 if (AR_SREV_9485(ah)) 857 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
961 ar9003_hw_tx_iq_cal_run(ah); 858 AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
962 else 859 DELPT);
963 ar9003_hw_tx_iq_cal(ah);
964 860
965 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); 861 /*
966 udelay(5); 862 * For AR9485 or later chips, TxIQ cal runs as part of
967 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); 863 * AGC calibration
864 */
865 if (AR_SREV_9485_OR_LATER(ah))
866 txiqcal_done = true;
867 else {
868 txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
869 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
870 udelay(5);
871 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
872 }
968 873
969 /* Calibrate the AGC */ 874 /* Calibrate the AGC */
970 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 875 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
@@ -979,7 +884,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
979 return false; 884 return false;
980 } 885 }
981 886
982 if (AR_SREV_9485(ah)) 887 if (txiqcal_done)
983 ar9003_hw_tx_iq_cal_post_proc(ah); 888 ar9003_hw_tx_iq_cal_post_proc(ah);
984 889
985 /* Revert chainmasks to their original values before NF cal */ 890 /* Revert chainmasks to their original values before NF cal */