diff options
author | Rajkumar Manoharan <rmanohar@qca.qualcomm.com> | 2011-10-13 01:30:41 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-10-14 14:48:22 -0400 |
commit | 324c74ad64c7528a9cf243455723d5ed57238e15 (patch) | |
tree | 1efd8d607d7908cf697f8e1fbe46d3b9921a466f | |
parent | 1aef40b82c48d028d92e811c7f7dc5a0dbf9fa9a (diff) |
ath9k_hw: Add radio retention support for AR9480
Supported calibrations of radio retention table (RTT) are
- DC offset
- Filter
- Peak detect
Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_calib.c | 115 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_phy.h | 20 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_rtt.c | 153 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_rtt.h | 28 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/reg.h | 1 |
8 files changed, 316 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 05a6fade7b1c..36ed3c46fec6 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -21,6 +21,7 @@ ath9k_hw-y:= \ | |||
21 | ar5008_phy.o \ | 21 | ar5008_phy.o \ |
22 | ar9002_calib.o \ | 22 | ar9002_calib.o \ |
23 | ar9003_calib.o \ | 23 | ar9003_calib.o \ |
24 | ar9003_rtt.o \ | ||
24 | calib.o \ | 25 | calib.o \ |
25 | eeprom.o \ | 26 | eeprom.o \ |
26 | eeprom_def.o \ | 27 | eeprom_def.o \ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 3506e7bd36eb..47f140ce00d2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "hw-ops.h" | 18 | #include "hw-ops.h" |
19 | #include "ar9003_phy.h" | 19 | #include "ar9003_phy.h" |
20 | #include "ar9003_rtt.h" | ||
20 | 21 | ||
21 | #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT | 22 | #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT |
22 | #define MAX_MAG_DELTA 11 | 23 | #define MAX_MAG_DELTA 11 |
@@ -900,25 +901,81 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah) | |||
900 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); | 901 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); |
901 | } | 902 | } |
902 | 903 | ||
904 | static bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) | ||
905 | { | ||
906 | struct ath9k_rtt_hist *hist; | ||
907 | u32 *table; | ||
908 | int i; | ||
909 | bool restore; | ||
910 | |||
911 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT) || !ah->caldata) | ||
912 | return false; | ||
913 | |||
914 | hist = &ah->caldata->rtt_hist; | ||
915 | ar9003_hw_rtt_enable(ah); | ||
916 | ar9003_hw_rtt_set_mask(ah, 0x10); | ||
917 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
918 | if (!(ah->rxchainmask & (1 << i))) | ||
919 | continue; | ||
920 | table = &hist->table[i][hist->num_readings][0]; | ||
921 | ar9003_hw_rtt_load_hist(ah, i, table); | ||
922 | } | ||
923 | restore = ar9003_hw_rtt_force_restore(ah); | ||
924 | ar9003_hw_rtt_disable(ah); | ||
925 | |||
926 | return restore; | ||
927 | } | ||
928 | |||
903 | static bool ar9003_hw_init_cal(struct ath_hw *ah, | 929 | static bool ar9003_hw_init_cal(struct ath_hw *ah, |
904 | struct ath9k_channel *chan) | 930 | struct ath9k_channel *chan) |
905 | { | 931 | { |
906 | struct ath_common *common = ath9k_hw_common(ah); | 932 | struct ath_common *common = ath9k_hw_common(ah); |
907 | struct ath9k_hw_cal_data *caldata = ah->caldata; | 933 | struct ath9k_hw_cal_data *caldata = ah->caldata; |
908 | bool txiqcal_done = false, txclcal_done = false; | 934 | bool txiqcal_done = false, txclcal_done = false; |
909 | bool is_reusable = true; | 935 | bool is_reusable = true, status = true; |
936 | bool run_rtt_cal = false, run_agc_cal; | ||
937 | bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT); | ||
938 | u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL | | ||
939 | AR_PHY_AGC_CONTROL_FLTR_CAL | | ||
940 | AR_PHY_AGC_CONTROL_PKDET_CAL; | ||
910 | int i, j; | 941 | int i, j; |
911 | u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0, | 942 | u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0, |
912 | AR_PHY_CL_TAB_1, | 943 | AR_PHY_CL_TAB_1, |
913 | AR_PHY_CL_TAB_2 }; | 944 | AR_PHY_CL_TAB_2 }; |
914 | 945 | ||
946 | if (rtt) { | ||
947 | if (!ar9003_hw_rtt_restore(ah, chan)) | ||
948 | run_rtt_cal = true; | ||
949 | |||
950 | ath_dbg(common, ATH_DBG_CALIBRATE, "RTT restore %s\n", | ||
951 | run_rtt_cal ? "failed" : "succeed"); | ||
952 | } | ||
953 | run_agc_cal = run_rtt_cal; | ||
954 | |||
955 | if (run_rtt_cal) { | ||
956 | ar9003_hw_rtt_enable(ah); | ||
957 | ar9003_hw_rtt_set_mask(ah, 0x00); | ||
958 | ar9003_hw_rtt_clear_hist(ah); | ||
959 | } | ||
960 | |||
961 | if (rtt && !run_rtt_cal) { | ||
962 | agc_ctrl = REG_READ(ah, AR_PHY_AGC_CONTROL); | ||
963 | agc_supp_cals &= agc_ctrl; | ||
964 | agc_ctrl &= ~(AR_PHY_AGC_CONTROL_OFFSET_CAL | | ||
965 | AR_PHY_AGC_CONTROL_FLTR_CAL | | ||
966 | AR_PHY_AGC_CONTROL_PKDET_CAL); | ||
967 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); | ||
968 | } | ||
969 | |||
915 | if (ah->enabled_cals & TX_CL_CAL) { | 970 | if (ah->enabled_cals & TX_CL_CAL) { |
916 | if (caldata && caldata->done_txclcal_once) | 971 | if (caldata && caldata->done_txclcal_once) |
917 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, | 972 | REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, |
918 | AR_PHY_CL_CAL_ENABLE); | 973 | AR_PHY_CL_CAL_ENABLE); |
919 | else | 974 | else { |
920 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, | 975 | REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, |
921 | AR_PHY_CL_CAL_ENABLE); | 976 | AR_PHY_CL_CAL_ENABLE); |
977 | run_agc_cal = true; | ||
978 | } | ||
922 | } | 979 | } |
923 | 980 | ||
924 | if (!(ah->enabled_cals & TX_IQ_CAL)) | 981 | if (!(ah->enabled_cals & TX_IQ_CAL)) |
@@ -940,25 +997,41 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
940 | else | 997 | else |
941 | REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, | 998 | REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0, |
942 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); | 999 | AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL); |
943 | txiqcal_done = true; | 1000 | txiqcal_done = run_agc_cal = true; |
944 | goto skip_tx_iqcal; | 1001 | goto skip_tx_iqcal; |
945 | } | 1002 | } else if (caldata && !caldata->done_txiqcal_once) |
1003 | run_agc_cal = true; | ||
1004 | |||
946 | txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); | 1005 | txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); |
947 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); | 1006 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); |
948 | udelay(5); | 1007 | udelay(5); |
949 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | 1008 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); |
950 | 1009 | ||
951 | skip_tx_iqcal: | 1010 | skip_tx_iqcal: |
952 | /* Calibrate the AGC */ | 1011 | |
953 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, | 1012 | if (run_agc_cal) { |
954 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | 1013 | /* Calibrate the AGC */ |
955 | AR_PHY_AGC_CONTROL_CAL); | 1014 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
956 | 1015 | REG_READ(ah, AR_PHY_AGC_CONTROL) | | |
957 | /* Poll for offset calibration complete */ | 1016 | AR_PHY_AGC_CONTROL_CAL); |
958 | if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, | 1017 | |
959 | 0, AH_WAIT_TIMEOUT)) { | 1018 | /* Poll for offset calibration complete */ |
1019 | status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, | ||
1020 | AR_PHY_AGC_CONTROL_CAL, | ||
1021 | 0, AH_WAIT_TIMEOUT); | ||
1022 | } | ||
1023 | if (rtt && !run_rtt_cal) { | ||
1024 | agc_ctrl |= agc_supp_cals; | ||
1025 | REG_WRITE(ah, AR_PHY_AGC_CONTROL, agc_ctrl); | ||
1026 | } | ||
1027 | |||
1028 | if (!status) { | ||
1029 | if (run_rtt_cal) | ||
1030 | ar9003_hw_rtt_disable(ah); | ||
1031 | |||
960 | ath_dbg(common, ATH_DBG_CALIBRATE, | 1032 | ath_dbg(common, ATH_DBG_CALIBRATE, |
961 | "offset calibration failed to complete in 1ms; noisy environment?\n"); | 1033 | "offset calibration failed to complete in 1ms;" |
1034 | "noisy environment?\n"); | ||
962 | return false; | 1035 | return false; |
963 | } | 1036 | } |
964 | 1037 | ||
@@ -993,6 +1066,22 @@ skip_tx_iqcal: | |||
993 | } | 1066 | } |
994 | #undef CL_TAB_ENTRY | 1067 | #undef CL_TAB_ENTRY |
995 | 1068 | ||
1069 | if (run_rtt_cal && caldata) { | ||
1070 | struct ath9k_rtt_hist *hist = &caldata->rtt_hist; | ||
1071 | if (is_reusable && (hist->num_readings < RTT_HIST_MAX)) { | ||
1072 | u32 *table; | ||
1073 | |||
1074 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
1075 | if (!(ah->rxchainmask & (1 << i))) | ||
1076 | continue; | ||
1077 | table = &hist->table[i][hist->num_readings][0]; | ||
1078 | ar9003_hw_rtt_fill_hist(ah, i, table); | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | ar9003_hw_rtt_disable(ah); | ||
1083 | } | ||
1084 | |||
996 | ath9k_hw_loadnf(ah, chan); | 1085 | ath9k_hw_loadnf(ah, chan); |
997 | ath9k_hw_start_nfcal(ah, true); | 1086 | ath9k_hw_start_nfcal(ah, true); |
998 | 1087 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 64e9bea93721..9fe6fbeb66d0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -584,8 +584,6 @@ | |||
584 | (AR_SREV_9485(ah) ? \ | 584 | (AR_SREV_9485(ah) ? \ |
585 | 0x3d0 : 0x450) + ((_i) << 2)) | 585 | 0x3d0 : 0x450) + ((_i) << 2)) |
586 | #define AR_PHY_RTT_CTRL (AR_SM_BASE + 0x380) | 586 | #define AR_PHY_RTT_CTRL (AR_SM_BASE + 0x380) |
587 | #define AR_PHY_RTT_TABLE_SW_INTF_B (AR_SM_BASE + 0x384) | ||
588 | #define AR_PHY_RTT_TABLE_SW_INTF_1_B0 (AR_SM_BASE + 0x388) | ||
589 | 587 | ||
590 | #define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0) | 588 | #define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0) |
591 | #define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4) | 589 | #define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4) |
@@ -825,6 +823,20 @@ | |||
825 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 | 823 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 |
826 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 | 824 | #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 |
827 | #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 | 825 | #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 |
826 | #define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION 0x00000001 | ||
827 | #define AR_PHY_RTT_CTRL_ENA_RADIO_RETENTION_S 0 | ||
828 | #define AR_PHY_RTT_CTRL_RESTORE_MASK 0x0000007E | ||
829 | #define AR_PHY_RTT_CTRL_RESTORE_MASK_S 1 | ||
830 | #define AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE 0x00000080 | ||
831 | #define AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE_S 7 | ||
832 | #define AR_PHY_RTT_SW_RTT_TABLE_ACCESS 0x00000001 | ||
833 | #define AR_PHY_RTT_SW_RTT_TABLE_ACCESS_S 0 | ||
834 | #define AR_PHY_RTT_SW_RTT_TABLE_WRITE 0x00000002 | ||
835 | #define AR_PHY_RTT_SW_RTT_TABLE_WRITE_S 1 | ||
836 | #define AR_PHY_RTT_SW_RTT_TABLE_ADDR 0x0000001C | ||
837 | #define AR_PHY_RTT_SW_RTT_TABLE_ADDR_S 2 | ||
838 | #define AR_PHY_RTT_SW_RTT_TABLE_DATA 0xFFFFFFF0 | ||
839 | #define AR_PHY_RTT_SW_RTT_TABLE_DATA_S 4 | ||
828 | #define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL 0x80000000 | 840 | #define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL 0x80000000 |
829 | #define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL_S 31 | 841 | #define AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL_S 31 |
830 | #define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 | 842 | #define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 |
@@ -919,6 +931,10 @@ | |||
919 | #define AR_PHY_AIC_SRAM_ADDR_B1 (AR_SM1_BASE + 0x5f0) | 931 | #define AR_PHY_AIC_SRAM_ADDR_B1 (AR_SM1_BASE + 0x5f0) |
920 | #define AR_PHY_AIC_SRAM_DATA_B1 (AR_SM1_BASE + 0x5f4) | 932 | #define AR_PHY_AIC_SRAM_DATA_B1 (AR_SM1_BASE + 0x5f4) |
921 | 933 | ||
934 | #define AR_PHY_RTT_TABLE_SW_INTF_B(i) (0x384 + (i) ? \ | ||
935 | AR_SM1_BASE : AR_SM_BASE) | ||
936 | #define AR_PHY_RTT_TABLE_SW_INTF_1_B(i) (0x388 + (i) ? \ | ||
937 | AR_SM1_BASE : AR_SM_BASE) | ||
922 | /* | 938 | /* |
923 | * Channel 2 Register Map | 939 | * Channel 2 Register Map |
924 | */ | 940 | */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c new file mode 100644 index 000000000000..48803ee9c0d6 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include "hw.h" | ||
18 | #include "ar9003_phy.h" | ||
19 | |||
20 | #define RTT_RESTORE_TIMEOUT 1000 | ||
21 | #define RTT_ACCESS_TIMEOUT 100 | ||
22 | #define RTT_BAD_VALUE 0x0bad0bad | ||
23 | |||
24 | /* | ||
25 | * RTT (Radio Retention Table) hardware implementation information | ||
26 | * | ||
27 | * There is an internal table (i.e. the rtt) for each chain (or bank). | ||
28 | * Each table contains 6 entries and each entry is corresponding to | ||
29 | * a specific calibration parameter as depicted below. | ||
30 | * 0~2 - DC offset DAC calibration: loop, low, high (offsetI/Q_...) | ||
31 | * 3 - Filter cal (filterfc) | ||
32 | * 4 - RX gain settings | ||
33 | * 5 - Peak detector offset calibration (agc_caldac) | ||
34 | */ | ||
35 | |||
36 | void ar9003_hw_rtt_enable(struct ath_hw *ah) | ||
37 | { | ||
38 | REG_WRITE(ah, AR_PHY_RTT_CTRL, 1); | ||
39 | } | ||
40 | |||
41 | void ar9003_hw_rtt_disable(struct ath_hw *ah) | ||
42 | { | ||
43 | REG_WRITE(ah, AR_PHY_RTT_CTRL, 0); | ||
44 | } | ||
45 | |||
46 | void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask) | ||
47 | { | ||
48 | REG_RMW_FIELD(ah, AR_PHY_RTT_CTRL, | ||
49 | AR_PHY_RTT_CTRL_RESTORE_MASK, rtt_mask); | ||
50 | } | ||
51 | |||
52 | bool ar9003_hw_rtt_force_restore(struct ath_hw *ah) | ||
53 | { | ||
54 | if (!ath9k_hw_wait(ah, AR_PHY_RTT_CTRL, | ||
55 | AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE, | ||
56 | 0, RTT_RESTORE_TIMEOUT)) | ||
57 | return false; | ||
58 | |||
59 | REG_RMW_FIELD(ah, AR_PHY_RTT_CTRL, | ||
60 | AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE, 1); | ||
61 | |||
62 | if (!ath9k_hw_wait(ah, AR_PHY_RTT_CTRL, | ||
63 | AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE, | ||
64 | 0, RTT_RESTORE_TIMEOUT)) | ||
65 | return false; | ||
66 | |||
67 | return true; | ||
68 | } | ||
69 | |||
70 | static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain, | ||
71 | u32 index, u32 data28) | ||
72 | { | ||
73 | u32 val; | ||
74 | |||
75 | val = SM(data28, AR_PHY_RTT_SW_RTT_TABLE_DATA); | ||
76 | REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain), val); | ||
77 | |||
78 | val = SM(0, AR_PHY_RTT_SW_RTT_TABLE_ACCESS) | | ||
79 | SM(1, AR_PHY_RTT_SW_RTT_TABLE_WRITE) | | ||
80 | SM(index, AR_PHY_RTT_SW_RTT_TABLE_ADDR); | ||
81 | REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); | ||
82 | udelay(1); | ||
83 | |||
84 | val |= SM(1, AR_PHY_RTT_SW_RTT_TABLE_ACCESS); | ||
85 | REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); | ||
86 | udelay(1); | ||
87 | |||
88 | if (!ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), | ||
89 | AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0, | ||
90 | RTT_ACCESS_TIMEOUT)) | ||
91 | return; | ||
92 | |||
93 | val &= ~SM(1, AR_PHY_RTT_SW_RTT_TABLE_WRITE); | ||
94 | REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); | ||
95 | udelay(1); | ||
96 | |||
97 | ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), | ||
98 | AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0, | ||
99 | RTT_ACCESS_TIMEOUT); | ||
100 | } | ||
101 | |||
102 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table) | ||
103 | { | ||
104 | int i; | ||
105 | |||
106 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) | ||
107 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, table[i]); | ||
108 | } | ||
109 | |||
110 | static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) | ||
111 | { | ||
112 | u32 val; | ||
113 | |||
114 | val = SM(0, AR_PHY_RTT_SW_RTT_TABLE_ACCESS) | | ||
115 | SM(0, AR_PHY_RTT_SW_RTT_TABLE_WRITE) | | ||
116 | SM(index, AR_PHY_RTT_SW_RTT_TABLE_ADDR); | ||
117 | |||
118 | REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); | ||
119 | udelay(1); | ||
120 | |||
121 | val |= SM(1, AR_PHY_RTT_SW_RTT_TABLE_ACCESS); | ||
122 | REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); | ||
123 | udelay(1); | ||
124 | |||
125 | if (!ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), | ||
126 | AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0, | ||
127 | RTT_ACCESS_TIMEOUT)) | ||
128 | return RTT_BAD_VALUE; | ||
129 | |||
130 | val = REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain)); | ||
131 | |||
132 | return val; | ||
133 | } | ||
134 | |||
135 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table) | ||
136 | { | ||
137 | int i; | ||
138 | |||
139 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) | ||
140 | table[i] = ar9003_hw_rtt_fill_hist_entry(ah, chain, i); | ||
141 | } | ||
142 | |||
143 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) | ||
144 | { | ||
145 | int i, j; | ||
146 | |||
147 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
148 | if (!(ah->rxchainmask & (1 << i))) | ||
149 | continue; | ||
150 | for (j = 0; j < MAX_RTT_TABLE_ENTRY; j++) | ||
151 | ar9003_hw_rtt_load_hist_entry(ah, i, j, 0); | ||
152 | } | ||
153 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h new file mode 100644 index 000000000000..030758d087d6 --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef AR9003_RTT_H | ||
18 | #define AR9003_RTT_H | ||
19 | |||
20 | void ar9003_hw_rtt_enable(struct ath_hw *ah); | ||
21 | void ar9003_hw_rtt_disable(struct ath_hw *ah); | ||
22 | void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask); | ||
23 | bool ar9003_hw_rtt_force_restore(struct ath_hw *ah); | ||
24 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table); | ||
25 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table); | ||
26 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah); | ||
27 | |||
28 | #endif | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index e6b0d6883ac5..0eb0b3bcb74e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1709,6 +1709,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1709 | if (caldata) { | 1709 | if (caldata) { |
1710 | caldata->done_txiqcal_once = false; | 1710 | caldata->done_txiqcal_once = false; |
1711 | caldata->done_txclcal_once = false; | 1711 | caldata->done_txclcal_once = false; |
1712 | caldata->rtt_hist.num_readings = 0; | ||
1712 | } | 1713 | } |
1713 | if (!ath9k_hw_init_cal(ah, chan)) | 1714 | if (!ath9k_hw_init_cal(ah, chan)) |
1714 | return -EIO; | 1715 | return -EIO; |
@@ -2319,6 +2320,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2319 | if (!AR_SREV_9330(ah)) | 2320 | if (!AR_SREV_9330(ah)) |
2320 | ah->enabled_cals |= TX_IQ_ON_AGC_CAL; | 2321 | ah->enabled_cals |= TX_IQ_ON_AGC_CAL; |
2321 | } | 2322 | } |
2323 | if (AR_SREV_9480(ah)) | ||
2324 | pCap->hw_caps |= ATH9K_HW_CAP_RTT; | ||
2325 | |||
2322 | return 0; | 2326 | return 0; |
2323 | } | 2327 | } |
2324 | 2328 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 75982a7ebcc0..0f6fc25bfb1f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -202,6 +202,7 @@ enum ath9k_hw_caps { | |||
202 | ATH9K_HW_CAP_2GHZ = BIT(13), | 202 | ATH9K_HW_CAP_2GHZ = BIT(13), |
203 | ATH9K_HW_CAP_5GHZ = BIT(14), | 203 | ATH9K_HW_CAP_5GHZ = BIT(14), |
204 | ATH9K_HW_CAP_APM = BIT(15), | 204 | ATH9K_HW_CAP_APM = BIT(15), |
205 | ATH9K_HW_CAP_RTT = BIT(16), | ||
205 | }; | 206 | }; |
206 | 207 | ||
207 | struct ath9k_hw_capabilities { | 208 | struct ath9k_hw_capabilities { |
@@ -337,6 +338,13 @@ enum ath9k_int { | |||
337 | CHANNEL_HT40PLUS | \ | 338 | CHANNEL_HT40PLUS | \ |
338 | CHANNEL_HT40MINUS) | 339 | CHANNEL_HT40MINUS) |
339 | 340 | ||
341 | #define MAX_RTT_TABLE_ENTRY 6 | ||
342 | #define RTT_HIST_MAX 3 | ||
343 | struct ath9k_rtt_hist { | ||
344 | u32 table[AR9300_MAX_CHAINS][RTT_HIST_MAX][MAX_RTT_TABLE_ENTRY]; | ||
345 | u8 num_readings; | ||
346 | }; | ||
347 | |||
340 | #define MAX_IQCAL_MEASUREMENT 8 | 348 | #define MAX_IQCAL_MEASUREMENT 8 |
341 | #define MAX_CL_TAB_ENTRY 16 | 349 | #define MAX_CL_TAB_ENTRY 16 |
342 | 350 | ||
@@ -357,6 +365,7 @@ struct ath9k_hw_cal_data { | |||
357 | int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS]; | 365 | int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS]; |
358 | u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY]; | 366 | u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY]; |
359 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | 367 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |
368 | struct ath9k_rtt_hist rtt_hist; | ||
360 | }; | 369 | }; |
361 | 370 | ||
362 | struct ath9k_channel { | 371 | struct ath9k_channel { |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index b76c49d9c503..87a1245a68e0 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -1933,6 +1933,7 @@ enum { | |||
1933 | #define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* don't update noise floor automatically */ | 1933 | #define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* don't update noise floor automatically */ |
1934 | #define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS 0x00040000 /* extend noise floor power measurement */ | 1934 | #define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS 0x00040000 /* extend noise floor power measurement */ |
1935 | #define AR_PHY_AGC_CONTROL_CLC_SUCCESS 0x00080000 /* carrier leak calibration done */ | 1935 | #define AR_PHY_AGC_CONTROL_CLC_SUCCESS 0x00080000 /* carrier leak calibration done */ |
1936 | #define AR_PHY_AGC_CONTROL_PKDET_CAL 0x00100000 | ||
1936 | #define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0 | 1937 | #define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0 |
1937 | #define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6 | 1938 | #define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6 |
1938 | 1939 | ||