xref: /linux/arch/arm/common/sa1111.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
3f30c2269SUwe Zeisberger  * linux/arch/arm/common/sa1111.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * SA1111 support
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Original code by John Dorsey
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * This file contains all generic SA1111 support.
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  * All initialization functions provided here are intended to be called
121da177e4SLinus Torvalds  * from machine specific code with proper arguments when required.
131da177e4SLinus Torvalds  */
141da177e4SLinus Torvalds #include <linux/module.h>
1517cf5011SRussell King #include <linux/gpio/driver.h>
161da177e4SLinus Torvalds #include <linux/init.h>
1736d31213SRussell King #include <linux/irq.h>
181da177e4SLinus Torvalds #include <linux/kernel.h>
191da177e4SLinus Torvalds #include <linux/delay.h>
201da177e4SLinus Torvalds #include <linux/errno.h>
211da177e4SLinus Torvalds #include <linux/ioport.h>
22d052d1beSRussell King #include <linux/platform_device.h>
231da177e4SLinus Torvalds #include <linux/slab.h>
241da177e4SLinus Torvalds #include <linux/spinlock.h>
250eb3b4abSChristoph Hellwig #include <linux/dma-map-ops.h>
2697d654f8SRussell King #include <linux/clk.h>
27fced80c7SRussell King #include <linux/io.h>
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds #include <asm/mach/irq.h>
3036d31213SRussell King #include <asm/mach-types.h>
3187dfb311SMasahiro Yamada #include <linux/sizes.h>
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds #include <asm/hardware/sa1111.h>
341da177e4SLinus Torvalds 
3508d3df8cSArnd Bergmann #ifdef CONFIG_ARCH_SA1100
3608d3df8cSArnd Bergmann #include <mach/hardware.h>
3708d3df8cSArnd Bergmann #endif
3808d3df8cSArnd Bergmann 
3919851c58SEric Miao /* SA1111 IRQs */
4019851c58SEric Miao #define IRQ_GPAIN0		(0)
4119851c58SEric Miao #define IRQ_GPAIN1		(1)
4219851c58SEric Miao #define IRQ_GPAIN2		(2)
4319851c58SEric Miao #define IRQ_GPAIN3		(3)
4419851c58SEric Miao #define IRQ_GPBIN0		(4)
4519851c58SEric Miao #define IRQ_GPBIN1		(5)
4619851c58SEric Miao #define IRQ_GPBIN2		(6)
4719851c58SEric Miao #define IRQ_GPBIN3		(7)
4819851c58SEric Miao #define IRQ_GPBIN4		(8)
4919851c58SEric Miao #define IRQ_GPBIN5		(9)
5019851c58SEric Miao #define IRQ_GPCIN0		(10)
5119851c58SEric Miao #define IRQ_GPCIN1		(11)
5219851c58SEric Miao #define IRQ_GPCIN2		(12)
5319851c58SEric Miao #define IRQ_GPCIN3		(13)
5419851c58SEric Miao #define IRQ_GPCIN4		(14)
5519851c58SEric Miao #define IRQ_GPCIN5		(15)
5619851c58SEric Miao #define IRQ_GPCIN6		(16)
5719851c58SEric Miao #define IRQ_GPCIN7		(17)
5819851c58SEric Miao #define IRQ_MSTXINT		(18)
5919851c58SEric Miao #define IRQ_MSRXINT		(19)
6019851c58SEric Miao #define IRQ_MSSTOPERRINT	(20)
6119851c58SEric Miao #define IRQ_TPTXINT		(21)
6219851c58SEric Miao #define IRQ_TPRXINT		(22)
6319851c58SEric Miao #define IRQ_TPSTOPERRINT	(23)
6419851c58SEric Miao #define SSPXMTINT		(24)
6519851c58SEric Miao #define SSPRCVINT		(25)
6619851c58SEric Miao #define SSPROR			(26)
6719851c58SEric Miao #define AUDXMTDMADONEA		(32)
6819851c58SEric Miao #define AUDRCVDMADONEA		(33)
6919851c58SEric Miao #define AUDXMTDMADONEB		(34)
7019851c58SEric Miao #define AUDRCVDMADONEB		(35)
7119851c58SEric Miao #define AUDTFSR			(36)
7219851c58SEric Miao #define AUDRFSR			(37)
7319851c58SEric Miao #define AUDTUR			(38)
7419851c58SEric Miao #define AUDROR			(39)
7519851c58SEric Miao #define AUDDTS			(40)
7619851c58SEric Miao #define AUDRDD			(41)
7719851c58SEric Miao #define AUDSTO			(42)
7819851c58SEric Miao #define IRQ_USBPWR		(43)
7919851c58SEric Miao #define IRQ_HCIM		(44)
8019851c58SEric Miao #define IRQ_HCIBUFFACC		(45)
8119851c58SEric Miao #define IRQ_HCIRMTWKP		(46)
8219851c58SEric Miao #define IRQ_NHCIMFCIR		(47)
8319851c58SEric Miao #define IRQ_USB_PORT_RESUME	(48)
8419851c58SEric Miao #define IRQ_S0_READY_NINT	(49)
8519851c58SEric Miao #define IRQ_S1_READY_NINT	(50)
8619851c58SEric Miao #define IRQ_S0_CD_VALID		(51)
8719851c58SEric Miao #define IRQ_S1_CD_VALID		(52)
8819851c58SEric Miao #define IRQ_S0_BVD1_STSCHG	(53)
8919851c58SEric Miao #define IRQ_S1_BVD1_STSCHG	(54)
9036d31213SRussell King #define SA1111_IRQ_NR		(55)
9119851c58SEric Miao 
9229c140b6SRussell King extern void sa1110_mb_enable(void);
9329c140b6SRussell King extern void sa1110_mb_disable(void);
941da177e4SLinus Torvalds 
951da177e4SLinus Torvalds /*
961da177e4SLinus Torvalds  * We keep the following data for the overall SA1111.  Note that the
971da177e4SLinus Torvalds  * struct device and struct resource are "fake"; they should be supplied
981da177e4SLinus Torvalds  * by the bus above us.  However, in the interests of getting all SA1111
991da177e4SLinus Torvalds  * drivers converted over to the device model, we provide this as an
1001da177e4SLinus Torvalds  * anchor point for all the other drivers.
1011da177e4SLinus Torvalds  */
1021da177e4SLinus Torvalds struct sa1111 {
1031da177e4SLinus Torvalds 	struct device	*dev;
10497d654f8SRussell King 	struct clk	*clk;
1051da177e4SLinus Torvalds 	unsigned long	phys;
1061da177e4SLinus Torvalds 	int		irq;
10719851c58SEric Miao 	int		irq_base;	/* base for cascaded on-chip IRQs */
1081da177e4SLinus Torvalds 	spinlock_t	lock;
1091da177e4SLinus Torvalds 	void __iomem	*base;
110ae99ddbcSRussell King 	struct sa1111_platform_data *pdata;
1114c9f6d31SRussell King 	struct irq_domain *irqdomain;
11217cf5011SRussell King 	struct gpio_chip gc;
11393160c63SRafael J. Wysocki #ifdef CONFIG_PM
11493160c63SRafael J. Wysocki 	void		*saved_state;
11593160c63SRafael J. Wysocki #endif
1161da177e4SLinus Torvalds };
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds /*
1191da177e4SLinus Torvalds  * We _really_ need to eliminate this.  Its only users
1201da177e4SLinus Torvalds  * are the PWM and DMA checking code.
1211da177e4SLinus Torvalds  */
1221da177e4SLinus Torvalds static struct sa1111 *g_sa1111;
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds struct sa1111_dev_info {
1251da177e4SLinus Torvalds 	unsigned long	offset;
1261da177e4SLinus Torvalds 	unsigned long	skpcr_mask;
12721d1c770SRussell King 	bool		dma;
1281da177e4SLinus Torvalds 	unsigned int	devid;
129be2bedb0SRussell King 	unsigned int	hwirq[6];
1301da177e4SLinus Torvalds };
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds static struct sa1111_dev_info sa1111_devices[] = {
1331da177e4SLinus Torvalds 	{
1341da177e4SLinus Torvalds 		.offset		= SA1111_USB,
1351da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_UCLKEN,
13621d1c770SRussell King 		.dma		= true,
1371da177e4SLinus Torvalds 		.devid		= SA1111_DEVID_USB,
138be2bedb0SRussell King 		.hwirq = {
1391da177e4SLinus Torvalds 			IRQ_USBPWR,
1401da177e4SLinus Torvalds 			IRQ_HCIM,
1411da177e4SLinus Torvalds 			IRQ_HCIBUFFACC,
1421da177e4SLinus Torvalds 			IRQ_HCIRMTWKP,
1431da177e4SLinus Torvalds 			IRQ_NHCIMFCIR,
1441da177e4SLinus Torvalds 			IRQ_USB_PORT_RESUME
1451da177e4SLinus Torvalds 		},
1461da177e4SLinus Torvalds 	},
1471da177e4SLinus Torvalds 	{
1481da177e4SLinus Torvalds 		.offset		= 0x0600,
1491da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_I2SCLKEN | SKPCR_L3CLKEN,
15021d1c770SRussell King 		.dma		= true,
1511da177e4SLinus Torvalds 		.devid		= SA1111_DEVID_SAC,
152be2bedb0SRussell King 		.hwirq = {
1531da177e4SLinus Torvalds 			AUDXMTDMADONEA,
1541da177e4SLinus Torvalds 			AUDXMTDMADONEB,
1551da177e4SLinus Torvalds 			AUDRCVDMADONEA,
1561da177e4SLinus Torvalds 			AUDRCVDMADONEB
1571da177e4SLinus Torvalds 		},
1581da177e4SLinus Torvalds 	},
1591da177e4SLinus Torvalds 	{
1601da177e4SLinus Torvalds 		.offset		= 0x0800,
1611da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_SCLKEN,
1621da177e4SLinus Torvalds 		.devid		= SA1111_DEVID_SSP,
1631da177e4SLinus Torvalds 	},
1641da177e4SLinus Torvalds 	{
1651da177e4SLinus Torvalds 		.offset		= SA1111_KBD,
1661da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_PTCLKEN,
167e5c0fc41SRussell King 		.devid		= SA1111_DEVID_PS2_KBD,
168be2bedb0SRussell King 		.hwirq = {
1691da177e4SLinus Torvalds 			IRQ_TPRXINT,
1701da177e4SLinus Torvalds 			IRQ_TPTXINT
1711da177e4SLinus Torvalds 		},
1721da177e4SLinus Torvalds 	},
1731da177e4SLinus Torvalds 	{
1741da177e4SLinus Torvalds 		.offset		= SA1111_MSE,
1751da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_PMCLKEN,
176e5c0fc41SRussell King 		.devid		= SA1111_DEVID_PS2_MSE,
177be2bedb0SRussell King 		.hwirq = {
1781da177e4SLinus Torvalds 			IRQ_MSRXINT,
1791da177e4SLinus Torvalds 			IRQ_MSTXINT
1801da177e4SLinus Torvalds 		},
1811da177e4SLinus Torvalds 	},
1821da177e4SLinus Torvalds 	{
1831da177e4SLinus Torvalds 		.offset		= 0x1800,
1841da177e4SLinus Torvalds 		.skpcr_mask	= 0,
1851da177e4SLinus Torvalds 		.devid		= SA1111_DEVID_PCMCIA,
186be2bedb0SRussell King 		.hwirq = {
1871da177e4SLinus Torvalds 			IRQ_S0_READY_NINT,
1881da177e4SLinus Torvalds 			IRQ_S0_CD_VALID,
1891da177e4SLinus Torvalds 			IRQ_S0_BVD1_STSCHG,
1901da177e4SLinus Torvalds 			IRQ_S1_READY_NINT,
1911da177e4SLinus Torvalds 			IRQ_S1_CD_VALID,
1921da177e4SLinus Torvalds 			IRQ_S1_BVD1_STSCHG,
1931da177e4SLinus Torvalds 		},
1941da177e4SLinus Torvalds 	},
1951da177e4SLinus Torvalds };
1961da177e4SLinus Torvalds 
sa1111_map_irq(struct sa1111 * sachip,irq_hw_number_t hwirq)197be2bedb0SRussell King static int sa1111_map_irq(struct sa1111 *sachip, irq_hw_number_t hwirq)
198be2bedb0SRussell King {
199be2bedb0SRussell King 	return irq_create_mapping(sachip->irqdomain, hwirq);
200be2bedb0SRussell King }
201be2bedb0SRussell King 
2021da177e4SLinus Torvalds /*
2031da177e4SLinus Torvalds  * SA1111 interrupt support.  Since clearing an IRQ while there are
2041da177e4SLinus Torvalds  * active IRQs causes the interrupt output to pulse, the upper levels
2051da177e4SLinus Torvalds  * will call us again if there are more interrupts to process.
2061da177e4SLinus Torvalds  */
sa1111_irq_handler(struct irq_desc * desc)207bd0b9ac4SThomas Gleixner static void sa1111_irq_handler(struct irq_desc *desc)
2081da177e4SLinus Torvalds {
2091da177e4SLinus Torvalds 	unsigned int stat0, stat1, i;
210f575398bSJiang Liu 	struct sa1111 *sachip = irq_desc_get_handler_data(desc);
2114c9f6d31SRussell King 	struct irq_domain *irqdomain;
21219851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
2131da177e4SLinus Torvalds 
214a5b549edSRussell King 	stat0 = readl_relaxed(mapbase + SA1111_INTSTATCLR0);
215a5b549edSRussell King 	stat1 = readl_relaxed(mapbase + SA1111_INTSTATCLR1);
2161da177e4SLinus Torvalds 
217a5b549edSRussell King 	writel_relaxed(stat0, mapbase + SA1111_INTSTATCLR0);
2181da177e4SLinus Torvalds 
2198231e741SLennert Buytenhek 	desc->irq_data.chip->irq_ack(&desc->irq_data);
2201da177e4SLinus Torvalds 
221a5b549edSRussell King 	writel_relaxed(stat1, mapbase + SA1111_INTSTATCLR1);
2221da177e4SLinus Torvalds 
2231da177e4SLinus Torvalds 	if (stat0 == 0 && stat1 == 0) {
224bd0b9ac4SThomas Gleixner 		do_bad_IRQ(desc);
2251da177e4SLinus Torvalds 		return;
2261da177e4SLinus Torvalds 	}
2271da177e4SLinus Torvalds 
2284c9f6d31SRussell King 	irqdomain = sachip->irqdomain;
2294c9f6d31SRussell King 
23019851c58SEric Miao 	for (i = 0; stat0; i++, stat0 >>= 1)
2311da177e4SLinus Torvalds 		if (stat0 & 1)
232a1e5cd96SMarc Zyngier 			generic_handle_domain_irq(irqdomain, i);
2331da177e4SLinus Torvalds 
23419851c58SEric Miao 	for (i = 32; stat1; i++, stat1 >>= 1)
2351da177e4SLinus Torvalds 		if (stat1 & 1)
236a1e5cd96SMarc Zyngier 			generic_handle_domain_irq(irqdomain, i);
2371da177e4SLinus Torvalds 
2381da177e4SLinus Torvalds 	/* For level-based interrupts */
2398231e741SLennert Buytenhek 	desc->irq_data.chip->irq_unmask(&desc->irq_data);
2401da177e4SLinus Torvalds }
2411da177e4SLinus Torvalds 
sa1111_irqmask(struct irq_data * d)2421629c9abSRussell King static u32 sa1111_irqmask(struct irq_data *d)
2431629c9abSRussell King {
2444c9f6d31SRussell King 	return BIT(irqd_to_hwirq(d) & 31);
2451629c9abSRussell King }
2461629c9abSRussell King 
sa1111_irqbank(struct irq_data * d)2471629c9abSRussell King static int sa1111_irqbank(struct irq_data *d)
2481629c9abSRussell King {
2494c9f6d31SRussell King 	return (irqd_to_hwirq(d) / 32) * 4;
2501629c9abSRussell King }
2511629c9abSRussell King 
sa1111_ack_irq(struct irq_data * d)2528231e741SLennert Buytenhek static void sa1111_ack_irq(struct irq_data *d)
2531da177e4SLinus Torvalds {
2541da177e4SLinus Torvalds }
2551da177e4SLinus Torvalds 
sa1111_mask_irq(struct irq_data * d)2561629c9abSRussell King static void sa1111_mask_irq(struct irq_data *d)
2571da177e4SLinus Torvalds {
2588231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
2591629c9abSRussell King 	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
2601629c9abSRussell King 	u32 ie;
2611da177e4SLinus Torvalds 
262a5b549edSRussell King 	ie = readl_relaxed(mapbase + SA1111_INTEN0);
2631629c9abSRussell King 	ie &= ~sa1111_irqmask(d);
264a5b549edSRussell King 	writel(ie, mapbase + SA1111_INTEN0);
2651da177e4SLinus Torvalds }
2661da177e4SLinus Torvalds 
sa1111_unmask_irq(struct irq_data * d)2671629c9abSRussell King static void sa1111_unmask_irq(struct irq_data *d)
2681da177e4SLinus Torvalds {
2698231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
2701629c9abSRussell King 	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
2711629c9abSRussell King 	u32 ie;
2721da177e4SLinus Torvalds 
273a5b549edSRussell King 	ie = readl_relaxed(mapbase + SA1111_INTEN0);
2741629c9abSRussell King 	ie |= sa1111_irqmask(d);
275a5b549edSRussell King 	writel_relaxed(ie, mapbase + SA1111_INTEN0);
2761da177e4SLinus Torvalds }
2771da177e4SLinus Torvalds 
2781da177e4SLinus Torvalds /*
2791da177e4SLinus Torvalds  * Attempt to re-trigger the interrupt.  The SA1111 contains a register
2801da177e4SLinus Torvalds  * (INTSET) which claims to do this.  However, in practice no amount of
2811da177e4SLinus Torvalds  * manipulation of INTEN and INTSET guarantees that the interrupt will
2821da177e4SLinus Torvalds  * be triggered.  In fact, its very difficult, if not impossible to get
2831da177e4SLinus Torvalds  * INTSET to re-trigger the interrupt.
2841da177e4SLinus Torvalds  */
sa1111_retrigger_irq(struct irq_data * d)2851629c9abSRussell King static int sa1111_retrigger_irq(struct irq_data *d)
2861da177e4SLinus Torvalds {
2878231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
2881629c9abSRussell King 	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
2891629c9abSRussell King 	u32 ip, mask = sa1111_irqmask(d);
2901da177e4SLinus Torvalds 	int i;
2911da177e4SLinus Torvalds 
292a5b549edSRussell King 	ip = readl_relaxed(mapbase + SA1111_INTPOL0);
2931da177e4SLinus Torvalds 	for (i = 0; i < 8; i++) {
294a5b549edSRussell King 		writel_relaxed(ip ^ mask, mapbase + SA1111_INTPOL0);
295a5b549edSRussell King 		writel_relaxed(ip, mapbase + SA1111_INTPOL0);
296a5b549edSRussell King 		if (readl_relaxed(mapbase + SA1111_INTSTATCLR0) & mask)
2971da177e4SLinus Torvalds 			break;
2981da177e4SLinus Torvalds 	}
2991da177e4SLinus Torvalds 
300ad00a325SMarc Zyngier 	if (i == 8) {
3014ed89f22SRussell King 		pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n",
3024ed89f22SRussell King 		       d->irq);
303ad00a325SMarc Zyngier 		return 0;
304ad00a325SMarc Zyngier 	}
305ad00a325SMarc Zyngier 
306ad00a325SMarc Zyngier 	return 1;
3071da177e4SLinus Torvalds }
3081da177e4SLinus Torvalds 
sa1111_type_irq(struct irq_data * d,unsigned int flags)3091629c9abSRussell King static int sa1111_type_irq(struct irq_data *d, unsigned int flags)
3101da177e4SLinus Torvalds {
3118231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
3121629c9abSRussell King 	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
3131629c9abSRussell King 	u32 ip, mask = sa1111_irqmask(d);
3141da177e4SLinus Torvalds 
3156cab4860SDmitry Baryshkov 	if (flags == IRQ_TYPE_PROBE)
3161da177e4SLinus Torvalds 		return 0;
3171da177e4SLinus Torvalds 
3186cab4860SDmitry Baryshkov 	if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
3191da177e4SLinus Torvalds 		return -EINVAL;
3201da177e4SLinus Torvalds 
321a5b549edSRussell King 	ip = readl_relaxed(mapbase + SA1111_INTPOL0);
3226cab4860SDmitry Baryshkov 	if (flags & IRQ_TYPE_EDGE_RISING)
3231629c9abSRussell King 		ip &= ~mask;
3241da177e4SLinus Torvalds 	else
3251629c9abSRussell King 		ip |= mask;
326a5b549edSRussell King 	writel_relaxed(ip, mapbase + SA1111_INTPOL0);
327a5b549edSRussell King 	writel_relaxed(ip, mapbase + SA1111_WAKEPOL0);
3281da177e4SLinus Torvalds 
3291da177e4SLinus Torvalds 	return 0;
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
sa1111_wake_irq(struct irq_data * d,unsigned int on)3321629c9abSRussell King static int sa1111_wake_irq(struct irq_data *d, unsigned int on)
3331da177e4SLinus Torvalds {
3348231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
3351629c9abSRussell King 	void __iomem *mapbase = sachip->base + SA1111_INTC + sa1111_irqbank(d);
3361629c9abSRussell King 	u32 we, mask = sa1111_irqmask(d);
3371da177e4SLinus Torvalds 
338a5b549edSRussell King 	we = readl_relaxed(mapbase + SA1111_WAKEEN0);
3391da177e4SLinus Torvalds 	if (on)
3401629c9abSRussell King 		we |= mask;
3411da177e4SLinus Torvalds 	else
3421629c9abSRussell King 		we &= ~mask;
343a5b549edSRussell King 	writel_relaxed(we, mapbase + SA1111_WAKEEN0);
3441da177e4SLinus Torvalds 
3451da177e4SLinus Torvalds 	return 0;
3461da177e4SLinus Torvalds }
3471da177e4SLinus Torvalds 
3481629c9abSRussell King static struct irq_chip sa1111_irq_chip = {
3491629c9abSRussell King 	.name		= "SA1111",
3508231e741SLennert Buytenhek 	.irq_ack	= sa1111_ack_irq,
3511629c9abSRussell King 	.irq_mask	= sa1111_mask_irq,
3521629c9abSRussell King 	.irq_unmask	= sa1111_unmask_irq,
3531629c9abSRussell King 	.irq_retrigger	= sa1111_retrigger_irq,
3541629c9abSRussell King 	.irq_set_type	= sa1111_type_irq,
3551629c9abSRussell King 	.irq_set_wake	= sa1111_wake_irq,
3561da177e4SLinus Torvalds };
3571da177e4SLinus Torvalds 
sa1111_irqdomain_map(struct irq_domain * d,unsigned int irq,irq_hw_number_t hwirq)3584c9f6d31SRussell King static int sa1111_irqdomain_map(struct irq_domain *d, unsigned int irq,
3594c9f6d31SRussell King 	irq_hw_number_t hwirq)
3604c9f6d31SRussell King {
3614c9f6d31SRussell King 	struct sa1111 *sachip = d->host_data;
3624c9f6d31SRussell King 
363be2bedb0SRussell King 	/* Disallow unavailable interrupts */
364be2bedb0SRussell King 	if (hwirq > SSPROR && hwirq < AUDXMTDMADONEA)
365be2bedb0SRussell King 		return -EINVAL;
366be2bedb0SRussell King 
3674c9f6d31SRussell King 	irq_set_chip_data(irq, sachip);
3684c9f6d31SRussell King 	irq_set_chip_and_handler(irq, &sa1111_irq_chip, handle_edge_irq);
3694c9f6d31SRussell King 	irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
3704c9f6d31SRussell King 
3714c9f6d31SRussell King 	return 0;
3724c9f6d31SRussell King }
3734c9f6d31SRussell King 
3744c9f6d31SRussell King static const struct irq_domain_ops sa1111_irqdomain_ops = {
3754c9f6d31SRussell King 	.map = sa1111_irqdomain_map,
3764c9f6d31SRussell King 	.xlate = irq_domain_xlate_twocell,
3774c9f6d31SRussell King };
3784c9f6d31SRussell King 
sa1111_setup_irq(struct sa1111 * sachip,unsigned irq_base)37936d31213SRussell King static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
3801da177e4SLinus Torvalds {
3811da177e4SLinus Torvalds 	void __iomem *irqbase = sachip->base + SA1111_INTC;
38236d31213SRussell King 	int ret;
3831da177e4SLinus Torvalds 
3841da177e4SLinus Torvalds 	/*
3851da177e4SLinus Torvalds 	 * We're guaranteed that this region hasn't been taken.
3861da177e4SLinus Torvalds 	 */
3871da177e4SLinus Torvalds 	request_mem_region(sachip->phys + SA1111_INTC, 512, "irq");
3881da177e4SLinus Torvalds 
38936d31213SRussell King 	ret = irq_alloc_descs(-1, irq_base, SA1111_IRQ_NR, -1);
39036d31213SRussell King 	if (ret <= 0) {
39136d31213SRussell King 		dev_err(sachip->dev, "unable to allocate %u irqs: %d\n",
39236d31213SRussell King 			SA1111_IRQ_NR, ret);
39336d31213SRussell King 		if (ret == 0)
39436d31213SRussell King 			ret = -EINVAL;
39536d31213SRussell King 		return ret;
39636d31213SRussell King 	}
39736d31213SRussell King 
39836d31213SRussell King 	sachip->irq_base = ret;
39936d31213SRussell King 
4001da177e4SLinus Torvalds 	/* disable all IRQs */
401a5b549edSRussell King 	writel_relaxed(0, irqbase + SA1111_INTEN0);
402a5b549edSRussell King 	writel_relaxed(0, irqbase + SA1111_INTEN1);
403a5b549edSRussell King 	writel_relaxed(0, irqbase + SA1111_WAKEEN0);
404a5b549edSRussell King 	writel_relaxed(0, irqbase + SA1111_WAKEEN1);
4051da177e4SLinus Torvalds 
4061da177e4SLinus Torvalds 	/*
4071da177e4SLinus Torvalds 	 * detect on rising edge.  Note: Feb 2001 Errata for SA1111
4081da177e4SLinus Torvalds 	 * specifies that S0ReadyInt and S1ReadyInt should be '1'.
4091da177e4SLinus Torvalds 	 */
410a5b549edSRussell King 	writel_relaxed(0, irqbase + SA1111_INTPOL0);
411a5b549edSRussell King 	writel_relaxed(BIT(IRQ_S0_READY_NINT & 31) |
4127c0091ecSRussell King 		       BIT(IRQ_S1_READY_NINT & 31),
4131da177e4SLinus Torvalds 		       irqbase + SA1111_INTPOL1);
4141da177e4SLinus Torvalds 
4151da177e4SLinus Torvalds 	/* clear all IRQs */
416a5b549edSRussell King 	writel_relaxed(~0, irqbase + SA1111_INTSTATCLR0);
417a5b549edSRussell King 	writel_relaxed(~0, irqbase + SA1111_INTSTATCLR1);
4181da177e4SLinus Torvalds 
4194c9f6d31SRussell King 	sachip->irqdomain = irq_domain_add_linear(NULL, SA1111_IRQ_NR,
4204c9f6d31SRussell King 						  &sa1111_irqdomain_ops,
4214c9f6d31SRussell King 						  sachip);
4224c9f6d31SRussell King 	if (!sachip->irqdomain) {
4234c9f6d31SRussell King 		irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);
4244c9f6d31SRussell King 		return -ENOMEM;
4251da177e4SLinus Torvalds 	}
4261da177e4SLinus Torvalds 
4274c9f6d31SRussell King 	irq_domain_associate_many(sachip->irqdomain,
4284c9f6d31SRussell King 				  sachip->irq_base + IRQ_GPAIN0,
4294c9f6d31SRussell King 				  IRQ_GPAIN0, SSPROR + 1 - IRQ_GPAIN0);
4304c9f6d31SRussell King 	irq_domain_associate_many(sachip->irqdomain,
4314c9f6d31SRussell King 				  sachip->irq_base + AUDXMTDMADONEA,
4324c9f6d31SRussell King 				  AUDXMTDMADONEA,
4334c9f6d31SRussell King 				  IRQ_S1_BVD1_STSCHG + 1 - AUDXMTDMADONEA);
4341da177e4SLinus Torvalds 
4351da177e4SLinus Torvalds 	/*
4361da177e4SLinus Torvalds 	 * Register SA1111 interrupt
4371da177e4SLinus Torvalds 	 */
4386845664aSThomas Gleixner 	irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
439056c0acfSRussell King 	irq_set_chained_handler_and_data(sachip->irq, sa1111_irq_handler,
440056c0acfSRussell King 					 sachip);
44136d31213SRussell King 
44236d31213SRussell King 	dev_info(sachip->dev, "Providing IRQ%u-%u\n",
44336d31213SRussell King 		sachip->irq_base, sachip->irq_base + SA1111_IRQ_NR - 1);
44436d31213SRussell King 
44536d31213SRussell King 	return 0;
4461da177e4SLinus Torvalds }
4471da177e4SLinus Torvalds 
sa1111_remove_irq(struct sa1111 * sachip)448ccb7d854SRussell King static void sa1111_remove_irq(struct sa1111 *sachip)
449ccb7d854SRussell King {
450be2bedb0SRussell King 	struct irq_domain *domain = sachip->irqdomain;
451ccb7d854SRussell King 	void __iomem *irqbase = sachip->base + SA1111_INTC;
452be2bedb0SRussell King 	int i;
453ccb7d854SRussell King 
454ccb7d854SRussell King 	/* disable all IRQs */
455a5b549edSRussell King 	writel_relaxed(0, irqbase + SA1111_INTEN0);
456a5b549edSRussell King 	writel_relaxed(0, irqbase + SA1111_INTEN1);
457a5b549edSRussell King 	writel_relaxed(0, irqbase + SA1111_WAKEEN0);
458a5b549edSRussell King 	writel_relaxed(0, irqbase + SA1111_WAKEEN1);
459ccb7d854SRussell King 
460ccb7d854SRussell King 	irq_set_chained_handler_and_data(sachip->irq, NULL, NULL);
461be2bedb0SRussell King 	for (i = 0; i < SA1111_IRQ_NR; i++)
462be2bedb0SRussell King 		irq_dispose_mapping(irq_find_mapping(domain, i));
463be2bedb0SRussell King 	irq_domain_remove(domain);
464ccb7d854SRussell King 
465ccb7d854SRussell King 	release_mem_region(sachip->phys + SA1111_INTC, 512);
466ccb7d854SRussell King }
467ccb7d854SRussell King 
46817cf5011SRussell King enum {
46917cf5011SRussell King 	SA1111_GPIO_PXDDR = (SA1111_GPIO_PADDR - SA1111_GPIO_PADDR),
47017cf5011SRussell King 	SA1111_GPIO_PXDRR = (SA1111_GPIO_PADRR - SA1111_GPIO_PADDR),
47117cf5011SRussell King 	SA1111_GPIO_PXDWR = (SA1111_GPIO_PADWR - SA1111_GPIO_PADDR),
47217cf5011SRussell King 	SA1111_GPIO_PXSDR = (SA1111_GPIO_PASDR - SA1111_GPIO_PADDR),
47317cf5011SRussell King 	SA1111_GPIO_PXSSR = (SA1111_GPIO_PASSR - SA1111_GPIO_PADDR),
47417cf5011SRussell King };
47517cf5011SRussell King 
gc_to_sa1111(struct gpio_chip * gc)47617cf5011SRussell King static struct sa1111 *gc_to_sa1111(struct gpio_chip *gc)
47717cf5011SRussell King {
47817cf5011SRussell King 	return container_of(gc, struct sa1111, gc);
47917cf5011SRussell King }
48017cf5011SRussell King 
sa1111_gpio_map_reg(struct sa1111 * sachip,unsigned offset)48117cf5011SRussell King static void __iomem *sa1111_gpio_map_reg(struct sa1111 *sachip, unsigned offset)
48217cf5011SRussell King {
48317cf5011SRussell King 	void __iomem *reg = sachip->base + SA1111_GPIO;
48417cf5011SRussell King 
48517cf5011SRussell King 	if (offset < 4)
48617cf5011SRussell King 		return reg + SA1111_GPIO_PADDR;
48717cf5011SRussell King 	if (offset < 10)
48817cf5011SRussell King 		return reg + SA1111_GPIO_PBDDR;
48917cf5011SRussell King 	if (offset < 18)
49017cf5011SRussell King 		return reg + SA1111_GPIO_PCDDR;
49117cf5011SRussell King 	return NULL;
49217cf5011SRussell King }
49317cf5011SRussell King 
sa1111_gpio_map_bit(unsigned offset)49417cf5011SRussell King static u32 sa1111_gpio_map_bit(unsigned offset)
49517cf5011SRussell King {
49617cf5011SRussell King 	if (offset < 4)
49717cf5011SRussell King 		return BIT(offset);
49817cf5011SRussell King 	if (offset < 10)
49917cf5011SRussell King 		return BIT(offset - 4);
50017cf5011SRussell King 	if (offset < 18)
50117cf5011SRussell King 		return BIT(offset - 10);
50217cf5011SRussell King 	return 0;
50317cf5011SRussell King }
50417cf5011SRussell King 
sa1111_gpio_modify(void __iomem * reg,u32 mask,u32 set)50517cf5011SRussell King static void sa1111_gpio_modify(void __iomem *reg, u32 mask, u32 set)
50617cf5011SRussell King {
50717cf5011SRussell King 	u32 val;
50817cf5011SRussell King 
50917cf5011SRussell King 	val = readl_relaxed(reg);
51017cf5011SRussell King 	val &= ~mask;
51117cf5011SRussell King 	val |= mask & set;
51217cf5011SRussell King 	writel_relaxed(val, reg);
51317cf5011SRussell King }
51417cf5011SRussell King 
sa1111_gpio_get_direction(struct gpio_chip * gc,unsigned offset)51517cf5011SRussell King static int sa1111_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
51617cf5011SRussell King {
51717cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
51817cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
51917cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
52017cf5011SRussell King 
52117cf5011SRussell King 	return !!(readl_relaxed(reg + SA1111_GPIO_PXDDR) & mask);
52217cf5011SRussell King }
52317cf5011SRussell King 
sa1111_gpio_direction_input(struct gpio_chip * gc,unsigned offset)52417cf5011SRussell King static int sa1111_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
52517cf5011SRussell King {
52617cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
52717cf5011SRussell King 	unsigned long flags;
52817cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
52917cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
53017cf5011SRussell King 
53117cf5011SRussell King 	spin_lock_irqsave(&sachip->lock, flags);
53217cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXDDR, mask, mask);
53317cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXSDR, mask, mask);
53417cf5011SRussell King 	spin_unlock_irqrestore(&sachip->lock, flags);
53517cf5011SRussell King 
53617cf5011SRussell King 	return 0;
53717cf5011SRussell King }
53817cf5011SRussell King 
sa1111_gpio_direction_output(struct gpio_chip * gc,unsigned offset,int value)53917cf5011SRussell King static int sa1111_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
54017cf5011SRussell King 	int value)
54117cf5011SRussell King {
54217cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
54317cf5011SRussell King 	unsigned long flags;
54417cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
54517cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
54617cf5011SRussell King 
54717cf5011SRussell King 	spin_lock_irqsave(&sachip->lock, flags);
54817cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXDWR, mask, value ? mask : 0);
54917cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXSSR, mask, value ? mask : 0);
55017cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXDDR, mask, 0);
55117cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXSDR, mask, 0);
55217cf5011SRussell King 	spin_unlock_irqrestore(&sachip->lock, flags);
55317cf5011SRussell King 
55417cf5011SRussell King 	return 0;
55517cf5011SRussell King }
55617cf5011SRussell King 
sa1111_gpio_get(struct gpio_chip * gc,unsigned offset)55717cf5011SRussell King static int sa1111_gpio_get(struct gpio_chip *gc, unsigned offset)
55817cf5011SRussell King {
55917cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
56017cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
56117cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
56217cf5011SRussell King 
56317cf5011SRussell King 	return !!(readl_relaxed(reg + SA1111_GPIO_PXDRR) & mask);
56417cf5011SRussell King }
56517cf5011SRussell King 
sa1111_gpio_set(struct gpio_chip * gc,unsigned offset,int value)56617cf5011SRussell King static void sa1111_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
56717cf5011SRussell King {
56817cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
56917cf5011SRussell King 	unsigned long flags;
57017cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
57117cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
57217cf5011SRussell King 
57317cf5011SRussell King 	spin_lock_irqsave(&sachip->lock, flags);
57417cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXDWR, mask, value ? mask : 0);
57517cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXSSR, mask, value ? mask : 0);
57617cf5011SRussell King 	spin_unlock_irqrestore(&sachip->lock, flags);
57717cf5011SRussell King }
57817cf5011SRussell King 
sa1111_gpio_set_multiple(struct gpio_chip * gc,unsigned long * mask,unsigned long * bits)57917cf5011SRussell King static void sa1111_gpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
58017cf5011SRussell King 	unsigned long *bits)
58117cf5011SRussell King {
58217cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
58317cf5011SRussell King 	unsigned long flags;
58417cf5011SRussell King 	void __iomem *reg = sachip->base + SA1111_GPIO;
58517cf5011SRussell King 	u32 msk, val;
58617cf5011SRussell King 
58717cf5011SRussell King 	msk = *mask;
58817cf5011SRussell King 	val = *bits;
58917cf5011SRussell King 
59017cf5011SRussell King 	spin_lock_irqsave(&sachip->lock, flags);
59117cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PADWR, msk & 15, val);
59217cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PASSR, msk & 15, val);
59317cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PBDWR, (msk >> 4) & 255, val >> 4);
59417cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PBSSR, (msk >> 4) & 255, val >> 4);
59517cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PCDWR, (msk >> 12) & 255, val >> 12);
59617cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PCSSR, (msk >> 12) & 255, val >> 12);
59717cf5011SRussell King 	spin_unlock_irqrestore(&sachip->lock, flags);
59817cf5011SRussell King }
59917cf5011SRussell King 
sa1111_gpio_to_irq(struct gpio_chip * gc,unsigned offset)60017cf5011SRussell King static int sa1111_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
60117cf5011SRussell King {
60217cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
60317cf5011SRussell King 
604be2bedb0SRussell King 	return sa1111_map_irq(sachip, offset);
60517cf5011SRussell King }
60617cf5011SRussell King 
sa1111_setup_gpios(struct sa1111 * sachip)60717cf5011SRussell King static int sa1111_setup_gpios(struct sa1111 *sachip)
60817cf5011SRussell King {
60917cf5011SRussell King 	sachip->gc.label = "sa1111";
61017cf5011SRussell King 	sachip->gc.parent = sachip->dev;
61117cf5011SRussell King 	sachip->gc.owner = THIS_MODULE;
61217cf5011SRussell King 	sachip->gc.get_direction = sa1111_gpio_get_direction;
61317cf5011SRussell King 	sachip->gc.direction_input = sa1111_gpio_direction_input;
61417cf5011SRussell King 	sachip->gc.direction_output = sa1111_gpio_direction_output;
61517cf5011SRussell King 	sachip->gc.get = sa1111_gpio_get;
61617cf5011SRussell King 	sachip->gc.set = sa1111_gpio_set;
61717cf5011SRussell King 	sachip->gc.set_multiple = sa1111_gpio_set_multiple;
61817cf5011SRussell King 	sachip->gc.to_irq = sa1111_gpio_to_irq;
61917cf5011SRussell King 	sachip->gc.base = -1;
62017cf5011SRussell King 	sachip->gc.ngpio = 18;
62117cf5011SRussell King 
62217cf5011SRussell King 	return devm_gpiochip_add_data(sachip->dev, &sachip->gc, sachip);
62317cf5011SRussell King }
62417cf5011SRussell King 
6251da177e4SLinus Torvalds /*
6261da177e4SLinus Torvalds  * Bring the SA1111 out of reset.  This requires a set procedure:
6271da177e4SLinus Torvalds  *  1. nRESET asserted (by hardware)
6281da177e4SLinus Torvalds  *  2. CLK turned on from SA1110
6291da177e4SLinus Torvalds  *  3. nRESET deasserted
6301da177e4SLinus Torvalds  *  4. VCO turned on, PLL_BYPASS turned off
6311da177e4SLinus Torvalds  *  5. Wait lock time, then assert RCLKEn
6321da177e4SLinus Torvalds  *  7. PCR set to allow clocking of individual functions
6331da177e4SLinus Torvalds  *
6341da177e4SLinus Torvalds  * Until we've done this, the only registers we can access are:
6351da177e4SLinus Torvalds  *   SBI_SKCR
6361da177e4SLinus Torvalds  *   SBI_SMCR
6371da177e4SLinus Torvalds  *   SBI_SKID
6381da177e4SLinus Torvalds  */
sa1111_wake(struct sa1111 * sachip)6391da177e4SLinus Torvalds static void sa1111_wake(struct sa1111 *sachip)
6401da177e4SLinus Torvalds {
6411da177e4SLinus Torvalds 	unsigned long flags, r;
6421da177e4SLinus Torvalds 
6431da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
6441da177e4SLinus Torvalds 
64597d654f8SRussell King 	clk_enable(sachip->clk);
6461da177e4SLinus Torvalds 
6471da177e4SLinus Torvalds 	/*
6481da177e4SLinus Torvalds 	 * Turn VCO on, and disable PLL Bypass.
6491da177e4SLinus Torvalds 	 */
650a5b549edSRussell King 	r = readl_relaxed(sachip->base + SA1111_SKCR);
6511da177e4SLinus Torvalds 	r &= ~SKCR_VCO_OFF;
652a5b549edSRussell King 	writel_relaxed(r, sachip->base + SA1111_SKCR);
6531da177e4SLinus Torvalds 	r |= SKCR_PLL_BYPASS | SKCR_OE_EN;
654a5b549edSRussell King 	writel_relaxed(r, sachip->base + SA1111_SKCR);
6551da177e4SLinus Torvalds 
6561da177e4SLinus Torvalds 	/*
6571da177e4SLinus Torvalds 	 * Wait lock time.  SA1111 manual _doesn't_
6581da177e4SLinus Torvalds 	 * specify a figure for this!  We choose 100us.
6591da177e4SLinus Torvalds 	 */
6601da177e4SLinus Torvalds 	udelay(100);
6611da177e4SLinus Torvalds 
6621da177e4SLinus Torvalds 	/*
6631da177e4SLinus Torvalds 	 * Enable RCLK.  We also ensure that RDYEN is set.
6641da177e4SLinus Torvalds 	 */
6651da177e4SLinus Torvalds 	r |= SKCR_RCLKEN | SKCR_RDYEN;
666a5b549edSRussell King 	writel_relaxed(r, sachip->base + SA1111_SKCR);
6671da177e4SLinus Torvalds 
6681da177e4SLinus Torvalds 	/*
6691da177e4SLinus Torvalds 	 * Wait 14 RCLK cycles for the chip to finish coming out
6701da177e4SLinus Torvalds 	 * of reset. (RCLK=24MHz).  This is 590ns.
6711da177e4SLinus Torvalds 	 */
6721da177e4SLinus Torvalds 	udelay(1);
6731da177e4SLinus Torvalds 
6741da177e4SLinus Torvalds 	/*
6751da177e4SLinus Torvalds 	 * Ensure all clocks are initially off.
6761da177e4SLinus Torvalds 	 */
677a5b549edSRussell King 	writel_relaxed(0, sachip->base + SA1111_SKPCR);
6781da177e4SLinus Torvalds 
6791da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
6801da177e4SLinus Torvalds }
6811da177e4SLinus Torvalds 
6821da177e4SLinus Torvalds #ifdef CONFIG_ARCH_SA1100
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds static u32 sa1111_dma_mask[] = {
6851da177e4SLinus Torvalds 	~0,
6861da177e4SLinus Torvalds 	~(1 << 20),
6871da177e4SLinus Torvalds 	~(1 << 23),
6881da177e4SLinus Torvalds 	~(1 << 24),
6891da177e4SLinus Torvalds 	~(1 << 25),
6901da177e4SLinus Torvalds 	~(1 << 20),
6911da177e4SLinus Torvalds 	~(1 << 20),
6921da177e4SLinus Torvalds 	0,
6931da177e4SLinus Torvalds };
6941da177e4SLinus Torvalds 
6951da177e4SLinus Torvalds /*
6961da177e4SLinus Torvalds  * Configure the SA1111 shared memory controller.
6971da177e4SLinus Torvalds  */
6986475f4bbSArnd Bergmann static void
sa1111_configure_smc(struct sa1111 * sachip,int sdram,unsigned int drac,unsigned int cas_latency)6991da177e4SLinus Torvalds sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
7001da177e4SLinus Torvalds 		     unsigned int cas_latency)
7011da177e4SLinus Torvalds {
7021da177e4SLinus Torvalds 	unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC);
7031da177e4SLinus Torvalds 
7041da177e4SLinus Torvalds 	if (cas_latency == 3)
7051da177e4SLinus Torvalds 		smcr |= SMCR_CLAT;
7061da177e4SLinus Torvalds 
707a5b549edSRussell King 	writel_relaxed(smcr, sachip->base + SA1111_SMCR);
7081da177e4SLinus Torvalds 
7091da177e4SLinus Torvalds 	/*
7101da177e4SLinus Torvalds 	 * Now clear the bits in the DMA mask to work around the SA1111
7111da177e4SLinus Torvalds 	 * DMA erratum (Intel StrongARM SA-1111 Microprocessor Companion
7121da177e4SLinus Torvalds 	 * Chip Specification Update, June 2000, Erratum #7).
7131da177e4SLinus Torvalds 	 */
7141da177e4SLinus Torvalds 	if (sachip->dev->dma_mask)
7151da177e4SLinus Torvalds 		*sachip->dev->dma_mask &= sa1111_dma_mask[drac >> 2];
7161da177e4SLinus Torvalds 
7171da177e4SLinus Torvalds 	sachip->dev->coherent_dma_mask &= sa1111_dma_mask[drac >> 2];
7181da177e4SLinus Torvalds }
7190703ed2aSRussell King #endif
7201da177e4SLinus Torvalds 
sa1111_dev_release(struct device * _dev)7211da177e4SLinus Torvalds static void sa1111_dev_release(struct device *_dev)
7221da177e4SLinus Torvalds {
723b60752f2SRussell King 	struct sa1111_dev *dev = to_sa1111_device(_dev);
7241da177e4SLinus Torvalds 
7251da177e4SLinus Torvalds 	kfree(dev);
7261da177e4SLinus Torvalds }
7271da177e4SLinus Torvalds 
7281da177e4SLinus Torvalds static int
sa1111_init_one_child(struct sa1111 * sachip,struct resource * parent,struct sa1111_dev_info * info)7291da177e4SLinus Torvalds sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
7301da177e4SLinus Torvalds 		      struct sa1111_dev_info *info)
7311da177e4SLinus Torvalds {
7321da177e4SLinus Torvalds 	struct sa1111_dev *dev;
733f03ecaa0SRussell King 	unsigned i;
7341da177e4SLinus Torvalds 	int ret;
7351da177e4SLinus Torvalds 
736d2a02b93SRussell King 	dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL);
7371da177e4SLinus Torvalds 	if (!dev) {
7381da177e4SLinus Torvalds 		ret = -ENOMEM;
739924e1d49SRussell King 		goto err_alloc;
7401da177e4SLinus Torvalds 	}
7411da177e4SLinus Torvalds 
742924e1d49SRussell King 	device_initialize(&dev->dev);
7433f978704SKay Sievers 	dev_set_name(&dev->dev, "%4.4lx", info->offset);
7441da177e4SLinus Torvalds 	dev->devid	 = info->devid;
7451da177e4SLinus Torvalds 	dev->dev.parent  = sachip->dev;
7461da177e4SLinus Torvalds 	dev->dev.bus     = &sa1111_bus_type;
7471da177e4SLinus Torvalds 	dev->dev.release = sa1111_dev_release;
7481da177e4SLinus Torvalds 	dev->res.start   = sachip->phys + info->offset;
7491da177e4SLinus Torvalds 	dev->res.end     = dev->res.start + 511;
7503f978704SKay Sievers 	dev->res.name    = dev_name(&dev->dev);
7511da177e4SLinus Torvalds 	dev->res.flags   = IORESOURCE_MEM;
7521da177e4SLinus Torvalds 	dev->mapbase     = sachip->base + info->offset;
7531da177e4SLinus Torvalds 	dev->skpcr_mask  = info->skpcr_mask;
754f03ecaa0SRussell King 
755be2bedb0SRussell King 	for (i = 0; i < ARRAY_SIZE(info->hwirq); i++)
756be2bedb0SRussell King 		dev->hwirq[i] = info->hwirq[i];
7571da177e4SLinus Torvalds 
75809a2ba2fSRussell King 	/*
75921d1c770SRussell King 	 * If the parent device has a DMA mask associated with it, and
76021d1c770SRussell King 	 * this child supports DMA, propagate it down to the children.
76109a2ba2fSRussell King 	 */
76221d1c770SRussell King 	if (info->dma && sachip->dev->dma_mask) {
76309a2ba2fSRussell King 		dev->dma_mask = *sachip->dev->dma_mask;
76409a2ba2fSRussell King 		dev->dev.dma_mask = &dev->dma_mask;
76509a2ba2fSRussell King 		dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask;
76609a2ba2fSRussell King 	}
76709a2ba2fSRussell King 
7681da177e4SLinus Torvalds 	ret = request_resource(parent, &dev->res);
7691da177e4SLinus Torvalds 	if (ret) {
77022eeaff3SRussell King 		dev_err(sachip->dev, "failed to allocate resource for %s\n",
7711da177e4SLinus Torvalds 			dev->res.name);
772924e1d49SRussell King 		goto err_resource;
7731da177e4SLinus Torvalds 	}
7741da177e4SLinus Torvalds 
775924e1d49SRussell King 	ret = device_add(&dev->dev);
776924e1d49SRussell King 	if (ret)
777924e1d49SRussell King 		goto err_add;
778924e1d49SRussell King 	return 0;
779924e1d49SRussell King 
780924e1d49SRussell King  err_add:
7811da177e4SLinus Torvalds 	release_resource(&dev->res);
782924e1d49SRussell King  err_resource:
783924e1d49SRussell King 	put_device(&dev->dev);
784924e1d49SRussell King  err_alloc:
7851da177e4SLinus Torvalds 	return ret;
7861da177e4SLinus Torvalds }
7871da177e4SLinus Torvalds 
__sa1111_probe(struct device * me,struct resource * mem,int irq)788351a102dSGreg Kroah-Hartman static int __sa1111_probe(struct device *me, struct resource *mem, int irq)
7891da177e4SLinus Torvalds {
790f03ecaa0SRussell King 	struct sa1111_platform_data *pd = me->platform_data;
7911da177e4SLinus Torvalds 	struct sa1111 *sachip;
7921da177e4SLinus Torvalds 	unsigned long id;
793416112f8SDavid Brownell 	unsigned int has_devs;
7941da177e4SLinus Torvalds 	int i, ret = -ENODEV;
7951da177e4SLinus Torvalds 
796f03ecaa0SRussell King 	if (!pd)
797f03ecaa0SRussell King 		return -EINVAL;
798f03ecaa0SRussell King 
7997d53c1f0SRussell King 	sachip = devm_kzalloc(me, sizeof(struct sa1111), GFP_KERNEL);
8001da177e4SLinus Torvalds 	if (!sachip)
8011da177e4SLinus Torvalds 		return -ENOMEM;
8021da177e4SLinus Torvalds 
803deee856aSRussell King 	sachip->clk = devm_clk_get(me, "SA1111_CLK");
804deee856aSRussell King 	if (IS_ERR(sachip->clk))
805deee856aSRussell King 		return PTR_ERR(sachip->clk);
80697d654f8SRussell King 
80772ae00c9SRussell King 	ret = clk_prepare(sachip->clk);
80872ae00c9SRussell King 	if (ret)
809deee856aSRussell King 		return ret;
81072ae00c9SRussell King 
8111da177e4SLinus Torvalds 	spin_lock_init(&sachip->lock);
8121da177e4SLinus Torvalds 
8131da177e4SLinus Torvalds 	sachip->dev = me;
8141da177e4SLinus Torvalds 	dev_set_drvdata(sachip->dev, sachip);
8151da177e4SLinus Torvalds 
816ae99ddbcSRussell King 	sachip->pdata = pd;
8171da177e4SLinus Torvalds 	sachip->phys = mem->start;
8181da177e4SLinus Torvalds 	sachip->irq = irq;
8191da177e4SLinus Torvalds 
8201da177e4SLinus Torvalds 	/*
8211da177e4SLinus Torvalds 	 * Map the whole region.  This also maps the
8221da177e4SLinus Torvalds 	 * registers for our children.
8231da177e4SLinus Torvalds 	 */
8241da177e4SLinus Torvalds 	sachip->base = ioremap(mem->start, PAGE_SIZE * 2);
8251da177e4SLinus Torvalds 	if (!sachip->base) {
8261da177e4SLinus Torvalds 		ret = -ENOMEM;
82772ae00c9SRussell King 		goto err_clk_unprep;
8281da177e4SLinus Torvalds 	}
8291da177e4SLinus Torvalds 
8301da177e4SLinus Torvalds 	/*
8311da177e4SLinus Torvalds 	 * Probe for the chip.  Only touch the SBI registers.
8321da177e4SLinus Torvalds 	 */
833a5b549edSRussell King 	id = readl_relaxed(sachip->base + SA1111_SKID);
8341da177e4SLinus Torvalds 	if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
8351da177e4SLinus Torvalds 		printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id);
8361da177e4SLinus Torvalds 		ret = -ENODEV;
83797d654f8SRussell King 		goto err_unmap;
8381da177e4SLinus Torvalds 	}
8391da177e4SLinus Torvalds 
8404ed89f22SRussell King 	pr_info("SA1111 Microprocessor Companion Chip: silicon revision %lx, metal revision %lx\n",
8414ed89f22SRussell King 		(id & SKID_SIREV_MASK) >> 4, id & SKID_MTREV_MASK);
8421da177e4SLinus Torvalds 
8431da177e4SLinus Torvalds 	/*
8441da177e4SLinus Torvalds 	 * We found it.  Wake the chip up, and initialise.
8451da177e4SLinus Torvalds 	 */
8461da177e4SLinus Torvalds 	sa1111_wake(sachip);
8471da177e4SLinus Torvalds 
84836d31213SRussell King 	/*
84936d31213SRussell King 	 * The interrupt controller must be initialised before any
85036d31213SRussell King 	 * other device to ensure that the interrupts are available.
85136d31213SRussell King 	 */
85236d31213SRussell King 	ret = sa1111_setup_irq(sachip, pd->irq_base);
85336d31213SRussell King 	if (ret)
85487d5dd62SRussell King 		goto err_clk;
85536d31213SRussell King 
85617cf5011SRussell King 	/* Setup the GPIOs - should really be done after the IRQ setup */
85717cf5011SRussell King 	ret = sa1111_setup_gpios(sachip);
85817cf5011SRussell King 	if (ret)
85917cf5011SRussell King 		goto err_irq;
86017cf5011SRussell King 
8611da177e4SLinus Torvalds #ifdef CONFIG_ARCH_SA1100
862416112f8SDavid Brownell 	{
863416112f8SDavid Brownell 	unsigned int val;
864416112f8SDavid Brownell 
8651da177e4SLinus Torvalds 	/*
8661da177e4SLinus Torvalds 	 * The SDRAM configuration of the SA1110 and the SA1111 must
8671da177e4SLinus Torvalds 	 * match.  This is very important to ensure that SA1111 accesses
8681da177e4SLinus Torvalds 	 * don't corrupt the SDRAM.  Note that this ungates the SA1111's
8691da177e4SLinus Torvalds 	 * MBGNT signal, so we must have called sa1110_mb_disable()
8701da177e4SLinus Torvalds 	 * beforehand.
8711da177e4SLinus Torvalds 	 */
8721da177e4SLinus Torvalds 	sa1111_configure_smc(sachip, 1,
8731da177e4SLinus Torvalds 			     FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
8741da177e4SLinus Torvalds 			     FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
8751da177e4SLinus Torvalds 
8761da177e4SLinus Torvalds 	/*
8771da177e4SLinus Torvalds 	 * We only need to turn on DCLK whenever we want to use the
8781da177e4SLinus Torvalds 	 * DMA.  It can otherwise be held firmly in the off position.
8791da177e4SLinus Torvalds 	 * (currently, we always enable it.)
8801da177e4SLinus Torvalds 	 */
881a5b549edSRussell King 	val = readl_relaxed(sachip->base + SA1111_SKPCR);
882a5b549edSRussell King 	writel_relaxed(val | SKPCR_DCLKEN, sachip->base + SA1111_SKPCR);
8831da177e4SLinus Torvalds 
8841da177e4SLinus Torvalds 	/*
8851da177e4SLinus Torvalds 	 * Enable the SA1110 memory bus request and grant signals.
8861da177e4SLinus Torvalds 	 */
8871da177e4SLinus Torvalds 	sa1110_mb_enable();
888416112f8SDavid Brownell 	}
8891da177e4SLinus Torvalds #endif
8901da177e4SLinus Torvalds 
8911da177e4SLinus Torvalds 	g_sa1111 = sachip;
8921da177e4SLinus Torvalds 
8931da177e4SLinus Torvalds 	has_devs = ~0;
89407be45f5SRussell King 	if (pd)
89507be45f5SRussell King 		has_devs &= ~pd->disable_devs;
8961da177e4SLinus Torvalds 
8971da177e4SLinus Torvalds 	for (i = 0; i < ARRAY_SIZE(sa1111_devices); i++)
898e5c0fc41SRussell King 		if (sa1111_devices[i].devid & has_devs)
8991da177e4SLinus Torvalds 			sa1111_init_one_child(sachip, mem, &sa1111_devices[i]);
9001da177e4SLinus Torvalds 
9011da177e4SLinus Torvalds 	return 0;
9021da177e4SLinus Torvalds 
90317cf5011SRussell King  err_irq:
90417cf5011SRussell King 	sa1111_remove_irq(sachip);
90587d5dd62SRussell King  err_clk:
90687d5dd62SRussell King 	clk_disable(sachip->clk);
90797d654f8SRussell King  err_unmap:
9081da177e4SLinus Torvalds 	iounmap(sachip->base);
90972ae00c9SRussell King  err_clk_unprep:
91072ae00c9SRussell King 	clk_unprepare(sachip->clk);
9111da177e4SLinus Torvalds 	return ret;
9121da177e4SLinus Torvalds }
9131da177e4SLinus Torvalds 
sa1111_remove_one(struct device * dev,void * data)914522c37b9SRussell King static int sa1111_remove_one(struct device *dev, void *data)
915522c37b9SRussell King {
916b60752f2SRussell King 	struct sa1111_dev *sadev = to_sa1111_device(dev);
917eac8dbf7SRussell King 	if (dev->bus != &sa1111_bus_type)
918eac8dbf7SRussell King 		return 0;
919924e1d49SRussell King 	device_del(&sadev->dev);
920924e1d49SRussell King 	release_resource(&sadev->res);
921924e1d49SRussell King 	put_device(&sadev->dev);
922522c37b9SRussell King 	return 0;
923522c37b9SRussell King }
924522c37b9SRussell King 
__sa1111_remove(struct sa1111 * sachip)9251da177e4SLinus Torvalds static void __sa1111_remove(struct sa1111 *sachip)
9261da177e4SLinus Torvalds {
927522c37b9SRussell King 	device_for_each_child(sachip->dev, NULL, sa1111_remove_one);
9281da177e4SLinus Torvalds 
929ccb7d854SRussell King 	sa1111_remove_irq(sachip);
9301da177e4SLinus Torvalds 
93197d654f8SRussell King 	clk_disable(sachip->clk);
93272ae00c9SRussell King 	clk_unprepare(sachip->clk);
93397d654f8SRussell King 
9341da177e4SLinus Torvalds 	iounmap(sachip->base);
9351da177e4SLinus Torvalds }
9361da177e4SLinus Torvalds 
9371da177e4SLinus Torvalds struct sa1111_save_data {
9381da177e4SLinus Torvalds 	unsigned int	skcr;
9391da177e4SLinus Torvalds 	unsigned int	skpcr;
9401da177e4SLinus Torvalds 	unsigned int	skcdr;
9411da177e4SLinus Torvalds 	unsigned char	skaud;
9421da177e4SLinus Torvalds 	unsigned char	skpwm0;
9431da177e4SLinus Torvalds 	unsigned char	skpwm1;
9441da177e4SLinus Torvalds 
9451da177e4SLinus Torvalds 	/*
9461da177e4SLinus Torvalds 	 * Interrupt controller
9471da177e4SLinus Torvalds 	 */
9481da177e4SLinus Torvalds 	unsigned int	intpol0;
9491da177e4SLinus Torvalds 	unsigned int	intpol1;
9501da177e4SLinus Torvalds 	unsigned int	inten0;
9511da177e4SLinus Torvalds 	unsigned int	inten1;
9521da177e4SLinus Torvalds 	unsigned int	wakepol0;
9531da177e4SLinus Torvalds 	unsigned int	wakepol1;
9541da177e4SLinus Torvalds 	unsigned int	wakeen0;
9551da177e4SLinus Torvalds 	unsigned int	wakeen1;
9561da177e4SLinus Torvalds };
9571da177e4SLinus Torvalds 
9581da177e4SLinus Torvalds #ifdef CONFIG_PM
9591da177e4SLinus Torvalds 
sa1111_suspend_noirq(struct device * dev)96006dfe5ccSRussell King static int sa1111_suspend_noirq(struct device *dev)
9611da177e4SLinus Torvalds {
96206dfe5ccSRussell King 	struct sa1111 *sachip = dev_get_drvdata(dev);
9631da177e4SLinus Torvalds 	struct sa1111_save_data *save;
9641da177e4SLinus Torvalds 	unsigned long flags;
9651da177e4SLinus Torvalds 	unsigned int val;
9661da177e4SLinus Torvalds 	void __iomem *base;
9671da177e4SLinus Torvalds 
9681da177e4SLinus Torvalds 	save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
9691da177e4SLinus Torvalds 	if (!save)
9701da177e4SLinus Torvalds 		return -ENOMEM;
97193160c63SRafael J. Wysocki 	sachip->saved_state = save;
9721da177e4SLinus Torvalds 
9731da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
9741da177e4SLinus Torvalds 
9751da177e4SLinus Torvalds 	/*
9761da177e4SLinus Torvalds 	 * Save state.
9771da177e4SLinus Torvalds 	 */
9781da177e4SLinus Torvalds 	base = sachip->base;
979a5b549edSRussell King 	save->skcr     = readl_relaxed(base + SA1111_SKCR);
980a5b549edSRussell King 	save->skpcr    = readl_relaxed(base + SA1111_SKPCR);
981a5b549edSRussell King 	save->skcdr    = readl_relaxed(base + SA1111_SKCDR);
982a5b549edSRussell King 	save->skaud    = readl_relaxed(base + SA1111_SKAUD);
983a5b549edSRussell King 	save->skpwm0   = readl_relaxed(base + SA1111_SKPWM0);
984a5b549edSRussell King 	save->skpwm1   = readl_relaxed(base + SA1111_SKPWM1);
9851da177e4SLinus Torvalds 
986a5b549edSRussell King 	writel_relaxed(0, sachip->base + SA1111_SKPWM0);
987a5b549edSRussell King 	writel_relaxed(0, sachip->base + SA1111_SKPWM1);
988a22db0f3SRussell King 
9891da177e4SLinus Torvalds 	base = sachip->base + SA1111_INTC;
990a5b549edSRussell King 	save->intpol0  = readl_relaxed(base + SA1111_INTPOL0);
991a5b549edSRussell King 	save->intpol1  = readl_relaxed(base + SA1111_INTPOL1);
992a5b549edSRussell King 	save->inten0   = readl_relaxed(base + SA1111_INTEN0);
993a5b549edSRussell King 	save->inten1   = readl_relaxed(base + SA1111_INTEN1);
994a5b549edSRussell King 	save->wakepol0 = readl_relaxed(base + SA1111_WAKEPOL0);
995a5b549edSRussell King 	save->wakepol1 = readl_relaxed(base + SA1111_WAKEPOL1);
996a5b549edSRussell King 	save->wakeen0  = readl_relaxed(base + SA1111_WAKEEN0);
997a5b549edSRussell King 	save->wakeen1  = readl_relaxed(base + SA1111_WAKEEN1);
9981da177e4SLinus Torvalds 
9991da177e4SLinus Torvalds 	/*
10001da177e4SLinus Torvalds 	 * Disable.
10011da177e4SLinus Torvalds 	 */
1002a5b549edSRussell King 	val = readl_relaxed(sachip->base + SA1111_SKCR);
1003a5b549edSRussell King 	writel_relaxed(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
10041da177e4SLinus Torvalds 
100597d654f8SRussell King 	clk_disable(sachip->clk);
100697d654f8SRussell King 
10071da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
10081da177e4SLinus Torvalds 
100929c140b6SRussell King #ifdef CONFIG_ARCH_SA1100
101029c140b6SRussell King 	sa1110_mb_disable();
101129c140b6SRussell King #endif
101229c140b6SRussell King 
10131da177e4SLinus Torvalds 	return 0;
10141da177e4SLinus Torvalds }
10151da177e4SLinus Torvalds 
10161da177e4SLinus Torvalds /*
10171da177e4SLinus Torvalds  *	sa1111_resume - Restore the SA1111 device state.
10181da177e4SLinus Torvalds  *	@dev: device to restore
10191da177e4SLinus Torvalds  *
10201da177e4SLinus Torvalds  *	Restore the general state of the SA1111; clock control and
10211da177e4SLinus Torvalds  *	interrupt controller.  Other parts of the SA1111 must be
10221da177e4SLinus Torvalds  *	restored by their respective drivers, and must be called
10231da177e4SLinus Torvalds  *	via LDM after this function.
10241da177e4SLinus Torvalds  */
sa1111_resume_noirq(struct device * dev)102506dfe5ccSRussell King static int sa1111_resume_noirq(struct device *dev)
10261da177e4SLinus Torvalds {
102706dfe5ccSRussell King 	struct sa1111 *sachip = dev_get_drvdata(dev);
10281da177e4SLinus Torvalds 	struct sa1111_save_data *save;
10291da177e4SLinus Torvalds 	unsigned long flags, id;
10301da177e4SLinus Torvalds 	void __iomem *base;
10311da177e4SLinus Torvalds 
103293160c63SRafael J. Wysocki 	save = sachip->saved_state;
10331da177e4SLinus Torvalds 	if (!save)
10341da177e4SLinus Torvalds 		return 0;
10351da177e4SLinus Torvalds 
10361da177e4SLinus Torvalds 	/*
10371da177e4SLinus Torvalds 	 * Ensure that the SA1111 is still here.
10381da177e4SLinus Torvalds 	 * FIXME: shouldn't do this here.
10391da177e4SLinus Torvalds 	 */
1040a5b549edSRussell King 	id = readl_relaxed(sachip->base + SA1111_SKID);
10411da177e4SLinus Torvalds 	if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
10421da177e4SLinus Torvalds 		__sa1111_remove(sachip);
104306dfe5ccSRussell King 		dev_set_drvdata(dev, NULL);
10441da177e4SLinus Torvalds 		kfree(save);
10451da177e4SLinus Torvalds 		return 0;
10461da177e4SLinus Torvalds 	}
10471da177e4SLinus Torvalds 
10481da177e4SLinus Torvalds 	/*
10491da177e4SLinus Torvalds 	 * First of all, wake up the chip.
10501da177e4SLinus Torvalds 	 */
10511da177e4SLinus Torvalds 	sa1111_wake(sachip);
10523defb247SMarek Vašut 
105329c140b6SRussell King #ifdef CONFIG_ARCH_SA1100
105429c140b6SRussell King 	/* Enable the memory bus request/grant signals */
105529c140b6SRussell King 	sa1110_mb_enable();
105629c140b6SRussell King #endif
105729c140b6SRussell King 
10583defb247SMarek Vašut 	/*
10593defb247SMarek Vašut 	 * Only lock for write ops. Also, sa1111_wake must be called with
10603defb247SMarek Vašut 	 * released spinlock!
10613defb247SMarek Vašut 	 */
10623defb247SMarek Vašut 	spin_lock_irqsave(&sachip->lock, flags);
10633defb247SMarek Vašut 
1064a5b549edSRussell King 	writel_relaxed(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
1065a5b549edSRussell King 	writel_relaxed(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
10661da177e4SLinus Torvalds 
10671da177e4SLinus Torvalds 	base = sachip->base;
1068a5b549edSRussell King 	writel_relaxed(save->skcr,     base + SA1111_SKCR);
1069a5b549edSRussell King 	writel_relaxed(save->skpcr,    base + SA1111_SKPCR);
1070a5b549edSRussell King 	writel_relaxed(save->skcdr,    base + SA1111_SKCDR);
1071a5b549edSRussell King 	writel_relaxed(save->skaud,    base + SA1111_SKAUD);
1072a5b549edSRussell King 	writel_relaxed(save->skpwm0,   base + SA1111_SKPWM0);
1073a5b549edSRussell King 	writel_relaxed(save->skpwm1,   base + SA1111_SKPWM1);
10741da177e4SLinus Torvalds 
10751da177e4SLinus Torvalds 	base = sachip->base + SA1111_INTC;
1076a5b549edSRussell King 	writel_relaxed(save->intpol0,  base + SA1111_INTPOL0);
1077a5b549edSRussell King 	writel_relaxed(save->intpol1,  base + SA1111_INTPOL1);
1078a5b549edSRussell King 	writel_relaxed(save->inten0,   base + SA1111_INTEN0);
1079a5b549edSRussell King 	writel_relaxed(save->inten1,   base + SA1111_INTEN1);
1080a5b549edSRussell King 	writel_relaxed(save->wakepol0, base + SA1111_WAKEPOL0);
1081a5b549edSRussell King 	writel_relaxed(save->wakepol1, base + SA1111_WAKEPOL1);
1082a5b549edSRussell King 	writel_relaxed(save->wakeen0,  base + SA1111_WAKEEN0);
1083a5b549edSRussell King 	writel_relaxed(save->wakeen1,  base + SA1111_WAKEEN1);
10841da177e4SLinus Torvalds 
10851da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
10861da177e4SLinus Torvalds 
108793160c63SRafael J. Wysocki 	sachip->saved_state = NULL;
10881da177e4SLinus Torvalds 	kfree(save);
10891da177e4SLinus Torvalds 
10901da177e4SLinus Torvalds 	return 0;
10911da177e4SLinus Torvalds }
10921da177e4SLinus Torvalds 
10931da177e4SLinus Torvalds #else
109406dfe5ccSRussell King #define sa1111_suspend_noirq NULL
109506dfe5ccSRussell King #define sa1111_resume_noirq  NULL
10961da177e4SLinus Torvalds #endif
10971da177e4SLinus Torvalds 
1098414f28a9SRandy Dunlap /**
1099414f28a9SRandy Dunlap  *	sa1111_probe - probe for a single SA1111 chip.
1100414f28a9SRandy Dunlap  *	@pdev: platform device.
1101414f28a9SRandy Dunlap  *
1102414f28a9SRandy Dunlap  *	Probe for a SA1111 chip.  This must be called
1103414f28a9SRandy Dunlap  *	before any other SA1111-specific code.
1104414f28a9SRandy Dunlap  *
1105414f28a9SRandy Dunlap  *	Returns:
1106414f28a9SRandy Dunlap  *	* %-ENODEV	- device not found.
1107414f28a9SRandy Dunlap  *	* %-ENOMEM	- memory allocation failure.
1108414f28a9SRandy Dunlap  *	* %-EBUSY	- physical address already marked in-use.
1109414f28a9SRandy Dunlap  *	* %-EINVAL	- no platform data passed
1110414f28a9SRandy Dunlap  *	* %0		- successful.
1111414f28a9SRandy Dunlap  */
sa1111_probe(struct platform_device * pdev)1112351a102dSGreg Kroah-Hartman static int sa1111_probe(struct platform_device *pdev)
11131da177e4SLinus Torvalds {
11141da177e4SLinus Torvalds 	struct resource *mem;
11151da177e4SLinus Torvalds 	int irq;
11161da177e4SLinus Torvalds 
11171da177e4SLinus Torvalds 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
11181da177e4SLinus Torvalds 	if (!mem)
11191da177e4SLinus Torvalds 		return -EINVAL;
11201da177e4SLinus Torvalds 	irq = platform_get_irq(pdev, 0);
112148944738SDavid Vrabel 	if (irq < 0)
1122cb034407SRussell King 		return irq;
11231da177e4SLinus Torvalds 
11243ae5eaecSRussell King 	return __sa1111_probe(&pdev->dev, mem, irq);
11251da177e4SLinus Torvalds }
11261da177e4SLinus Torvalds 
sa1111_remove(struct platform_device * pdev)112774a5b94bSUwe Kleine-König static void sa1111_remove(struct platform_device *pdev)
11281da177e4SLinus Torvalds {
11293ae5eaecSRussell King 	struct sa1111 *sachip = platform_get_drvdata(pdev);
11301da177e4SLinus Torvalds 
11311da177e4SLinus Torvalds 	if (sachip) {
11321da177e4SLinus Torvalds #ifdef CONFIG_PM
113393160c63SRafael J. Wysocki 		kfree(sachip->saved_state);
113493160c63SRafael J. Wysocki 		sachip->saved_state = NULL;
11351da177e4SLinus Torvalds #endif
1136f2d2420bSJulia Lawall 		__sa1111_remove(sachip);
1137f2d2420bSJulia Lawall 		platform_set_drvdata(pdev, NULL);
11381da177e4SLinus Torvalds 	}
11391da177e4SLinus Torvalds }
11401da177e4SLinus Torvalds 
114106dfe5ccSRussell King static struct dev_pm_ops sa1111_pm_ops = {
114206dfe5ccSRussell King 	.suspend_noirq = sa1111_suspend_noirq,
114306dfe5ccSRussell King 	.resume_noirq = sa1111_resume_noirq,
114406dfe5ccSRussell King };
114506dfe5ccSRussell King 
11461da177e4SLinus Torvalds /*
11471da177e4SLinus Torvalds  *	Not sure if this should be on the system bus or not yet.
11481da177e4SLinus Torvalds  *	We really want some way to register a system device at
11491da177e4SLinus Torvalds  *	the per-machine level, and then have this driver pick
11501da177e4SLinus Torvalds  *	up the registered devices.
11511da177e4SLinus Torvalds  *
11521da177e4SLinus Torvalds  *	We also need to handle the SDRAM configuration for
11531da177e4SLinus Torvalds  *	PXA250/SA1110 machine classes.
11541da177e4SLinus Torvalds  */
11553ae5eaecSRussell King static struct platform_driver sa1111_device_driver = {
11561da177e4SLinus Torvalds 	.probe		= sa1111_probe,
115774a5b94bSUwe Kleine-König 	.remove_new	= sa1111_remove,
11583ae5eaecSRussell King 	.driver		= {
11593ae5eaecSRussell King 		.name	= "sa1111",
116006dfe5ccSRussell King 		.pm	= &sa1111_pm_ops,
11613ae5eaecSRussell King 	},
11621da177e4SLinus Torvalds };
11631da177e4SLinus Torvalds 
11641da177e4SLinus Torvalds /*
11651da177e4SLinus Torvalds  *	Get the parent device driver (us) structure
11661da177e4SLinus Torvalds  *	from a child function device
11671da177e4SLinus Torvalds  */
sa1111_chip_driver(struct sa1111_dev * sadev)11681da177e4SLinus Torvalds static inline struct sa1111 *sa1111_chip_driver(struct sa1111_dev *sadev)
11691da177e4SLinus Torvalds {
11701da177e4SLinus Torvalds 	return (struct sa1111 *)dev_get_drvdata(sadev->dev.parent);
11711da177e4SLinus Torvalds }
11721da177e4SLinus Torvalds 
11731da177e4SLinus Torvalds /*
11741da177e4SLinus Torvalds  * The bits in the opdiv field are non-linear.
11751da177e4SLinus Torvalds  */
11761da177e4SLinus Torvalds static unsigned char opdiv_table[] = { 1, 4, 2, 8 };
11771da177e4SLinus Torvalds 
__sa1111_pll_clock(struct sa1111 * sachip)11781da177e4SLinus Torvalds static unsigned int __sa1111_pll_clock(struct sa1111 *sachip)
11791da177e4SLinus Torvalds {
11801da177e4SLinus Torvalds 	unsigned int skcdr, fbdiv, ipdiv, opdiv;
11811da177e4SLinus Torvalds 
1182a5b549edSRussell King 	skcdr = readl_relaxed(sachip->base + SA1111_SKCDR);
11831da177e4SLinus Torvalds 
11841da177e4SLinus Torvalds 	fbdiv = (skcdr & 0x007f) + 2;
11851da177e4SLinus Torvalds 	ipdiv = ((skcdr & 0x0f80) >> 7) + 2;
11861da177e4SLinus Torvalds 	opdiv = opdiv_table[(skcdr & 0x3000) >> 12];
11871da177e4SLinus Torvalds 
11881da177e4SLinus Torvalds 	return 3686400 * fbdiv / (ipdiv * opdiv);
11891da177e4SLinus Torvalds }
11901da177e4SLinus Torvalds 
11911da177e4SLinus Torvalds /**
11921da177e4SLinus Torvalds  *	sa1111_pll_clock - return the current PLL clock frequency.
11931da177e4SLinus Torvalds  *	@sadev: SA1111 function block
11941da177e4SLinus Torvalds  *
11951da177e4SLinus Torvalds  *	BUG: we should look at SKCR.  We also blindly believe that
11961da177e4SLinus Torvalds  *	the chip is being fed with the 3.6864MHz clock.
11971da177e4SLinus Torvalds  *
11981da177e4SLinus Torvalds  *	Returns the PLL clock in Hz.
11991da177e4SLinus Torvalds  */
sa1111_pll_clock(struct sa1111_dev * sadev)12001da177e4SLinus Torvalds unsigned int sa1111_pll_clock(struct sa1111_dev *sadev)
12011da177e4SLinus Torvalds {
12021da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
12031da177e4SLinus Torvalds 
12041da177e4SLinus Torvalds 	return __sa1111_pll_clock(sachip);
12051da177e4SLinus Torvalds }
12060a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_pll_clock);
12071da177e4SLinus Torvalds 
12081da177e4SLinus Torvalds /**
12091da177e4SLinus Torvalds  *	sa1111_select_audio_mode - select I2S or AC link mode
12101da177e4SLinus Torvalds  *	@sadev: SA1111 function block
12111da177e4SLinus Torvalds  *	@mode: One of %SA1111_AUDIO_ACLINK or %SA1111_AUDIO_I2S
12121da177e4SLinus Torvalds  *
12131da177e4SLinus Torvalds  *	Frob the SKCR to select AC Link mode or I2S mode for
12141da177e4SLinus Torvalds  *	the audio block.
12151da177e4SLinus Torvalds  */
sa1111_select_audio_mode(struct sa1111_dev * sadev,int mode)12161da177e4SLinus Torvalds void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode)
12171da177e4SLinus Torvalds {
12181da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
12191da177e4SLinus Torvalds 	unsigned long flags;
12201da177e4SLinus Torvalds 	unsigned int val;
12211da177e4SLinus Torvalds 
12221da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
12231da177e4SLinus Torvalds 
1224a5b549edSRussell King 	val = readl_relaxed(sachip->base + SA1111_SKCR);
12251da177e4SLinus Torvalds 	if (mode == SA1111_AUDIO_I2S) {
12261da177e4SLinus Torvalds 		val &= ~SKCR_SELAC;
12271da177e4SLinus Torvalds 	} else {
12281da177e4SLinus Torvalds 		val |= SKCR_SELAC;
12291da177e4SLinus Torvalds 	}
1230a5b549edSRussell King 	writel_relaxed(val, sachip->base + SA1111_SKCR);
12311da177e4SLinus Torvalds 
12321da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
12331da177e4SLinus Torvalds }
12340a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_select_audio_mode);
12351da177e4SLinus Torvalds 
12361da177e4SLinus Torvalds /**
12371da177e4SLinus Torvalds  *	sa1111_set_audio_rate - set the audio sample rate
12381da177e4SLinus Torvalds  *	@sadev: SA1111 SAC function block
12391da177e4SLinus Torvalds  *	@rate: sample rate to select
12401da177e4SLinus Torvalds  */
sa1111_set_audio_rate(struct sa1111_dev * sadev,int rate)12411da177e4SLinus Torvalds int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate)
12421da177e4SLinus Torvalds {
12431da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
12441da177e4SLinus Torvalds 	unsigned int div;
12451da177e4SLinus Torvalds 
12461da177e4SLinus Torvalds 	if (sadev->devid != SA1111_DEVID_SAC)
12471da177e4SLinus Torvalds 		return -EINVAL;
12481da177e4SLinus Torvalds 
12491da177e4SLinus Torvalds 	div = (__sa1111_pll_clock(sachip) / 256 + rate / 2) / rate;
12501da177e4SLinus Torvalds 	if (div == 0)
12511da177e4SLinus Torvalds 		div = 1;
12521da177e4SLinus Torvalds 	if (div > 128)
12531da177e4SLinus Torvalds 		div = 128;
12541da177e4SLinus Torvalds 
1255a5b549edSRussell King 	writel_relaxed(div - 1, sachip->base + SA1111_SKAUD);
12561da177e4SLinus Torvalds 
12571da177e4SLinus Torvalds 	return 0;
12581da177e4SLinus Torvalds }
12590a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_set_audio_rate);
12601da177e4SLinus Torvalds 
12611da177e4SLinus Torvalds /**
12621da177e4SLinus Torvalds  *	sa1111_get_audio_rate - get the audio sample rate
12631da177e4SLinus Torvalds  *	@sadev: SA1111 SAC function block device
12641da177e4SLinus Torvalds  */
sa1111_get_audio_rate(struct sa1111_dev * sadev)12651da177e4SLinus Torvalds int sa1111_get_audio_rate(struct sa1111_dev *sadev)
12661da177e4SLinus Torvalds {
12671da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
12681da177e4SLinus Torvalds 	unsigned long div;
12691da177e4SLinus Torvalds 
12701da177e4SLinus Torvalds 	if (sadev->devid != SA1111_DEVID_SAC)
12711da177e4SLinus Torvalds 		return -EINVAL;
12721da177e4SLinus Torvalds 
1273a5b549edSRussell King 	div = readl_relaxed(sachip->base + SA1111_SKAUD) + 1;
12741da177e4SLinus Torvalds 
12751da177e4SLinus Torvalds 	return __sa1111_pll_clock(sachip) / (256 * div);
12761da177e4SLinus Torvalds }
12770a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_get_audio_rate);
12781da177e4SLinus Torvalds 
12791da177e4SLinus Torvalds /*
12801da177e4SLinus Torvalds  * Individual device operations.
12811da177e4SLinus Torvalds  */
12821da177e4SLinus Torvalds 
12831da177e4SLinus Torvalds /**
12841da177e4SLinus Torvalds  *	sa1111_enable_device - enable an on-chip SA1111 function block
12851da177e4SLinus Torvalds  *	@sadev: SA1111 function block device to enable
12861da177e4SLinus Torvalds  */
sa1111_enable_device(struct sa1111_dev * sadev)1287ae99ddbcSRussell King int sa1111_enable_device(struct sa1111_dev *sadev)
12881da177e4SLinus Torvalds {
12891da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
12901da177e4SLinus Torvalds 	unsigned long flags;
12911da177e4SLinus Torvalds 	unsigned int val;
1292ae99ddbcSRussell King 	int ret = 0;
12931da177e4SLinus Torvalds 
1294ae99ddbcSRussell King 	if (sachip->pdata && sachip->pdata->enable)
1295ae99ddbcSRussell King 		ret = sachip->pdata->enable(sachip->pdata->data, sadev->devid);
1296ae99ddbcSRussell King 
1297ae99ddbcSRussell King 	if (ret == 0) {
12981da177e4SLinus Torvalds 		spin_lock_irqsave(&sachip->lock, flags);
1299a5b549edSRussell King 		val = readl_relaxed(sachip->base + SA1111_SKPCR);
1300a5b549edSRussell King 		writel_relaxed(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
13011da177e4SLinus Torvalds 		spin_unlock_irqrestore(&sachip->lock, flags);
13021da177e4SLinus Torvalds 	}
1303ae99ddbcSRussell King 	return ret;
1304ae99ddbcSRussell King }
13050a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_enable_device);
13061da177e4SLinus Torvalds 
13071da177e4SLinus Torvalds /**
13081da177e4SLinus Torvalds  *	sa1111_disable_device - disable an on-chip SA1111 function block
13091da177e4SLinus Torvalds  *	@sadev: SA1111 function block device to disable
13101da177e4SLinus Torvalds  */
sa1111_disable_device(struct sa1111_dev * sadev)13111da177e4SLinus Torvalds void sa1111_disable_device(struct sa1111_dev *sadev)
13121da177e4SLinus Torvalds {
13131da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
13141da177e4SLinus Torvalds 	unsigned long flags;
13151da177e4SLinus Torvalds 	unsigned int val;
13161da177e4SLinus Torvalds 
13171da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
1318a5b549edSRussell King 	val = readl_relaxed(sachip->base + SA1111_SKPCR);
1319a5b549edSRussell King 	writel_relaxed(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
13201da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
1321ae99ddbcSRussell King 
1322ae99ddbcSRussell King 	if (sachip->pdata && sachip->pdata->disable)
1323ae99ddbcSRussell King 		sachip->pdata->disable(sachip->pdata->data, sadev->devid);
13241da177e4SLinus Torvalds }
13250a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_disable_device);
13261da177e4SLinus Torvalds 
sa1111_get_irq(struct sa1111_dev * sadev,unsigned num)1327cf6e4ca3SRussell King int sa1111_get_irq(struct sa1111_dev *sadev, unsigned num)
1328cf6e4ca3SRussell King {
1329be2bedb0SRussell King 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
1330be2bedb0SRussell King 	if (num >= ARRAY_SIZE(sadev->hwirq))
1331cf6e4ca3SRussell King 		return -EINVAL;
1332be2bedb0SRussell King 	return sa1111_map_irq(sachip, sadev->hwirq[num]);
1333cf6e4ca3SRussell King }
1334cf6e4ca3SRussell King EXPORT_SYMBOL_GPL(sa1111_get_irq);
1335cf6e4ca3SRussell King 
13361da177e4SLinus Torvalds /*
13371da177e4SLinus Torvalds  *	SA1111 "Register Access Bus."
13381da177e4SLinus Torvalds  *
13391da177e4SLinus Torvalds  *	We model this as a regular bus type, and hang devices directly
13401da177e4SLinus Torvalds  *	off this.
13411da177e4SLinus Torvalds  */
sa1111_match(struct device * _dev,const struct device_driver * _drv)1342*b57d5ffcSGreg Kroah-Hartman static int sa1111_match(struct device *_dev, const struct device_driver *_drv)
13431da177e4SLinus Torvalds {
1344b60752f2SRussell King 	struct sa1111_dev *dev = to_sa1111_device(_dev);
1345*b57d5ffcSGreg Kroah-Hartman 	const struct sa1111_driver *drv = SA1111_DRV(_drv);
13461da177e4SLinus Torvalds 
134717f29d36SMarek Szyprowski 	return !!(dev->devid & drv->devid);
13481da177e4SLinus Torvalds }
13491da177e4SLinus Torvalds 
sa1111_bus_probe(struct device * dev)13501da177e4SLinus Torvalds static int sa1111_bus_probe(struct device *dev)
13511da177e4SLinus Torvalds {
1352b60752f2SRussell King 	struct sa1111_dev *sadev = to_sa1111_device(dev);
13531da177e4SLinus Torvalds 	struct sa1111_driver *drv = SA1111_DRV(dev->driver);
13541da177e4SLinus Torvalds 	int ret = -ENODEV;
13551da177e4SLinus Torvalds 
13561da177e4SLinus Torvalds 	if (drv->probe)
13571da177e4SLinus Torvalds 		ret = drv->probe(sadev);
13581da177e4SLinus Torvalds 	return ret;
13591da177e4SLinus Torvalds }
13601da177e4SLinus Torvalds 
sa1111_bus_remove(struct device * dev)1361fc7a6209SUwe Kleine-König static void sa1111_bus_remove(struct device *dev)
13621da177e4SLinus Torvalds {
1363b60752f2SRussell King 	struct sa1111_dev *sadev = to_sa1111_device(dev);
13641da177e4SLinus Torvalds 	struct sa1111_driver *drv = SA1111_DRV(dev->driver);
13651da177e4SLinus Torvalds 
13661da177e4SLinus Torvalds 	if (drv->remove)
1367074a6bdaSUwe Kleine-König 		drv->remove(sadev);
13681da177e4SLinus Torvalds }
13691da177e4SLinus Torvalds 
13701da177e4SLinus Torvalds struct bus_type sa1111_bus_type = {
13711da177e4SLinus Torvalds 	.name		= "sa1111-rab",
13721da177e4SLinus Torvalds 	.match		= sa1111_match,
13732876ba43SRussell King 	.probe		= sa1111_bus_probe,
13742876ba43SRussell King 	.remove		= sa1111_bus_remove,
13751da177e4SLinus Torvalds };
13760a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_bus_type);
13771da177e4SLinus Torvalds 
sa1111_driver_register(struct sa1111_driver * driver)13781da177e4SLinus Torvalds int sa1111_driver_register(struct sa1111_driver *driver)
13791da177e4SLinus Torvalds {
13801da177e4SLinus Torvalds 	driver->drv.bus = &sa1111_bus_type;
13811da177e4SLinus Torvalds 	return driver_register(&driver->drv);
13821da177e4SLinus Torvalds }
13830a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_driver_register);
13841da177e4SLinus Torvalds 
sa1111_driver_unregister(struct sa1111_driver * driver)13851da177e4SLinus Torvalds void sa1111_driver_unregister(struct sa1111_driver *driver)
13861da177e4SLinus Torvalds {
13871da177e4SLinus Torvalds 	driver_unregister(&driver->drv);
13881da177e4SLinus Torvalds }
13890a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_driver_unregister);
13901da177e4SLinus Torvalds 
sa1111_init(void)13911da177e4SLinus Torvalds static int __init sa1111_init(void)
13921da177e4SLinus Torvalds {
13931da177e4SLinus Torvalds 	int ret = bus_register(&sa1111_bus_type);
13941da177e4SLinus Torvalds 	if (ret == 0)
13953ae5eaecSRussell King 		platform_driver_register(&sa1111_device_driver);
13961da177e4SLinus Torvalds 	return ret;
13971da177e4SLinus Torvalds }
13981da177e4SLinus Torvalds 
sa1111_exit(void)13991da177e4SLinus Torvalds static void __exit sa1111_exit(void)
14001da177e4SLinus Torvalds {
14013ae5eaecSRussell King 	platform_driver_unregister(&sa1111_device_driver);
14021da177e4SLinus Torvalds 	bus_unregister(&sa1111_bus_type);
14031da177e4SLinus Torvalds }
14041da177e4SLinus Torvalds 
140572724382SRussell King subsys_initcall(sa1111_init);
14061da177e4SLinus Torvalds module_exit(sa1111_exit);
14071da177e4SLinus Torvalds 
14081da177e4SLinus Torvalds MODULE_DESCRIPTION("Intel Corporation SA1111 core driver");
14091da177e4SLinus Torvalds MODULE_LICENSE("GPL");
1410