Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79612336 authored by Dmitry Eremin-Solenikov's avatar Dmitry Eremin-Solenikov Committed by Mark Brown
Browse files

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: default avatarDmitry Baryshkov <dbaryshkov@gmail.com>
Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 05d5e991
Loading
Loading
Loading
Loading
+16 −9
Original line number Original line Diff line number Diff line
@@ -321,10 +321,6 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
{
{
	int ret;
	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()) {
	if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
		pxa_gpio_mode(GPIO30_SDATA_OUT_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)) {
		if (IS_ERR(ac97conf_clk)) {
			ret = PTR_ERR(ac97conf_clk);
			ret = PTR_ERR(ac97conf_clk);
			ac97conf_clk = NULL;
			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)) {
	if (IS_ERR(ac97_clk)) {
		ret = PTR_ERR(ac97_clk);
		ret = PTR_ERR(ac97_clk);
		ac97_clk = NULL;
		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:
err_irq:
	GCR |= GCR_ACLINK_OFF;
	GCR |= GCR_ACLINK_OFF;
err_clk2:
	clk_put(ac97_clk);
	ac97_clk = NULL;
err_clk:
	if (ac97conf_clk) {
	if (ac97conf_clk) {
		clk_put(ac97conf_clk);
		clk_put(ac97conf_clk);
		ac97conf_clk = NULL;
		ac97conf_clk = NULL;
	}
	}
	free_irq(IRQ_AC97, NULL);
err_conf:
err:
	return ret;
	return ret;
}
}
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);
EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);