diff options
author | Felix Fietkau <nbd@openwrt.org> | 2010-12-02 04:27:21 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-12-02 15:17:51 -0500 |
commit | 4cebb34caa5122216a1e2451eae9e0fc47ec2589 (patch) | |
tree | 7a4281d259e127270d0a68d0aa8a9a178e897781 /drivers/net/wireless/ath/ath5k/reset.c | |
parent | a0b907ee2a71052fefdf6151764095f3f97b3275 (diff) |
ath5k: Fix reset and interrupts for AHB type of devices.
On WiSoc we cannot access mac register before it is resetted.
It will crash hardware otherwise.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Wojciech Dubowik <Wojciech.Dubowik@neratec.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/reset.c')
-rw-r--r-- | drivers/net/wireless/ath/ath5k/reset.c | 103 |
1 files changed, 91 insertions, 12 deletions
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index f2f889d0cf59..bc84aaa31446 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | #include <linux/pci.h> /* To determine if a card is pci-e */ | 28 | #include <linux/pci.h> /* To determine if a card is pci-e */ |
29 | #include <linux/log2.h> | 29 | #include <linux/log2.h> |
30 | #include <linux/platform_device.h> | ||
30 | #include "ath5k.h" | 31 | #include "ath5k.h" |
31 | #include "reg.h" | 32 | #include "reg.h" |
32 | #include "base.h" | 33 | #include "base.h" |
@@ -141,7 +142,9 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) | |||
141 | 142 | ||
142 | /* Set 32MHz USEC counter */ | 143 | /* Set 32MHz USEC counter */ |
143 | if ((ah->ah_radio == AR5K_RF5112) || | 144 | if ((ah->ah_radio == AR5K_RF5112) || |
144 | (ah->ah_radio == AR5K_RF5413)) | 145 | (ah->ah_radio == AR5K_RF5413) || |
146 | (ah->ah_radio == AR5K_RF2316) || | ||
147 | (ah->ah_radio == AR5K_RF2317)) | ||
145 | /* Remain on 40MHz clock ? */ | 148 | /* Remain on 40MHz clock ? */ |
146 | sclock = 40 - 1; | 149 | sclock = 40 - 1; |
147 | else | 150 | else |
@@ -244,6 +247,7 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | |||
244 | 247 | ||
245 | if ((ah->ah_radio == AR5K_RF5112) || | 248 | if ((ah->ah_radio == AR5K_RF5112) || |
246 | (ah->ah_radio == AR5K_RF5413) || | 249 | (ah->ah_radio == AR5K_RF5413) || |
250 | (ah->ah_radio == AR5K_RF2316) || | ||
247 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | 251 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) |
248 | spending = 0x14; | 252 | spending = 0x14; |
249 | else | 253 | else |
@@ -299,6 +303,7 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) | |||
299 | 303 | ||
300 | if ((ah->ah_radio == AR5K_RF5112) || | 304 | if ((ah->ah_radio == AR5K_RF5112) || |
301 | (ah->ah_radio == AR5K_RF5413) || | 305 | (ah->ah_radio == AR5K_RF5413) || |
306 | (ah->ah_radio == AR5K_RF2316) || | ||
302 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) | 307 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) |
303 | spending = 0x14; | 308 | spending = 0x14; |
304 | else | 309 | else |
@@ -358,6 +363,64 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) | |||
358 | } | 363 | } |
359 | 364 | ||
360 | /* | 365 | /* |
366 | * Reset AHB chipset | ||
367 | * AR5K_RESET_CTL_PCU flag resets WMAC | ||
368 | * AR5K_RESET_CTL_BASEBAND flag resets WBB | ||
369 | */ | ||
370 | static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) | ||
371 | { | ||
372 | u32 mask = flags ? flags : ~0U; | ||
373 | volatile u32 *reg; | ||
374 | u32 regval; | ||
375 | u32 val = 0; | ||
376 | |||
377 | /* ah->ah_mac_srev is not available at this point yet */ | ||
378 | if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) { | ||
379 | reg = (u32 *) AR5K_AR2315_RESET; | ||
380 | if (mask & AR5K_RESET_CTL_PCU) | ||
381 | val |= AR5K_AR2315_RESET_WMAC; | ||
382 | if (mask & AR5K_RESET_CTL_BASEBAND) | ||
383 | val |= AR5K_AR2315_RESET_BB_WARM; | ||
384 | } else { | ||
385 | reg = (u32 *) AR5K_AR5312_RESET; | ||
386 | if (to_platform_device(ah->ah_sc->dev)->id == 0) { | ||
387 | if (mask & AR5K_RESET_CTL_PCU) | ||
388 | val |= AR5K_AR5312_RESET_WMAC0; | ||
389 | if (mask & AR5K_RESET_CTL_BASEBAND) | ||
390 | val |= AR5K_AR5312_RESET_BB0_COLD | | ||
391 | AR5K_AR5312_RESET_BB0_WARM; | ||
392 | } else { | ||
393 | if (mask & AR5K_RESET_CTL_PCU) | ||
394 | val |= AR5K_AR5312_RESET_WMAC1; | ||
395 | if (mask & AR5K_RESET_CTL_BASEBAND) | ||
396 | val |= AR5K_AR5312_RESET_BB1_COLD | | ||
397 | AR5K_AR5312_RESET_BB1_WARM; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | /* Put BB/MAC into reset */ | ||
402 | regval = __raw_readl(reg); | ||
403 | __raw_writel(regval | val, reg); | ||
404 | regval = __raw_readl(reg); | ||
405 | udelay(100); | ||
406 | |||
407 | /* Bring BB/MAC out of reset */ | ||
408 | __raw_writel(regval & ~val, reg); | ||
409 | regval = __raw_readl(reg); | ||
410 | |||
411 | /* | ||
412 | * Reset configuration register (for hw byte-swap). Note that this | ||
413 | * is only set for big endian. We do the necessary magic in | ||
414 | * AR5K_INIT_CFG. | ||
415 | */ | ||
416 | if ((flags & AR5K_RESET_CTL_PCU) == 0) | ||
417 | ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | |||
423 | /* | ||
361 | * Sleep control | 424 | * Sleep control |
362 | */ | 425 | */ |
363 | static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, | 426 | static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, |
@@ -456,6 +519,9 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah) | |||
456 | u32 bus_flags; | 519 | u32 bus_flags; |
457 | int ret; | 520 | int ret; |
458 | 521 | ||
522 | if (ath5k_get_bus_type(ah) == ATH_AHB) | ||
523 | return 0; | ||
524 | |||
459 | /* Make sure device is awake */ | 525 | /* Make sure device is awake */ |
460 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 526 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); |
461 | if (ret) { | 527 | if (ret) { |
@@ -511,11 +577,13 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
511 | mode = 0; | 577 | mode = 0; |
512 | clock = 0; | 578 | clock = 0; |
513 | 579 | ||
514 | /* Wakeup the device */ | 580 | if ((ath5k_get_bus_type(ah) != ATH_AHB) || !initial) { |
515 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); | 581 | /* Wakeup the device */ |
516 | if (ret) { | 582 | ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); |
517 | ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); | 583 | if (ret) { |
518 | return ret; | 584 | ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); |
585 | return ret; | ||
586 | } | ||
519 | } | 587 | } |
520 | 588 | ||
521 | /* | 589 | /* |
@@ -534,8 +602,12 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
534 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); | 602 | AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); |
535 | mdelay(2); | 603 | mdelay(2); |
536 | } else { | 604 | } else { |
537 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | 605 | if (ath5k_get_bus_type(ah) == ATH_AHB) |
538 | AR5K_RESET_CTL_BASEBAND | bus_flags); | 606 | ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | |
607 | AR5K_RESET_CTL_BASEBAND); | ||
608 | else | ||
609 | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | | ||
610 | AR5K_RESET_CTL_BASEBAND | bus_flags); | ||
539 | } | 611 | } |
540 | 612 | ||
541 | if (ret) { | 613 | if (ret) { |
@@ -550,9 +622,15 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) | |||
550 | return ret; | 622 | return ret; |
551 | } | 623 | } |
552 | 624 | ||
553 | /* ...clear reset control register and pull device out of | 625 | /* ...reset configuration regiter on Wisoc ... |
554 | * warm reset */ | 626 | * ...clear reset control register and pull device out of |
555 | if (ath5k_hw_nic_reset(ah, 0)) { | 627 | * warm reset on others */ |
628 | if (ath5k_get_bus_type(ah) == ATH_AHB) | ||
629 | ret = ath5k_hw_wisoc_reset(ah, 0); | ||
630 | else | ||
631 | ret = ath5k_hw_nic_reset(ah, 0); | ||
632 | |||
633 | if (ret) { | ||
556 | ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); | 634 | ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); |
557 | return -EIO; | 635 | return -EIO; |
558 | } | 636 | } |
@@ -708,7 +786,8 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, | |||
708 | 786 | ||
709 | /* Set fast ADC */ | 787 | /* Set fast ADC */ |
710 | if ((ah->ah_radio == AR5K_RF5413) || | 788 | if ((ah->ah_radio == AR5K_RF5413) || |
711 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { | 789 | (ah->ah_radio == AR5K_RF2317) || |
790 | (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { | ||
712 | u32 fast_adc = true; | 791 | u32 fast_adc = true; |
713 | 792 | ||
714 | if (channel->center_freq == 2462 || | 793 | if (channel->center_freq == 2462 || |