diff options
author | Dmitry Baryshkov <dbaryshkov@gmail.com> | 2009-01-05 12:58:06 +0300 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-01-05 17:47:17 +0000 |
commit | 796123368871e4a838dc0dfd5dbc3cd8981ef429 (patch) | |
tree | 281f0576a8a5af9002c00e154d99d5a19759bbae /sound | |
parent | 05d5e991a7290807e7d62a7d272bb4f37c27c6ae (diff) | |
download | linux-796123368871e4a838dc0dfd5dbc3cd8981ef429.tar.bz2 |
pxa2xx-ac97: switch AC unit to correct state before probing
If AC97 unit is in partially enabled state, early request_irq can trigger
IRQ storm or even full hang up. Workaround this by forcibly switching ACLINK off
at the start of the probe.
Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/arm/pxa2xx-ac97-lib.c | 25 |
1 files changed, 16 insertions, 9 deletions
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index ef6539eea579..35afd0c33be5 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -321,10 +321,6 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) { int ret; - ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL); - if (ret < 0) - goto err; - if (cpu_is_pxa25x() || cpu_is_pxa27x()) { pxa_gpio_mode(GPIO31_SYNC_AC97_MD); pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD); @@ -339,7 +335,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) if (IS_ERR(ac97conf_clk)) { ret = PTR_ERR(ac97conf_clk); ac97conf_clk = NULL; - goto err_irq; + goto err_conf; } } @@ -347,19 +343,30 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) if (IS_ERR(ac97_clk)) { ret = PTR_ERR(ac97_clk); ac97_clk = NULL; - goto err_irq; + goto err_clk; } - return clk_enable(ac97_clk); + ret = clk_enable(ac97_clk); + if (ret) + goto err_clk2; + + ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL); + if (ret < 0) + goto err_irq; + + return 0; err_irq: GCR |= GCR_ACLINK_OFF; +err_clk2: + clk_put(ac97_clk); + ac97_clk = NULL; +err_clk: if (ac97conf_clk) { clk_put(ac97conf_clk); ac97conf_clk = NULL; } - free_irq(IRQ_AC97, NULL); -err: +err_conf: return ret; } EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); |