diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_phy.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_phy.c | 213 |
1 files changed, 24 insertions, 189 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 19bc05c4113..7c93338540a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -1015,213 +1015,38 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, | |||
1015 | return true; | 1015 | return true; |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | static void ar9003_hw_nf_sanitize_2g(struct ath_hw *ah, s16 *nf) | ||
1019 | { | ||
1020 | struct ath_common *common = ath9k_hw_common(ah); | ||
1021 | |||
1022 | if (*nf > ah->nf_2g_max) { | ||
1023 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1024 | "2 GHz NF (%d) > MAX (%d), " | ||
1025 | "correcting to MAX", | ||
1026 | *nf, ah->nf_2g_max); | ||
1027 | *nf = ah->nf_2g_max; | ||
1028 | } else if (*nf < ah->nf_2g_min) { | ||
1029 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1030 | "2 GHz NF (%d) < MIN (%d), " | ||
1031 | "correcting to MIN", | ||
1032 | *nf, ah->nf_2g_min); | ||
1033 | *nf = ah->nf_2g_min; | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1037 | static void ar9003_hw_nf_sanitize_5g(struct ath_hw *ah, s16 *nf) | ||
1038 | { | ||
1039 | struct ath_common *common = ath9k_hw_common(ah); | ||
1040 | |||
1041 | if (*nf > ah->nf_5g_max) { | ||
1042 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1043 | "5 GHz NF (%d) > MAX (%d), " | ||
1044 | "correcting to MAX", | ||
1045 | *nf, ah->nf_5g_max); | ||
1046 | *nf = ah->nf_5g_max; | ||
1047 | } else if (*nf < ah->nf_5g_min) { | ||
1048 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1049 | "5 GHz NF (%d) < MIN (%d), " | ||
1050 | "correcting to MIN", | ||
1051 | *nf, ah->nf_5g_min); | ||
1052 | *nf = ah->nf_5g_min; | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | static void ar9003_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) | ||
1057 | { | ||
1058 | if (IS_CHAN_2GHZ(ah->curchan)) | ||
1059 | ar9003_hw_nf_sanitize_2g(ah, nf); | ||
1060 | else | ||
1061 | ar9003_hw_nf_sanitize_5g(ah, nf); | ||
1062 | } | ||
1063 | |||
1064 | static void ar9003_hw_do_getnf(struct ath_hw *ah, | 1018 | static void ar9003_hw_do_getnf(struct ath_hw *ah, |
1065 | int16_t nfarray[NUM_NF_READINGS]) | 1019 | int16_t nfarray[NUM_NF_READINGS]) |
1066 | { | 1020 | { |
1067 | struct ath_common *common = ath9k_hw_common(ah); | ||
1068 | int16_t nf; | 1021 | int16_t nf; |
1069 | 1022 | ||
1070 | nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR); | 1023 | nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR); |
1071 | if (nf & 0x100) | 1024 | nfarray[0] = sign_extend(nf, 9); |
1072 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1073 | ar9003_hw_nf_sanitize(ah, &nf); | ||
1074 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1075 | "NF calibrated [ctl] [chain 0] is %d\n", nf); | ||
1076 | nfarray[0] = nf; | ||
1077 | 1025 | ||
1078 | nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR); | 1026 | nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR); |
1079 | if (nf & 0x100) | 1027 | nfarray[1] = sign_extend(nf, 9); |
1080 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1081 | ar9003_hw_nf_sanitize(ah, &nf); | ||
1082 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1083 | "NF calibrated [ctl] [chain 1] is %d\n", nf); | ||
1084 | nfarray[1] = nf; | ||
1085 | 1028 | ||
1086 | nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR); | 1029 | nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR); |
1087 | if (nf & 0x100) | 1030 | nfarray[2] = sign_extend(nf, 9); |
1088 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1089 | ar9003_hw_nf_sanitize(ah, &nf); | ||
1090 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1091 | "NF calibrated [ctl] [chain 2] is %d\n", nf); | ||
1092 | nfarray[2] = nf; | ||
1093 | 1031 | ||
1094 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); | 1032 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR); |
1095 | if (nf & 0x100) | 1033 | nfarray[3] = sign_extend(nf, 9); |
1096 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1097 | ar9003_hw_nf_sanitize(ah, &nf); | ||
1098 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1099 | "NF calibrated [ext] [chain 0] is %d\n", nf); | ||
1100 | nfarray[3] = nf; | ||
1101 | 1034 | ||
1102 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR); | 1035 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR); |
1103 | if (nf & 0x100) | 1036 | nfarray[4] = sign_extend(nf, 9); |
1104 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1105 | ar9003_hw_nf_sanitize(ah, &nf); | ||
1106 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1107 | "NF calibrated [ext] [chain 1] is %d\n", nf); | ||
1108 | nfarray[4] = nf; | ||
1109 | 1037 | ||
1110 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR); | 1038 | nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR); |
1111 | if (nf & 0x100) | 1039 | nfarray[5] = sign_extend(nf, 9); |
1112 | nf = 0 - ((nf ^ 0x1ff) + 1); | ||
1113 | ar9003_hw_nf_sanitize(ah, &nf); | ||
1114 | ath_print(common, ATH_DBG_CALIBRATE, | ||
1115 | "NF calibrated [ext] [chain 2] is %d\n", nf); | ||
1116 | nfarray[5] = nf; | ||
1117 | } | 1040 | } |
1118 | 1041 | ||
1119 | void ar9003_hw_set_nf_limits(struct ath_hw *ah) | 1042 | static void ar9003_hw_set_nf_limits(struct ath_hw *ah) |
1120 | { | 1043 | { |
1121 | ah->nf_2g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ; | 1044 | ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ; |
1122 | ah->nf_2g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ; | 1045 | ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ; |
1123 | ah->nf_5g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ; | 1046 | ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ; |
1124 | ah->nf_5g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ; | 1047 | ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ; |
1125 | } | 1048 | ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ; |
1126 | 1049 | ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ; | |
1127 | /* | ||
1128 | * Find out which of the RX chains are enabled | ||
1129 | */ | ||
1130 | static u32 ar9003_hw_get_rx_chainmask(struct ath_hw *ah) | ||
1131 | { | ||
1132 | u32 chain = REG_READ(ah, AR_PHY_RX_CHAINMASK); | ||
1133 | /* | ||
1134 | * The bits [2:0] indicate the rx chain mask and are to be | ||
1135 | * interpreted as follows: | ||
1136 | * 00x => Only chain 0 is enabled | ||
1137 | * 01x => Chain 1 and 0 enabled | ||
1138 | * 1xx => Chain 2,1 and 0 enabled | ||
1139 | */ | ||
1140 | return chain & 0x7; | ||
1141 | } | ||
1142 | |||
1143 | static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | ||
1144 | { | ||
1145 | struct ath9k_nfcal_hist *h; | ||
1146 | unsigned i, j; | ||
1147 | int32_t val; | ||
1148 | const u32 ar9300_cca_regs[6] = { | ||
1149 | AR_PHY_CCA_0, | ||
1150 | AR_PHY_CCA_1, | ||
1151 | AR_PHY_CCA_2, | ||
1152 | AR_PHY_EXT_CCA, | ||
1153 | AR_PHY_EXT_CCA_1, | ||
1154 | AR_PHY_EXT_CCA_2, | ||
1155 | }; | ||
1156 | u8 chainmask, rx_chain_status; | ||
1157 | struct ath_common *common = ath9k_hw_common(ah); | ||
1158 | |||
1159 | rx_chain_status = ar9003_hw_get_rx_chainmask(ah); | ||
1160 | |||
1161 | chainmask = 0x3F; | ||
1162 | h = ah->nfCalHist; | ||
1163 | |||
1164 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
1165 | if (chainmask & (1 << i)) { | ||
1166 | val = REG_READ(ah, ar9300_cca_regs[i]); | ||
1167 | val &= 0xFFFFFE00; | ||
1168 | val |= (((u32) (h[i].privNF) << 1) & 0x1ff); | ||
1169 | REG_WRITE(ah, ar9300_cca_regs[i], val); | ||
1170 | } | ||
1171 | } | ||
1172 | |||
1173 | /* | ||
1174 | * Load software filtered NF value into baseband internal minCCApwr | ||
1175 | * variable. | ||
1176 | */ | ||
1177 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
1178 | AR_PHY_AGC_CONTROL_ENABLE_NF); | ||
1179 | REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, | ||
1180 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); | ||
1181 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | ||
1182 | |||
1183 | /* | ||
1184 | * Wait for load to complete, should be fast, a few 10s of us. | ||
1185 | * The max delay was changed from an original 250us to 10000us | ||
1186 | * since 250us often results in NF load timeout and causes deaf | ||
1187 | * condition during stress testing 12/12/2009 | ||
1188 | */ | ||
1189 | for (j = 0; j < 1000; j++) { | ||
1190 | if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & | ||
1191 | AR_PHY_AGC_CONTROL_NF) == 0) | ||
1192 | break; | ||
1193 | udelay(10); | ||
1194 | } | ||
1195 | |||
1196 | /* | ||
1197 | * We timed out waiting for the noisefloor to load, probably due to an | ||
1198 | * in-progress rx. Simply return here and allow the load plenty of time | ||
1199 | * to complete before the next calibration interval. We need to avoid | ||
1200 | * trying to load -50 (which happens below) while the previous load is | ||
1201 | * still in progress as this can cause rx deafness. Instead by returning | ||
1202 | * here, the baseband nf cal will just be capped by our present | ||
1203 | * noisefloor until the next calibration timer. | ||
1204 | */ | ||
1205 | if (j == 1000) { | ||
1206 | ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf " | ||
1207 | "to load: AR_PHY_AGC_CONTROL=0x%x\n", | ||
1208 | REG_READ(ah, AR_PHY_AGC_CONTROL)); | ||
1209 | return; | ||
1210 | } | ||
1211 | |||
1212 | /* | ||
1213 | * Restore maxCCAPower register parameter again so that we're not capped | ||
1214 | * by the median we just loaded. This will be initial (and max) value | ||
1215 | * of next noise floor calibration the baseband does. | ||
1216 | */ | ||
1217 | for (i = 0; i < NUM_NF_READINGS; i++) { | ||
1218 | if (chainmask & (1 << i)) { | ||
1219 | val = REG_READ(ah, ar9300_cca_regs[i]); | ||
1220 | val &= 0xFFFFFE00; | ||
1221 | val |= (((u32) (-50) << 1) & 0x1ff); | ||
1222 | REG_WRITE(ah, ar9300_cca_regs[i], val); | ||
1223 | } | ||
1224 | } | ||
1225 | } | 1050 | } |
1226 | 1051 | ||
1227 | /* | 1052 | /* |
@@ -1291,6 +1116,14 @@ static void ar9003_hw_ani_cache_ini_regs(struct ath_hw *ah) | |||
1291 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1116 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
1292 | { | 1117 | { |
1293 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1118 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
1119 | const u32 ar9300_cca_regs[6] = { | ||
1120 | AR_PHY_CCA_0, | ||
1121 | AR_PHY_CCA_1, | ||
1122 | AR_PHY_CCA_2, | ||
1123 | AR_PHY_EXT_CCA, | ||
1124 | AR_PHY_EXT_CCA_1, | ||
1125 | AR_PHY_EXT_CCA_2, | ||
1126 | }; | ||
1294 | 1127 | ||
1295 | priv_ops->rf_set_freq = ar9003_hw_set_channel; | 1128 | priv_ops->rf_set_freq = ar9003_hw_set_channel; |
1296 | priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate; | 1129 | priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate; |
@@ -1307,8 +1140,10 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
1307 | priv_ops->set_diversity = ar9003_hw_set_diversity; | 1140 | priv_ops->set_diversity = ar9003_hw_set_diversity; |
1308 | priv_ops->ani_control = ar9003_hw_ani_control; | 1141 | priv_ops->ani_control = ar9003_hw_ani_control; |
1309 | priv_ops->do_getnf = ar9003_hw_do_getnf; | 1142 | priv_ops->do_getnf = ar9003_hw_do_getnf; |
1310 | priv_ops->loadnf = ar9003_hw_loadnf; | ||
1311 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; | 1143 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; |
1144 | |||
1145 | ar9003_hw_set_nf_limits(ah); | ||
1146 | memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); | ||
1312 | } | 1147 | } |
1313 | 1148 | ||
1314 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) | 1149 | void ar9003_hw_bb_watchdog_config(struct ath_hw *ah) |