diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/reset.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 216 |
1 files changed, 164 insertions, 52 deletions
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index de28be4296a6..4aed3a3ab109 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -19,9 +19,9 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | /*****************************\ | 22 | /****************************\ |
23 | Reset functions and helpers | 23 | Reset function and helpers |
24 | \*****************************/ | 24 | \****************************/ |
25 | 25 | ||
26 | #include <asm/unaligned.h> | 26 | #include <asm/unaligned.h> |
27 | 27 | ||
@@ -33,14 +33,36 @@ | |||
33 | #include "debug.h" | 33 | #include "debug.h" |
34 | 34 | ||
35 | 35 | ||
36 | /** | ||
37 | * DOC: Reset function and helpers | ||
38 | * | ||
39 | * Here we implement the main reset routine, used to bring the card | ||
40 | * to a working state and ready to receive. We also handle routines | ||
41 | * that don't fit on other places such as clock, sleep and power control | ||
42 | */ | ||
43 | |||
44 | |||
36 | /******************\ | 45 | /******************\ |
37 | * Helper functions * | 46 | * Helper functions * |
38 | \******************/ | 47 | \******************/ |
39 | 48 | ||
40 | /* | 49 | /** |
41 | * Check if a register write has been completed | 50 | * ath5k_hw_register_timeout() - Poll a register for a flag/field change |
51 | * @ah: The &struct ath5k_hw | ||
52 | * @reg: The register to read | ||
53 | * @flag: The flag/field to check on the register | ||
54 | * @val: The field value we expect (if we check a field) | ||
55 | * @is_set: Instead of checking if the flag got cleared, check if it got set | ||
56 | * | ||
57 | * Some registers contain flags that indicate that an operation is | ||
58 | * running. We use this function to poll these registers and check | ||
59 | * if these flags get cleared. We also use it to poll a register | ||
60 | * field (containing multiple flags) until it gets a specific value. | ||
61 | * | ||
62 | * Returns -EAGAIN if we exceeded AR5K_TUNE_REGISTER_TIMEOUT * 15us or 0 | ||
42 | */ | 63 | */ |
43 | int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | 64 | int |
65 | ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | ||
44 | bool is_set) | 66 | bool is_set) |
45 | { | 67 | { |
46 | int i; | 68 | int i; |
@@ -64,35 +86,48 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, | |||
64 | \*************************/ | 86 | \*************************/ |
65 | 87 | ||
66 | /** | 88 | /** |
67 | * ath5k_hw_htoclock - Translate usec to hw clock units | 89 | * ath5k_hw_htoclock() - Translate usec to hw clock units |
68 | * | ||
69 | * @ah: The &struct ath5k_hw | 90 | * @ah: The &struct ath5k_hw |
70 | * @usec: value in microseconds | 91 | * @usec: value in microseconds |
92 | * | ||
93 | * Translate usecs to hw clock units based on the current | ||
94 | * hw clock rate. | ||
95 | * | ||
96 | * Returns number of clock units | ||
71 | */ | 97 | */ |
72 | unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) | 98 | unsigned int |
99 | ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) | ||
73 | { | 100 | { |
74 | struct ath_common *common = ath5k_hw_common(ah); | 101 | struct ath_common *common = ath5k_hw_common(ah); |
75 | return usec * common->clockrate; | 102 | return usec * common->clockrate; |
76 | } | 103 | } |
77 | 104 | ||
78 | /** | 105 | /** |
79 | * ath5k_hw_clocktoh - Translate hw clock units to usec | 106 | * ath5k_hw_clocktoh() - Translate hw clock units to usec |
107 | * @ah: The &struct ath5k_hw | ||
80 | * @clock: value in hw clock units | 108 | * @clock: value in hw clock units |
109 | * | ||
110 | * Translate hw clock units to usecs based on the current | ||
111 | * hw clock rate. | ||
112 | * | ||
113 | * Returns number of usecs | ||
81 | */ | 114 | */ |
82 | unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | 115 | unsigned int |
116 | ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) | ||
83 | { | 117 | { |
84 | struct ath_common *common = ath5k_hw_common(ah); | 118 | struct ath_common *common = ath5k_hw_common(ah); |
85 | return clock / common->clockrate; | 119 | return clock / common->clockrate; |
86 | } | 120 | } |
87 | 121 | ||
88 | /** | 122 | /** |
89 | * ath5k_hw_init_core_clock - Initialize core clock | 123 | * ath5k_hw_init_core_clock() - Initialize core clock |
90 | * | 124 | * @ah: The &struct ath5k_hw |
91 | * @ah The &struct ath5k_hw | ||
92 | * | 125 | * |
93 | * Initialize core clock parameters (usec, usec32, latencies etc). | 126 | * Initialize core clock parameters (usec, usec32, latencies etc), |
127 | * based on current bwmode and chipset properties. | ||
94 | */ | 128 | */ |
95 | static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) | 129 | static void |
130 | ath5k_hw_init_core_clock(struct ath5k_hw *ah) | ||
96 | { | 131 | { |
97 | struct ieee80211_channel *channel = ah->ah_current_channel; | 132 | struct ieee80211_channel *channel = ah->ah_current_channel; |
98 | struct ath_common *common = ath5k_hw_common(ah); | 133 | struct ath_common *common = ath5k_hw_common(ah); |
@@ -227,16 +262,21 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) | |||
227 | } | 262 | } |
228 | } | 263 | } |
229 | 264 | ||
230 | /* | 265 | /** |
266 | * ath5k_hw_set_sleep_clock() - Setup sleep clock operation | ||
267 | * @ah: The &struct ath5k_hw | ||
268 | * @enable: Enable sleep clock operation (false to disable) | ||
269 | * | ||
231 | * If there is an external 32KHz crystal available, use it | 270 | * If there is an external 32KHz crystal available, use it |
232 | * as ref. clock instead of 32/40MHz clock and baseband clocks | 271 | * as ref. clock instead of 32/40MHz clock and baseband clocks |
233 | * to save power during sleep or restore normal 32/40MHz | 272 | * to save power during sleep or restore normal 32/40MHz |
234 | * operation. | 273 | * operation. |
235 | * | 274 | * |
236 | * XXX: When operating on 32KHz certain PHY registers (27 - 31, | 275 | * NOTE: When operating on 32KHz certain PHY registers (27 - 31, |
237 | * 123 - 127) require delay on access. | 276 | * 123 - 127) require delay on access. |
238 | */ | 277 | */ |
239 | static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | 278 | static void |
279 | ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | ||
240 | { | 280 | { |
241 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 281 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
242 | u32 scal, spending, sclock; | 282 | u32 scal, spending, sclock; |
@@ -340,10 +380,19 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | |||
340 | * Reset/Sleep control * | 380 | * Reset/Sleep control * |
341 | \*********************/ | 381 | \*********************/ |
342 | 382 | ||
343 | /* | 383 | /** |
344 | * Reset chipset | 384 | * ath5k_hw_nic_reset() - Reset the various chipset units |
385 | * @ah: The &struct ath5k_hw | ||
386 | * @val: Mask to indicate what units to reset | ||
387 | * | ||
388 | * To reset the various chipset units we need to write | ||
389 | * the mask to AR5K_RESET_CTL and poll the register until | ||
390 | * all flags are cleared. | ||
391 | * | ||
392 | * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) | ||
345 | */ | 393 | */ |
346 | static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | 394 | static int |
395 | ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | ||
347 | { | 396 | { |
348 | int ret; | 397 | int ret; |
349 | u32 mask = val ? val : ~0U; | 398 | u32 mask = val ? val : ~0U; |
@@ -382,12 +431,17 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |||
382 | return ret; | 431 | return ret; |
383 | } | 432 | } |
384 | 433 | ||
385 | /* | 434 | /** |
386 | * Reset AHB chipset | 435 | * ath5k_hw_wisoc_reset() - Reset AHB chipset |
387 | * AR5K_RESET_CTL_PCU flag resets WMAC | 436 | * @ah: The &struct ath5k_hw |
388 | * AR5K_RESET_CTL_BASEBAND flag resets WBB | 437 | * @flags: Mask to indicate what units to reset |
438 | * | ||
439 | * Same as ath5k_hw_nic_reset but for AHB based devices | ||
440 | * | ||
441 | * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) | ||
389 | */ | 442 | */ |
390 | static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | 443 | static int |
444 | ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | ||
391 | { | 445 | { |
392 | u32 mask = flags ? flags : ~0U; | 446 | u32 mask = flags ? flags : ~0U; |
393 | u32 __iomem *reg; | 447 | u32 __iomem *reg; |
@@ -439,11 +493,23 @@ static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | |||
439 | return 0; | 493 | return 0; |
440 | } | 494 | } |
441 | 495 | ||
442 | 496 | /** | |
443 | /* | 497 | * ath5k_hw_set_power_mode() - Set power mode |
444 | * Sleep control | 498 | * @ah: The &struct ath5k_hw |
499 | * @mode: One of enum ath5k_power_mode | ||
500 | * @set_chip: Set to true to write sleep control register | ||
501 | * @sleep_duration: How much time the device is allowed to sleep | ||
502 | * when sleep logic is enabled (in 128 microsecond increments). | ||
503 | * | ||
504 | * This function is used to configure sleep policy and allowed | ||
505 | * sleep modes. For more information check out the sleep control | ||
506 | * register on reg.h and STA_ID1. | ||
507 | * | ||
508 | * Returns 0 on success, -EIO if chip didn't wake up or -EINVAL if an invalid | ||
509 | * mode is requested. | ||
445 | */ | 510 | */ |
446 | static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | 511 | static int |
512 | ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode, | ||
447 | bool set_chip, u16 sleep_duration) | 513 | bool set_chip, u16 sleep_duration) |
448 | { | 514 | { |
449 | unsigned int i; | 515 | unsigned int i; |
@@ -523,17 +589,20 @@ commit: | |||
523 | return 0; | 589 | return 0; |
524 | } | 590 | } |
525 | 591 | ||
526 | /* | 592 | /** |
527 | * Put device on hold | 593 | * ath5k_hw_on_hold() - Put device on hold |
594 | * @ah: The &struct ath5k_hw | ||
528 | * | 595 | * |
529 | * Put MAC and Baseband on warm reset and | 596 | * Put MAC and Baseband on warm reset and keep that state |
530 | * keep that state (don't clean sleep control | 597 | * (don't clean sleep control register). After this MAC |
531 | * register). After this MAC and Baseband are | 598 | * and Baseband are disabled and a full reset is needed |
532 | * disabled and a full reset is needed to come | 599 | * to come back. This way we save as much power as possible |
533 | * back. This way we save as much power as possible | ||
534 | * without putting the card on full sleep. | 600 | * without putting the card on full sleep. |
601 | * | ||
602 | * Returns 0 on success or -EIO on error | ||
535 | */ | 603 | */ |
536 | int ath5k_hw_on_hold(struct ath5k_hw *ah) | 604 | int |
605 | ath5k_hw_on_hold(struct ath5k_hw *ah) | ||
537 | { | 606 | { |
538 | struct pci_dev *pdev = ah->pdev; | 607 | struct pci_dev *pdev = ah->pdev; |
539 | u32 bus_flags; | 608 | u32 bus_flags; |
@@ -543,7 +612,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
543 | return 0; | 612 | return 0; |
544 | 613 | ||
545 | /* Make sure device is awake */ | 614 | /* Make sure device is awake */ |
546 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 615 | ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); |
547 | if (ret) { | 616 | if (ret) { |
548 | ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); | 617 | ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); |
549 | return ret; | 618 | return ret; |
@@ -575,7 +644,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
575 | } | 644 | } |
576 | 645 | ||
577 | /* ...wakeup again!*/ | 646 | /* ...wakeup again!*/ |
578 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 647 | ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); |
579 | if (ret) { | 648 | if (ret) { |
580 | ATH5K_ERR(ah, "failed to put device on hold\n"); | 649 | ATH5K_ERR(ah, "failed to put device on hold\n"); |
581 | return ret; | 650 | return ret; |
@@ -584,11 +653,18 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
584 | return ret; | 653 | return ret; |
585 | } | 654 | } |
586 | 655 | ||
587 | /* | 656 | /** |
657 | * ath5k_hw_nic_wakeup() - Force card out of sleep | ||
658 | * @ah: The &struct ath5k_hw | ||
659 | * @channel: The &struct ieee80211_channel | ||
660 | * | ||
588 | * Bring up MAC + PHY Chips and program PLL | 661 | * Bring up MAC + PHY Chips and program PLL |
589 | * Channel is NULL for the initial wakeup. | 662 | * NOTE: Channel is NULL for the initial wakeup. |
663 | * | ||
664 | * Returns 0 on success, -EIO on hw failure or -EINVAL for false channel infos | ||
590 | */ | 665 | */ |
591 | int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | 666 | int |
667 | ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | ||
592 | { | 668 | { |
593 | struct pci_dev *pdev = ah->pdev; | 669 | struct pci_dev *pdev = ah->pdev; |
594 | u32 turbo, mode, clock, bus_flags; | 670 | u32 turbo, mode, clock, bus_flags; |
@@ -600,7 +676,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
600 | 676 | ||
601 | if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) { | 677 | if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) { |
602 | /* Wakeup the device */ | 678 | /* Wakeup the device */ |
603 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 679 | ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); |
604 | if (ret) { | 680 | if (ret) { |
605 | ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); | 681 | ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); |
606 | return ret; | 682 | return ret; |
@@ -637,7 +713,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
637 | } | 713 | } |
638 | 714 | ||
639 | /* ...wakeup again!...*/ | 715 | /* ...wakeup again!...*/ |
640 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 716 | ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); |
641 | if (ret) { | 717 | if (ret) { |
642 | ATH5K_ERR(ah, "failed to resume the MAC Chip\n"); | 718 | ATH5K_ERR(ah, "failed to resume the MAC Chip\n"); |
643 | return ret; | 719 | return ret; |
@@ -755,8 +831,19 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) | |||
755 | * Post-initvals register modifications * | 831 | * Post-initvals register modifications * |
756 | \**************************************/ | 832 | \**************************************/ |
757 | 833 | ||
758 | /* TODO: Half/Quarter rate */ | 834 | /** |
759 | static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | 835 | * ath5k_hw_tweak_initval_settings() - Tweak initial settings |
836 | * @ah: The &struct ath5k_hw | ||
837 | * @channel: The &struct ieee80211_channel | ||
838 | * | ||
839 | * Some settings are not handled on initvals, e.g. bwmode | ||
840 | * settings, some phy settings, workarounds etc that in general | ||
841 | * don't fit anywhere else or are too small to introduce a separate | ||
842 | * function for each one. So we have this function to handle | ||
843 | * them all during reset and complete card's initialization. | ||
844 | */ | ||
845 | static void | ||
846 | ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | ||
760 | struct ieee80211_channel *channel) | 847 | struct ieee80211_channel *channel) |
761 | { | 848 | { |
762 | if (ah->ah_version == AR5K_AR5212 && | 849 | if (ah->ah_version == AR5K_AR5212 && |
@@ -875,7 +962,16 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | |||
875 | } | 962 | } |
876 | } | 963 | } |
877 | 964 | ||
878 | static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | 965 | /** |
966 | * ath5k_hw_commit_eeprom_settings() - Commit settings from EEPROM | ||
967 | * @ah: The &struct ath5k_hw | ||
968 | * @channel: The &struct ieee80211_channel | ||
969 | * | ||
970 | * Use settings stored on EEPROM to properly initialize the card | ||
971 | * based on various infos and per-mode calibration data. | ||
972 | */ | ||
973 | static void | ||
974 | ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | ||
879 | struct ieee80211_channel *channel) | 975 | struct ieee80211_channel *channel) |
880 | { | 976 | { |
881 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 977 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
@@ -1029,7 +1125,23 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, | |||
1029 | * Main reset function * | 1125 | * Main reset function * |
1030 | \*********************/ | 1126 | \*********************/ |
1031 | 1127 | ||
1032 | int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | 1128 | /** |
1129 | * ath5k_hw_reset() - The main reset function | ||
1130 | * @ah: The &struct ath5k_hw | ||
1131 | * @op_mode: One of enum nl80211_iftype | ||
1132 | * @channel: The &struct ieee80211_channel | ||
1133 | * @fast: Enable fast channel switching | ||
1134 | * @skip_pcu: Skip pcu initialization | ||
1135 | * | ||
1136 | * This is the function we call each time we want to (re)initialize the | ||
1137 | * card and pass new settings to hw. We also call it when hw runs into | ||
1138 | * trouble to make it come back to a working state. | ||
1139 | * | ||
1140 | * Returns 0 on success, -EINVAL on false op_mode or channel infos, or -EIO | ||
1141 | * on failure. | ||
1142 | */ | ||
1143 | int | ||
1144 | ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | ||
1033 | struct ieee80211_channel *channel, bool fast, bool skip_pcu) | 1145 | struct ieee80211_channel *channel, bool fast, bool skip_pcu) |
1034 | { | 1146 | { |
1035 | u32 s_seq[10], s_led[3], tsf_up, tsf_lo; | 1147 | u32 s_seq[10], s_led[3], tsf_up, tsf_lo; |
@@ -1242,7 +1354,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1242 | /* | 1354 | /* |
1243 | * Initialize PCU | 1355 | * Initialize PCU |
1244 | */ | 1356 | */ |
1245 | ath5k_hw_pcu_init(ah, op_mode, mode); | 1357 | ath5k_hw_pcu_init(ah, op_mode); |
1246 | 1358 | ||
1247 | /* | 1359 | /* |
1248 | * Initialize PHY | 1360 | * Initialize PHY |