xref: /openbmc/linux/sound/arm/pxa2xx-ac97-lib.c (revision d2912cb15bdda8ba4a5dd73396ad62641af2f520)
1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29c636342SDmitry Baryshkov /*
39c636342SDmitry Baryshkov  * Based on sound/arm/pxa2xx-ac97.c and sound/soc/pxa/pxa2xx-ac97.c
49c636342SDmitry Baryshkov  * which contain:
59c636342SDmitry Baryshkov  *
69c636342SDmitry Baryshkov  * Author:	Nicolas Pitre
79c636342SDmitry Baryshkov  * Created:	Dec 02, 2004
89c636342SDmitry Baryshkov  * Copyright:	MontaVista Software Inc.
99c636342SDmitry Baryshkov  */
109c636342SDmitry Baryshkov 
119c636342SDmitry Baryshkov #include <linux/kernel.h>
129c636342SDmitry Baryshkov #include <linux/platform_device.h>
139c636342SDmitry Baryshkov #include <linux/interrupt.h>
149c636342SDmitry Baryshkov #include <linux/clk.h>
159c636342SDmitry Baryshkov #include <linux/delay.h>
16da155d5bSPaul Gortmaker #include <linux/module.h>
1723019a73SRob Herring #include <linux/io.h>
183b4bc7bcSMike Dunn #include <linux/gpio.h>
19a4519526SRobert Jarzmik #include <linux/of_gpio.h>
209c636342SDmitry Baryshkov 
219c636342SDmitry Baryshkov #include <sound/pxa2xx-lib.h>
229c636342SDmitry Baryshkov 
239482ee71SRob Herring #include <mach/irqs.h>
241f017a99SEric Miao #include <mach/regs-ac97.h>
259c636342SDmitry Baryshkov #include <mach/audio.h>
269c636342SDmitry Baryshkov 
279c636342SDmitry Baryshkov static DEFINE_MUTEX(car_mutex);
289c636342SDmitry Baryshkov static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
299c636342SDmitry Baryshkov static volatile long gsr_bits;
309c636342SDmitry Baryshkov static struct clk *ac97_clk;
319c636342SDmitry Baryshkov static struct clk *ac97conf_clk;
3226ade896SRobert Jarzmik static int reset_gpio;
339c636342SDmitry Baryshkov 
34053fe0f1SMike Dunn extern void pxa27x_configure_ac97reset(int reset_gpio, bool to_gpio);
35fb1bf8cdSEric Miao 
369c636342SDmitry Baryshkov /*
379c636342SDmitry Baryshkov  * Beware PXA27x bugs:
389c636342SDmitry Baryshkov  *
399c636342SDmitry Baryshkov  *   o Slot 12 read from modem space will hang controller.
409c636342SDmitry Baryshkov  *   o CDONE, SDONE interrupt fails after any slot 12 IO.
419c636342SDmitry Baryshkov  *
429c636342SDmitry Baryshkov  * We therefore have an hybrid approach for waiting on SDONE (interrupt or
439c636342SDmitry Baryshkov  * 1 jiffy timeout if interrupt never comes).
449c636342SDmitry Baryshkov  */
459c636342SDmitry Baryshkov 
466f8acad6SRobert Jarzmik int pxa2xx_ac97_read(int slot, unsigned short reg)
479c636342SDmitry Baryshkov {
486f8acad6SRobert Jarzmik 	int val = -ENODEV;
499c636342SDmitry Baryshkov 	volatile u32 *reg_addr;
509c636342SDmitry Baryshkov 
516f8acad6SRobert Jarzmik 	if (slot > 0)
526f8acad6SRobert Jarzmik 		return -ENODEV;
536f8acad6SRobert Jarzmik 
549c636342SDmitry Baryshkov 	mutex_lock(&car_mutex);
559c636342SDmitry Baryshkov 
569c636342SDmitry Baryshkov 	/* set up primary or secondary codec space */
578825e8e8SMarc Zyngier 	if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
586f8acad6SRobert Jarzmik 		reg_addr = slot ? &SMC_REG_BASE : &PMC_REG_BASE;
599c636342SDmitry Baryshkov 	else
606f8acad6SRobert Jarzmik 		reg_addr = slot ? &SAC_REG_BASE : &PAC_REG_BASE;
619c636342SDmitry Baryshkov 	reg_addr += (reg >> 1);
629c636342SDmitry Baryshkov 
639c636342SDmitry Baryshkov 	/* start read access across the ac97 link */
649c636342SDmitry Baryshkov 	GSR = GSR_CDONE | GSR_SDONE;
659c636342SDmitry Baryshkov 	gsr_bits = 0;
666f8acad6SRobert Jarzmik 	val = (*reg_addr & 0xffff);
679c636342SDmitry Baryshkov 	if (reg == AC97_GPIO_STATUS)
689c636342SDmitry Baryshkov 		goto out;
699c636342SDmitry Baryshkov 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 &&
709c636342SDmitry Baryshkov 	    !((GSR | gsr_bits) & GSR_SDONE)) {
719c636342SDmitry Baryshkov 		printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n",
729c636342SDmitry Baryshkov 				__func__, reg, GSR | gsr_bits);
736f8acad6SRobert Jarzmik 		val = -ETIMEDOUT;
749c636342SDmitry Baryshkov 		goto out;
759c636342SDmitry Baryshkov 	}
769c636342SDmitry Baryshkov 
779c636342SDmitry Baryshkov 	/* valid data now */
789c636342SDmitry Baryshkov 	GSR = GSR_CDONE | GSR_SDONE;
799c636342SDmitry Baryshkov 	gsr_bits = 0;
806f8acad6SRobert Jarzmik 	val = (*reg_addr & 0xffff);
819c636342SDmitry Baryshkov 	/* but we've just started another cycle... */
829c636342SDmitry Baryshkov 	wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
839c636342SDmitry Baryshkov 
849c636342SDmitry Baryshkov out:	mutex_unlock(&car_mutex);
859c636342SDmitry Baryshkov 	return val;
869c636342SDmitry Baryshkov }
879c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_read);
889c636342SDmitry Baryshkov 
896f8acad6SRobert Jarzmik int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val)
909c636342SDmitry Baryshkov {
919c636342SDmitry Baryshkov 	volatile u32 *reg_addr;
926f8acad6SRobert Jarzmik 	int ret = 0;
939c636342SDmitry Baryshkov 
949c636342SDmitry Baryshkov 	mutex_lock(&car_mutex);
959c636342SDmitry Baryshkov 
969c636342SDmitry Baryshkov 	/* set up primary or secondary codec space */
978825e8e8SMarc Zyngier 	if (cpu_is_pxa25x() && reg == AC97_GPIO_STATUS)
986f8acad6SRobert Jarzmik 		reg_addr = slot ? &SMC_REG_BASE : &PMC_REG_BASE;
999c636342SDmitry Baryshkov 	else
1006f8acad6SRobert Jarzmik 		reg_addr = slot ? &SAC_REG_BASE : &PAC_REG_BASE;
1019c636342SDmitry Baryshkov 	reg_addr += (reg >> 1);
1029c636342SDmitry Baryshkov 
1039c636342SDmitry Baryshkov 	GSR = GSR_CDONE | GSR_SDONE;
1049c636342SDmitry Baryshkov 	gsr_bits = 0;
1059c636342SDmitry Baryshkov 	*reg_addr = val;
1069c636342SDmitry Baryshkov 	if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 &&
1076f8acad6SRobert Jarzmik 	    !((GSR | gsr_bits) & GSR_CDONE)) {
1089c636342SDmitry Baryshkov 		printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n",
1099c636342SDmitry Baryshkov 				__func__, reg, GSR | gsr_bits);
1106f8acad6SRobert Jarzmik 		ret = -EIO;
1116f8acad6SRobert Jarzmik 	}
1129c636342SDmitry Baryshkov 
1139c636342SDmitry Baryshkov 	mutex_unlock(&car_mutex);
1146f8acad6SRobert Jarzmik 	return ret;
1159c636342SDmitry Baryshkov }
1169c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_write);
1179c636342SDmitry Baryshkov 
1189d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA25x
1199d1cf39bSDmitry Baryshkov static inline void pxa_ac97_warm_pxa25x(void)
1209c636342SDmitry Baryshkov {
1219c636342SDmitry Baryshkov 	gsr_bits = 0;
1229c636342SDmitry Baryshkov 
123beb02cddSDmitry Eremin-Solenikov 	GCR |= GCR_WARM_RST;
1249d1cf39bSDmitry Baryshkov }
1259d1cf39bSDmitry Baryshkov 
1269d1cf39bSDmitry Baryshkov static inline void pxa_ac97_cold_pxa25x(void)
1279d1cf39bSDmitry Baryshkov {
1289d1cf39bSDmitry Baryshkov 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
1299d1cf39bSDmitry Baryshkov 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
1309d1cf39bSDmitry Baryshkov 
1319d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
1329d1cf39bSDmitry Baryshkov 
1339d1cf39bSDmitry Baryshkov 	GCR = GCR_COLD_RST;
1349d1cf39bSDmitry Baryshkov }
1359d1cf39bSDmitry Baryshkov #endif
1369d1cf39bSDmitry Baryshkov 
1379c636342SDmitry Baryshkov #ifdef CONFIG_PXA27x
1389d1cf39bSDmitry Baryshkov static inline void pxa_ac97_warm_pxa27x(void)
1399d1cf39bSDmitry Baryshkov {
1409d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
1419d1cf39bSDmitry Baryshkov 
142fb1bf8cdSEric Miao 	/* warm reset broken on Bulverde, so manually keep AC97 reset high */
143053fe0f1SMike Dunn 	pxa27x_configure_ac97reset(reset_gpio, true);
1449c636342SDmitry Baryshkov 	udelay(10);
1459c636342SDmitry Baryshkov 	GCR |= GCR_WARM_RST;
146053fe0f1SMike Dunn 	pxa27x_configure_ac97reset(reset_gpio, false);
1479c636342SDmitry Baryshkov 	udelay(500);
1489d1cf39bSDmitry Baryshkov }
1499d1cf39bSDmitry Baryshkov 
1509d1cf39bSDmitry Baryshkov static inline void pxa_ac97_cold_pxa27x(void)
1519d1cf39bSDmitry Baryshkov {
1529d1cf39bSDmitry Baryshkov 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
1539d1cf39bSDmitry Baryshkov 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
1549d1cf39bSDmitry Baryshkov 
1559d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
1569d1cf39bSDmitry Baryshkov 
1579d1cf39bSDmitry Baryshkov 	/* PXA27x Developers Manual section 13.5.2.2.1 */
1584091d342SRobert Jarzmik 	clk_prepare_enable(ac97conf_clk);
1599d1cf39bSDmitry Baryshkov 	udelay(5);
1604091d342SRobert Jarzmik 	clk_disable_unprepare(ac97conf_clk);
16141b645c8SMike Dunn 	GCR = GCR_COLD_RST | GCR_WARM_RST;
1629d1cf39bSDmitry Baryshkov }
1639d1cf39bSDmitry Baryshkov #endif
1649d1cf39bSDmitry Baryshkov 
1659d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA3xx
1669d1cf39bSDmitry Baryshkov static inline void pxa_ac97_warm_pxa3xx(void)
1679d1cf39bSDmitry Baryshkov {
1689d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
1699d1cf39bSDmitry Baryshkov 
1709c636342SDmitry Baryshkov 	/* Can't use interrupts */
1719c636342SDmitry Baryshkov 	GCR |= GCR_WARM_RST;
1729d1cf39bSDmitry Baryshkov }
1739d1cf39bSDmitry Baryshkov 
1749d1cf39bSDmitry Baryshkov static inline void pxa_ac97_cold_pxa3xx(void)
1759d1cf39bSDmitry Baryshkov {
1769d1cf39bSDmitry Baryshkov 	/* Hold CLKBPB for 100us */
1779d1cf39bSDmitry Baryshkov 	GCR = 0;
1789d1cf39bSDmitry Baryshkov 	GCR = GCR_CLKBPB;
1799d1cf39bSDmitry Baryshkov 	udelay(100);
1809d1cf39bSDmitry Baryshkov 	GCR = 0;
1819d1cf39bSDmitry Baryshkov 
1829d1cf39bSDmitry Baryshkov 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
1839d1cf39bSDmitry Baryshkov 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
1849d1cf39bSDmitry Baryshkov 
1859d1cf39bSDmitry Baryshkov 	gsr_bits = 0;
1869d1cf39bSDmitry Baryshkov 
1879d1cf39bSDmitry Baryshkov 	/* Can't use interrupts on PXA3xx */
1889d1cf39bSDmitry Baryshkov 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
1899d1cf39bSDmitry Baryshkov 
1909d1cf39bSDmitry Baryshkov 	GCR = GCR_WARM_RST | GCR_COLD_RST;
1919d1cf39bSDmitry Baryshkov }
1929c636342SDmitry Baryshkov #endif
1939c636342SDmitry Baryshkov 
1946f8acad6SRobert Jarzmik bool pxa2xx_ac97_try_warm_reset(void)
1959d1cf39bSDmitry Baryshkov {
196057de50cSLuotao Fu 	unsigned long gsr;
197beb02cddSDmitry Eremin-Solenikov 	unsigned int timeout = 100;
198057de50cSLuotao Fu 
1999d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA25x
2008825e8e8SMarc Zyngier 	if (cpu_is_pxa25x())
2019d1cf39bSDmitry Baryshkov 		pxa_ac97_warm_pxa25x();
2029d1cf39bSDmitry Baryshkov 	else
2039d1cf39bSDmitry Baryshkov #endif
2049d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA27x
2059d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa27x())
2069d1cf39bSDmitry Baryshkov 		pxa_ac97_warm_pxa27x();
2079d1cf39bSDmitry Baryshkov 	else
2089d1cf39bSDmitry Baryshkov #endif
2099d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA3xx
2109d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa3xx())
2119d1cf39bSDmitry Baryshkov 		pxa_ac97_warm_pxa3xx();
2129d1cf39bSDmitry Baryshkov 	else
2139d1cf39bSDmitry Baryshkov #endif
21488ec7ae8STakashi Iwai 		snd_BUG();
215beb02cddSDmitry Eremin-Solenikov 
216beb02cddSDmitry Eremin-Solenikov 	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
217beb02cddSDmitry Eremin-Solenikov 		mdelay(1);
218beb02cddSDmitry Eremin-Solenikov 
219057de50cSLuotao Fu 	gsr = GSR | gsr_bits;
220057de50cSLuotao Fu 	if (!(gsr & (GSR_PCR | GSR_SCR))) {
2219c636342SDmitry Baryshkov 		printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
222057de50cSLuotao Fu 				 __func__, gsr);
2239c636342SDmitry Baryshkov 
2249c636342SDmitry Baryshkov 		return false;
2259c636342SDmitry Baryshkov 	}
2269c636342SDmitry Baryshkov 
2279c636342SDmitry Baryshkov 	return true;
2289c636342SDmitry Baryshkov }
2299c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
2309c636342SDmitry Baryshkov 
2316f8acad6SRobert Jarzmik bool pxa2xx_ac97_try_cold_reset(void)
2329c636342SDmitry Baryshkov {
233057de50cSLuotao Fu 	unsigned long gsr;
234beb02cddSDmitry Eremin-Solenikov 	unsigned int timeout = 1000;
235057de50cSLuotao Fu 
2369d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA25x
2378825e8e8SMarc Zyngier 	if (cpu_is_pxa25x())
2389d1cf39bSDmitry Baryshkov 		pxa_ac97_cold_pxa25x();
2399d1cf39bSDmitry Baryshkov 	else
2409c636342SDmitry Baryshkov #endif
2419c636342SDmitry Baryshkov #ifdef CONFIG_PXA27x
2429d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa27x())
2439d1cf39bSDmitry Baryshkov 		pxa_ac97_cold_pxa27x();
2449d1cf39bSDmitry Baryshkov 	else
2459c636342SDmitry Baryshkov #endif
2469d1cf39bSDmitry Baryshkov #ifdef CONFIG_PXA3xx
2479d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa3xx())
2489d1cf39bSDmitry Baryshkov 		pxa_ac97_cold_pxa3xx();
2499d1cf39bSDmitry Baryshkov 	else
2509d1cf39bSDmitry Baryshkov #endif
25188ec7ae8STakashi Iwai 		snd_BUG();
2529c636342SDmitry Baryshkov 
253beb02cddSDmitry Eremin-Solenikov 	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
254beb02cddSDmitry Eremin-Solenikov 		mdelay(1);
255beb02cddSDmitry Eremin-Solenikov 
256057de50cSLuotao Fu 	gsr = GSR | gsr_bits;
257057de50cSLuotao Fu 	if (!(gsr & (GSR_PCR | GSR_SCR))) {
2589c636342SDmitry Baryshkov 		printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
259057de50cSLuotao Fu 				 __func__, gsr);
2609c636342SDmitry Baryshkov 
2619c636342SDmitry Baryshkov 		return false;
2629c636342SDmitry Baryshkov 	}
2639c636342SDmitry Baryshkov 
2649c636342SDmitry Baryshkov 	return true;
2659c636342SDmitry Baryshkov }
2669c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset);
2679c636342SDmitry Baryshkov 
2689c636342SDmitry Baryshkov 
2696f8acad6SRobert Jarzmik void pxa2xx_ac97_finish_reset(void)
2709c636342SDmitry Baryshkov {
2719c636342SDmitry Baryshkov 	GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
2729c636342SDmitry Baryshkov 	GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
2739c636342SDmitry Baryshkov }
2749c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_finish_reset);
2759c636342SDmitry Baryshkov 
2769c636342SDmitry Baryshkov static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
2779c636342SDmitry Baryshkov {
2789c636342SDmitry Baryshkov 	long status;
2799c636342SDmitry Baryshkov 
2809c636342SDmitry Baryshkov 	status = GSR;
2819c636342SDmitry Baryshkov 	if (status) {
2829c636342SDmitry Baryshkov 		GSR = status;
2839c636342SDmitry Baryshkov 		gsr_bits |= status;
2849c636342SDmitry Baryshkov 		wake_up(&gsr_wq);
2859c636342SDmitry Baryshkov 
2869c636342SDmitry Baryshkov 		/* Although we don't use those we still need to clear them
2879c636342SDmitry Baryshkov 		   since they tend to spuriously trigger when MMC is used
2889c636342SDmitry Baryshkov 		   (hardware bug? go figure)... */
2899d1cf39bSDmitry Baryshkov 		if (cpu_is_pxa27x()) {
2909c636342SDmitry Baryshkov 			MISR = MISR_EOC;
2919c636342SDmitry Baryshkov 			PISR = PISR_EOC;
2929c636342SDmitry Baryshkov 			MCSR = MCSR_EOC;
2939d1cf39bSDmitry Baryshkov 		}
2949c636342SDmitry Baryshkov 
2959c636342SDmitry Baryshkov 		return IRQ_HANDLED;
2969c636342SDmitry Baryshkov 	}
2979c636342SDmitry Baryshkov 
2989c636342SDmitry Baryshkov 	return IRQ_NONE;
2999c636342SDmitry Baryshkov }
3009c636342SDmitry Baryshkov 
3019c636342SDmitry Baryshkov #ifdef CONFIG_PM
3029c636342SDmitry Baryshkov int pxa2xx_ac97_hw_suspend(void)
3039c636342SDmitry Baryshkov {
3049c636342SDmitry Baryshkov 	GCR |= GCR_ACLINK_OFF;
3054091d342SRobert Jarzmik 	clk_disable_unprepare(ac97_clk);
3069c636342SDmitry Baryshkov 	return 0;
3079c636342SDmitry Baryshkov }
3089c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
3099c636342SDmitry Baryshkov 
3109c636342SDmitry Baryshkov int pxa2xx_ac97_hw_resume(void)
3119c636342SDmitry Baryshkov {
3124091d342SRobert Jarzmik 	clk_prepare_enable(ac97_clk);
3139c636342SDmitry Baryshkov 	return 0;
3149c636342SDmitry Baryshkov }
3159c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
3169c636342SDmitry Baryshkov #endif
3179c636342SDmitry Baryshkov 
318e21596bbSBill Pemberton int pxa2xx_ac97_hw_probe(struct platform_device *dev)
3199c636342SDmitry Baryshkov {
3209c636342SDmitry Baryshkov 	int ret;
321eae17754SMark Brown 	pxa2xx_audio_ops_t *pdata = dev->dev.platform_data;
32226ade896SRobert Jarzmik 
32326ade896SRobert Jarzmik 	if (pdata) {
32426ade896SRobert Jarzmik 		switch (pdata->reset_gpio) {
32526ade896SRobert Jarzmik 		case 95:
32626ade896SRobert Jarzmik 		case 113:
32726ade896SRobert Jarzmik 			reset_gpio = pdata->reset_gpio;
32826ade896SRobert Jarzmik 			break;
32926ade896SRobert Jarzmik 		case 0:
33026ade896SRobert Jarzmik 			reset_gpio = 113;
33126ade896SRobert Jarzmik 			break;
33226ade896SRobert Jarzmik 		case -1:
33326ade896SRobert Jarzmik 			break;
33426ade896SRobert Jarzmik 		default:
3351f218695STakashi Iwai 			dev_err(&dev->dev, "Invalid reset GPIO %d\n",
33626ade896SRobert Jarzmik 				pdata->reset_gpio);
33726ade896SRobert Jarzmik 		}
338a4519526SRobert Jarzmik 	} else if (!pdata && dev->dev.of_node) {
339a4519526SRobert Jarzmik 		pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
340a4519526SRobert Jarzmik 		if (!pdata)
341a4519526SRobert Jarzmik 			return -ENOMEM;
342a4519526SRobert Jarzmik 		pdata->reset_gpio = of_get_named_gpio(dev->dev.of_node,
343a4519526SRobert Jarzmik 						      "reset-gpios", 0);
344a4519526SRobert Jarzmik 		if (pdata->reset_gpio == -ENOENT)
345a4519526SRobert Jarzmik 			pdata->reset_gpio = -1;
346a4519526SRobert Jarzmik 		else if (pdata->reset_gpio < 0)
347a4519526SRobert Jarzmik 			return pdata->reset_gpio;
348a4519526SRobert Jarzmik 		reset_gpio = pdata->reset_gpio;
34926ade896SRobert Jarzmik 	} else {
35026ade896SRobert Jarzmik 		if (cpu_is_pxa27x())
35126ade896SRobert Jarzmik 			reset_gpio = 113;
35226ade896SRobert Jarzmik 	}
3539c636342SDmitry Baryshkov 
3549d1cf39bSDmitry Baryshkov 	if (cpu_is_pxa27x()) {
3553b4bc7bcSMike Dunn 		/*
3563b4bc7bcSMike Dunn 		 * This gpio is needed for a work-around to a bug in the ac97
3573b4bc7bcSMike Dunn 		 * controller during warm reset.  The direction and level is set
3583b4bc7bcSMike Dunn 		 * here so that it is an output driven high when switching from
3593b4bc7bcSMike Dunn 		 * AC97_nRESET alt function to generic gpio.
3603b4bc7bcSMike Dunn 		 */
3613b4bc7bcSMike Dunn 		ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH,
3623b4bc7bcSMike Dunn 				       "pxa27x ac97 reset");
3633b4bc7bcSMike Dunn 		if (ret < 0) {
3643b4bc7bcSMike Dunn 			pr_err("%s: gpio_request_one() failed: %d\n",
3653b4bc7bcSMike Dunn 			       __func__, ret);
3663b4bc7bcSMike Dunn 			goto err_conf;
3673b4bc7bcSMike Dunn 		}
368053fe0f1SMike Dunn 		pxa27x_configure_ac97reset(reset_gpio, false);
3693b4bc7bcSMike Dunn 
3709c636342SDmitry Baryshkov 		ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
3719c636342SDmitry Baryshkov 		if (IS_ERR(ac97conf_clk)) {
3729c636342SDmitry Baryshkov 			ret = PTR_ERR(ac97conf_clk);
3739c636342SDmitry Baryshkov 			ac97conf_clk = NULL;
37479612336SDmitry Baryshkov 			goto err_conf;
3759c636342SDmitry Baryshkov 		}
3769d1cf39bSDmitry Baryshkov 	}
3779c636342SDmitry Baryshkov 
3789c636342SDmitry Baryshkov 	ac97_clk = clk_get(&dev->dev, "AC97CLK");
3799c636342SDmitry Baryshkov 	if (IS_ERR(ac97_clk)) {
3809c636342SDmitry Baryshkov 		ret = PTR_ERR(ac97_clk);
3819c636342SDmitry Baryshkov 		ac97_clk = NULL;
38279612336SDmitry Baryshkov 		goto err_clk;
3839c636342SDmitry Baryshkov 	}
3849c636342SDmitry Baryshkov 
3854091d342SRobert Jarzmik 	ret = clk_prepare_enable(ac97_clk);
38679612336SDmitry Baryshkov 	if (ret)
38779612336SDmitry Baryshkov 		goto err_clk2;
38879612336SDmitry Baryshkov 
38988e24c3aSYong Zhang 	ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
39079612336SDmitry Baryshkov 	if (ret < 0)
39179612336SDmitry Baryshkov 		goto err_irq;
39279612336SDmitry Baryshkov 
39379612336SDmitry Baryshkov 	return 0;
3949c636342SDmitry Baryshkov 
3959c636342SDmitry Baryshkov err_irq:
3969c636342SDmitry Baryshkov 	GCR |= GCR_ACLINK_OFF;
39779612336SDmitry Baryshkov err_clk2:
39879612336SDmitry Baryshkov 	clk_put(ac97_clk);
39979612336SDmitry Baryshkov 	ac97_clk = NULL;
40079612336SDmitry Baryshkov err_clk:
4019c636342SDmitry Baryshkov 	if (ac97conf_clk) {
4029c636342SDmitry Baryshkov 		clk_put(ac97conf_clk);
4039c636342SDmitry Baryshkov 		ac97conf_clk = NULL;
4049c636342SDmitry Baryshkov 	}
40579612336SDmitry Baryshkov err_conf:
4069c636342SDmitry Baryshkov 	return ret;
4079c636342SDmitry Baryshkov }
4089c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);
4099c636342SDmitry Baryshkov 
4109c636342SDmitry Baryshkov void pxa2xx_ac97_hw_remove(struct platform_device *dev)
4119c636342SDmitry Baryshkov {
4123b4bc7bcSMike Dunn 	if (cpu_is_pxa27x())
4133b4bc7bcSMike Dunn 		gpio_free(reset_gpio);
4149c636342SDmitry Baryshkov 	GCR |= GCR_ACLINK_OFF;
4159c636342SDmitry Baryshkov 	free_irq(IRQ_AC97, NULL);
4169d1cf39bSDmitry Baryshkov 	if (ac97conf_clk) {
4179c636342SDmitry Baryshkov 		clk_put(ac97conf_clk);
4189c636342SDmitry Baryshkov 		ac97conf_clk = NULL;
4199d1cf39bSDmitry Baryshkov 	}
4204091d342SRobert Jarzmik 	clk_disable_unprepare(ac97_clk);
4219c636342SDmitry Baryshkov 	clk_put(ac97_clk);
4229c636342SDmitry Baryshkov 	ac97_clk = NULL;
4239c636342SDmitry Baryshkov }
4249c636342SDmitry Baryshkov EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_remove);
4259c636342SDmitry Baryshkov 
4269c636342SDmitry Baryshkov MODULE_AUTHOR("Nicolas Pitre");
4279c636342SDmitry Baryshkov MODULE_DESCRIPTION("Intel/Marvell PXA sound library");
4289c636342SDmitry Baryshkov MODULE_LICENSE("GPL");
4299c636342SDmitry Baryshkov 
430