aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/ar9003_calib.c
diff options
context:
space:
mode:
authorRajkumar Manoharan <rmanoharan@atheros.com>2011-04-24 12:04:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-26 15:50:27 -0400
commit3782c69d6e35e698bcc2aefe803e62d06c5c4997 (patch)
tree1cb38bc080c1f66024cc29fe827390d76739a224 /drivers/net/wireless/ath/ath9k/ar9003_calib.c
parent429576b97c623b9c4e3375fb7c37bce377f51e68 (diff)
ath9k_hw: Fix Tx IQ Calibration hang issue in AR9003 chips
On AR9003 chips, doing three IQ calibrations will possibly cause chip in stuck state. In noisy environment, chip could receive a packet during the middle of three calibrations and it causes the conflict of HW access and the eventual failure. It also causes IQ calibration outliers which results in poor Tx EVM. The IQ Cal procedure is after resetting the chip, run IQ cal 3 times per each cal cycle and find the two closest readings and average of two. The advantage of running Tx IQ cal more than once is that we can compare calibration results for the same gain setting over multiple iterations. Most of the cases the IQ failures were observed after first pass. For the AR9485 and later chips, Tx IQ Calibration is performed along with AGC cal. But for pre-AR9485 chips, Tx IQ cal HW has to be separated from the rest of calibration HW to avoid chip hang. After all calibrations are done in HW, we can start SW post-processing. By doing this way, we minimize the SW difference among all chips. The order of calibration (run IQ cal before other calibration) is also needed to avoid chip hang for chips before AR9485. This issue was originally observed with AR9382. During the issue kernel log was filled with following message ath: timeout (100000 us) on reg 0xa640: 0x00000001 & 0x00000001 != 0x00000000 ath: timeout (100000 us) on reg 0xa2c4: 0x00158dd9 & 0x00000001 != 0x00000000 ath: Unable to reset channel (2412 MHz), reset status -5 ath: Unable to set channel Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_calib.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c350
1 files changed, 128 insertions, 222 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index bceff49d150..f276cb922b4 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
@@ -610,36 +610,48 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
610 return true; 610 return true;
611} 611}
612 612
613static 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)
614{ 615{
615 int diff[MPASS]; 616 int mp_max = -64, max_idx = 0;
616 617 int mp_min = 63, min_idx = 0;
617 diff[0] = abs(mp_coeff[0] - mp_coeff[1]); 618 int mp_avg = 0, i, outlier_idx = 0;
618 diff[1] = abs(mp_coeff[1] - mp_coeff[2]); 619
619 diff[2] = abs(mp_coeff[2] - mp_coeff[0]); 620 /* find min/max mismatch across all calibrated gains */
620 621 for (i = 0; i < nmeasurement; i++) {
621 if (diff[0] > MAX_DIFFERENCE && 622 mp_avg += mp_coeff[i];
622 diff[1] > MAX_DIFFERENCE && 623 if (mp_coeff[i] > mp_max) {
623 diff[2] > MAX_DIFFERENCE) 624 mp_max = mp_coeff[i];
624 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 }
625 631
626 if (diff[0] <= diff[1] && diff[0] <= diff[2]) 632 /* find average (exclude max abs value) */
627 *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; 633 for (i = 0; i < nmeasurement; i++) {
628 else if (diff[1] <= diff[2]) 634 if ((abs(mp_coeff[i]) < abs(mp_max)) ||
629 *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; 635 (abs(mp_coeff[i]) < abs(mp_min)))
630 else 636 mp_avg += mp_coeff[i];
631 *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; 637 }
638 mp_avg /= (nmeasurement - 1);
632 639
633 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;
634} 648}
635 649
636static 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,
637 u8 num_chains, 651 u8 num_chains,
638 struct coeff *coeff) 652 struct coeff *coeff)
639{ 653{
640 struct ath_common *common = ath9k_hw_common(ah);
641 int i, im, nmeasurement; 654 int i, im, nmeasurement;
642 int magnitude, phase;
643 u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; 655 u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
644 656
645 memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); 657 memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff));
@@ -659,37 +671,28 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
659 671
660 /* Load the average of 2 passes */ 672 /* Load the average of 2 passes */
661 for (i = 0; i < num_chains; i++) { 673 for (i = 0; i < num_chains; i++) {
662 if (AR_SREV_9485(ah)) 674 nmeasurement = REG_READ_FIELD(ah,
663 nmeasurement = REG_READ_FIELD(ah, 675 AR_PHY_TX_IQCAL_STATUS_B0,
664 AR_PHY_TX_IQCAL_STATUS_B0_9485, 676 AR_PHY_CALIBRATED_GAINS_0);
665 AR_PHY_CALIBRATED_GAINS_0);
666 else
667 nmeasurement = REG_READ_FIELD(ah,
668 AR_PHY_TX_IQCAL_STATUS_B0,
669 AR_PHY_CALIBRATED_GAINS_0);
670 677
671 if (nmeasurement > MAX_MEASUREMENT) 678 if (nmeasurement > MAX_MEASUREMENT)
672 nmeasurement = MAX_MEASUREMENT; 679 nmeasurement = MAX_MEASUREMENT;
673 680
674 for (im = 0; im < nmeasurement; im++) { 681 /* detect outlier only if nmeasurement > 1 */
675 /* 682 if (nmeasurement > 1) {
676 * Determine which 2 passes are closest and compute avg 683 /* Detect magnitude outlier */
677 * magnitude 684 ar9003_hw_detect_outlier(coeff->mag_coeff[i],
678 */ 685 nmeasurement, MAX_MAG_DELTA);
679 if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im],
680 &magnitude))
681 goto disable_txiqcal;
682 686
683 /* 687 /* Detect phase outlier */
684 * Determine which 2 passes are closest and compute avg 688 ar9003_hw_detect_outlier(coeff->phs_coeff[i],
685 * phase 689 nmeasurement, MAX_PHS_DELTA);
686 */ 690 }
687 if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im],
688 &phase))
689 goto disable_txiqcal;
690 691
691 coeff->iqc_coeff[0] = (magnitude & 0x7f) | 692 for (im = 0; im < nmeasurement; im++) {
692 ((phase & 0x7f) << 7); 693
694 coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
695 ((coeff->phs_coeff[i][im] & 0x7f) << 7);
693 696
694 if ((im % 2) == 0) 697 if ((im % 2) == 0)
695 REG_RMW_FIELD(ah, tx_corr_coeff[im][i], 698 REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
@@ -709,141 +712,37 @@ static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
709 712
710 return; 713 return;
711 714
712disable_txiqcal:
713 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
714 AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0);
715 REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
716 AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0);
717
718 ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n");
719} 715}
720 716
721static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) 717static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
722{ 718{
723 struct ath_common *common = ath9k_hw_common(ah); 719 struct ath_common *common = ath9k_hw_common(ah);
724 static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
725 AR_PHY_TX_IQCAL_STATUS_B0,
726 AR_PHY_TX_IQCAL_STATUS_B1,
727 AR_PHY_TX_IQCAL_STATUS_B2,
728 };
729 static const u32 chan_info_tab[] = {
730 AR_PHY_CHAN_INFO_TAB_0,
731 AR_PHY_CHAN_INFO_TAB_1,
732 AR_PHY_CHAN_INFO_TAB_2,
733 };
734 struct coeff coeff;
735 s32 iq_res[6];
736 s32 i, j, ip, im, nmeasurement;
737 u8 nchains = get_streams(common->tx_chainmask);
738
739 for (ip = 0; ip < MPASS; ip++) {
740 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
741 AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
742 DELPT);
743 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
744 AR_PHY_TX_IQCAL_START_DO_CAL,
745 AR_PHY_TX_IQCAL_START_DO_CAL);
746
747 if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
748 AR_PHY_TX_IQCAL_START_DO_CAL,
749 0, AH_WAIT_TIMEOUT)) {
750 ath_dbg(common, ATH_DBG_CALIBRATE,
751 "Tx IQ Cal not complete.\n");
752 goto TX_IQ_CAL_FAILED;
753 }
754
755 nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0,
756 AR_PHY_CALIBRATED_GAINS_0);
757 if (nmeasurement > MAX_MEASUREMENT)
758 nmeasurement = MAX_MEASUREMENT;
759
760 for (i = 0; i < nchains; i++) {
761 ath_dbg(common, ATH_DBG_CALIBRATE,
762 "Doing Tx IQ Cal for chain %d.\n", i);
763 for (im = 0; im < nmeasurement; im++) {
764 if (REG_READ(ah, txiqcal_status[i]) &
765 AR_PHY_TX_IQCAL_STATUS_FAILED) {
766 ath_dbg(common, ATH_DBG_CALIBRATE,
767 "Tx IQ Cal failed for chain %d.\n", i);
768 goto TX_IQ_CAL_FAILED;
769 }
770
771 for (j = 0; j < 3; j++) {
772 u8 idx = 2 * j,
773 offset = 4 * (3 * im + j);
774
775 REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
776 AR_PHY_CHAN_INFO_TAB_S2_READ,
777 0);
778
779 /* 32 bits */
780 iq_res[idx] = REG_READ(ah,
781 chan_info_tab[i] +
782 offset);
783
784 REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
785 AR_PHY_CHAN_INFO_TAB_S2_READ,
786 1);
787
788 /* 16 bits */
789 iq_res[idx+1] = 0xffff & REG_READ(ah,
790 chan_info_tab[i] +
791 offset);
792
793 ath_dbg(common, ATH_DBG_CALIBRATE,
794 "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
795 idx, iq_res[idx], idx+1, iq_res[idx+1]);
796 }
797
798 if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
799 coeff.iqc_coeff)) {
800 ath_dbg(common, ATH_DBG_CALIBRATE,
801 "Failed in calculation of IQ correction.\n");
802 goto TX_IQ_CAL_FAILED;
803 }
804 coeff.mag_coeff[i][im][ip] =
805 coeff.iqc_coeff[0] & 0x7f;
806 coeff.phs_coeff[i][im][ip] =
807 (coeff.iqc_coeff[0] >> 7) & 0x7f;
808
809 if (coeff.mag_coeff[i][im][ip] > 63)
810 coeff.mag_coeff[i][im][ip] -= 128;
811 if (coeff.phs_coeff[i][im][ip] > 63)
812 coeff.phs_coeff[i][im][ip] -= 128;
813
814 }
815 }
816 }
817
818 ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff);
819
820 return;
821
822TX_IQ_CAL_FAILED:
823 ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
824}
825
826static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
827{
828 u8 tx_gain_forced; 720 u8 tx_gain_forced;
829 721
830 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485,
831 AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT);
832 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,
833 AR_PHY_TXGAIN_FORCE); 723 AR_PHY_TXGAIN_FORCE);
834 if (tx_gain_forced) 724 if (tx_gain_forced)
835 REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, 725 REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN,
836 AR_PHY_TXGAIN_FORCE, 0); 726 AR_PHY_TXGAIN_FORCE, 0);
837 727
838 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, 728 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
839 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;
840} 739}
841 740
842static 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)
843{ 742{
844 struct ath_common *common = ath9k_hw_common(ah); 743 struct ath_common *common = ath9k_hw_common(ah);
845 const u32 txiqcal_status[AR9300_MAX_CHAINS] = { 744 const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
846 AR_PHY_TX_IQCAL_STATUS_B0_9485, 745 AR_PHY_TX_IQCAL_STATUS_B0,
847 AR_PHY_TX_IQCAL_STATUS_B1, 746 AR_PHY_TX_IQCAL_STATUS_B1,
848 AR_PHY_TX_IQCAL_STATUS_B2, 747 AR_PHY_TX_IQCAL_STATUS_B2,
849 }; 748 };
@@ -855,7 +754,7 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
855 struct coeff coeff; 754 struct coeff coeff;
856 s32 iq_res[6]; 755 s32 iq_res[6];
857 u8 num_chains = 0; 756 u8 num_chains = 0;
858 int i, ip, im, j; 757 int i, im, j;
859 int nmeasurement; 758 int nmeasurement;
860 759
861 for (i = 0; i < AR9300_MAX_CHAINS; i++) { 760 for (i = 0; i < AR9300_MAX_CHAINS; i++) {
@@ -863,71 +762,69 @@ static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah)
863 num_chains++; 762 num_chains++;
864 } 763 }
865 764
866 for (ip = 0; ip < MPASS; ip++) { 765 for (i = 0; i < num_chains; i++) {
867 for (i = 0; i < num_chains; i++) { 766 nmeasurement = REG_READ_FIELD(ah,
868 nmeasurement = REG_READ_FIELD(ah, 767 AR_PHY_TX_IQCAL_STATUS_B0,
869 AR_PHY_TX_IQCAL_STATUS_B0_9485, 768 AR_PHY_CALIBRATED_GAINS_0);
870 AR_PHY_CALIBRATED_GAINS_0); 769 if (nmeasurement > MAX_MEASUREMENT)
871 if (nmeasurement > MAX_MEASUREMENT) 770 nmeasurement = MAX_MEASUREMENT;
872 nmeasurement = MAX_MEASUREMENT;
873 771
874 for (im = 0; im < nmeasurement; im++) { 772 for (im = 0; im < nmeasurement; im++) {
875 ath_dbg(common, ATH_DBG_CALIBRATE, 773 ath_dbg(common, ATH_DBG_CALIBRATE,
876 "Doing Tx IQ Cal for chain %d.\n", i); 774 "Doing Tx IQ Cal for chain %d.\n", i);
877 775
878 if (REG_READ(ah, txiqcal_status[i]) & 776 if (REG_READ(ah, txiqcal_status[i]) &
879 AR_PHY_TX_IQCAL_STATUS_FAILED) { 777 AR_PHY_TX_IQCAL_STATUS_FAILED) {
880 ath_dbg(common, ATH_DBG_CALIBRATE, 778 ath_dbg(common, ATH_DBG_CALIBRATE,
881 "Tx IQ Cal failed for chain %d.\n", i); 779 "Tx IQ Cal failed for chain %d.\n", i);
882 goto tx_iqcal_fail; 780 goto tx_iqcal_fail;
883 } 781 }
884 782
885 for (j = 0; j < 3; j++) { 783 for (j = 0; j < 3; j++) {
886 u32 idx = 2 * j, offset = 4 * (3 * im + j); 784 u32 idx = 2 * j, offset = 4 * (3 * im + j);
887 785
888 REG_RMW_FIELD(ah, 786 REG_RMW_FIELD(ah,
889 AR_PHY_CHAN_INFO_MEMORY, 787 AR_PHY_CHAN_INFO_MEMORY,
890 AR_PHY_CHAN_INFO_TAB_S2_READ, 788 AR_PHY_CHAN_INFO_TAB_S2_READ,
891 0); 789 0);
892 790
893 /* 32 bits */ 791 /* 32 bits */
894 iq_res[idx] = REG_READ(ah, 792 iq_res[idx] = REG_READ(ah,
895 chan_info_tab[i] + 793 chan_info_tab[i] +
896 offset); 794 offset);
897 795
898 REG_RMW_FIELD(ah, 796 REG_RMW_FIELD(ah,
899 AR_PHY_CHAN_INFO_MEMORY, 797 AR_PHY_CHAN_INFO_MEMORY,
900 AR_PHY_CHAN_INFO_TAB_S2_READ, 798 AR_PHY_CHAN_INFO_TAB_S2_READ,
901 1); 799 1);
902 800
903 /* 16 bits */ 801 /* 16 bits */
904 iq_res[idx + 1] = 0xffff & REG_READ(ah, 802 iq_res[idx + 1] = 0xffff & REG_READ(ah,
905 chan_info_tab[i] + offset); 803 chan_info_tab[i] + offset);
906 804
907 ath_dbg(common, ATH_DBG_CALIBRATE, 805 ath_dbg(common, ATH_DBG_CALIBRATE,
908 "IQ RES[%d]=0x%x" 806 "IQ RES[%d]=0x%x"
909 "IQ_RES[%d]=0x%x\n", 807 "IQ_RES[%d]=0x%x\n",
910 idx, iq_res[idx], idx + 1, 808 idx, iq_res[idx], idx + 1,
911 iq_res[idx + 1]); 809 iq_res[idx + 1]);
912 } 810 }
913 811
914 if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, 812 if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
915 coeff.iqc_coeff)) { 813 coeff.iqc_coeff)) {
916 ath_dbg(common, ATH_DBG_CALIBRATE, 814 ath_dbg(common, ATH_DBG_CALIBRATE,
917 "Failed in calculation of IQ correction.\n"); 815 "Failed in calculation of \
918 goto tx_iqcal_fail; 816 IQ correction.\n");
919 } 817 goto tx_iqcal_fail;
818 }
920 819
921 coeff.mag_coeff[i][im][ip] = 820 coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
922 coeff.iqc_coeff[0] & 0x7f; 821 coeff.phs_coeff[i][im] =
923 coeff.phs_coeff[i][im][ip] = 822 (coeff.iqc_coeff[0] >> 7) & 0x7f;
924 (coeff.iqc_coeff[0] >> 7) & 0x7f;
925 823
926 if (coeff.mag_coeff[i][im][ip] > 63) 824 if (coeff.mag_coeff[i][im] > 63)
927 coeff.mag_coeff[i][im][ip] -= 128; 825 coeff.mag_coeff[i][im] -= 128;
928 if (coeff.phs_coeff[i][im][ip] > 63) 826 if (coeff.phs_coeff[i][im] > 63)
929 coeff.phs_coeff[i][im][ip] -= 128; 827 coeff.phs_coeff[i][im] -= 128;
930 }
931 } 828 }
932 } 829 }
933 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);
@@ -944,6 +841,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
944 struct ath_common *common = ath9k_hw_common(ah); 841 struct ath_common *common = ath9k_hw_common(ah);
945 struct ath9k_hw_capabilities *pCap = &ah->caps; 842 struct ath9k_hw_capabilities *pCap = &ah->caps;
946 int val; 843 int val;
844 bool txiqcal_done = false;
947 845
948 val = REG_READ(ah, AR_ENT_OTP); 846 val = REG_READ(ah, AR_ENT_OTP);
949 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);
@@ -956,14 +854,22 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
956 pCap->tx_chainmask); 854 pCap->tx_chainmask);
957 855
958 /* Do Tx IQ Calibration */ 856 /* Do Tx IQ Calibration */
959 if (AR_SREV_9485(ah)) 857 REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
960 ar9003_hw_tx_iq_cal_run(ah); 858 AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
961 else 859 DELPT);
962 ar9003_hw_tx_iq_cal(ah);
963 860
964 REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); 861 /*
965 udelay(5); 862 * For AR9485 or later chips, TxIQ cal runs as part of
966 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 }
967 873
968 /* Calibrate the AGC */ 874 /* Calibrate the AGC */
969 REG_WRITE(ah, AR_PHY_AGC_CONTROL, 875 REG_WRITE(ah, AR_PHY_AGC_CONTROL,
@@ -978,7 +884,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
978 return false; 884 return false;
979 } 885 }
980 886
981 if (AR_SREV_9485(ah)) 887 if (txiqcal_done)
982 ar9003_hw_tx_iq_cal_post_proc(ah); 888 ar9003_hw_tx_iq_cal_post_proc(ah);
983 889
984 /* Revert chainmasks to their original values before NF cal */ 890 /* Revert chainmasks to their original values before NF cal */