aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-12-02 04:27:21 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-02 15:17:51 -0500
commit4cebb34caa5122216a1e2451eae9e0fc47ec2589 (patch)
tree7a4281d259e127270d0a68d0aa8a9a178e897781 /drivers
parenta0b907ee2a71052fefdf6151764095f3f97b3275 (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')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c7
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c103
2 files changed, 97 insertions, 13 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 685de2d7572..0a7071a6dd7 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2148,7 +2148,8 @@ ath5k_intr(int irq, void *dev_id)
2148 unsigned int counter = 1000; 2148 unsigned int counter = 1000;
2149 2149
2150 if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || 2150 if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
2151 !ath5k_hw_is_intr_pending(ah))) 2151 ((ath5k_get_bus_type(ah) != ATH_AHB) &&
2152 !ath5k_hw_is_intr_pending(ah))))
2152 return IRQ_NONE; 2153 return IRQ_NONE;
2153 2154
2154 do { 2155 do {
@@ -2214,6 +2215,10 @@ ath5k_intr(int irq, void *dev_id)
2214 tasklet_schedule(&sc->rf_kill.toggleq); 2215 tasklet_schedule(&sc->rf_kill.toggleq);
2215 2216
2216 } 2217 }
2218
2219 if (ath5k_get_bus_type(ah) == ATH_AHB)
2220 break;
2221
2217 } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); 2222 } while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
2218 2223
2219 if (unlikely(!counter)) 2224 if (unlikely(!counter))
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index f2f889d0cf5..bc84aaa3144 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 */
370static 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 */
363static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, 426static 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 ||