summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Baryshkov <dbaryshkov@gmail.com>2009-01-05 10:58:06 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-01-05 18:47:17 +0100
commit796123368871e4a838dc0dfd5dbc3cd8981ef429 (patch)
tree281f0576a8a5af9002c00e154d99d5a19759bbae
parentASoC: Clocking fixes for davinci-evm.c (diff)
downloadlinux-796123368871e4a838dc0dfd5dbc3cd8981ef429.tar.xz
linux-796123368871e4a838dc0dfd5dbc3cd8981ef429.zip
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>
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c25
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);