diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2010-04-15 17:39:11 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-16 15:43:35 -0400 |
commit | df23acaa5d3239745805650e2f27a4252182c063 (patch) | |
tree | 045e59bc9d7bd70ddbf4e2b9c0f8e623157a5f41 /drivers/net/wireless/ath/ath9k/ar9003_phy.c | |
parent | 4b01931e3a3ca5ec49604e2b279b8b9dd42fbe4c (diff) |
ath9k_hw: complete AR9003 calibration
This goes with some new shiny TX IQ calibration that AR9003
hardware family supports.
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_phy.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_phy.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 67b3b651843..fee07fd7a59 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -814,6 +814,105 @@ void ar9003_hw_set_nf_limits(struct ath_hw *ah) | |||
814 | ah->nf_5g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ; | 814 | ah->nf_5g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ; |
815 | } | 815 | } |
816 | 816 | ||
817 | /* | ||
818 | * Find out which of the RX chains are enabled | ||
819 | */ | ||
820 | static u32 ar9003_hw_get_rx_chainmask(struct ath_hw *ah) | ||
821 | { | ||
822 | u32 chain = REG_READ(ah, AR_PHY_RX_CHAINMASK); | ||
823 | /* | ||
824 | * The bits [2:0] indicate the rx chain mask and are to be | ||
825 | * interpreted as follows: | ||
826 | * 00x => Only chain 0 is enabled | ||
827 | * 01x => Chain 1 and 0 enabled | ||
828 | * 1xx => Chain 2,1 and 0 enabled | ||
829 | */ | ||
830 | return chain & 0x7; | ||
831 | } | ||
832 | |||
833 | static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | ||
834 | { | ||
835 | struct ath9k_nfcal_hist *h; | ||
836 | unsigned i, j; | ||
837 | int32_t val; | ||
838 | const u32 ar9300_cca_regs[6] = { | ||
839 | AR_PHY_CCA_0, | ||
840 | AR_PHY_CCA_1, | ||
841 | AR_PHY_CCA_2, | ||
842 | AR_PHY_EXT_CCA, | ||
843 | AR_PHY_EXT_CCA_1, | ||
844 | AR_PHY_EXT_CCA_2, | ||
845 | }; | ||
846 | u8 chainmask, rx_chain_status; | ||
847 | struct ath_common *common = ath9k_hw_common(ah); | ||
848 | |||
849 | rx_chain_status = ar9003_hw_get_rx_chainmask(ah); | ||
850 | |||
851 | chainmask = 0x3F; | ||
852 | h = ah->nfCalHist; | ||
853 | |||
854 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
855 | if (chainmask & (1 << i)) { | ||
856 | val = REG_READ(ah, ar9300_cca_regs[i]); | ||
857 | val &= 0xFFFFFE00; | ||
858 | val |= (((u32) (h[i].privNF) << 1) & 0x1ff); | ||
859 | REG_WRITE(ah, ar9300_cca_regs[i], val); | ||
860 | } | ||
861 | } | ||
862 | |||
863 | /* | ||
864 | * Load software filtered NF value into baseband internal minCCApwr | ||
865 | * variable. | ||
866 | */ | ||
867 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
868 | AR_PHY_AGC_CONTROL_ENABLE_NF); | ||
869 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
870 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | ||
871 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | ||
872 | |||
873 | /* | ||
874 | * Wait for load to complete, should be fast, a few 10s of us. | ||
875 | * The max delay was changed from an original 250us to 10000us | ||
876 | * since 250us often results in NF load timeout and causes deaf | ||
877 | * condition during stress testing 12/12/2009 | ||
878 | */ | ||
879 | for (j = 0; j < 1000; j++) { | ||
880 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & | ||
881 | AR_PHY_AGC_CONTROL_NF) == 0) | ||
882 | break; | ||
883 | udelay(10); | ||
884 | } | ||
885 | |||
886 | /* | ||
887 | * We timed out waiting for the noisefloor to load, probably due to an | ||
888 | * in-progress rx. Simply return here and allow the load plenty of time | ||
889 | * to complete before the next calibration interval. We need to avoid | ||
890 | * trying to load -50 (which happens below) while the previous load is | ||
891 | * still in progress as this can cause rx deafness. Instead by returning | ||
892 | * here, the baseband nf cal will just be capped by our present | ||
893 | * noisefloor until the next calibration timer. | ||
894 | */ | ||
895 | if (j == 1000) { | ||
896 | ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf " | ||
897 | "to load: AR_PHY_AGC_CONTROL=0x%x\n", | ||
898 | REG_READ(ah, AR_PHY_AGC_CONTROL)); | ||
899 | } | ||
900 | |||
901 | /* | ||
902 | * Restore maxCCAPower register parameter again so that we're not capped | ||
903 | * by the median we just loaded. This will be initial (and max) value | ||
904 | * of next noise floor calibration the baseband does. | ||
905 | */ | ||
906 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
907 | if (chainmask & (1 << i)) { | ||
908 | val = REG_READ(ah, ar9300_cca_regs[i]); | ||
909 | val &= 0xFFFFFE00; | ||
910 | val |= (((u32) (-50) << 1) & 0x1ff); | ||
911 | REG_WRITE(ah, ar9300_cca_regs[i], val); | ||
912 | } | ||
913 | } | ||
914 | } | ||
915 | |||
817 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 916 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
818 | { | 917 | { |
819 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 918 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
@@ -833,4 +932,5 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
833 | priv_ops->set_diversity = ar9003_hw_set_diversity; | 932 | priv_ops->set_diversity = ar9003_hw_set_diversity; |
834 | priv_ops->ani_control = ar9003_hw_ani_control; | 933 | priv_ops->ani_control = ar9003_hw_ani_control; |
835 | priv_ops->do_getnf = ar9003_hw_do_getnf; | 934 | priv_ops->do_getnf = ar9003_hw_do_getnf; |
935 | priv_ops->loadnf = ar9003_hw_loadnf; | ||
836 | } | 936 | } |