diff options
author | Nick Kossifidis <mickflemm@gmail.com> | 2010-11-23 13:36:45 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-30 13:52:29 -0500 |
commit | 9320b5c4a7260d9593102f378201d17e3f030739 (patch) | |
tree | d4a85a6286b47f86a66a82ad3e756f5117af2b39 /drivers/net | |
parent | ea066d5a91f2610116dcd27054f749e4f07799d8 (diff) |
ath5k: Reset cleanup and generic cleanup
* No functional changes
* Clean up reset:
Introduce init functions for each unit and call them instead
of having everything inside ath5k_hw_reset (it's just c/p for
now so nothing changes except calling order -I tested it with
various cards and it's ok-)
* Further cleanups:
ofdm_timings belongs to phy.c
rate_duration belongs to pcu.c
clock functions are general and belong to reset.c (more to follow)
* Reorder functions for better organization:
We start with helpers and other functions follow in categories,
init functions are last
Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ani.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/ath5k.h | 60 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/desc.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/dma.c | 45 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/eeprom.c | 147 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/pcu.c | 438 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/phy.c | 444 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/qcu.c | 130 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 642 |
9 files changed, 1042 insertions, 894 deletions
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index 6b75b22a929..f915f404302 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -58,19 +58,19 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level) | |||
58 | { | 58 | { |
59 | /* TODO: | 59 | /* TODO: |
60 | * ANI documents suggest the following five levels to use, but the HAL | 60 | * ANI documents suggest the following five levels to use, but the HAL |
61 | * and ath9k use only use the last two levels, making this | 61 | * and ath9k use only the last two levels, making this |
62 | * essentially an on/off option. There *may* be a reason for this (???), | 62 | * essentially an on/off option. There *may* be a reason for this (???), |
63 | * so i stick with the HAL version for now... | 63 | * so i stick with the HAL version for now... |
64 | */ | 64 | */ |
65 | #if 0 | 65 | #if 0 |
66 | static const s8 hi[] = { -18, -18, -16, -14, -12 }; | ||
67 | static const s8 lo[] = { -52, -56, -60, -64, -70 }; | 66 | static const s8 lo[] = { -52, -56, -60, -64, -70 }; |
67 | static const s8 hi[] = { -18, -18, -16, -14, -12 }; | ||
68 | static const s8 sz[] = { -34, -41, -48, -55, -62 }; | 68 | static const s8 sz[] = { -34, -41, -48, -55, -62 }; |
69 | static const s8 fr[] = { -70, -72, -75, -78, -80 }; | 69 | static const s8 fr[] = { -70, -72, -75, -78, -80 }; |
70 | #else | 70 | #else |
71 | static const s8 sz[] = { -55, -62 }; | ||
72 | static const s8 lo[] = { -64, -70 }; | 71 | static const s8 lo[] = { -64, -70 }; |
73 | static const s8 hi[] = { -14, -12 }; | 72 | static const s8 hi[] = { -14, -12 }; |
73 | static const s8 sz[] = { -55, -62 }; | ||
74 | static const s8 fr[] = { -78, -80 }; | 74 | static const s8 fr[] = { -78, -80 }; |
75 | #endif | 75 | #endif |
76 | if (level < 0 || level >= ARRAY_SIZE(sz)) { | 76 | if (level < 0 || level >= ARRAY_SIZE(sz)) { |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 2718136e488..85ff822c81f 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -1140,12 +1140,14 @@ void ath5k_hw_detach(struct ath5k_hw *ah); | |||
1140 | int ath5k_sysfs_register(struct ath5k_softc *sc); | 1140 | int ath5k_sysfs_register(struct ath5k_softc *sc); |
1141 | void ath5k_sysfs_unregister(struct ath5k_softc *sc); | 1141 | void ath5k_sysfs_unregister(struct ath5k_softc *sc); |
1142 | 1142 | ||
1143 | |||
1143 | /* LED functions */ | 1144 | /* LED functions */ |
1144 | int ath5k_init_leds(struct ath5k_softc *sc); | 1145 | int ath5k_init_leds(struct ath5k_softc *sc); |
1145 | void ath5k_led_enable(struct ath5k_softc *sc); | 1146 | void ath5k_led_enable(struct ath5k_softc *sc); |
1146 | void ath5k_led_off(struct ath5k_softc *sc); | 1147 | void ath5k_led_off(struct ath5k_softc *sc); |
1147 | void ath5k_unregister_leds(struct ath5k_softc *sc); | 1148 | void ath5k_unregister_leds(struct ath5k_softc *sc); |
1148 | 1149 | ||
1150 | |||
1149 | /* Reset Functions */ | 1151 | /* Reset Functions */ |
1150 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); | 1152 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); |
1151 | int ath5k_hw_on_hold(struct ath5k_hw *ah); | 1153 | int ath5k_hw_on_hold(struct ath5k_hw *ah); |
@@ -1155,6 +1157,13 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | |||
1155 | bool is_set); | 1157 | bool is_set); |
1156 | /* Power management functions */ | 1158 | /* Power management functions */ |
1157 | 1159 | ||
1160 | |||
1161 | /* Clock rate related functions */ | ||
1162 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | ||
1163 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | ||
1164 | void ath5k_hw_set_clockrate(struct ath5k_hw *ah); | ||
1165 | |||
1166 | |||
1158 | /* DMA Related Functions */ | 1167 | /* DMA Related Functions */ |
1159 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); | 1168 | void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); |
1160 | int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); | 1169 | int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); |
@@ -1171,26 +1180,28 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); | |||
1171 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); | 1180 | int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); |
1172 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); | 1181 | enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask); |
1173 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); | 1182 | void ath5k_hw_update_mib_counters(struct ath5k_hw *ah); |
1183 | /* Init function */ | ||
1184 | void ath5k_hw_dma_init(struct ath5k_hw *ah); | ||
1174 | 1185 | ||
1175 | /* EEPROM access functions */ | 1186 | /* EEPROM access functions */ |
1176 | int ath5k_eeprom_init(struct ath5k_hw *ah); | 1187 | int ath5k_eeprom_init(struct ath5k_hw *ah); |
1177 | void ath5k_eeprom_detach(struct ath5k_hw *ah); | 1188 | void ath5k_eeprom_detach(struct ath5k_hw *ah); |
1178 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); | 1189 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); |
1179 | 1190 | ||
1191 | |||
1180 | /* Protocol Control Unit Functions */ | 1192 | /* Protocol Control Unit Functions */ |
1181 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); | 1193 | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); |
1182 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); | 1194 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); |
1183 | /* BSSID Functions */ | 1195 | /* RX filter control*/ |
1184 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1196 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1185 | void ath5k_hw_set_bssid(struct ath5k_hw *ah); | 1197 | void ath5k_hw_set_bssid(struct ath5k_hw *ah); |
1186 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | 1198 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
1187 | /* Receive start/stop functions */ | ||
1188 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | ||
1189 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | ||
1190 | /* RX Filter functions */ | ||
1191 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); | 1199 | void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); |
1192 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); | 1200 | u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); |
1193 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); | 1201 | void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); |
1202 | /* Receive (DRU) start/stop functions */ | ||
1203 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | ||
1204 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); | ||
1194 | /* Beacon control functions */ | 1205 | /* Beacon control functions */ |
1195 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); | 1206 | u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); |
1196 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); | 1207 | void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); |
@@ -1199,10 +1210,9 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); | |||
1199 | bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); | 1210 | bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); |
1200 | /* ACK bit rate */ | 1211 | /* ACK bit rate */ |
1201 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); | 1212 | void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); |
1202 | /* Clock rate related functions */ | 1213 | /* Init function */ |
1203 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); | 1214 | void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
1204 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); | 1215 | u8 mode); |
1205 | void ath5k_hw_set_clockrate(struct ath5k_hw *ah); | ||
1206 | 1216 | ||
1207 | /* Queue Control Unit, DFS Control Unit Functions */ | 1217 | /* Queue Control Unit, DFS Control Unit Functions */ |
1208 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | 1218 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, |
@@ -1216,6 +1226,8 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); | |||
1216 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1226 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1217 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); | 1227 | int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); |
1218 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); | 1228 | int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); |
1229 | /* Init function */ | ||
1230 | int ath5k_hw_init_queues(struct ath5k_hw *ah); | ||
1219 | 1231 | ||
1220 | /* Hardware Descriptor Functions */ | 1232 | /* Hardware Descriptor Functions */ |
1221 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); | 1233 | int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); |
@@ -1225,6 +1237,7 @@ int ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
1225 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | 1237 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, |
1226 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3); | 1238 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3); |
1227 | 1239 | ||
1240 | |||
1228 | /* GPIO Functions */ | 1241 | /* GPIO Functions */ |
1229 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); | 1242 | void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); |
1230 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); | 1243 | int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); |
@@ -1234,11 +1247,13 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); | |||
1234 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, | 1247 | void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, |
1235 | u32 interrupt_level); | 1248 | u32 interrupt_level); |
1236 | 1249 | ||
1237 | /* rfkill Functions */ | 1250 | |
1251 | /* RFkill Functions */ | ||
1238 | void ath5k_rfkill_hw_start(struct ath5k_hw *ah); | 1252 | void ath5k_rfkill_hw_start(struct ath5k_hw *ah); |
1239 | void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); | 1253 | void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); |
1240 | 1254 | ||
1241 | /* Misc functions */ | 1255 | |
1256 | /* Misc functions TODO: Cleanup */ | ||
1242 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah); | 1257 | int ath5k_hw_set_capabilities(struct ath5k_hw *ah); |
1243 | int ath5k_hw_get_capability(struct ath5k_hw *ah, | 1258 | int ath5k_hw_get_capability(struct ath5k_hw *ah, |
1244 | enum ath5k_capability_type cap_type, u32 capability, | 1259 | enum ath5k_capability_type cap_type, u32 capability, |
@@ -1246,19 +1261,20 @@ int ath5k_hw_get_capability(struct ath5k_hw *ah, | |||
1246 | int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); | 1261 | int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); |
1247 | int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); | 1262 | int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); |
1248 | 1263 | ||
1264 | |||
1249 | /* Initial register settings functions */ | 1265 | /* Initial register settings functions */ |
1250 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); | 1266 | int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); |
1251 | 1267 | ||
1252 | /* Initialize RF */ | 1268 | |
1253 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, | 1269 | /* PHY functions */ |
1254 | struct ieee80211_channel *channel, | 1270 | /* Misc PHY functions */ |
1255 | unsigned int mode); | 1271 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); |
1256 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); | 1272 | int ath5k_hw_phy_disable(struct ath5k_hw *ah); |
1273 | /* Gain_F optimization */ | ||
1257 | enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); | 1274 | enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); |
1258 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); | 1275 | int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); |
1259 | /* PHY/RF channel functions */ | 1276 | /* PHY/RF channel functions */ |
1260 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); | 1277 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); |
1261 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); | ||
1262 | /* PHY calibration */ | 1278 | /* PHY calibration */ |
1263 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); | 1279 | void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); |
1264 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | 1280 | int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, |
@@ -1267,18 +1283,14 @@ void ath5k_hw_update_noise_floor(struct ath5k_hw *ah); | |||
1267 | /* Spur mitigation */ | 1283 | /* Spur mitigation */ |
1268 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1284 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, |
1269 | struct ieee80211_channel *channel); | 1285 | struct ieee80211_channel *channel); |
1270 | void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | ||
1271 | struct ieee80211_channel *channel); | ||
1272 | /* Misc PHY functions */ | ||
1273 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); | ||
1274 | int ath5k_hw_phy_disable(struct ath5k_hw *ah); | ||
1275 | /* Antenna control */ | 1286 | /* Antenna control */ |
1276 | void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); | 1287 | void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); |
1277 | void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode); | 1288 | void ath5k_hw_set_antenna_switch(struct ath5k_hw *ah, u8 ee_mode); |
1278 | /* TX power setup */ | 1289 | /* TX power setup */ |
1279 | int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | ||
1280 | u8 ee_mode, u8 txpower); | ||
1281 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); | 1290 | int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); |
1291 | /* Init function */ | ||
1292 | int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | ||
1293 | u8 mode, u8 ee_mode, u8 freq); | ||
1282 | 1294 | ||
1283 | /* | 1295 | /* |
1284 | * Functions used internaly | 1296 | * Functions used internaly |
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c index 43244382f21..16b44ff7dd3 100644 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ b/drivers/net/wireless/ath/ath5k/desc.c | |||
@@ -26,9 +26,10 @@ | |||
26 | #include "debug.h" | 26 | #include "debug.h" |
27 | #include "base.h" | 27 | #include "base.h" |
28 | 28 | ||
29 | /* | 29 | |
30 | * TX Descriptors | 30 | /************************\ |
31 | */ | 31 | * TX Control descriptors * |
32 | \************************/ | ||
32 | 33 | ||
33 | /* | 34 | /* |
34 | * Initialize the 2-word tx control descriptor on 5210/5211 | 35 | * Initialize the 2-word tx control descriptor on 5210/5211 |
@@ -335,6 +336,11 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
335 | return 0; | 336 | return 0; |
336 | } | 337 | } |
337 | 338 | ||
339 | |||
340 | /***********************\ | ||
341 | * TX Status descriptors * | ||
342 | \***********************/ | ||
343 | |||
338 | /* | 344 | /* |
339 | * Proccess the tx status descriptor on 5210/5211 | 345 | * Proccess the tx status descriptor on 5210/5211 |
340 | */ | 346 | */ |
@@ -476,9 +482,10 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
476 | return 0; | 482 | return 0; |
477 | } | 483 | } |
478 | 484 | ||
479 | /* | 485 | |
480 | * RX Descriptors | 486 | /****************\ |
481 | */ | 487 | * RX Descriptors * |
488 | \****************/ | ||
482 | 489 | ||
483 | /* | 490 | /* |
484 | * Initialize an rx control descriptor | 491 | * Initialize an rx control descriptor |
@@ -666,6 +673,11 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, | |||
666 | return 0; | 673 | return 0; |
667 | } | 674 | } |
668 | 675 | ||
676 | |||
677 | /********\ | ||
678 | * Attach * | ||
679 | \********/ | ||
680 | |||
669 | /* | 681 | /* |
670 | * Init function pointers inside ath5k_hw struct | 682 | * Init function pointers inside ath5k_hw struct |
671 | */ | 683 | */ |
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 923c9ca5c4f..b991b058509 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "debug.h" | 37 | #include "debug.h" |
38 | #include "base.h" | 38 | #include "base.h" |
39 | 39 | ||
40 | |||
40 | /*********\ | 41 | /*********\ |
41 | * Receive * | 42 | * Receive * |
42 | \*********/ | 43 | \*********/ |
@@ -427,6 +428,7 @@ done: | |||
427 | return ret; | 428 | return ret; |
428 | } | 429 | } |
429 | 430 | ||
431 | |||
430 | /*******************\ | 432 | /*******************\ |
431 | * Interrupt masking * | 433 | * Interrupt masking * |
432 | \*******************/ | 434 | \*******************/ |
@@ -688,3 +690,46 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) | |||
688 | return old_mask; | 690 | return old_mask; |
689 | } | 691 | } |
690 | 692 | ||
693 | |||
694 | /********************\ | ||
695 | Init/Stop functions | ||
696 | \********************/ | ||
697 | |||
698 | /** | ||
699 | * ath5k_hw_dma_init - Initialize DMA unit | ||
700 | * | ||
701 | * @ah: The &struct ath5k_hw | ||
702 | * | ||
703 | * Set DMA size and pre-enable interrupts | ||
704 | * (driver handles tx/rx buffer setup and | ||
705 | * dma start/stop) | ||
706 | * | ||
707 | * XXX: Save/restore RXDP/TXDP registers ? | ||
708 | */ | ||
709 | void ath5k_hw_dma_init(struct ath5k_hw *ah) | ||
710 | { | ||
711 | /* | ||
712 | * Set Rx/Tx DMA Configuration | ||
713 | * | ||
714 | * Set standard DMA size (128). Note that | ||
715 | * a DMA size of 512 causes rx overruns and tx errors | ||
716 | * on pci-e cards (tested on 5424 but since rx overruns | ||
717 | * also occur on 5416/5418 with madwifi we set 128 | ||
718 | * for all PCI-E cards to be safe). | ||
719 | * | ||
720 | * XXX: need to check 5210 for this | ||
721 | * TODO: Check out tx triger level, it's always 64 on dumps but I | ||
722 | * guess we can tweak it and see how it goes ;-) | ||
723 | */ | ||
724 | if (ah->ah_version != AR5K_AR5210) { | ||
725 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | ||
726 | AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); | ||
727 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, | ||
728 | AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); | ||
729 | } | ||
730 | |||
731 | /* Pre-enable interrupts on 5211/5212*/ | ||
732 | if (ah->ah_version != AR5K_AR5210) | ||
733 | ath5k_hw_set_imr(ah, ah->ah_imr); | ||
734 | |||
735 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 39722dd73e4..033eab9ad4e 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -28,6 +28,43 @@ | |||
28 | #include "debug.h" | 28 | #include "debug.h" |
29 | #include "base.h" | 29 | #include "base.h" |
30 | 30 | ||
31 | |||
32 | /******************\ | ||
33 | * Helper functions * | ||
34 | \******************/ | ||
35 | |||
36 | /* | ||
37 | * Translate binary channel representation in EEPROM to frequency | ||
38 | */ | ||
39 | static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, | ||
40 | unsigned int mode) | ||
41 | { | ||
42 | u16 val; | ||
43 | |||
44 | if (bin == AR5K_EEPROM_CHANNEL_DIS) | ||
45 | return bin; | ||
46 | |||
47 | if (mode == AR5K_EEPROM_MODE_11A) { | ||
48 | if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) | ||
49 | val = (5 * bin) + 4800; | ||
50 | else | ||
51 | val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : | ||
52 | (bin * 10) + 5100; | ||
53 | } else { | ||
54 | if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) | ||
55 | val = bin + 2300; | ||
56 | else | ||
57 | val = bin + 2400; | ||
58 | } | ||
59 | |||
60 | return val; | ||
61 | } | ||
62 | |||
63 | |||
64 | /*********\ | ||
65 | * Parsers * | ||
66 | \*********/ | ||
67 | |||
31 | /* | 68 | /* |
32 | * Read from eeprom | 69 | * Read from eeprom |
33 | */ | 70 | */ |
@@ -63,33 +100,6 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) | |||
63 | } | 100 | } |
64 | 101 | ||
65 | /* | 102 | /* |
66 | * Translate binary channel representation in EEPROM to frequency | ||
67 | */ | ||
68 | static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, | ||
69 | unsigned int mode) | ||
70 | { | ||
71 | u16 val; | ||
72 | |||
73 | if (bin == AR5K_EEPROM_CHANNEL_DIS) | ||
74 | return bin; | ||
75 | |||
76 | if (mode == AR5K_EEPROM_MODE_11A) { | ||
77 | if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) | ||
78 | val = (5 * bin) + 4800; | ||
79 | else | ||
80 | val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : | ||
81 | (bin * 10) + 5100; | ||
82 | } else { | ||
83 | if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) | ||
84 | val = bin + 2300; | ||
85 | else | ||
86 | val = bin + 2400; | ||
87 | } | ||
88 | |||
89 | return val; | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Initialize eeprom & capabilities structs | 103 | * Initialize eeprom & capabilities structs |
94 | */ | 104 | */ |
95 | static int | 105 | static int |
@@ -647,6 +657,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) | |||
647 | return 0; | 657 | return 0; |
648 | } | 658 | } |
649 | 659 | ||
660 | |||
650 | /* | 661 | /* |
651 | * Read power calibration for RF5111 chips | 662 | * Read power calibration for RF5111 chips |
652 | * | 663 | * |
@@ -1514,6 +1525,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) | |||
1514 | return 0; | 1525 | return 0; |
1515 | } | 1526 | } |
1516 | 1527 | ||
1528 | |||
1517 | /* | 1529 | /* |
1518 | * Read per channel calibration info from EEPROM | 1530 | * Read per channel calibration info from EEPROM |
1519 | * | 1531 | * |
@@ -1607,15 +1619,6 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) | |||
1607 | return 0; | 1619 | return 0; |
1608 | } | 1620 | } |
1609 | 1621 | ||
1610 | void | ||
1611 | ath5k_eeprom_detach(struct ath5k_hw *ah) | ||
1612 | { | ||
1613 | u8 mode; | ||
1614 | |||
1615 | for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) | ||
1616 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
1617 | } | ||
1618 | |||
1619 | /* Read conformance test limits used for regulatory control */ | 1622 | /* Read conformance test limits used for regulatory control */ |
1620 | static int | 1623 | static int |
1621 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) | 1624 | ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) |
@@ -1757,6 +1760,44 @@ ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) | |||
1757 | } | 1760 | } |
1758 | 1761 | ||
1759 | /* | 1762 | /* |
1763 | * Read the MAC address from eeprom | ||
1764 | */ | ||
1765 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
1766 | { | ||
1767 | u8 mac_d[ETH_ALEN] = {}; | ||
1768 | u32 total, offset; | ||
1769 | u16 data; | ||
1770 | int octet, ret; | ||
1771 | |||
1772 | ret = ath5k_hw_eeprom_read(ah, 0x20, &data); | ||
1773 | if (ret) | ||
1774 | return ret; | ||
1775 | |||
1776 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | ||
1777 | ret = ath5k_hw_eeprom_read(ah, offset, &data); | ||
1778 | if (ret) | ||
1779 | return ret; | ||
1780 | |||
1781 | total += data; | ||
1782 | mac_d[octet + 1] = data & 0xff; | ||
1783 | mac_d[octet] = data >> 8; | ||
1784 | octet += 2; | ||
1785 | } | ||
1786 | |||
1787 | if (!total || total == 3 * 0xffff) | ||
1788 | return -EINVAL; | ||
1789 | |||
1790 | memcpy(mac, mac_d, ETH_ALEN); | ||
1791 | |||
1792 | return 0; | ||
1793 | } | ||
1794 | |||
1795 | |||
1796 | /***********************\ | ||
1797 | * Init/Detach functions * | ||
1798 | \***********************/ | ||
1799 | |||
1800 | /* | ||
1760 | * Initialize eeprom data structure | 1801 | * Initialize eeprom data structure |
1761 | */ | 1802 | */ |
1762 | int | 1803 | int |
@@ -1787,35 +1828,11 @@ ath5k_eeprom_init(struct ath5k_hw *ah) | |||
1787 | return 0; | 1828 | return 0; |
1788 | } | 1829 | } |
1789 | 1830 | ||
1790 | /* | 1831 | void |
1791 | * Read the MAC address from eeprom | 1832 | ath5k_eeprom_detach(struct ath5k_hw *ah) |
1792 | */ | ||
1793 | int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) | ||
1794 | { | 1833 | { |
1795 | u8 mac_d[ETH_ALEN] = {}; | 1834 | u8 mode; |
1796 | u32 total, offset; | ||
1797 | u16 data; | ||
1798 | int octet, ret; | ||
1799 | |||
1800 | ret = ath5k_hw_eeprom_read(ah, 0x20, &data); | ||
1801 | if (ret) | ||
1802 | return ret; | ||
1803 | |||
1804 | for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { | ||
1805 | ret = ath5k_hw_eeprom_read(ah, offset, &data); | ||
1806 | if (ret) | ||
1807 | return ret; | ||
1808 | |||
1809 | total += data; | ||
1810 | mac_d[octet + 1] = data & 0xff; | ||
1811 | mac_d[octet] = data >> 8; | ||
1812 | octet += 2; | ||
1813 | } | ||
1814 | |||
1815 | if (!total || total == 3 * 0xffff) | ||
1816 | return -EINVAL; | ||
1817 | |||
1818 | memcpy(mac, mac_d, ETH_ALEN); | ||
1819 | 1835 | ||
1820 | return 0; | 1836 | for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) |
1837 | ath5k_eeprom_free_pcal_info(ah, mode); | ||
1821 | } | 1838 | } |
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 074b4c64439..2c2ea153984 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -32,86 +32,47 @@ | |||
32 | #include "base.h" | 32 | #include "base.h" |
33 | 33 | ||
34 | /*******************\ | 34 | /*******************\ |
35 | * Generic functions * | 35 | * Helper functions * |
36 | \*******************/ | 36 | \*******************/ |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * ath5k_hw_set_opmode - Set PCU operating mode | 39 | * ath5k_hw_get_default_slottime - Get the default slot time for current mode |
40 | * | 40 | * |
41 | * @ah: The &struct ath5k_hw | 41 | * @ah: The &struct ath5k_hw |
42 | * @op_mode: &enum nl80211_iftype operating mode | ||
43 | * | ||
44 | * Initialize PCU for the various operating modes (AP/STA etc) | ||
45 | */ | 42 | */ |
46 | int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | 43 | static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) |
47 | { | 44 | { |
48 | struct ath_common *common = ath5k_hw_common(ah); | 45 | struct ieee80211_channel *channel = ah->ah_current_channel; |
49 | u32 pcu_reg, beacon_reg, low_id, high_id; | ||
50 | |||
51 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); | ||
52 | |||
53 | /* Preserve rest settings */ | ||
54 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | ||
55 | pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP | ||
56 | | AR5K_STA_ID1_KEYSRCH_MODE | ||
57 | | (ah->ah_version == AR5K_AR5210 ? | ||
58 | (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); | ||
59 | |||
60 | beacon_reg = 0; | ||
61 | 46 | ||
62 | switch (op_mode) { | 47 | if (channel->hw_value & CHANNEL_TURBO) |
63 | case NL80211_IFTYPE_ADHOC: | 48 | return 6; /* both turbo modes */ |
64 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; | ||
65 | beacon_reg |= AR5K_BCR_ADHOC; | ||
66 | if (ah->ah_version == AR5K_AR5210) | ||
67 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
68 | else | ||
69 | AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | ||
70 | break; | ||
71 | 49 | ||
72 | case NL80211_IFTYPE_AP: | 50 | if (channel->hw_value & CHANNEL_CCK) |
73 | case NL80211_IFTYPE_MESH_POINT: | 51 | return 20; /* 802.11b */ |
74 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; | ||
75 | beacon_reg |= AR5K_BCR_AP; | ||
76 | if (ah->ah_version == AR5K_AR5210) | ||
77 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
78 | else | ||
79 | AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | ||
80 | break; | ||
81 | 52 | ||
82 | case NL80211_IFTYPE_STATION: | 53 | return 9; /* 802.11 a/g */ |
83 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | 54 | } |
84 | | (ah->ah_version == AR5K_AR5210 ? | ||
85 | AR5K_STA_ID1_PWR_SV : 0); | ||
86 | case NL80211_IFTYPE_MONITOR: | ||
87 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | ||
88 | | (ah->ah_version == AR5K_AR5210 ? | ||
89 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
90 | break; | ||
91 | 55 | ||
92 | default: | 56 | /** |
93 | return -EINVAL; | 57 | * ath5k_hw_get_default_sifs - Get the default SIFS for current mode |
94 | } | 58 | * |
59 | * @ah: The &struct ath5k_hw | ||
60 | */ | ||
61 | static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | ||
62 | { | ||
63 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
95 | 64 | ||
96 | /* | 65 | if (channel->hw_value & CHANNEL_TURBO) |
97 | * Set PCU registers | 66 | return 8; /* both turbo modes */ |
98 | */ | ||
99 | low_id = get_unaligned_le32(common->macaddr); | ||
100 | high_id = get_unaligned_le16(common->macaddr + 4); | ||
101 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | ||
102 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | ||
103 | 67 | ||
104 | /* | 68 | if (channel->hw_value & CHANNEL_5GHZ) |
105 | * Set Beacon Control Register on 5210 | 69 | return 16; /* 802.11a */ |
106 | */ | ||
107 | if (ah->ah_version == AR5K_AR5210) | ||
108 | ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); | ||
109 | 70 | ||
110 | return 0; | 71 | return 10; /* 802.11 b/g */ |
111 | } | 72 | } |
112 | 73 | ||
113 | /** | 74 | /** |
114 | * ath5k_hw_update - Update MIB counters (mac layer statistics) | 75 | * ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics) |
115 | * | 76 | * |
116 | * @ah: The &struct ath5k_hw | 77 | * @ah: The &struct ath5k_hw |
117 | * | 78 | * |
@@ -163,6 +124,82 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) | |||
163 | * ACK/CTS Timeouts * | 124 | * ACK/CTS Timeouts * |
164 | \******************/ | 125 | \******************/ |
165 | 126 | ||
127 | /* | ||
128 | * index into rates for control rates, we can set it up like this because | ||
129 | * this is only used for AR5212 and we know it supports G mode | ||
130 | */ | ||
131 | static const unsigned int control_rates[] = | ||
132 | { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; | ||
133 | |||
134 | /** | ||
135 | * ath5k_hw_write_rate_duration - fill rate code to duration table | ||
136 | * | ||
137 | * @ah: the &struct ath5k_hw | ||
138 | * @mode: one of enum ath5k_driver_mode | ||
139 | * | ||
140 | * Write the rate code to duration table upon hw reset. This is a helper for | ||
141 | * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on | ||
142 | * the hardware, based on current mode, for each rate. The rates which are | ||
143 | * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have | ||
144 | * different rate code so we write their value twice (one for long preamble | ||
145 | * and one for short). | ||
146 | * | ||
147 | * Note: Band doesn't matter here, if we set the values for OFDM it works | ||
148 | * on both a and g modes. So all we have to do is set values for all g rates | ||
149 | * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ | ||
150 | * quarter rate mode, we need to use another set of bitrates (that's why we | ||
151 | * need the mode parameter) but we don't handle these proprietary modes yet. | ||
152 | */ | ||
153 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, | ||
154 | unsigned int mode) | ||
155 | { | ||
156 | struct ath5k_softc *sc = ah->ah_sc; | ||
157 | struct ieee80211_rate *rate; | ||
158 | unsigned int i; | ||
159 | |||
160 | /* Write rate duration table */ | ||
161 | for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { | ||
162 | u32 reg; | ||
163 | u16 tx_time; | ||
164 | |||
165 | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; | ||
166 | |||
167 | /* Set ACK timeout */ | ||
168 | reg = AR5K_RATE_DUR(rate->hw_value); | ||
169 | |||
170 | /* An ACK frame consists of 10 bytes. If you add the FCS, | ||
171 | * which ieee80211_generic_frame_duration() adds, | ||
172 | * its 14 bytes. Note we use the control rate and not the | ||
173 | * actual rate for this rate. See mac80211 tx.c | ||
174 | * ieee80211_duration() for a brief description of | ||
175 | * what rate we should choose to TX ACKs. */ | ||
176 | tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, | ||
177 | NULL, 10, rate)); | ||
178 | |||
179 | ath5k_hw_reg_write(ah, tx_time, reg); | ||
180 | |||
181 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | ||
182 | continue; | ||
183 | |||
184 | /* | ||
185 | * We're not distinguishing short preamble here, | ||
186 | * This is true, all we'll get is a longer value here | ||
187 | * which is not necessarilly bad. We could use | ||
188 | * export ieee80211_frame_duration() but that needs to be | ||
189 | * fixed first to be properly used by mac802111 drivers: | ||
190 | * | ||
191 | * - remove erp stuff and let the routine figure ofdm | ||
192 | * erp rates | ||
193 | * - remove passing argument ieee80211_local as | ||
194 | * drivers don't have access to it | ||
195 | * - move drivers using ieee80211_generic_frame_duration() | ||
196 | * to this | ||
197 | */ | ||
198 | ath5k_hw_reg_write(ah, tx_time, | ||
199 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | ||
200 | } | ||
201 | } | ||
202 | |||
166 | /** | 203 | /** |
167 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU | 204 | * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU |
168 | * | 205 | * |
@@ -199,88 +236,10 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) | |||
199 | return 0; | 236 | return 0; |
200 | } | 237 | } |
201 | 238 | ||
202 | /** | ||
203 | * ath5k_hw_htoclock - Translate usec to hw clock units | ||
204 | * | ||
205 | * @ah: The &struct ath5k_hw | ||
206 | * @usec: value in microseconds | ||
207 | */ | ||
208 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) | ||
209 | { | ||
210 | struct ath_common *common = ath5k_hw_common(ah); | ||
211 | return usec * common->clockrate; | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * ath5k_hw_clocktoh - Translate hw clock units to usec | ||
216 | * @clock: value in hw clock units | ||
217 | */ | ||
218 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | ||
219 | { | ||
220 | struct ath_common *common = ath5k_hw_common(ah); | ||
221 | return clock / common->clockrate; | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * ath5k_hw_set_clockrate - Set common->clockrate for the current channel | ||
226 | * | ||
227 | * @ah: The &struct ath5k_hw | ||
228 | */ | ||
229 | void ath5k_hw_set_clockrate(struct ath5k_hw *ah) | ||
230 | { | ||
231 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
232 | struct ath_common *common = ath5k_hw_common(ah); | ||
233 | int clock; | ||
234 | |||
235 | if (channel->hw_value & CHANNEL_5GHZ) | ||
236 | clock = 40; /* 802.11a */ | ||
237 | else if (channel->hw_value & CHANNEL_CCK) | ||
238 | clock = 22; /* 802.11b */ | ||
239 | else | ||
240 | clock = 44; /* 802.11g */ | ||
241 | |||
242 | /* Clock rate in turbo modes is twice the normal rate */ | ||
243 | if (channel->hw_value & CHANNEL_TURBO) | ||
244 | clock *= 2; | ||
245 | |||
246 | common->clockrate = clock; | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * ath5k_hw_get_default_slottime - Get the default slot time for current mode | ||
251 | * | ||
252 | * @ah: The &struct ath5k_hw | ||
253 | */ | ||
254 | static unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) | ||
255 | { | ||
256 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
257 | |||
258 | if (channel->hw_value & CHANNEL_TURBO) | ||
259 | return 6; /* both turbo modes */ | ||
260 | |||
261 | if (channel->hw_value & CHANNEL_CCK) | ||
262 | return 20; /* 802.11b */ | ||
263 | |||
264 | return 9; /* 802.11 a/g */ | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * ath5k_hw_get_default_sifs - Get the default SIFS for current mode | ||
269 | * | ||
270 | * @ah: The &struct ath5k_hw | ||
271 | */ | ||
272 | static unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) | ||
273 | { | ||
274 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
275 | |||
276 | if (channel->hw_value & CHANNEL_TURBO) | ||
277 | return 8; /* both turbo modes */ | ||
278 | |||
279 | if (channel->hw_value & CHANNEL_5GHZ) | ||
280 | return 16; /* 802.11a */ | ||
281 | 239 | ||
282 | return 10; /* 802.11 b/g */ | 240 | /*******************\ |
283 | } | 241 | * RX filter Control * |
242 | \*******************/ | ||
284 | 243 | ||
285 | /** | 244 | /** |
286 | * ath5k_hw_set_lladdr - Set station id | 245 | * ath5k_hw_set_lladdr - Set station id |
@@ -362,39 +321,6 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) | |||
362 | ath_hw_setbssidmask(common); | 321 | ath_hw_setbssidmask(common); |
363 | } | 322 | } |
364 | 323 | ||
365 | /************\ | ||
366 | * RX Control * | ||
367 | \************/ | ||
368 | |||
369 | /** | ||
370 | * ath5k_hw_start_rx_pcu - Start RX engine | ||
371 | * | ||
372 | * @ah: The &struct ath5k_hw | ||
373 | * | ||
374 | * Starts RX engine on PCU so that hw can process RXed frames | ||
375 | * (ACK etc). | ||
376 | * | ||
377 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | ||
378 | */ | ||
379 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | ||
380 | { | ||
381 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * at5k_hw_stop_rx_pcu - Stop RX engine | ||
386 | * | ||
387 | * @ah: The &struct ath5k_hw | ||
388 | * | ||
389 | * Stops RX engine on PCU | ||
390 | * | ||
391 | * TODO: Detach ANI here | ||
392 | */ | ||
393 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | ||
394 | { | ||
395 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
396 | } | ||
397 | |||
398 | /* | 324 | /* |
399 | * Set multicast filter | 325 | * Set multicast filter |
400 | */ | 326 | */ |
@@ -761,3 +687,161 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) | |||
761 | 687 | ||
762 | ah->ah_coverage_class = coverage_class; | 688 | ah->ah_coverage_class = coverage_class; |
763 | } | 689 | } |
690 | |||
691 | /***************************\ | ||
692 | * Init/Start/Stop functions * | ||
693 | \***************************/ | ||
694 | |||
695 | /** | ||
696 | * ath5k_hw_start_rx_pcu - Start RX engine | ||
697 | * | ||
698 | * @ah: The &struct ath5k_hw | ||
699 | * | ||
700 | * Starts RX engine on PCU so that hw can process RXed frames | ||
701 | * (ACK etc). | ||
702 | * | ||
703 | * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma | ||
704 | */ | ||
705 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) | ||
706 | { | ||
707 | AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
708 | } | ||
709 | |||
710 | /** | ||
711 | * at5k_hw_stop_rx_pcu - Stop RX engine | ||
712 | * | ||
713 | * @ah: The &struct ath5k_hw | ||
714 | * | ||
715 | * Stops RX engine on PCU | ||
716 | */ | ||
717 | void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) | ||
718 | { | ||
719 | AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); | ||
720 | } | ||
721 | |||
722 | /** | ||
723 | * ath5k_hw_set_opmode - Set PCU operating mode | ||
724 | * | ||
725 | * @ah: The &struct ath5k_hw | ||
726 | * @op_mode: &enum nl80211_iftype operating mode | ||
727 | * | ||
728 | * Configure PCU for the various operating modes (AP/STA etc) | ||
729 | */ | ||
730 | int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) | ||
731 | { | ||
732 | struct ath_common *common = ath5k_hw_common(ah); | ||
733 | u32 pcu_reg, beacon_reg, low_id, high_id; | ||
734 | |||
735 | ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); | ||
736 | |||
737 | /* Preserve rest settings */ | ||
738 | pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; | ||
739 | pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP | ||
740 | | AR5K_STA_ID1_KEYSRCH_MODE | ||
741 | | (ah->ah_version == AR5K_AR5210 ? | ||
742 | (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); | ||
743 | |||
744 | beacon_reg = 0; | ||
745 | |||
746 | switch (op_mode) { | ||
747 | case NL80211_IFTYPE_ADHOC: | ||
748 | pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; | ||
749 | beacon_reg |= AR5K_BCR_ADHOC; | ||
750 | if (ah->ah_version == AR5K_AR5210) | ||
751 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
752 | else | ||
753 | AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | ||
754 | break; | ||
755 | |||
756 | case NL80211_IFTYPE_AP: | ||
757 | case NL80211_IFTYPE_MESH_POINT: | ||
758 | pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; | ||
759 | beacon_reg |= AR5K_BCR_AP; | ||
760 | if (ah->ah_version == AR5K_AR5210) | ||
761 | pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; | ||
762 | else | ||
763 | AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); | ||
764 | break; | ||
765 | |||
766 | case NL80211_IFTYPE_STATION: | ||
767 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | ||
768 | | (ah->ah_version == AR5K_AR5210 ? | ||
769 | AR5K_STA_ID1_PWR_SV : 0); | ||
770 | case NL80211_IFTYPE_MONITOR: | ||
771 | pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE | ||
772 | | (ah->ah_version == AR5K_AR5210 ? | ||
773 | AR5K_STA_ID1_NO_PSPOLL : 0); | ||
774 | break; | ||
775 | |||
776 | default: | ||
777 | return -EINVAL; | ||
778 | } | ||
779 | |||
780 | /* | ||
781 | * Set PCU registers | ||
782 | */ | ||
783 | low_id = get_unaligned_le32(common->macaddr); | ||
784 | high_id = get_unaligned_le16(common->macaddr + 4); | ||
785 | ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); | ||
786 | ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); | ||
787 | |||
788 | /* | ||
789 | * Set Beacon Control Register on 5210 | ||
790 | */ | ||
791 | if (ah->ah_version == AR5K_AR5210) | ||
792 | ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); | ||
793 | |||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | ||
798 | u8 mode) | ||
799 | { | ||
800 | /* Set bssid and bssid mask */ | ||
801 | ath5k_hw_set_bssid(ah); | ||
802 | |||
803 | /* Set PCU config */ | ||
804 | ath5k_hw_set_opmode(ah, op_mode); | ||
805 | |||
806 | /* Write rate duration table only on AR5212 and if | ||
807 | * virtual interface has already been brought up | ||
808 | * XXX: rethink this after new mode changes to | ||
809 | * mac80211 are integrated */ | ||
810 | if (ah->ah_version == AR5K_AR5212 && | ||
811 | ah->ah_sc->nvifs) | ||
812 | ath5k_hw_write_rate_duration(ah, mode); | ||
813 | |||
814 | /* Set RSSI/BRSSI thresholds | ||
815 | * | ||
816 | * Note: If we decide to set this value | ||
817 | * dynamicaly, have in mind that when AR5K_RSSI_THR | ||
818 | * register is read it might return 0x40 if we haven't | ||
819 | * wrote anything to it plus BMISS RSSI threshold is zeroed. | ||
820 | * So doing a save/restore procedure here isn't the right | ||
821 | * choice. Instead store it on ath5k_hw */ | ||
822 | ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | | ||
823 | AR5K_TUNE_BMISS_THRES << | ||
824 | AR5K_RSSI_THR_BMISS_S), | ||
825 | AR5K_RSSI_THR); | ||
826 | |||
827 | /* MIC QoS support */ | ||
828 | if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { | ||
829 | ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); | ||
830 | ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); | ||
831 | } | ||
832 | |||
833 | /* QoS NOACK Policy */ | ||
834 | if (ah->ah_version == AR5K_AR5212) { | ||
835 | ath5k_hw_reg_write(ah, | ||
836 | AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | | ||
837 | AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | | ||
838 | AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), | ||
839 | AR5K_QOS_NOACK); | ||
840 | } | ||
841 | |||
842 | /* Restore slot time and ACK timeouts */ | ||
843 | if (ah->ah_coverage_class > 0) | ||
844 | ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); | ||
845 | |||
846 | return; | ||
847 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 6b43f535ff5..1c41fa83745 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -29,6 +29,95 @@ | |||
29 | #include "rfbuffer.h" | 29 | #include "rfbuffer.h" |
30 | #include "rfgain.h" | 30 | #include "rfgain.h" |
31 | 31 | ||
32 | |||
33 | /******************\ | ||
34 | * Helper functions * | ||
35 | \******************/ | ||
36 | |||
37 | /* | ||
38 | * Get the PHY Chip revision | ||
39 | */ | ||
40 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | ||
41 | { | ||
42 | unsigned int i; | ||
43 | u32 srev; | ||
44 | u16 ret; | ||
45 | |||
46 | /* | ||
47 | * Set the radio chip access register | ||
48 | */ | ||
49 | switch (chan) { | ||
50 | case CHANNEL_2GHZ: | ||
51 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); | ||
52 | break; | ||
53 | case CHANNEL_5GHZ: | ||
54 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
55 | break; | ||
56 | default: | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | mdelay(2); | ||
61 | |||
62 | /* ...wait until PHY is ready and read the selected radio revision */ | ||
63 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | ||
64 | |||
65 | for (i = 0; i < 8; i++) | ||
66 | ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); | ||
67 | |||
68 | if (ah->ah_version == AR5K_AR5210) { | ||
69 | srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; | ||
70 | ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; | ||
71 | } else { | ||
72 | srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; | ||
73 | ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | | ||
74 | ((srev & 0x0f) << 4), 8); | ||
75 | } | ||
76 | |||
77 | /* Reset to the 5GHz mode */ | ||
78 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
79 | |||
80 | return ret; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Check if a channel is supported | ||
85 | */ | ||
86 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) | ||
87 | { | ||
88 | /* Check if the channel is in our supported range */ | ||
89 | if (flags & CHANNEL_2GHZ) { | ||
90 | if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && | ||
91 | (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) | ||
92 | return true; | ||
93 | } else if (flags & CHANNEL_5GHZ) | ||
94 | if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && | ||
95 | (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) | ||
96 | return true; | ||
97 | |||
98 | return false; | ||
99 | } | ||
100 | |||
101 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | ||
102 | struct ieee80211_channel *channel) | ||
103 | { | ||
104 | u8 refclk_freq; | ||
105 | |||
106 | if ((ah->ah_radio == AR5K_RF5112) || | ||
107 | (ah->ah_radio == AR5K_RF5413) || | ||
108 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
109 | refclk_freq = 40; | ||
110 | else | ||
111 | refclk_freq = 32; | ||
112 | |||
113 | if ((channel->center_freq % refclk_freq != 0) && | ||
114 | ((channel->center_freq % refclk_freq < 10) || | ||
115 | (channel->center_freq % refclk_freq > 22))) | ||
116 | return true; | ||
117 | else | ||
118 | return false; | ||
119 | } | ||
120 | |||
32 | /* | 121 | /* |
33 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER | 122 | * Used to modify RF Banks before writing them to AR5K_RF_BUFFER |
34 | */ | 123 | */ |
@@ -110,6 +199,78 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
110 | return data; | 199 | return data; |
111 | } | 200 | } |
112 | 201 | ||
202 | /** | ||
203 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | ||
204 | * | ||
205 | * @ah: the &struct ath5k_hw | ||
206 | * @channel: the currently set channel upon reset | ||
207 | * | ||
208 | * Write the delta slope coefficient (used on pilot tracking ?) for OFDM | ||
209 | * operation on the AR5212 upon reset. This is a helper for ath5k_hw_phy_init. | ||
210 | * | ||
211 | * Since delta slope is floating point we split it on its exponent and | ||
212 | * mantissa and provide these values on hw. | ||
213 | * | ||
214 | * For more infos i think this patent is related | ||
215 | * http://www.freepatentsonline.com/7184495.html | ||
216 | */ | ||
217 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | ||
218 | struct ieee80211_channel *channel) | ||
219 | { | ||
220 | /* Get exponent and mantissa and set it */ | ||
221 | u32 coef_scaled, coef_exp, coef_man, | ||
222 | ds_coef_exp, ds_coef_man, clock; | ||
223 | |||
224 | BUG_ON(!(ah->ah_version == AR5K_AR5212) || | ||
225 | !(channel->hw_value & CHANNEL_OFDM)); | ||
226 | |||
227 | /* Get coefficient | ||
228 | * ALGO: coef = (5 * clock / carrier_freq) / 2 | ||
229 | * we scale coef by shifting clock value by 24 for | ||
230 | * better precision since we use integers */ | ||
231 | /* TODO: Half/quarter rate */ | ||
232 | clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; | ||
233 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; | ||
234 | |||
235 | /* Get exponent | ||
236 | * ALGO: coef_exp = 14 - highest set bit position */ | ||
237 | coef_exp = ilog2(coef_scaled); | ||
238 | |||
239 | /* Doesn't make sense if it's zero*/ | ||
240 | if (!coef_scaled || !coef_exp) | ||
241 | return -EINVAL; | ||
242 | |||
243 | /* Note: we've shifted coef_scaled by 24 */ | ||
244 | coef_exp = 14 - (coef_exp - 24); | ||
245 | |||
246 | |||
247 | /* Get mantissa (significant digits) | ||
248 | * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ | ||
249 | coef_man = coef_scaled + | ||
250 | (1 << (24 - coef_exp - 1)); | ||
251 | |||
252 | /* Calculate delta slope coefficient exponent | ||
253 | * and mantissa (remove scaling) and set them on hw */ | ||
254 | ds_coef_man = coef_man >> (24 - coef_exp); | ||
255 | ds_coef_exp = coef_exp - 16; | ||
256 | |||
257 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
258 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | ||
259 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | ||
260 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | ||
261 | |||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | ||
266 | { | ||
267 | /*Just a try M.F.*/ | ||
268 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | |||
113 | /**********************\ | 274 | /**********************\ |
114 | * RF Gain optimization * | 275 | * RF Gain optimization * |
115 | \**********************/ | 276 | \**********************/ |
@@ -436,7 +597,7 @@ done: | |||
436 | /* Write initial RF gain table to set the RF sensitivity | 597 | /* Write initial RF gain table to set the RF sensitivity |
437 | * this one works on all RF chips and has nothing to do | 598 | * this one works on all RF chips and has nothing to do |
438 | * with gain_F calibration */ | 599 | * with gain_F calibration */ |
439 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | 600 | static int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) |
440 | { | 601 | { |
441 | const struct ath5k_ini_rfgain *ath5k_rfg; | 602 | const struct ath5k_ini_rfgain *ath5k_rfg; |
442 | unsigned int i, size; | 603 | unsigned int i, size; |
@@ -494,12 +655,11 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
494 | * RF Registers setup * | 655 | * RF Registers setup * |
495 | \********************/ | 656 | \********************/ |
496 | 657 | ||
497 | |||
498 | /* | 658 | /* |
499 | * Setup RF registers by writing RF buffer on hw | 659 | * Setup RF registers by writing RF buffer on hw |
500 | */ | 660 | */ |
501 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 661 | static int ath5k_hw_rfregs_init(struct ath5k_hw *ah, |
502 | unsigned int mode) | 662 | struct ieee80211_channel *channel, unsigned int mode) |
503 | { | 663 | { |
504 | const struct ath5k_rf_reg *rf_regs; | 664 | const struct ath5k_rf_reg *rf_regs; |
505 | const struct ath5k_ini_rfbuffer *ini_rfb; | 665 | const struct ath5k_ini_rfbuffer *ini_rfb; |
@@ -822,24 +982,6 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
822 | \**************************/ | 982 | \**************************/ |
823 | 983 | ||
824 | /* | 984 | /* |
825 | * Check if a channel is supported | ||
826 | */ | ||
827 | bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) | ||
828 | { | ||
829 | /* Check if the channel is in our supported range */ | ||
830 | if (flags & CHANNEL_2GHZ) { | ||
831 | if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && | ||
832 | (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) | ||
833 | return true; | ||
834 | } else if (flags & CHANNEL_5GHZ) | ||
835 | if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && | ||
836 | (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) | ||
837 | return true; | ||
838 | |||
839 | return false; | ||
840 | } | ||
841 | |||
842 | /* | ||
843 | * Convertion needed for RF5110 | 985 | * Convertion needed for RF5110 |
844 | */ | 986 | */ |
845 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) | 987 | static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) |
@@ -1045,7 +1187,8 @@ static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, | |||
1045 | /* | 1187 | /* |
1046 | * Set a channel on the radio chip | 1188 | * Set a channel on the radio chip |
1047 | */ | 1189 | */ |
1048 | int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) | 1190 | static int ath5k_hw_channel(struct ath5k_hw *ah, |
1191 | struct ieee80211_channel *channel) | ||
1049 | { | 1192 | { |
1050 | int ret; | 1193 | int ret; |
1051 | /* | 1194 | /* |
@@ -1419,31 +1562,12 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, | |||
1419 | return ret; | 1562 | return ret; |
1420 | } | 1563 | } |
1421 | 1564 | ||
1565 | |||
1422 | /***************************\ | 1566 | /***************************\ |
1423 | * Spur mitigation functions * | 1567 | * Spur mitigation functions * |
1424 | \***************************/ | 1568 | \***************************/ |
1425 | 1569 | ||
1426 | bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, | 1570 | static void |
1427 | struct ieee80211_channel *channel) | ||
1428 | { | ||
1429 | u8 refclk_freq; | ||
1430 | |||
1431 | if ((ah->ah_radio == AR5K_RF5112) || | ||
1432 | (ah->ah_radio == AR5K_RF5413) || | ||
1433 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
1434 | refclk_freq = 40; | ||
1435 | else | ||
1436 | refclk_freq = 32; | ||
1437 | |||
1438 | if ((channel->center_freq % refclk_freq != 0) && | ||
1439 | ((channel->center_freq % refclk_freq < 10) || | ||
1440 | (channel->center_freq % refclk_freq > 22))) | ||
1441 | return true; | ||
1442 | else | ||
1443 | return false; | ||
1444 | } | ||
1445 | |||
1446 | void | ||
1447 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | 1571 | ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, |
1448 | struct ieee80211_channel *channel) | 1572 | struct ieee80211_channel *channel) |
1449 | { | 1573 | { |
@@ -1666,63 +1790,6 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, | |||
1666 | } | 1790 | } |
1667 | } | 1791 | } |
1668 | 1792 | ||
1669 | /********************\ | ||
1670 | Misc PHY functions | ||
1671 | \********************/ | ||
1672 | |||
1673 | int ath5k_hw_phy_disable(struct ath5k_hw *ah) | ||
1674 | { | ||
1675 | /*Just a try M.F.*/ | ||
1676 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
1677 | |||
1678 | return 0; | ||
1679 | } | ||
1680 | |||
1681 | /* | ||
1682 | * Get the PHY Chip revision | ||
1683 | */ | ||
1684 | u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) | ||
1685 | { | ||
1686 | unsigned int i; | ||
1687 | u32 srev; | ||
1688 | u16 ret; | ||
1689 | |||
1690 | /* | ||
1691 | * Set the radio chip access register | ||
1692 | */ | ||
1693 | switch (chan) { | ||
1694 | case CHANNEL_2GHZ: | ||
1695 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); | ||
1696 | break; | ||
1697 | case CHANNEL_5GHZ: | ||
1698 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
1699 | break; | ||
1700 | default: | ||
1701 | return 0; | ||
1702 | } | ||
1703 | |||
1704 | mdelay(2); | ||
1705 | |||
1706 | /* ...wait until PHY is ready and read the selected radio revision */ | ||
1707 | ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); | ||
1708 | |||
1709 | for (i = 0; i < 8; i++) | ||
1710 | ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); | ||
1711 | |||
1712 | if (ah->ah_version == AR5K_AR5210) { | ||
1713 | srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; | ||
1714 | ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; | ||
1715 | } else { | ||
1716 | srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; | ||
1717 | ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | | ||
1718 | ((srev & 0x0f) << 4), 8); | ||
1719 | } | ||
1720 | |||
1721 | /* Reset to the 5GHz mode */ | ||
1722 | ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); | ||
1723 | |||
1724 | return ret; | ||
1725 | } | ||
1726 | 1793 | ||
1727 | /*****************\ | 1794 | /*****************\ |
1728 | * Antenna control * | 1795 | * Antenna control * |
@@ -2984,7 +3051,7 @@ ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, | |||
2984 | /* | 3051 | /* |
2985 | * Set transmission power | 3052 | * Set transmission power |
2986 | */ | 3053 | */ |
2987 | int | 3054 | static int |
2988 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 3055 | ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
2989 | u8 ee_mode, u8 txpower) | 3056 | u8 ee_mode, u8 txpower) |
2990 | { | 3057 | { |
@@ -3108,3 +3175,176 @@ int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) | |||
3108 | 3175 | ||
3109 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); | 3176 | return ath5k_hw_txpower(ah, channel, ee_mode, txpower); |
3110 | } | 3177 | } |
3178 | |||
3179 | /*************\ | ||
3180 | Init function | ||
3181 | \*************/ | ||
3182 | |||
3183 | int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | ||
3184 | u8 mode, u8 ee_mode, u8 freq) | ||
3185 | { | ||
3186 | int ret, i; | ||
3187 | u32 phy_tst1; | ||
3188 | |||
3189 | ret = 0; | ||
3190 | |||
3191 | /* | ||
3192 | * 5211/5212 Specific | ||
3193 | */ | ||
3194 | if (ah->ah_version != AR5K_AR5210) { | ||
3195 | |||
3196 | /* | ||
3197 | * Write initial RF gain settings | ||
3198 | * This should work for both 5111/5112 | ||
3199 | */ | ||
3200 | ret = ath5k_hw_rfgain_init(ah, freq); | ||
3201 | if (ret) | ||
3202 | return ret; | ||
3203 | |||
3204 | mdelay(1); | ||
3205 | |||
3206 | /* | ||
3207 | * Set TX power | ||
3208 | */ | ||
3209 | ret = ath5k_hw_txpower(ah, channel, ee_mode, | ||
3210 | ah->ah_txpower.txp_max_pwr / 2); | ||
3211 | if (ret) | ||
3212 | return ret; | ||
3213 | |||
3214 | /* | ||
3215 | * Write RF buffer | ||
3216 | */ | ||
3217 | ret = ath5k_hw_rfregs_init(ah, channel, mode); | ||
3218 | if (ret) | ||
3219 | return ret; | ||
3220 | |||
3221 | |||
3222 | /* Write OFDM timings on 5212*/ | ||
3223 | if (ah->ah_version == AR5K_AR5212 && | ||
3224 | channel->hw_value & CHANNEL_OFDM) { | ||
3225 | |||
3226 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | ||
3227 | if (ret) | ||
3228 | return ret; | ||
3229 | |||
3230 | /* Spur info is available only from EEPROM versions | ||
3231 | * greater than 5.3, but the EEPROM routines will use | ||
3232 | * static values for older versions */ | ||
3233 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | ||
3234 | ath5k_hw_set_spur_mitigation_filter(ah, | ||
3235 | channel); | ||
3236 | } | ||
3237 | |||
3238 | /*Enable/disable 802.11b mode on 5111 | ||
3239 | (enable 2111 frequency converter + CCK)*/ | ||
3240 | if (ah->ah_radio == AR5K_RF5111) { | ||
3241 | if (mode == AR5K_MODE_11B) | ||
3242 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | ||
3243 | AR5K_TXCFG_B_MODE); | ||
3244 | else | ||
3245 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | ||
3246 | AR5K_TXCFG_B_MODE); | ||
3247 | } | ||
3248 | |||
3249 | } else { | ||
3250 | /* | ||
3251 | * For 5210 we do all initialization using | ||
3252 | * initvals, so we don't have to modify | ||
3253 | * any settings (5210 also only supports | ||
3254 | * a/aturbo modes) | ||
3255 | */ | ||
3256 | mdelay(1); | ||
3257 | /* Disable phy and wait */ | ||
3258 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
3259 | mdelay(1); | ||
3260 | } | ||
3261 | |||
3262 | /* Set channel on PHY */ | ||
3263 | ret = ath5k_hw_channel(ah, channel); | ||
3264 | if (ret) | ||
3265 | return ret; | ||
3266 | |||
3267 | /* | ||
3268 | * Enable the PHY and wait until completion | ||
3269 | * This includes BaseBand and Synthesizer | ||
3270 | * activation. | ||
3271 | */ | ||
3272 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
3273 | |||
3274 | /* | ||
3275 | * On 5211+ read activation -> rx delay | ||
3276 | * and use it. | ||
3277 | * | ||
3278 | * TODO: Half/quarter rate support | ||
3279 | */ | ||
3280 | if (ah->ah_version != AR5K_AR5210) { | ||
3281 | u32 delay; | ||
3282 | delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
3283 | AR5K_PHY_RX_DELAY_M; | ||
3284 | delay = (channel->hw_value & CHANNEL_CCK) ? | ||
3285 | ((delay << 2) / 22) : (delay / 10); | ||
3286 | |||
3287 | udelay(100 + (2 * delay)); | ||
3288 | } else { | ||
3289 | mdelay(1); | ||
3290 | } | ||
3291 | |||
3292 | /* | ||
3293 | * Perform ADC test to see if baseband is ready | ||
3294 | * Set TX hold and check ADC test register | ||
3295 | */ | ||
3296 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | ||
3297 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | ||
3298 | for (i = 0; i <= 20; i++) { | ||
3299 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | ||
3300 | break; | ||
3301 | udelay(200); | ||
3302 | } | ||
3303 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); | ||
3304 | |||
3305 | /* | ||
3306 | * Start automatic gain control calibration | ||
3307 | * | ||
3308 | * During AGC calibration RX path is re-routed to | ||
3309 | * a power detector so we don't receive anything. | ||
3310 | * | ||
3311 | * This method is used to calibrate some static offsets | ||
3312 | * used together with on-the fly I/Q calibration (the | ||
3313 | * one performed via ath5k_hw_phy_calibrate), which doesn't | ||
3314 | * interrupt rx path. | ||
3315 | * | ||
3316 | * While rx path is re-routed to the power detector we also | ||
3317 | * start a noise floor calibration to measure the | ||
3318 | * card's noise floor (the noise we measure when we are not | ||
3319 | * transmitting or receiving anything). | ||
3320 | * | ||
3321 | * If we are in a noisy environment, AGC calibration may time | ||
3322 | * out and/or noise floor calibration might timeout. | ||
3323 | */ | ||
3324 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
3325 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); | ||
3326 | |||
3327 | /* At the same time start I/Q calibration for QAM constellation | ||
3328 | * -no need for CCK- */ | ||
3329 | ah->ah_calibration = false; | ||
3330 | if (!(mode == AR5K_MODE_11B)) { | ||
3331 | ah->ah_calibration = true; | ||
3332 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
3333 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
3334 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
3335 | AR5K_PHY_IQ_RUN); | ||
3336 | } | ||
3337 | |||
3338 | /* Wait for gain calibration to finish (we check for I/Q calibration | ||
3339 | * during ath5k_phy_calibrate) */ | ||
3340 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
3341 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | ||
3342 | ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", | ||
3343 | channel->center_freq); | ||
3344 | } | ||
3345 | |||
3346 | /* Restore antenna mode */ | ||
3347 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | ||
3348 | |||
3349 | return ret; | ||
3350 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c index 84c717ded1c..52eee34fd54 100644 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ b/drivers/net/wireless/ath/ath5k/qcu.c | |||
@@ -25,14 +25,52 @@ Queue Control Unit, DFS Control Unit Functions | |||
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | #include "base.h" | 26 | #include "base.h" |
27 | 27 | ||
28 | |||
29 | /******************\ | ||
30 | * Helper functions * | ||
31 | \******************/ | ||
32 | |||
28 | /* | 33 | /* |
29 | * Get properties for a transmit queue | 34 | * Get number of pending frames |
35 | * for a specific queue [5211+] | ||
30 | */ | 36 | */ |
31 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | 37 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) |
32 | struct ath5k_txq_info *queue_info) | ||
33 | { | 38 | { |
34 | memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); | 39 | u32 pending; |
35 | return 0; | 40 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); |
41 | |||
42 | /* Return if queue is declared inactive */ | ||
43 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
44 | return false; | ||
45 | |||
46 | /* XXX: How about AR5K_CFG_TXCNT ? */ | ||
47 | if (ah->ah_version == AR5K_AR5210) | ||
48 | return false; | ||
49 | |||
50 | pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); | ||
51 | pending &= AR5K_QCU_STS_FRMPENDCNT; | ||
52 | |||
53 | /* It's possible to have no frames pending even if TXE | ||
54 | * is set. To indicate that q has not stopped return | ||
55 | * true */ | ||
56 | if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
57 | return true; | ||
58 | |||
59 | return pending; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Set a transmit queue inactive | ||
64 | */ | ||
65 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
66 | { | ||
67 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) | ||
68 | return; | ||
69 | |||
70 | /* This queue will be skipped in further operations */ | ||
71 | ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; | ||
72 | /*For SIMR setup*/ | ||
73 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); | ||
36 | } | 74 | } |
37 | 75 | ||
38 | /* | 76 | /* |
@@ -50,6 +88,16 @@ static u16 ath5k_cw_validate(u16 cw_req) | |||
50 | } | 88 | } |
51 | 89 | ||
52 | /* | 90 | /* |
91 | * Get properties for a transmit queue | ||
92 | */ | ||
93 | int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, | ||
94 | struct ath5k_txq_info *queue_info) | ||
95 | { | ||
96 | memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* | ||
53 | * Set properties for a transmit queue | 101 | * Set properties for a transmit queue |
54 | */ | 102 | */ |
55 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, | 103 | int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, |
@@ -172,48 +220,10 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, | |||
172 | return queue; | 220 | return queue; |
173 | } | 221 | } |
174 | 222 | ||
175 | /* | ||
176 | * Get number of pending frames | ||
177 | * for a specific queue [5211+] | ||
178 | */ | ||
179 | u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) | ||
180 | { | ||
181 | u32 pending; | ||
182 | AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); | ||
183 | |||
184 | /* Return if queue is declared inactive */ | ||
185 | if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) | ||
186 | return false; | ||
187 | |||
188 | /* XXX: How about AR5K_CFG_TXCNT ? */ | ||
189 | if (ah->ah_version == AR5K_AR5210) | ||
190 | return false; | ||
191 | |||
192 | pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); | ||
193 | pending &= AR5K_QCU_STS_FRMPENDCNT; | ||
194 | |||
195 | /* It's possible to have no frames pending even if TXE | ||
196 | * is set. To indicate that q has not stopped return | ||
197 | * true */ | ||
198 | if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) | ||
199 | return true; | ||
200 | |||
201 | return pending; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * Set a transmit queue inactive | ||
206 | */ | ||
207 | void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) | ||
208 | { | ||
209 | if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) | ||
210 | return; | ||
211 | 223 | ||
212 | /* This queue will be skipped in further operations */ | 224 | /*******************************\ |
213 | ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; | 225 | * Single QCU/DCU initialization * |
214 | /*For SIMR setup*/ | 226 | \*******************************/ |
215 | AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); | ||
216 | } | ||
217 | 227 | ||
218 | /* | 228 | /* |
219 | * Set DFS properties for a transmit queue on DCU | 229 | * Set DFS properties for a transmit queue on DCU |
@@ -512,6 +522,11 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) | |||
512 | return 0; | 522 | return 0; |
513 | } | 523 | } |
514 | 524 | ||
525 | |||
526 | /**************************\ | ||
527 | * Global QCU/DCU functions * | ||
528 | \**************************/ | ||
529 | |||
515 | /* | 530 | /* |
516 | * Set slot time on DCU | 531 | * Set slot time on DCU |
517 | */ | 532 | */ |
@@ -530,3 +545,26 @@ int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) | |||
530 | return 0; | 545 | return 0; |
531 | } | 546 | } |
532 | 547 | ||
548 | int ath5k_hw_init_queues(struct ath5k_hw *ah) | ||
549 | { | ||
550 | int i, ret; | ||
551 | |||
552 | /* TODO: HW Compression support for data queues */ | ||
553 | /* TODO: Burst prefetch for data queues */ | ||
554 | |||
555 | /* | ||
556 | * Reset queues and start beacon timers at the end of the reset routine | ||
557 | * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping | ||
558 | * Note: If we want we can assign multiple qcus on one dcu. | ||
559 | */ | ||
560 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { | ||
561 | ret = ath5k_hw_reset_tx_queue(ah, i); | ||
562 | if (ret) { | ||
563 | ATH5K_ERR(ah->ah_sc, | ||
564 | "failed to reset TX queue #%d\n", i); | ||
565 | return ret; | ||
566 | } | ||
567 | } | ||
568 | |||
569 | return 0; | ||
570 | } | ||
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 5b179d01f97..9dd5792780b 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -32,6 +32,11 @@ | |||
32 | #include "base.h" | 32 | #include "base.h" |
33 | #include "debug.h" | 33 | #include "debug.h" |
34 | 34 | ||
35 | |||
36 | /******************\ | ||
37 | * Helper functions * | ||
38 | \******************/ | ||
39 | |||
35 | /* | 40 | /* |
36 | * Check if a register write has been completed | 41 | * Check if a register write has been completed |
37 | */ | 42 | */ |
@@ -53,146 +58,165 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | |||
53 | return (i <= 0) ? -EAGAIN : 0; | 58 | return (i <= 0) ? -EAGAIN : 0; |
54 | } | 59 | } |
55 | 60 | ||
61 | |||
62 | /*************************\ | ||
63 | * Clock related functions * | ||
64 | \*************************/ | ||
65 | |||
56 | /** | 66 | /** |
57 | * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 | 67 | * ath5k_hw_htoclock - Translate usec to hw clock units |
58 | * | ||
59 | * @ah: the &struct ath5k_hw | ||
60 | * @channel: the currently set channel upon reset | ||
61 | * | 68 | * |
62 | * Write the delta slope coefficient (used on pilot tracking ?) for OFDM | 69 | * @ah: The &struct ath5k_hw |
63 | * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset(). | 70 | * @usec: value in microseconds |
64 | * | ||
65 | * Since delta slope is floating point we split it on its exponent and | ||
66 | * mantissa and provide these values on hw. | ||
67 | * | ||
68 | * For more infos i think this patent is related | ||
69 | * http://www.freepatentsonline.com/7184495.html | ||
70 | */ | 71 | */ |
71 | static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, | 72 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) |
72 | struct ieee80211_channel *channel) | ||
73 | { | 73 | { |
74 | /* Get exponent and mantissa and set it */ | 74 | struct ath_common *common = ath5k_hw_common(ah); |
75 | u32 coef_scaled, coef_exp, coef_man, | 75 | return usec * common->clockrate; |
76 | ds_coef_exp, ds_coef_man, clock; | 76 | } |
77 | |||
78 | BUG_ON(!(ah->ah_version == AR5K_AR5212) || | ||
79 | !(channel->hw_value & CHANNEL_OFDM)); | ||
80 | |||
81 | /* Get coefficient | ||
82 | * ALGO: coef = (5 * clock / carrier_freq) / 2 | ||
83 | * we scale coef by shifting clock value by 24 for | ||
84 | * better precision since we use integers */ | ||
85 | /* TODO: Half/quarter rate */ | ||
86 | clock = (channel->hw_value & CHANNEL_TURBO) ? 80 : 40; | ||
87 | coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; | ||
88 | |||
89 | /* Get exponent | ||
90 | * ALGO: coef_exp = 14 - highest set bit position */ | ||
91 | coef_exp = ilog2(coef_scaled); | ||
92 | |||
93 | /* Doesn't make sense if it's zero*/ | ||
94 | if (!coef_scaled || !coef_exp) | ||
95 | return -EINVAL; | ||
96 | |||
97 | /* Note: we've shifted coef_scaled by 24 */ | ||
98 | coef_exp = 14 - (coef_exp - 24); | ||
99 | 77 | ||
78 | /** | ||
79 | * ath5k_hw_clocktoh - Translate hw clock units to usec | ||
80 | * @clock: value in hw clock units | ||
81 | */ | ||
82 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | ||
83 | { | ||
84 | struct ath_common *common = ath5k_hw_common(ah); | ||
85 | return clock / common->clockrate; | ||
86 | } | ||
100 | 87 | ||
101 | /* Get mantissa (significant digits) | 88 | /** |
102 | * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ | 89 | * ath5k_hw_set_clockrate - Set common->clockrate for the current channel |
103 | coef_man = coef_scaled + | 90 | * |
104 | (1 << (24 - coef_exp - 1)); | 91 | * @ah: The &struct ath5k_hw |
92 | */ | ||
93 | void ath5k_hw_set_clockrate(struct ath5k_hw *ah) | ||
94 | { | ||
95 | struct ieee80211_channel *channel = ah->ah_current_channel; | ||
96 | struct ath_common *common = ath5k_hw_common(ah); | ||
97 | int clock; | ||
105 | 98 | ||
106 | /* Calculate delta slope coefficient exponent | 99 | if (channel->hw_value & CHANNEL_5GHZ) |
107 | * and mantissa (remove scaling) and set them on hw */ | 100 | clock = 40; /* 802.11a */ |
108 | ds_coef_man = coef_man >> (24 - coef_exp); | 101 | else if (channel->hw_value & CHANNEL_CCK) |
109 | ds_coef_exp = coef_exp - 16; | 102 | clock = 22; /* 802.11b */ |
103 | else | ||
104 | clock = 44; /* 802.11g */ | ||
110 | 105 | ||
111 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | 106 | /* Clock rate in turbo modes is twice the normal rate */ |
112 | AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); | 107 | if (channel->hw_value & CHANNEL_TURBO) |
113 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, | 108 | clock *= 2; |
114 | AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); | ||
115 | 109 | ||
116 | return 0; | 110 | common->clockrate = clock; |
117 | } | 111 | } |
118 | 112 | ||
119 | |||
120 | /* | 113 | /* |
121 | * index into rates for control rates, we can set it up like this because | 114 | * If there is an external 32KHz crystal available, use it |
122 | * this is only used for AR5212 and we know it supports G mode | 115 | * as ref. clock instead of 32/40MHz clock and baseband clocks |
123 | */ | 116 | * to save power during sleep or restore normal 32/40MHz |
124 | static const unsigned int control_rates[] = | 117 | * operation. |
125 | { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; | ||
126 | |||
127 | /** | ||
128 | * ath5k_hw_write_rate_duration - fill rate code to duration table | ||
129 | * | ||
130 | * @ah: the &struct ath5k_hw | ||
131 | * @mode: one of enum ath5k_driver_mode | ||
132 | * | ||
133 | * Write the rate code to duration table upon hw reset. This is a helper for | ||
134 | * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on | ||
135 | * the hardware, based on current mode, for each rate. The rates which are | ||
136 | * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have | ||
137 | * different rate code so we write their value twice (one for long preample | ||
138 | * and one for short). | ||
139 | * | 118 | * |
140 | * Note: Band doesn't matter here, if we set the values for OFDM it works | 119 | * XXX: When operating on 32KHz certain PHY registers (27 - 31, |
141 | * on both a and g modes. So all we have to do is set values for all g rates | 120 | * 123 - 127) require delay on access. |
142 | * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ | ||
143 | * quarter rate mode, we need to use another set of bitrates (that's why we | ||
144 | * need the mode parameter) but we don't handle these proprietary modes yet. | ||
145 | */ | 121 | */ |
146 | static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, | 122 | static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) |
147 | unsigned int mode) | ||
148 | { | 123 | { |
149 | struct ath5k_softc *sc = ah->ah_sc; | 124 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
150 | struct ieee80211_rate *rate; | 125 | u32 scal, spending, usec32; |
151 | unsigned int i; | 126 | |
127 | /* Only set 32KHz settings if we have an external | ||
128 | * 32KHz crystal present */ | ||
129 | if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || | ||
130 | AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && | ||
131 | enable) { | ||
132 | |||
133 | /* 1 usec/cycle */ | ||
134 | AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); | ||
135 | /* Set up tsf increment on each cycle */ | ||
136 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); | ||
137 | |||
138 | /* Set baseband sleep control registers | ||
139 | * and sleep control rate */ | ||
140 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); | ||
141 | |||
142 | if ((ah->ah_radio == AR5K_RF5112) || | ||
143 | (ah->ah_radio == AR5K_RF5413) || | ||
144 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
145 | spending = 0x14; | ||
146 | else | ||
147 | spending = 0x18; | ||
148 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); | ||
149 | |||
150 | if ((ah->ah_radio == AR5K_RF5112) || | ||
151 | (ah->ah_radio == AR5K_RF5413) || | ||
152 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { | ||
153 | ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); | ||
154 | ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); | ||
155 | ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); | ||
156 | ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); | ||
157 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | ||
158 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); | ||
159 | } else { | ||
160 | ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); | ||
161 | ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); | ||
162 | ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); | ||
163 | ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); | ||
164 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | ||
165 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); | ||
166 | } | ||
152 | 167 | ||
153 | /* Write rate duration table */ | 168 | /* Enable sleep clock operation */ |
154 | for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { | 169 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, |
155 | u32 reg; | 170 | AR5K_PCICFG_SLEEP_CLOCK_EN); |
156 | u16 tx_time; | ||
157 | 171 | ||
158 | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; | 172 | } else { |
159 | 173 | ||
160 | /* Set ACK timeout */ | 174 | /* Disable sleep clock operation and |
161 | reg = AR5K_RATE_DUR(rate->hw_value); | 175 | * restore default parameters */ |
176 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, | ||
177 | AR5K_PCICFG_SLEEP_CLOCK_EN); | ||
162 | 178 | ||
163 | /* An ACK frame consists of 10 bytes. If you add the FCS, | 179 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, |
164 | * which ieee80211_generic_frame_duration() adds, | 180 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); |
165 | * its 14 bytes. Note we use the control rate and not the | ||
166 | * actual rate for this rate. See mac80211 tx.c | ||
167 | * ieee80211_duration() for a brief description of | ||
168 | * what rate we should choose to TX ACKs. */ | ||
169 | tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, | ||
170 | NULL, 10, rate)); | ||
171 | 181 | ||
172 | ath5k_hw_reg_write(ah, tx_time, reg); | 182 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); |
183 | ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); | ||
173 | 184 | ||
174 | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) | 185 | if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) |
175 | continue; | 186 | scal = AR5K_PHY_SCAL_32MHZ_2417; |
187 | else if (ee->ee_is_hb63) | ||
188 | scal = AR5K_PHY_SCAL_32MHZ_HB63; | ||
189 | else | ||
190 | scal = AR5K_PHY_SCAL_32MHZ; | ||
191 | ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); | ||
176 | 192 | ||
177 | /* | 193 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); |
178 | * We're not distinguishing short preamble here, | 194 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); |
179 | * This is true, all we'll get is a longer value here | 195 | |
180 | * which is not necessarilly bad. We could use | 196 | if ((ah->ah_radio == AR5K_RF5112) || |
181 | * export ieee80211_frame_duration() but that needs to be | 197 | (ah->ah_radio == AR5K_RF5413) || |
182 | * fixed first to be properly used by mac802111 drivers: | 198 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) |
183 | * | 199 | spending = 0x14; |
184 | * - remove erp stuff and let the routine figure ofdm | 200 | else |
185 | * erp rates | 201 | spending = 0x18; |
186 | * - remove passing argument ieee80211_local as | 202 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); |
187 | * drivers don't have access to it | 203 | |
188 | * - move drivers using ieee80211_generic_frame_duration() | 204 | if ((ah->ah_radio == AR5K_RF5112) || |
189 | * to this | 205 | (ah->ah_radio == AR5K_RF5413)) |
190 | */ | 206 | usec32 = 39; |
191 | ath5k_hw_reg_write(ah, tx_time, | 207 | else |
192 | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); | 208 | usec32 = 31; |
209 | AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32); | ||
210 | |||
211 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); | ||
193 | } | 212 | } |
194 | } | 213 | } |
195 | 214 | ||
215 | |||
216 | /*********************\ | ||
217 | * Reset/Sleep control * | ||
218 | \*********************/ | ||
219 | |||
196 | /* | 220 | /* |
197 | * Reset chipset | 221 | * Reset chipset |
198 | */ | 222 | */ |
@@ -522,107 +546,10 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
522 | return 0; | 546 | return 0; |
523 | } | 547 | } |
524 | 548 | ||
525 | /* | ||
526 | * If there is an external 32KHz crystal available, use it | ||
527 | * as ref. clock instead of 32/40MHz clock and baseband clocks | ||
528 | * to save power during sleep or restore normal 32/40MHz | ||
529 | * operation. | ||
530 | * | ||
531 | * XXX: When operating on 32KHz certain PHY registers (27 - 31, | ||
532 | * 123 - 127) require delay on access. | ||
533 | */ | ||
534 | static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | ||
535 | { | ||
536 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | ||
537 | u32 scal, spending, usec32; | ||
538 | |||
539 | /* Only set 32KHz settings if we have an external | ||
540 | * 32KHz crystal present */ | ||
541 | if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || | ||
542 | AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && | ||
543 | enable) { | ||
544 | |||
545 | /* 1 usec/cycle */ | ||
546 | AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); | ||
547 | /* Set up tsf increment on each cycle */ | ||
548 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); | ||
549 | |||
550 | /* Set baseband sleep control registers | ||
551 | * and sleep control rate */ | ||
552 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); | ||
553 | |||
554 | if ((ah->ah_radio == AR5K_RF5112) || | ||
555 | (ah->ah_radio == AR5K_RF5413) || | ||
556 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
557 | spending = 0x14; | ||
558 | else | ||
559 | spending = 0x18; | ||
560 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); | ||
561 | |||
562 | if ((ah->ah_radio == AR5K_RF5112) || | ||
563 | (ah->ah_radio == AR5K_RF5413) || | ||
564 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { | ||
565 | ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); | ||
566 | ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); | ||
567 | ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); | ||
568 | ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); | ||
569 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | ||
570 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); | ||
571 | } else { | ||
572 | ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); | ||
573 | ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); | ||
574 | ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); | ||
575 | ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); | ||
576 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | ||
577 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); | ||
578 | } | ||
579 | 549 | ||
580 | /* Enable sleep clock operation */ | 550 | /**************************************\ |
581 | AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, | 551 | * Post-initvals register modifications * |
582 | AR5K_PCICFG_SLEEP_CLOCK_EN); | 552 | \**************************************/ |
583 | |||
584 | } else { | ||
585 | |||
586 | /* Disable sleep clock operation and | ||
587 | * restore default parameters */ | ||
588 | AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, | ||
589 | AR5K_PCICFG_SLEEP_CLOCK_EN); | ||
590 | |||
591 | AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, | ||
592 | AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); | ||
593 | |||
594 | ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); | ||
595 | ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); | ||
596 | |||
597 | if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) | ||
598 | scal = AR5K_PHY_SCAL_32MHZ_2417; | ||
599 | else if (ee->ee_is_hb63) | ||
600 | scal = AR5K_PHY_SCAL_32MHZ_HB63; | ||
601 | else | ||
602 | scal = AR5K_PHY_SCAL_32MHZ; | ||
603 | ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); | ||
604 | |||
605 | ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); | ||
606 | ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); | ||
607 | |||
608 | if ((ah->ah_radio == AR5K_RF5112) || | ||
609 | (ah->ah_radio == AR5K_RF5413) || | ||
610 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | ||
611 | spending = 0x14; | ||
612 | else | ||
613 | spending = 0x18; | ||
614 | ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); | ||
615 | |||
616 | if ((ah->ah_radio == AR5K_RF5112) || | ||
617 | (ah->ah_radio == AR5K_RF5413)) | ||
618 | usec32 = 39; | ||
619 | else | ||
620 | usec32 = 31; | ||
621 | AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32); | ||
622 | |||
623 | AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); | ||
624 | } | ||
625 | } | ||
626 | 553 | ||
627 | /* TODO: Half/Quarter rate */ | 554 | /* TODO: Half/Quarter rate */ |
628 | static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | 555 | static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, |
@@ -705,7 +632,8 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | |||
705 | ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); | 632 | ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); |
706 | } | 633 | } |
707 | 634 | ||
708 | if (ah->ah_mac_srev < AR5K_SREV_AR5211) { | 635 | if ((ah->ah_radio == AR5K_RF5112) && |
636 | (ah->ah_mac_srev < AR5K_SREV_AR5211)) { | ||
709 | u32 usec_reg; | 637 | u32 usec_reg; |
710 | /* 5311 has different tx/rx latency masks | 638 | /* 5311 has different tx/rx latency masks |
711 | * from 5211, since we deal 5311 the same | 639 | * from 5211, since we deal 5311 the same |
@@ -734,6 +662,10 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
734 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 662 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
735 | s16 cck_ofdm_pwr_delta; | 663 | s16 cck_ofdm_pwr_delta; |
736 | 664 | ||
665 | /* TODO: Add support for AR5210 EEPROM */ | ||
666 | if (ah->ah_version == AR5K_AR5210) | ||
667 | return; | ||
668 | |||
737 | /* Adjust power delta for channel 14 */ | 669 | /* Adjust power delta for channel 14 */ |
738 | if (channel->center_freq == 2484) | 670 | if (channel->center_freq == 2484) |
739 | cck_ofdm_pwr_delta = | 671 | cck_ofdm_pwr_delta = |
@@ -870,15 +802,16 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
870 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); | 802 | ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); |
871 | } | 803 | } |
872 | 804 | ||
873 | /* | 805 | |
874 | * Main reset function | 806 | /*********************\ |
875 | */ | 807 | * Main reset function * |
808 | \*********************/ | ||
809 | |||
876 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 810 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, |
877 | struct ieee80211_channel *channel, bool change_channel) | 811 | struct ieee80211_channel *channel, bool change_channel) |
878 | { | 812 | { |
879 | struct ath_common *common = ath5k_hw_common(ah); | 813 | struct ath_common *common = ath5k_hw_common(ah); |
880 | u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo; | 814 | u32 s_seq[10], s_led[3], staid1_flags, tsf_up, tsf_lo; |
881 | u32 phy_tst1; | ||
882 | u8 mode, freq, ee_mode; | 815 | u8 mode, freq, ee_mode; |
883 | int i, ret; | 816 | int i, ret; |
884 | 817 | ||
@@ -1026,93 +959,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1026 | return ret; | 959 | return ret; |
1027 | 960 | ||
1028 | /* | 961 | /* |
1029 | * 5211/5212 Specific | 962 | * Tweak initval settings for revised |
963 | * chipsets and add some more config | ||
964 | * bits | ||
1030 | */ | 965 | */ |
1031 | if (ah->ah_version != AR5K_AR5210) { | 966 | ath5k_hw_tweak_initval_settings(ah, channel); |
1032 | |||
1033 | /* | ||
1034 | * Write initial RF gain settings | ||
1035 | * This should work for both 5111/5112 | ||
1036 | */ | ||
1037 | ret = ath5k_hw_rfgain_init(ah, freq); | ||
1038 | if (ret) | ||
1039 | return ret; | ||
1040 | |||
1041 | mdelay(1); | ||
1042 | |||
1043 | /* | ||
1044 | * Tweak initval settings for revised | ||
1045 | * chipsets and add some more config | ||
1046 | * bits | ||
1047 | */ | ||
1048 | ath5k_hw_tweak_initval_settings(ah, channel); | ||
1049 | |||
1050 | /* | ||
1051 | * Set TX power | ||
1052 | */ | ||
1053 | ret = ath5k_hw_txpower(ah, channel, ee_mode, | ||
1054 | ah->ah_txpower.txp_max_pwr / 2); | ||
1055 | if (ret) | ||
1056 | return ret; | ||
1057 | |||
1058 | /* Write rate duration table only on AR5212 and if | ||
1059 | * virtual interface has already been brought up | ||
1060 | * XXX: rethink this after new mode changes to | ||
1061 | * mac80211 are integrated */ | ||
1062 | if (ah->ah_version == AR5K_AR5212 && | ||
1063 | ah->ah_sc->nvifs) | ||
1064 | ath5k_hw_write_rate_duration(ah, mode); | ||
1065 | |||
1066 | /* | ||
1067 | * Write RF buffer | ||
1068 | */ | ||
1069 | ret = ath5k_hw_rfregs_init(ah, channel, mode); | ||
1070 | if (ret) | ||
1071 | return ret; | ||
1072 | |||
1073 | |||
1074 | /* Write OFDM timings on 5212*/ | ||
1075 | if (ah->ah_version == AR5K_AR5212 && | ||
1076 | channel->hw_value & CHANNEL_OFDM) { | ||
1077 | 967 | ||
1078 | ret = ath5k_hw_write_ofdm_timings(ah, channel); | 968 | /* Commit values from EEPROM */ |
1079 | if (ret) | 969 | ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode); |
1080 | return ret; | ||
1081 | 970 | ||
1082 | /* Spur info is available only from EEPROM versions | ||
1083 | * greater than 5.3, but the EEPROM routines will use | ||
1084 | * static values for older versions */ | ||
1085 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | ||
1086 | ath5k_hw_set_spur_mitigation_filter(ah, | ||
1087 | channel); | ||
1088 | } | ||
1089 | |||
1090 | /*Enable/disable 802.11b mode on 5111 | ||
1091 | (enable 2111 frequency converter + CCK)*/ | ||
1092 | if (ah->ah_radio == AR5K_RF5111) { | ||
1093 | if (mode == AR5K_MODE_11B) | ||
1094 | AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, | ||
1095 | AR5K_TXCFG_B_MODE); | ||
1096 | else | ||
1097 | AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, | ||
1098 | AR5K_TXCFG_B_MODE); | ||
1099 | } | ||
1100 | |||
1101 | /* Commit values from EEPROM */ | ||
1102 | ath5k_hw_commit_eeprom_settings(ah, channel, ee_mode); | ||
1103 | |||
1104 | } else { | ||
1105 | /* | ||
1106 | * For 5210 we do all initialization using | ||
1107 | * initvals, so we don't have to modify | ||
1108 | * any settings (5210 also only supports | ||
1109 | * a/aturbo modes) | ||
1110 | */ | ||
1111 | mdelay(1); | ||
1112 | /* Disable phy and wait */ | ||
1113 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); | ||
1114 | mdelay(1); | ||
1115 | } | ||
1116 | 971 | ||
1117 | /* | 972 | /* |
1118 | * Restore saved values | 973 | * Restore saved values |
@@ -1156,193 +1011,38 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1156 | 1011 | ||
1157 | 1012 | ||
1158 | /* | 1013 | /* |
1159 | * Configure PCU | 1014 | * Initialize PCU |
1160 | */ | 1015 | */ |
1161 | 1016 | ath5k_hw_pcu_init(ah, op_mode, mode); | |
1162 | /* Restore bssid and bssid mask */ | ||
1163 | ath5k_hw_set_bssid(ah); | ||
1164 | |||
1165 | /* Set PCU config */ | ||
1166 | ath5k_hw_set_opmode(ah, op_mode); | ||
1167 | 1017 | ||
1168 | /* Clear any pending interrupts | 1018 | /* Clear any pending interrupts |
1169 | * PISR/SISR Not available on 5210 */ | 1019 | * PISR/SISR Not available on 5210 */ |
1170 | if (ah->ah_version != AR5K_AR5210) | 1020 | if (ah->ah_version != AR5K_AR5210) |
1171 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); | 1021 | ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); |
1172 | 1022 | ||
1173 | /* Set RSSI/BRSSI thresholds | ||
1174 | * | ||
1175 | * Note: If we decide to set this value | ||
1176 | * dynamically, keep in mind that when AR5K_RSSI_THR | ||
1177 | * register is read, it might return 0x40 if we haven't | ||
1178 | * written anything to it. Also, BMISS RSSI threshold is zeroed. | ||
1179 | * So doing a save/restore procedure here isn't the right | ||
1180 | * choice. Instead, store it in ath5k_hw */ | ||
1181 | ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | | ||
1182 | AR5K_TUNE_BMISS_THRES << | ||
1183 | AR5K_RSSI_THR_BMISS_S), | ||
1184 | AR5K_RSSI_THR); | ||
1185 | |||
1186 | /* MIC QoS support */ | ||
1187 | if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { | ||
1188 | ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); | ||
1189 | ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); | ||
1190 | } | ||
1191 | |||
1192 | /* QoS NOACK Policy */ | ||
1193 | if (ah->ah_version == AR5K_AR5212) { | ||
1194 | ath5k_hw_reg_write(ah, | ||
1195 | AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | | ||
1196 | AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | | ||
1197 | AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), | ||
1198 | AR5K_QOS_NOACK); | ||
1199 | } | ||
1200 | |||
1201 | |||
1202 | /* | 1023 | /* |
1203 | * Configure PHY | 1024 | * Initialize PHY |
1204 | */ | 1025 | */ |
1205 | 1026 | ret = ath5k_hw_phy_init(ah, channel, mode, ee_mode, freq); | |
1206 | /* Set channel on PHY */ | 1027 | if (ret) { |
1207 | ret = ath5k_hw_channel(ah, channel); | 1028 | ATH5K_ERR(ah->ah_sc, |
1208 | if (ret) | 1029 | "failed to initialize PHY (%i) !\n", ret); |
1209 | return ret; | 1030 | return ret; |
1210 | |||
1211 | /* | ||
1212 | * Enable the PHY and wait until completion | ||
1213 | * This includes BaseBand and Synthesizer | ||
1214 | * activation. | ||
1215 | */ | ||
1216 | ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); | ||
1217 | |||
1218 | /* | ||
1219 | * On 5211+ read activation -> rx delay | ||
1220 | * and use it. | ||
1221 | * | ||
1222 | * TODO: Half/quarter rate support | ||
1223 | */ | ||
1224 | if (ah->ah_version != AR5K_AR5210) { | ||
1225 | u32 delay; | ||
1226 | delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & | ||
1227 | AR5K_PHY_RX_DELAY_M; | ||
1228 | delay = (channel->hw_value & CHANNEL_CCK) ? | ||
1229 | ((delay << 2) / 22) : (delay / 10); | ||
1230 | |||
1231 | udelay(100 + (2 * delay)); | ||
1232 | } else { | ||
1233 | mdelay(1); | ||
1234 | } | ||
1235 | |||
1236 | /* | ||
1237 | * Perform ADC test to see if baseband is ready | ||
1238 | * Set TX hold and check ADC test register | ||
1239 | */ | ||
1240 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | ||
1241 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | ||
1242 | for (i = 0; i <= 20; i++) { | ||
1243 | if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) | ||
1244 | break; | ||
1245 | udelay(200); | ||
1246 | } | ||
1247 | ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); | ||
1248 | |||
1249 | /* | ||
1250 | * Start automatic gain control calibration | ||
1251 | * | ||
1252 | * During AGC calibration RX path is re-routed to | ||
1253 | * a power detector so we don't receive anything. | ||
1254 | * | ||
1255 | * This method is used to calibrate some static offsets | ||
1256 | * used together with on-the fly I/Q calibration (the | ||
1257 | * one performed via ath5k_hw_phy_calibrate), which doesn't | ||
1258 | * interrupt rx path. | ||
1259 | * | ||
1260 | * While rx path is re-routed to the power detector we also | ||
1261 | * start a noise floor calibration to measure the | ||
1262 | * card's noise floor (the noise we measure when we are not | ||
1263 | * transmitting or receiving anything). | ||
1264 | * | ||
1265 | * If we are in a noisy environment, AGC calibration may time | ||
1266 | * out and/or noise floor calibration might timeout. | ||
1267 | */ | ||
1268 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | ||
1269 | AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF); | ||
1270 | |||
1271 | /* At the same time start I/Q calibration for QAM constellation | ||
1272 | * -no need for CCK- */ | ||
1273 | ah->ah_calibration = false; | ||
1274 | if (!(mode == AR5K_MODE_11B)) { | ||
1275 | ah->ah_calibration = true; | ||
1276 | AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, | ||
1277 | AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); | ||
1278 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, | ||
1279 | AR5K_PHY_IQ_RUN); | ||
1280 | } | ||
1281 | |||
1282 | /* Wait for gain calibration to finish (we check for I/Q calibration | ||
1283 | * during ath5k_phy_calibrate) */ | ||
1284 | if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, | ||
1285 | AR5K_PHY_AGCCTL_CAL, 0, false)) { | ||
1286 | ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", | ||
1287 | channel->center_freq); | ||
1288 | } | 1031 | } |
1289 | 1032 | ||
1290 | /* Restore antenna mode */ | ||
1291 | ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); | ||
1292 | |||
1293 | /* Restore slot time and ACK timeouts */ | ||
1294 | if (ah->ah_coverage_class > 0) | ||
1295 | ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); | ||
1296 | |||
1297 | /* | 1033 | /* |
1298 | * Configure QCUs/DCUs | 1034 | * Configure QCUs/DCUs |
1299 | */ | 1035 | */ |
1036 | ret = ath5k_hw_init_queues(ah); | ||
1037 | if (ret) | ||
1038 | return ret; | ||
1300 | 1039 | ||
1301 | /* TODO: HW Compression support for data queues */ | ||
1302 | /* TODO: Burst prefetch for data queues */ | ||
1303 | |||
1304 | /* | ||
1305 | * Reset queues and start beacon timers at the end of the reset routine | ||
1306 | * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping | ||
1307 | * Note: If we want we can assign multiple qcus on one dcu. | ||
1308 | */ | ||
1309 | for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { | ||
1310 | ret = ath5k_hw_reset_tx_queue(ah, i); | ||
1311 | if (ret) { | ||
1312 | ATH5K_ERR(ah->ah_sc, | ||
1313 | "failed to reset TX queue #%d\n", i); | ||
1314 | return ret; | ||
1315 | } | ||
1316 | } | ||
1317 | |||
1318 | |||
1319 | /* | ||
1320 | * Configure DMA/Interrupts | ||
1321 | */ | ||
1322 | 1040 | ||
1323 | /* | 1041 | /* |
1324 | * Set Rx/Tx DMA Configuration | 1042 | * Initialize DMA/Interrupts |
1325 | * | ||
1326 | * Set standard DMA size (128). Note that | ||
1327 | * a DMA size of 512 causes rx overruns and tx errors | ||
1328 | * on pci-e cards (tested on 5424 but since rx overruns | ||
1329 | * also occur on 5416/5418 with madwifi we set 128 | ||
1330 | * for all PCI-E cards to be safe). | ||
1331 | * | ||
1332 | * XXX: need to check 5210 for this | ||
1333 | * TODO: Check out tx triger level, it's always 64 on dumps but I | ||
1334 | * guess we can tweak it and see how it goes ;-) | ||
1335 | */ | 1043 | */ |
1336 | if (ah->ah_version != AR5K_AR5210) { | 1044 | ath5k_hw_dma_init(ah); |
1337 | AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, | ||
1338 | AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); | ||
1339 | AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, | ||
1340 | AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); | ||
1341 | } | ||
1342 | 1045 | ||
1343 | /* Pre-enable interrupts on 5211/5212*/ | ||
1344 | if (ah->ah_version != AR5K_AR5210) | ||
1345 | ath5k_hw_set_imr(ah, ah->ah_imr); | ||
1346 | 1046 | ||
1347 | /* Enable 32KHz clock function for AR5212+ chips | 1047 | /* Enable 32KHz clock function for AR5212+ chips |
1348 | * Set clocks to 32KHz operation and use an | 1048 | * Set clocks to 32KHz operation and use an |