xref: /linux/arch/arm/common/sa1111.c (revision 17cf50116e10affaadfee9af2253c841f7ac0623)
11da177e4SLinus Torvalds /*
2f30c2269SUwe Zeisberger  * linux/arch/arm/common/sa1111.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * SA1111 support
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Original code by John Dorsey
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or modify
91da177e4SLinus Torvalds  * it under the terms of the GNU General Public License version 2 as
101da177e4SLinus Torvalds  * published by the Free Software Foundation.
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  * This file contains all generic SA1111 support.
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  * All initialization functions provided here are intended to be called
151da177e4SLinus Torvalds  * from machine specific code with proper arguments when required.
161da177e4SLinus Torvalds  */
171da177e4SLinus Torvalds #include <linux/module.h>
18*17cf5011SRussell King #include <linux/gpio/driver.h>
191da177e4SLinus Torvalds #include <linux/init.h>
2036d31213SRussell King #include <linux/irq.h>
211da177e4SLinus Torvalds #include <linux/kernel.h>
221da177e4SLinus Torvalds #include <linux/delay.h>
231da177e4SLinus Torvalds #include <linux/errno.h>
241da177e4SLinus Torvalds #include <linux/ioport.h>
25d052d1beSRussell King #include <linux/platform_device.h>
261da177e4SLinus Torvalds #include <linux/slab.h>
271da177e4SLinus Torvalds #include <linux/spinlock.h>
281da177e4SLinus Torvalds #include <linux/dma-mapping.h>
2997d654f8SRussell King #include <linux/clk.h>
30fced80c7SRussell King #include <linux/io.h>
311da177e4SLinus Torvalds 
32a09e64fbSRussell King #include <mach/hardware.h>
331da177e4SLinus Torvalds #include <asm/mach/irq.h>
3436d31213SRussell King #include <asm/mach-types.h>
3545e109d0SRussell King #include <asm/sizes.h>
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds #include <asm/hardware/sa1111.h>
381da177e4SLinus Torvalds 
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;
111*17cf5011SRussell King 	struct gpio_chip gc;
11293160c63SRafael J. Wysocki #ifdef CONFIG_PM
11393160c63SRafael J. Wysocki 	void		*saved_state;
11493160c63SRafael J. Wysocki #endif
1151da177e4SLinus Torvalds };
1161da177e4SLinus Torvalds 
1171da177e4SLinus Torvalds /*
1181da177e4SLinus Torvalds  * We _really_ need to eliminate this.  Its only users
1191da177e4SLinus Torvalds  * are the PWM and DMA checking code.
1201da177e4SLinus Torvalds  */
1211da177e4SLinus Torvalds static struct sa1111 *g_sa1111;
1221da177e4SLinus Torvalds 
1231da177e4SLinus Torvalds struct sa1111_dev_info {
1241da177e4SLinus Torvalds 	unsigned long	offset;
1251da177e4SLinus Torvalds 	unsigned long	skpcr_mask;
12621d1c770SRussell King 	bool		dma;
1271da177e4SLinus Torvalds 	unsigned int	devid;
1281da177e4SLinus Torvalds 	unsigned int	irq[6];
1291da177e4SLinus Torvalds };
1301da177e4SLinus Torvalds 
1311da177e4SLinus Torvalds static struct sa1111_dev_info sa1111_devices[] = {
1321da177e4SLinus Torvalds 	{
1331da177e4SLinus Torvalds 		.offset		= SA1111_USB,
1341da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_UCLKEN,
13521d1c770SRussell King 		.dma		= true,
1361da177e4SLinus Torvalds 		.devid		= SA1111_DEVID_USB,
1371da177e4SLinus Torvalds 		.irq = {
1381da177e4SLinus Torvalds 			IRQ_USBPWR,
1391da177e4SLinus Torvalds 			IRQ_HCIM,
1401da177e4SLinus Torvalds 			IRQ_HCIBUFFACC,
1411da177e4SLinus Torvalds 			IRQ_HCIRMTWKP,
1421da177e4SLinus Torvalds 			IRQ_NHCIMFCIR,
1431da177e4SLinus Torvalds 			IRQ_USB_PORT_RESUME
1441da177e4SLinus Torvalds 		},
1451da177e4SLinus Torvalds 	},
1461da177e4SLinus Torvalds 	{
1471da177e4SLinus Torvalds 		.offset		= 0x0600,
1481da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_I2SCLKEN | SKPCR_L3CLKEN,
14921d1c770SRussell King 		.dma		= true,
1501da177e4SLinus Torvalds 		.devid		= SA1111_DEVID_SAC,
1511da177e4SLinus Torvalds 		.irq = {
1521da177e4SLinus Torvalds 			AUDXMTDMADONEA,
1531da177e4SLinus Torvalds 			AUDXMTDMADONEB,
1541da177e4SLinus Torvalds 			AUDRCVDMADONEA,
1551da177e4SLinus Torvalds 			AUDRCVDMADONEB
1561da177e4SLinus Torvalds 		},
1571da177e4SLinus Torvalds 	},
1581da177e4SLinus Torvalds 	{
1591da177e4SLinus Torvalds 		.offset		= 0x0800,
1601da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_SCLKEN,
1611da177e4SLinus Torvalds 		.devid		= SA1111_DEVID_SSP,
1621da177e4SLinus Torvalds 	},
1631da177e4SLinus Torvalds 	{
1641da177e4SLinus Torvalds 		.offset		= SA1111_KBD,
1651da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_PTCLKEN,
166e5c0fc41SRussell King 		.devid		= SA1111_DEVID_PS2_KBD,
1671da177e4SLinus Torvalds 		.irq = {
1681da177e4SLinus Torvalds 			IRQ_TPRXINT,
1691da177e4SLinus Torvalds 			IRQ_TPTXINT
1701da177e4SLinus Torvalds 		},
1711da177e4SLinus Torvalds 	},
1721da177e4SLinus Torvalds 	{
1731da177e4SLinus Torvalds 		.offset		= SA1111_MSE,
1741da177e4SLinus Torvalds 		.skpcr_mask	= SKPCR_PMCLKEN,
175e5c0fc41SRussell King 		.devid		= SA1111_DEVID_PS2_MSE,
1761da177e4SLinus Torvalds 		.irq = {
1771da177e4SLinus Torvalds 			IRQ_MSRXINT,
1781da177e4SLinus Torvalds 			IRQ_MSTXINT
1791da177e4SLinus Torvalds 		},
1801da177e4SLinus Torvalds 	},
1811da177e4SLinus Torvalds 	{
1821da177e4SLinus Torvalds 		.offset		= 0x1800,
1831da177e4SLinus Torvalds 		.skpcr_mask	= 0,
1841da177e4SLinus Torvalds 		.devid		= SA1111_DEVID_PCMCIA,
1851da177e4SLinus Torvalds 		.irq = {
1861da177e4SLinus Torvalds 			IRQ_S0_READY_NINT,
1871da177e4SLinus Torvalds 			IRQ_S0_CD_VALID,
1881da177e4SLinus Torvalds 			IRQ_S0_BVD1_STSCHG,
1891da177e4SLinus Torvalds 			IRQ_S1_READY_NINT,
1901da177e4SLinus Torvalds 			IRQ_S1_CD_VALID,
1911da177e4SLinus Torvalds 			IRQ_S1_BVD1_STSCHG,
1921da177e4SLinus Torvalds 		},
1931da177e4SLinus Torvalds 	},
1941da177e4SLinus Torvalds };
1951da177e4SLinus Torvalds 
1961da177e4SLinus Torvalds /*
1971da177e4SLinus Torvalds  * SA1111 interrupt support.  Since clearing an IRQ while there are
1981da177e4SLinus Torvalds  * active IRQs causes the interrupt output to pulse, the upper levels
1991da177e4SLinus Torvalds  * will call us again if there are more interrupts to process.
2001da177e4SLinus Torvalds  */
201bd0b9ac4SThomas Gleixner static void sa1111_irq_handler(struct irq_desc *desc)
2021da177e4SLinus Torvalds {
2031da177e4SLinus Torvalds 	unsigned int stat0, stat1, i;
204f575398bSJiang Liu 	struct sa1111 *sachip = irq_desc_get_handler_data(desc);
20519851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
2061da177e4SLinus Torvalds 
20719851c58SEric Miao 	stat0 = sa1111_readl(mapbase + SA1111_INTSTATCLR0);
20819851c58SEric Miao 	stat1 = sa1111_readl(mapbase + SA1111_INTSTATCLR1);
2091da177e4SLinus Torvalds 
21019851c58SEric Miao 	sa1111_writel(stat0, mapbase + SA1111_INTSTATCLR0);
2111da177e4SLinus Torvalds 
2128231e741SLennert Buytenhek 	desc->irq_data.chip->irq_ack(&desc->irq_data);
2131da177e4SLinus Torvalds 
21419851c58SEric Miao 	sa1111_writel(stat1, mapbase + SA1111_INTSTATCLR1);
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds 	if (stat0 == 0 && stat1 == 0) {
217bd0b9ac4SThomas Gleixner 		do_bad_IRQ(desc);
2181da177e4SLinus Torvalds 		return;
2191da177e4SLinus Torvalds 	}
2201da177e4SLinus Torvalds 
22119851c58SEric Miao 	for (i = 0; stat0; i++, stat0 >>= 1)
2221da177e4SLinus Torvalds 		if (stat0 & 1)
22319851c58SEric Miao 			generic_handle_irq(i + sachip->irq_base);
2241da177e4SLinus Torvalds 
22519851c58SEric Miao 	for (i = 32; stat1; i++, stat1 >>= 1)
2261da177e4SLinus Torvalds 		if (stat1 & 1)
22719851c58SEric Miao 			generic_handle_irq(i + sachip->irq_base);
2281da177e4SLinus Torvalds 
2291da177e4SLinus Torvalds 	/* For level-based interrupts */
2308231e741SLennert Buytenhek 	desc->irq_data.chip->irq_unmask(&desc->irq_data);
2311da177e4SLinus Torvalds }
2321da177e4SLinus Torvalds 
23319851c58SEric Miao #define SA1111_IRQMASK_LO(x)	(1 << (x - sachip->irq_base))
23419851c58SEric Miao #define SA1111_IRQMASK_HI(x)	(1 << (x - sachip->irq_base - 32))
2351da177e4SLinus Torvalds 
2368231e741SLennert Buytenhek static void sa1111_ack_irq(struct irq_data *d)
2371da177e4SLinus Torvalds {
2381da177e4SLinus Torvalds }
2391da177e4SLinus Torvalds 
2408231e741SLennert Buytenhek static void sa1111_mask_lowirq(struct irq_data *d)
2411da177e4SLinus Torvalds {
2428231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
24319851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
2441da177e4SLinus Torvalds 	unsigned long ie0;
2451da177e4SLinus Torvalds 
2461da177e4SLinus Torvalds 	ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
2478231e741SLennert Buytenhek 	ie0 &= ~SA1111_IRQMASK_LO(d->irq);
2481da177e4SLinus Torvalds 	writel(ie0, mapbase + SA1111_INTEN0);
2491da177e4SLinus Torvalds }
2501da177e4SLinus Torvalds 
2518231e741SLennert Buytenhek static void sa1111_unmask_lowirq(struct irq_data *d)
2521da177e4SLinus Torvalds {
2538231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
25419851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
2551da177e4SLinus Torvalds 	unsigned long ie0;
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
2588231e741SLennert Buytenhek 	ie0 |= SA1111_IRQMASK_LO(d->irq);
2591da177e4SLinus Torvalds 	sa1111_writel(ie0, mapbase + SA1111_INTEN0);
2601da177e4SLinus Torvalds }
2611da177e4SLinus Torvalds 
2621da177e4SLinus Torvalds /*
2631da177e4SLinus Torvalds  * Attempt to re-trigger the interrupt.  The SA1111 contains a register
2641da177e4SLinus Torvalds  * (INTSET) which claims to do this.  However, in practice no amount of
2651da177e4SLinus Torvalds  * manipulation of INTEN and INTSET guarantees that the interrupt will
2661da177e4SLinus Torvalds  * be triggered.  In fact, its very difficult, if not impossible to get
2671da177e4SLinus Torvalds  * INTSET to re-trigger the interrupt.
2681da177e4SLinus Torvalds  */
2698231e741SLennert Buytenhek static int sa1111_retrigger_lowirq(struct irq_data *d)
2701da177e4SLinus Torvalds {
2718231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
27219851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
2738231e741SLennert Buytenhek 	unsigned int mask = SA1111_IRQMASK_LO(d->irq);
2741da177e4SLinus Torvalds 	unsigned long ip0;
2751da177e4SLinus Torvalds 	int i;
2761da177e4SLinus Torvalds 
2771da177e4SLinus Torvalds 	ip0 = sa1111_readl(mapbase + SA1111_INTPOL0);
2781da177e4SLinus Torvalds 	for (i = 0; i < 8; i++) {
2791da177e4SLinus Torvalds 		sa1111_writel(ip0 ^ mask, mapbase + SA1111_INTPOL0);
2801da177e4SLinus Torvalds 		sa1111_writel(ip0, mapbase + SA1111_INTPOL0);
281cae39988SPavel Machek 		if (sa1111_readl(mapbase + SA1111_INTSTATCLR0) & mask)
2821da177e4SLinus Torvalds 			break;
2831da177e4SLinus Torvalds 	}
2841da177e4SLinus Torvalds 
2851da177e4SLinus Torvalds 	if (i == 8)
2864ed89f22SRussell King 		pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n",
2874ed89f22SRussell King 		       d->irq);
2881da177e4SLinus Torvalds 	return i == 8 ? -1 : 0;
2891da177e4SLinus Torvalds }
2901da177e4SLinus Torvalds 
2918231e741SLennert Buytenhek static int sa1111_type_lowirq(struct irq_data *d, unsigned int flags)
2921da177e4SLinus Torvalds {
2938231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
29419851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
2958231e741SLennert Buytenhek 	unsigned int mask = SA1111_IRQMASK_LO(d->irq);
2961da177e4SLinus Torvalds 	unsigned long ip0;
2971da177e4SLinus Torvalds 
2986cab4860SDmitry Baryshkov 	if (flags == IRQ_TYPE_PROBE)
2991da177e4SLinus Torvalds 		return 0;
3001da177e4SLinus Torvalds 
3016cab4860SDmitry Baryshkov 	if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
3021da177e4SLinus Torvalds 		return -EINVAL;
3031da177e4SLinus Torvalds 
3041da177e4SLinus Torvalds 	ip0 = sa1111_readl(mapbase + SA1111_INTPOL0);
3056cab4860SDmitry Baryshkov 	if (flags & IRQ_TYPE_EDGE_RISING)
3061da177e4SLinus Torvalds 		ip0 &= ~mask;
3071da177e4SLinus Torvalds 	else
3081da177e4SLinus Torvalds 		ip0 |= mask;
3091da177e4SLinus Torvalds 	sa1111_writel(ip0, mapbase + SA1111_INTPOL0);
3101da177e4SLinus Torvalds 	sa1111_writel(ip0, mapbase + SA1111_WAKEPOL0);
3111da177e4SLinus Torvalds 
3121da177e4SLinus Torvalds 	return 0;
3131da177e4SLinus Torvalds }
3141da177e4SLinus Torvalds 
3158231e741SLennert Buytenhek static int sa1111_wake_lowirq(struct irq_data *d, unsigned int on)
3161da177e4SLinus Torvalds {
3178231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
31819851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
3198231e741SLennert Buytenhek 	unsigned int mask = SA1111_IRQMASK_LO(d->irq);
3201da177e4SLinus Torvalds 	unsigned long we0;
3211da177e4SLinus Torvalds 
3221da177e4SLinus Torvalds 	we0 = sa1111_readl(mapbase + SA1111_WAKEEN0);
3231da177e4SLinus Torvalds 	if (on)
3241da177e4SLinus Torvalds 		we0 |= mask;
3251da177e4SLinus Torvalds 	else
3261da177e4SLinus Torvalds 		we0 &= ~mask;
3271da177e4SLinus Torvalds 	sa1111_writel(we0, mapbase + SA1111_WAKEEN0);
3281da177e4SLinus Torvalds 
3291da177e4SLinus Torvalds 	return 0;
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
33238c677cbSDavid Brownell static struct irq_chip sa1111_low_chip = {
33338c677cbSDavid Brownell 	.name		= "SA1111-l",
3348231e741SLennert Buytenhek 	.irq_ack	= sa1111_ack_irq,
3358231e741SLennert Buytenhek 	.irq_mask	= sa1111_mask_lowirq,
3368231e741SLennert Buytenhek 	.irq_unmask	= sa1111_unmask_lowirq,
3378231e741SLennert Buytenhek 	.irq_retrigger	= sa1111_retrigger_lowirq,
3388231e741SLennert Buytenhek 	.irq_set_type	= sa1111_type_lowirq,
3398231e741SLennert Buytenhek 	.irq_set_wake	= sa1111_wake_lowirq,
3401da177e4SLinus Torvalds };
3411da177e4SLinus Torvalds 
3428231e741SLennert Buytenhek static void sa1111_mask_highirq(struct irq_data *d)
3431da177e4SLinus Torvalds {
3448231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
34519851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
3461da177e4SLinus Torvalds 	unsigned long ie1;
3471da177e4SLinus Torvalds 
3481da177e4SLinus Torvalds 	ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
3498231e741SLennert Buytenhek 	ie1 &= ~SA1111_IRQMASK_HI(d->irq);
3501da177e4SLinus Torvalds 	sa1111_writel(ie1, mapbase + SA1111_INTEN1);
3511da177e4SLinus Torvalds }
3521da177e4SLinus Torvalds 
3538231e741SLennert Buytenhek static void sa1111_unmask_highirq(struct irq_data *d)
3541da177e4SLinus Torvalds {
3558231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
35619851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
3571da177e4SLinus Torvalds 	unsigned long ie1;
3581da177e4SLinus Torvalds 
3591da177e4SLinus Torvalds 	ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
3608231e741SLennert Buytenhek 	ie1 |= SA1111_IRQMASK_HI(d->irq);
3611da177e4SLinus Torvalds 	sa1111_writel(ie1, mapbase + SA1111_INTEN1);
3621da177e4SLinus Torvalds }
3631da177e4SLinus Torvalds 
3641da177e4SLinus Torvalds /*
3651da177e4SLinus Torvalds  * Attempt to re-trigger the interrupt.  The SA1111 contains a register
3661da177e4SLinus Torvalds  * (INTSET) which claims to do this.  However, in practice no amount of
3671da177e4SLinus Torvalds  * manipulation of INTEN and INTSET guarantees that the interrupt will
3681da177e4SLinus Torvalds  * be triggered.  In fact, its very difficult, if not impossible to get
3691da177e4SLinus Torvalds  * INTSET to re-trigger the interrupt.
3701da177e4SLinus Torvalds  */
3718231e741SLennert Buytenhek static int sa1111_retrigger_highirq(struct irq_data *d)
3721da177e4SLinus Torvalds {
3738231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
37419851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
3758231e741SLennert Buytenhek 	unsigned int mask = SA1111_IRQMASK_HI(d->irq);
3761da177e4SLinus Torvalds 	unsigned long ip1;
3771da177e4SLinus Torvalds 	int i;
3781da177e4SLinus Torvalds 
3791da177e4SLinus Torvalds 	ip1 = sa1111_readl(mapbase + SA1111_INTPOL1);
3801da177e4SLinus Torvalds 	for (i = 0; i < 8; i++) {
3811da177e4SLinus Torvalds 		sa1111_writel(ip1 ^ mask, mapbase + SA1111_INTPOL1);
3821da177e4SLinus Torvalds 		sa1111_writel(ip1, mapbase + SA1111_INTPOL1);
3831da177e4SLinus Torvalds 		if (sa1111_readl(mapbase + SA1111_INTSTATCLR1) & mask)
3841da177e4SLinus Torvalds 			break;
3851da177e4SLinus Torvalds 	}
3861da177e4SLinus Torvalds 
3871da177e4SLinus Torvalds 	if (i == 8)
3884ed89f22SRussell King 		pr_err("Danger Will Robinson: failed to re-trigger IRQ%d\n",
3894ed89f22SRussell King 		       d->irq);
3901da177e4SLinus Torvalds 	return i == 8 ? -1 : 0;
3911da177e4SLinus Torvalds }
3921da177e4SLinus Torvalds 
3938231e741SLennert Buytenhek static int sa1111_type_highirq(struct irq_data *d, unsigned int flags)
3941da177e4SLinus Torvalds {
3958231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
39619851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
3978231e741SLennert Buytenhek 	unsigned int mask = SA1111_IRQMASK_HI(d->irq);
3981da177e4SLinus Torvalds 	unsigned long ip1;
3991da177e4SLinus Torvalds 
4006cab4860SDmitry Baryshkov 	if (flags == IRQ_TYPE_PROBE)
4011da177e4SLinus Torvalds 		return 0;
4021da177e4SLinus Torvalds 
4036cab4860SDmitry Baryshkov 	if ((!(flags & IRQ_TYPE_EDGE_RISING) ^ !(flags & IRQ_TYPE_EDGE_FALLING)) == 0)
4041da177e4SLinus Torvalds 		return -EINVAL;
4051da177e4SLinus Torvalds 
4061da177e4SLinus Torvalds 	ip1 = sa1111_readl(mapbase + SA1111_INTPOL1);
4076cab4860SDmitry Baryshkov 	if (flags & IRQ_TYPE_EDGE_RISING)
4081da177e4SLinus Torvalds 		ip1 &= ~mask;
4091da177e4SLinus Torvalds 	else
4101da177e4SLinus Torvalds 		ip1 |= mask;
4111da177e4SLinus Torvalds 	sa1111_writel(ip1, mapbase + SA1111_INTPOL1);
4121da177e4SLinus Torvalds 	sa1111_writel(ip1, mapbase + SA1111_WAKEPOL1);
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds 	return 0;
4151da177e4SLinus Torvalds }
4161da177e4SLinus Torvalds 
4178231e741SLennert Buytenhek static int sa1111_wake_highirq(struct irq_data *d, unsigned int on)
4181da177e4SLinus Torvalds {
4198231e741SLennert Buytenhek 	struct sa1111 *sachip = irq_data_get_irq_chip_data(d);
42019851c58SEric Miao 	void __iomem *mapbase = sachip->base + SA1111_INTC;
4218231e741SLennert Buytenhek 	unsigned int mask = SA1111_IRQMASK_HI(d->irq);
4221da177e4SLinus Torvalds 	unsigned long we1;
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds 	we1 = sa1111_readl(mapbase + SA1111_WAKEEN1);
4251da177e4SLinus Torvalds 	if (on)
4261da177e4SLinus Torvalds 		we1 |= mask;
4271da177e4SLinus Torvalds 	else
4281da177e4SLinus Torvalds 		we1 &= ~mask;
4291da177e4SLinus Torvalds 	sa1111_writel(we1, mapbase + SA1111_WAKEEN1);
4301da177e4SLinus Torvalds 
4311da177e4SLinus Torvalds 	return 0;
4321da177e4SLinus Torvalds }
4331da177e4SLinus Torvalds 
43438c677cbSDavid Brownell static struct irq_chip sa1111_high_chip = {
43538c677cbSDavid Brownell 	.name		= "SA1111-h",
4368231e741SLennert Buytenhek 	.irq_ack	= sa1111_ack_irq,
4378231e741SLennert Buytenhek 	.irq_mask	= sa1111_mask_highirq,
4388231e741SLennert Buytenhek 	.irq_unmask	= sa1111_unmask_highirq,
4398231e741SLennert Buytenhek 	.irq_retrigger	= sa1111_retrigger_highirq,
4408231e741SLennert Buytenhek 	.irq_set_type	= sa1111_type_highirq,
4418231e741SLennert Buytenhek 	.irq_set_wake	= sa1111_wake_highirq,
4421da177e4SLinus Torvalds };
4431da177e4SLinus Torvalds 
44436d31213SRussell King static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
4451da177e4SLinus Torvalds {
4461da177e4SLinus Torvalds 	void __iomem *irqbase = sachip->base + SA1111_INTC;
447f03ecaa0SRussell King 	unsigned i, irq;
44836d31213SRussell King 	int ret;
4491da177e4SLinus Torvalds 
4501da177e4SLinus Torvalds 	/*
4511da177e4SLinus Torvalds 	 * We're guaranteed that this region hasn't been taken.
4521da177e4SLinus Torvalds 	 */
4531da177e4SLinus Torvalds 	request_mem_region(sachip->phys + SA1111_INTC, 512, "irq");
4541da177e4SLinus Torvalds 
45536d31213SRussell King 	ret = irq_alloc_descs(-1, irq_base, SA1111_IRQ_NR, -1);
45636d31213SRussell King 	if (ret <= 0) {
45736d31213SRussell King 		dev_err(sachip->dev, "unable to allocate %u irqs: %d\n",
45836d31213SRussell King 			SA1111_IRQ_NR, ret);
45936d31213SRussell King 		if (ret == 0)
46036d31213SRussell King 			ret = -EINVAL;
46136d31213SRussell King 		return ret;
46236d31213SRussell King 	}
46336d31213SRussell King 
46436d31213SRussell King 	sachip->irq_base = ret;
46536d31213SRussell King 
4661da177e4SLinus Torvalds 	/* disable all IRQs */
4671da177e4SLinus Torvalds 	sa1111_writel(0, irqbase + SA1111_INTEN0);
4681da177e4SLinus Torvalds 	sa1111_writel(0, irqbase + SA1111_INTEN1);
4691da177e4SLinus Torvalds 	sa1111_writel(0, irqbase + SA1111_WAKEEN0);
4701da177e4SLinus Torvalds 	sa1111_writel(0, irqbase + SA1111_WAKEEN1);
4711da177e4SLinus Torvalds 
4721da177e4SLinus Torvalds 	/*
4731da177e4SLinus Torvalds 	 * detect on rising edge.  Note: Feb 2001 Errata for SA1111
4741da177e4SLinus Torvalds 	 * specifies that S0ReadyInt and S1ReadyInt should be '1'.
4751da177e4SLinus Torvalds 	 */
4761da177e4SLinus Torvalds 	sa1111_writel(0, irqbase + SA1111_INTPOL0);
4777c0091ecSRussell King 	sa1111_writel(BIT(IRQ_S0_READY_NINT & 31) |
4787c0091ecSRussell King 		      BIT(IRQ_S1_READY_NINT & 31),
4791da177e4SLinus Torvalds 		      irqbase + SA1111_INTPOL1);
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds 	/* clear all IRQs */
4821da177e4SLinus Torvalds 	sa1111_writel(~0, irqbase + SA1111_INTSTATCLR0);
4831da177e4SLinus Torvalds 	sa1111_writel(~0, irqbase + SA1111_INTSTATCLR1);
4841da177e4SLinus Torvalds 
485f03ecaa0SRussell King 	for (i = IRQ_GPAIN0; i <= SSPROR; i++) {
486f03ecaa0SRussell King 		irq = sachip->irq_base + i;
487f38c02f3SThomas Gleixner 		irq_set_chip_and_handler(irq, &sa1111_low_chip,
488f38c02f3SThomas Gleixner 					 handle_edge_irq);
4899323f261SThomas Gleixner 		irq_set_chip_data(irq, sachip);
490e8d36d5dSRob Herring 		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
4911da177e4SLinus Torvalds 	}
4921da177e4SLinus Torvalds 
493f03ecaa0SRussell King 	for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) {
494f03ecaa0SRussell King 		irq = sachip->irq_base + i;
495f38c02f3SThomas Gleixner 		irq_set_chip_and_handler(irq, &sa1111_high_chip,
496f38c02f3SThomas Gleixner 					 handle_edge_irq);
4979323f261SThomas Gleixner 		irq_set_chip_data(irq, sachip);
498e8d36d5dSRob Herring 		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
4991da177e4SLinus Torvalds 	}
5001da177e4SLinus Torvalds 
5011da177e4SLinus Torvalds 	/*
5021da177e4SLinus Torvalds 	 * Register SA1111 interrupt
5031da177e4SLinus Torvalds 	 */
5046845664aSThomas Gleixner 	irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
505056c0acfSRussell King 	irq_set_chained_handler_and_data(sachip->irq, sa1111_irq_handler,
506056c0acfSRussell King 					 sachip);
50736d31213SRussell King 
50836d31213SRussell King 	dev_info(sachip->dev, "Providing IRQ%u-%u\n",
50936d31213SRussell King 		sachip->irq_base, sachip->irq_base + SA1111_IRQ_NR - 1);
51036d31213SRussell King 
51136d31213SRussell King 	return 0;
5121da177e4SLinus Torvalds }
5131da177e4SLinus Torvalds 
514ccb7d854SRussell King static void sa1111_remove_irq(struct sa1111 *sachip)
515ccb7d854SRussell King {
516ccb7d854SRussell King 	void __iomem *irqbase = sachip->base + SA1111_INTC;
517ccb7d854SRussell King 
518ccb7d854SRussell King 	/* disable all IRQs */
519ccb7d854SRussell King 	sa1111_writel(0, irqbase + SA1111_INTEN0);
520ccb7d854SRussell King 	sa1111_writel(0, irqbase + SA1111_INTEN1);
521ccb7d854SRussell King 	sa1111_writel(0, irqbase + SA1111_WAKEEN0);
522ccb7d854SRussell King 	sa1111_writel(0, irqbase + SA1111_WAKEEN1);
523ccb7d854SRussell King 
524ccb7d854SRussell King 	if (sachip->irq != NO_IRQ) {
525ccb7d854SRussell King 		irq_set_chained_handler_and_data(sachip->irq, NULL, NULL);
526ccb7d854SRussell King 		irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);
527ccb7d854SRussell King 
528ccb7d854SRussell King 		release_mem_region(sachip->phys + SA1111_INTC, 512);
529ccb7d854SRussell King 	}
530ccb7d854SRussell King }
531ccb7d854SRussell King 
532*17cf5011SRussell King enum {
533*17cf5011SRussell King 	SA1111_GPIO_PXDDR = (SA1111_GPIO_PADDR - SA1111_GPIO_PADDR),
534*17cf5011SRussell King 	SA1111_GPIO_PXDRR = (SA1111_GPIO_PADRR - SA1111_GPIO_PADDR),
535*17cf5011SRussell King 	SA1111_GPIO_PXDWR = (SA1111_GPIO_PADWR - SA1111_GPIO_PADDR),
536*17cf5011SRussell King 	SA1111_GPIO_PXSDR = (SA1111_GPIO_PASDR - SA1111_GPIO_PADDR),
537*17cf5011SRussell King 	SA1111_GPIO_PXSSR = (SA1111_GPIO_PASSR - SA1111_GPIO_PADDR),
538*17cf5011SRussell King };
539*17cf5011SRussell King 
540*17cf5011SRussell King static struct sa1111 *gc_to_sa1111(struct gpio_chip *gc)
541*17cf5011SRussell King {
542*17cf5011SRussell King 	return container_of(gc, struct sa1111, gc);
543*17cf5011SRussell King }
544*17cf5011SRussell King 
545*17cf5011SRussell King static void __iomem *sa1111_gpio_map_reg(struct sa1111 *sachip, unsigned offset)
546*17cf5011SRussell King {
547*17cf5011SRussell King 	void __iomem *reg = sachip->base + SA1111_GPIO;
548*17cf5011SRussell King 
549*17cf5011SRussell King 	if (offset < 4)
550*17cf5011SRussell King 		return reg + SA1111_GPIO_PADDR;
551*17cf5011SRussell King 	if (offset < 10)
552*17cf5011SRussell King 		return reg + SA1111_GPIO_PBDDR;
553*17cf5011SRussell King 	if (offset < 18)
554*17cf5011SRussell King 		return reg + SA1111_GPIO_PCDDR;
555*17cf5011SRussell King 	return NULL;
556*17cf5011SRussell King }
557*17cf5011SRussell King 
558*17cf5011SRussell King static u32 sa1111_gpio_map_bit(unsigned offset)
559*17cf5011SRussell King {
560*17cf5011SRussell King 	if (offset < 4)
561*17cf5011SRussell King 		return BIT(offset);
562*17cf5011SRussell King 	if (offset < 10)
563*17cf5011SRussell King 		return BIT(offset - 4);
564*17cf5011SRussell King 	if (offset < 18)
565*17cf5011SRussell King 		return BIT(offset - 10);
566*17cf5011SRussell King 	return 0;
567*17cf5011SRussell King }
568*17cf5011SRussell King 
569*17cf5011SRussell King static void sa1111_gpio_modify(void __iomem *reg, u32 mask, u32 set)
570*17cf5011SRussell King {
571*17cf5011SRussell King 	u32 val;
572*17cf5011SRussell King 
573*17cf5011SRussell King 	val = readl_relaxed(reg);
574*17cf5011SRussell King 	val &= ~mask;
575*17cf5011SRussell King 	val |= mask & set;
576*17cf5011SRussell King 	writel_relaxed(val, reg);
577*17cf5011SRussell King }
578*17cf5011SRussell King 
579*17cf5011SRussell King static int sa1111_gpio_get_direction(struct gpio_chip *gc, unsigned offset)
580*17cf5011SRussell King {
581*17cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
582*17cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
583*17cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
584*17cf5011SRussell King 
585*17cf5011SRussell King 	return !!(readl_relaxed(reg + SA1111_GPIO_PXDDR) & mask);
586*17cf5011SRussell King }
587*17cf5011SRussell King 
588*17cf5011SRussell King static int sa1111_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
589*17cf5011SRussell King {
590*17cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
591*17cf5011SRussell King 	unsigned long flags;
592*17cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
593*17cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
594*17cf5011SRussell King 
595*17cf5011SRussell King 	spin_lock_irqsave(&sachip->lock, flags);
596*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXDDR, mask, mask);
597*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXSDR, mask, mask);
598*17cf5011SRussell King 	spin_unlock_irqrestore(&sachip->lock, flags);
599*17cf5011SRussell King 
600*17cf5011SRussell King 	return 0;
601*17cf5011SRussell King }
602*17cf5011SRussell King 
603*17cf5011SRussell King static int sa1111_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
604*17cf5011SRussell King 	int value)
605*17cf5011SRussell King {
606*17cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
607*17cf5011SRussell King 	unsigned long flags;
608*17cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
609*17cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
610*17cf5011SRussell King 
611*17cf5011SRussell King 	spin_lock_irqsave(&sachip->lock, flags);
612*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXDWR, mask, value ? mask : 0);
613*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXSSR, mask, value ? mask : 0);
614*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXDDR, mask, 0);
615*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXSDR, mask, 0);
616*17cf5011SRussell King 	spin_unlock_irqrestore(&sachip->lock, flags);
617*17cf5011SRussell King 
618*17cf5011SRussell King 	return 0;
619*17cf5011SRussell King }
620*17cf5011SRussell King 
621*17cf5011SRussell King static int sa1111_gpio_get(struct gpio_chip *gc, unsigned offset)
622*17cf5011SRussell King {
623*17cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
624*17cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
625*17cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
626*17cf5011SRussell King 
627*17cf5011SRussell King 	return !!(readl_relaxed(reg + SA1111_GPIO_PXDRR) & mask);
628*17cf5011SRussell King }
629*17cf5011SRussell King 
630*17cf5011SRussell King static void sa1111_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
631*17cf5011SRussell King {
632*17cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
633*17cf5011SRussell King 	unsigned long flags;
634*17cf5011SRussell King 	void __iomem *reg = sa1111_gpio_map_reg(sachip, offset);
635*17cf5011SRussell King 	u32 mask = sa1111_gpio_map_bit(offset);
636*17cf5011SRussell King 
637*17cf5011SRussell King 	spin_lock_irqsave(&sachip->lock, flags);
638*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXDWR, mask, value ? mask : 0);
639*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PXSSR, mask, value ? mask : 0);
640*17cf5011SRussell King 	spin_unlock_irqrestore(&sachip->lock, flags);
641*17cf5011SRussell King }
642*17cf5011SRussell King 
643*17cf5011SRussell King static void sa1111_gpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
644*17cf5011SRussell King 	unsigned long *bits)
645*17cf5011SRussell King {
646*17cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
647*17cf5011SRussell King 	unsigned long flags;
648*17cf5011SRussell King 	void __iomem *reg = sachip->base + SA1111_GPIO;
649*17cf5011SRussell King 	u32 msk, val;
650*17cf5011SRussell King 
651*17cf5011SRussell King 	msk = *mask;
652*17cf5011SRussell King 	val = *bits;
653*17cf5011SRussell King 
654*17cf5011SRussell King 	spin_lock_irqsave(&sachip->lock, flags);
655*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PADWR, msk & 15, val);
656*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PASSR, msk & 15, val);
657*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PBDWR, (msk >> 4) & 255, val >> 4);
658*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PBSSR, (msk >> 4) & 255, val >> 4);
659*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PCDWR, (msk >> 12) & 255, val >> 12);
660*17cf5011SRussell King 	sa1111_gpio_modify(reg + SA1111_GPIO_PCSSR, (msk >> 12) & 255, val >> 12);
661*17cf5011SRussell King 	spin_unlock_irqrestore(&sachip->lock, flags);
662*17cf5011SRussell King }
663*17cf5011SRussell King 
664*17cf5011SRussell King static int sa1111_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
665*17cf5011SRussell King {
666*17cf5011SRussell King 	struct sa1111 *sachip = gc_to_sa1111(gc);
667*17cf5011SRussell King 
668*17cf5011SRussell King 	return sachip->irq_base + offset;
669*17cf5011SRussell King }
670*17cf5011SRussell King 
671*17cf5011SRussell King static int sa1111_setup_gpios(struct sa1111 *sachip)
672*17cf5011SRussell King {
673*17cf5011SRussell King 	sachip->gc.label = "sa1111";
674*17cf5011SRussell King 	sachip->gc.parent = sachip->dev;
675*17cf5011SRussell King 	sachip->gc.owner = THIS_MODULE;
676*17cf5011SRussell King 	sachip->gc.get_direction = sa1111_gpio_get_direction;
677*17cf5011SRussell King 	sachip->gc.direction_input = sa1111_gpio_direction_input;
678*17cf5011SRussell King 	sachip->gc.direction_output = sa1111_gpio_direction_output;
679*17cf5011SRussell King 	sachip->gc.get = sa1111_gpio_get;
680*17cf5011SRussell King 	sachip->gc.set = sa1111_gpio_set;
681*17cf5011SRussell King 	sachip->gc.set_multiple = sa1111_gpio_set_multiple;
682*17cf5011SRussell King 	sachip->gc.to_irq = sa1111_gpio_to_irq;
683*17cf5011SRussell King 	sachip->gc.base = -1;
684*17cf5011SRussell King 	sachip->gc.ngpio = 18;
685*17cf5011SRussell King 
686*17cf5011SRussell King 	return devm_gpiochip_add_data(sachip->dev, &sachip->gc, sachip);
687*17cf5011SRussell King }
688*17cf5011SRussell King 
6891da177e4SLinus Torvalds /*
6901da177e4SLinus Torvalds  * Bring the SA1111 out of reset.  This requires a set procedure:
6911da177e4SLinus Torvalds  *  1. nRESET asserted (by hardware)
6921da177e4SLinus Torvalds  *  2. CLK turned on from SA1110
6931da177e4SLinus Torvalds  *  3. nRESET deasserted
6941da177e4SLinus Torvalds  *  4. VCO turned on, PLL_BYPASS turned off
6951da177e4SLinus Torvalds  *  5. Wait lock time, then assert RCLKEn
6961da177e4SLinus Torvalds  *  7. PCR set to allow clocking of individual functions
6971da177e4SLinus Torvalds  *
6981da177e4SLinus Torvalds  * Until we've done this, the only registers we can access are:
6991da177e4SLinus Torvalds  *   SBI_SKCR
7001da177e4SLinus Torvalds  *   SBI_SMCR
7011da177e4SLinus Torvalds  *   SBI_SKID
7021da177e4SLinus Torvalds  */
7031da177e4SLinus Torvalds static void sa1111_wake(struct sa1111 *sachip)
7041da177e4SLinus Torvalds {
7051da177e4SLinus Torvalds 	unsigned long flags, r;
7061da177e4SLinus Torvalds 
7071da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
7081da177e4SLinus Torvalds 
70997d654f8SRussell King 	clk_enable(sachip->clk);
7101da177e4SLinus Torvalds 
7111da177e4SLinus Torvalds 	/*
7121da177e4SLinus Torvalds 	 * Turn VCO on, and disable PLL Bypass.
7131da177e4SLinus Torvalds 	 */
7141da177e4SLinus Torvalds 	r = sa1111_readl(sachip->base + SA1111_SKCR);
7151da177e4SLinus Torvalds 	r &= ~SKCR_VCO_OFF;
7161da177e4SLinus Torvalds 	sa1111_writel(r, sachip->base + SA1111_SKCR);
7171da177e4SLinus Torvalds 	r |= SKCR_PLL_BYPASS | SKCR_OE_EN;
7181da177e4SLinus Torvalds 	sa1111_writel(r, sachip->base + SA1111_SKCR);
7191da177e4SLinus Torvalds 
7201da177e4SLinus Torvalds 	/*
7211da177e4SLinus Torvalds 	 * Wait lock time.  SA1111 manual _doesn't_
7221da177e4SLinus Torvalds 	 * specify a figure for this!  We choose 100us.
7231da177e4SLinus Torvalds 	 */
7241da177e4SLinus Torvalds 	udelay(100);
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds 	/*
7271da177e4SLinus Torvalds 	 * Enable RCLK.  We also ensure that RDYEN is set.
7281da177e4SLinus Torvalds 	 */
7291da177e4SLinus Torvalds 	r |= SKCR_RCLKEN | SKCR_RDYEN;
7301da177e4SLinus Torvalds 	sa1111_writel(r, sachip->base + SA1111_SKCR);
7311da177e4SLinus Torvalds 
7321da177e4SLinus Torvalds 	/*
7331da177e4SLinus Torvalds 	 * Wait 14 RCLK cycles for the chip to finish coming out
7341da177e4SLinus Torvalds 	 * of reset. (RCLK=24MHz).  This is 590ns.
7351da177e4SLinus Torvalds 	 */
7361da177e4SLinus Torvalds 	udelay(1);
7371da177e4SLinus Torvalds 
7381da177e4SLinus Torvalds 	/*
7391da177e4SLinus Torvalds 	 * Ensure all clocks are initially off.
7401da177e4SLinus Torvalds 	 */
7411da177e4SLinus Torvalds 	sa1111_writel(0, sachip->base + SA1111_SKPCR);
7421da177e4SLinus Torvalds 
7431da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
7441da177e4SLinus Torvalds }
7451da177e4SLinus Torvalds 
7461da177e4SLinus Torvalds #ifdef CONFIG_ARCH_SA1100
7471da177e4SLinus Torvalds 
7481da177e4SLinus Torvalds static u32 sa1111_dma_mask[] = {
7491da177e4SLinus Torvalds 	~0,
7501da177e4SLinus Torvalds 	~(1 << 20),
7511da177e4SLinus Torvalds 	~(1 << 23),
7521da177e4SLinus Torvalds 	~(1 << 24),
7531da177e4SLinus Torvalds 	~(1 << 25),
7541da177e4SLinus Torvalds 	~(1 << 20),
7551da177e4SLinus Torvalds 	~(1 << 20),
7561da177e4SLinus Torvalds 	0,
7571da177e4SLinus Torvalds };
7581da177e4SLinus Torvalds 
7591da177e4SLinus Torvalds /*
7601da177e4SLinus Torvalds  * Configure the SA1111 shared memory controller.
7611da177e4SLinus Torvalds  */
7621da177e4SLinus Torvalds void
7631da177e4SLinus Torvalds sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
7641da177e4SLinus Torvalds 		     unsigned int cas_latency)
7651da177e4SLinus Torvalds {
7661da177e4SLinus Torvalds 	unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC);
7671da177e4SLinus Torvalds 
7681da177e4SLinus Torvalds 	if (cas_latency == 3)
7691da177e4SLinus Torvalds 		smcr |= SMCR_CLAT;
7701da177e4SLinus Torvalds 
7711da177e4SLinus Torvalds 	sa1111_writel(smcr, sachip->base + SA1111_SMCR);
7721da177e4SLinus Torvalds 
7731da177e4SLinus Torvalds 	/*
7741da177e4SLinus Torvalds 	 * Now clear the bits in the DMA mask to work around the SA1111
7751da177e4SLinus Torvalds 	 * DMA erratum (Intel StrongARM SA-1111 Microprocessor Companion
7761da177e4SLinus Torvalds 	 * Chip Specification Update, June 2000, Erratum #7).
7771da177e4SLinus Torvalds 	 */
7781da177e4SLinus Torvalds 	if (sachip->dev->dma_mask)
7791da177e4SLinus Torvalds 		*sachip->dev->dma_mask &= sa1111_dma_mask[drac >> 2];
7801da177e4SLinus Torvalds 
7811da177e4SLinus Torvalds 	sachip->dev->coherent_dma_mask &= sa1111_dma_mask[drac >> 2];
7821da177e4SLinus Torvalds }
7830703ed2aSRussell King #endif
7841da177e4SLinus Torvalds 
7851da177e4SLinus Torvalds static void sa1111_dev_release(struct device *_dev)
7861da177e4SLinus Torvalds {
7871da177e4SLinus Torvalds 	struct sa1111_dev *dev = SA1111_DEV(_dev);
7881da177e4SLinus Torvalds 
7891da177e4SLinus Torvalds 	kfree(dev);
7901da177e4SLinus Torvalds }
7911da177e4SLinus Torvalds 
7921da177e4SLinus Torvalds static int
7931da177e4SLinus Torvalds sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
7941da177e4SLinus Torvalds 		      struct sa1111_dev_info *info)
7951da177e4SLinus Torvalds {
7961da177e4SLinus Torvalds 	struct sa1111_dev *dev;
797f03ecaa0SRussell King 	unsigned i;
7981da177e4SLinus Torvalds 	int ret;
7991da177e4SLinus Torvalds 
800d2a02b93SRussell King 	dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL);
8011da177e4SLinus Torvalds 	if (!dev) {
8021da177e4SLinus Torvalds 		ret = -ENOMEM;
803924e1d49SRussell King 		goto err_alloc;
8041da177e4SLinus Torvalds 	}
8051da177e4SLinus Torvalds 
806924e1d49SRussell King 	device_initialize(&dev->dev);
8073f978704SKay Sievers 	dev_set_name(&dev->dev, "%4.4lx", info->offset);
8081da177e4SLinus Torvalds 	dev->devid	 = info->devid;
8091da177e4SLinus Torvalds 	dev->dev.parent  = sachip->dev;
8101da177e4SLinus Torvalds 	dev->dev.bus     = &sa1111_bus_type;
8111da177e4SLinus Torvalds 	dev->dev.release = sa1111_dev_release;
8121da177e4SLinus Torvalds 	dev->res.start   = sachip->phys + info->offset;
8131da177e4SLinus Torvalds 	dev->res.end     = dev->res.start + 511;
8143f978704SKay Sievers 	dev->res.name    = dev_name(&dev->dev);
8151da177e4SLinus Torvalds 	dev->res.flags   = IORESOURCE_MEM;
8161da177e4SLinus Torvalds 	dev->mapbase     = sachip->base + info->offset;
8171da177e4SLinus Torvalds 	dev->skpcr_mask  = info->skpcr_mask;
818f03ecaa0SRussell King 
819f03ecaa0SRussell King 	for (i = 0; i < ARRAY_SIZE(info->irq); i++)
820f03ecaa0SRussell King 		dev->irq[i] = sachip->irq_base + info->irq[i];
8211da177e4SLinus Torvalds 
82209a2ba2fSRussell King 	/*
82321d1c770SRussell King 	 * If the parent device has a DMA mask associated with it, and
82421d1c770SRussell King 	 * this child supports DMA, propagate it down to the children.
82509a2ba2fSRussell King 	 */
82621d1c770SRussell King 	if (info->dma && sachip->dev->dma_mask) {
82709a2ba2fSRussell King 		dev->dma_mask = *sachip->dev->dma_mask;
82809a2ba2fSRussell King 		dev->dev.dma_mask = &dev->dma_mask;
82909a2ba2fSRussell King 		dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask;
83009a2ba2fSRussell King 	}
83109a2ba2fSRussell King 
8321da177e4SLinus Torvalds 	ret = request_resource(parent, &dev->res);
8331da177e4SLinus Torvalds 	if (ret) {
83422eeaff3SRussell King 		dev_err(sachip->dev, "failed to allocate resource for %s\n",
8351da177e4SLinus Torvalds 			dev->res.name);
836924e1d49SRussell King 		goto err_resource;
8371da177e4SLinus Torvalds 	}
8381da177e4SLinus Torvalds 
839924e1d49SRussell King 	ret = device_add(&dev->dev);
840924e1d49SRussell King 	if (ret)
841924e1d49SRussell King 		goto err_add;
842924e1d49SRussell King 	return 0;
843924e1d49SRussell King 
844924e1d49SRussell King  err_add:
8451da177e4SLinus Torvalds 	release_resource(&dev->res);
846924e1d49SRussell King  err_resource:
847924e1d49SRussell King 	put_device(&dev->dev);
848924e1d49SRussell King  err_alloc:
8491da177e4SLinus Torvalds 	return ret;
8501da177e4SLinus Torvalds }
8511da177e4SLinus Torvalds 
8521da177e4SLinus Torvalds /**
8531da177e4SLinus Torvalds  *	sa1111_probe - probe for a single SA1111 chip.
8541da177e4SLinus Torvalds  *	@phys_addr: physical address of device.
8551da177e4SLinus Torvalds  *
8561da177e4SLinus Torvalds  *	Probe for a SA1111 chip.  This must be called
8571da177e4SLinus Torvalds  *	before any other SA1111-specific code.
8581da177e4SLinus Torvalds  *
8591da177e4SLinus Torvalds  *	Returns:
8601da177e4SLinus Torvalds  *	%-ENODEV	device not found.
8611da177e4SLinus Torvalds  *	%-EBUSY		physical address already marked in-use.
862f03ecaa0SRussell King  *	%-EINVAL	no platform data passed
8631da177e4SLinus Torvalds  *	%0		successful.
8641da177e4SLinus Torvalds  */
865351a102dSGreg Kroah-Hartman static int __sa1111_probe(struct device *me, struct resource *mem, int irq)
8661da177e4SLinus Torvalds {
867f03ecaa0SRussell King 	struct sa1111_platform_data *pd = me->platform_data;
8681da177e4SLinus Torvalds 	struct sa1111 *sachip;
8691da177e4SLinus Torvalds 	unsigned long id;
870416112f8SDavid Brownell 	unsigned int has_devs;
8711da177e4SLinus Torvalds 	int i, ret = -ENODEV;
8721da177e4SLinus Torvalds 
873f03ecaa0SRussell King 	if (!pd)
874f03ecaa0SRussell King 		return -EINVAL;
875f03ecaa0SRussell King 
8767d53c1f0SRussell King 	sachip = devm_kzalloc(me, sizeof(struct sa1111), GFP_KERNEL);
8771da177e4SLinus Torvalds 	if (!sachip)
8781da177e4SLinus Torvalds 		return -ENOMEM;
8791da177e4SLinus Torvalds 
880deee856aSRussell King 	sachip->clk = devm_clk_get(me, "SA1111_CLK");
881deee856aSRussell King 	if (IS_ERR(sachip->clk))
882deee856aSRussell King 		return PTR_ERR(sachip->clk);
88397d654f8SRussell King 
88472ae00c9SRussell King 	ret = clk_prepare(sachip->clk);
88572ae00c9SRussell King 	if (ret)
886deee856aSRussell King 		return ret;
88772ae00c9SRussell King 
8881da177e4SLinus Torvalds 	spin_lock_init(&sachip->lock);
8891da177e4SLinus Torvalds 
8901da177e4SLinus Torvalds 	sachip->dev = me;
8911da177e4SLinus Torvalds 	dev_set_drvdata(sachip->dev, sachip);
8921da177e4SLinus Torvalds 
893ae99ddbcSRussell King 	sachip->pdata = pd;
8941da177e4SLinus Torvalds 	sachip->phys = mem->start;
8951da177e4SLinus Torvalds 	sachip->irq = irq;
8961da177e4SLinus Torvalds 
8971da177e4SLinus Torvalds 	/*
8981da177e4SLinus Torvalds 	 * Map the whole region.  This also maps the
8991da177e4SLinus Torvalds 	 * registers for our children.
9001da177e4SLinus Torvalds 	 */
9011da177e4SLinus Torvalds 	sachip->base = ioremap(mem->start, PAGE_SIZE * 2);
9021da177e4SLinus Torvalds 	if (!sachip->base) {
9031da177e4SLinus Torvalds 		ret = -ENOMEM;
90472ae00c9SRussell King 		goto err_clk_unprep;
9051da177e4SLinus Torvalds 	}
9061da177e4SLinus Torvalds 
9071da177e4SLinus Torvalds 	/*
9081da177e4SLinus Torvalds 	 * Probe for the chip.  Only touch the SBI registers.
9091da177e4SLinus Torvalds 	 */
9101da177e4SLinus Torvalds 	id = sa1111_readl(sachip->base + SA1111_SKID);
9111da177e4SLinus Torvalds 	if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
9121da177e4SLinus Torvalds 		printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id);
9131da177e4SLinus Torvalds 		ret = -ENODEV;
91497d654f8SRussell King 		goto err_unmap;
9151da177e4SLinus Torvalds 	}
9161da177e4SLinus Torvalds 
9174ed89f22SRussell King 	pr_info("SA1111 Microprocessor Companion Chip: silicon revision %lx, metal revision %lx\n",
9184ed89f22SRussell King 		(id & SKID_SIREV_MASK) >> 4, id & SKID_MTREV_MASK);
9191da177e4SLinus Torvalds 
9201da177e4SLinus Torvalds 	/*
9211da177e4SLinus Torvalds 	 * We found it.  Wake the chip up, and initialise.
9221da177e4SLinus Torvalds 	 */
9231da177e4SLinus Torvalds 	sa1111_wake(sachip);
9241da177e4SLinus Torvalds 
92536d31213SRussell King 	/*
92636d31213SRussell King 	 * The interrupt controller must be initialised before any
92736d31213SRussell King 	 * other device to ensure that the interrupts are available.
92836d31213SRussell King 	 */
92936d31213SRussell King 	if (sachip->irq != NO_IRQ) {
93036d31213SRussell King 		ret = sa1111_setup_irq(sachip, pd->irq_base);
93136d31213SRussell King 		if (ret)
93287d5dd62SRussell King 			goto err_clk;
93336d31213SRussell King 	}
93436d31213SRussell King 
935*17cf5011SRussell King 	/* Setup the GPIOs - should really be done after the IRQ setup */
936*17cf5011SRussell King 	ret = sa1111_setup_gpios(sachip);
937*17cf5011SRussell King 	if (ret)
938*17cf5011SRussell King 		goto err_irq;
939*17cf5011SRussell King 
9401da177e4SLinus Torvalds #ifdef CONFIG_ARCH_SA1100
941416112f8SDavid Brownell 	{
942416112f8SDavid Brownell 	unsigned int val;
943416112f8SDavid Brownell 
9441da177e4SLinus Torvalds 	/*
9451da177e4SLinus Torvalds 	 * The SDRAM configuration of the SA1110 and the SA1111 must
9461da177e4SLinus Torvalds 	 * match.  This is very important to ensure that SA1111 accesses
9471da177e4SLinus Torvalds 	 * don't corrupt the SDRAM.  Note that this ungates the SA1111's
9481da177e4SLinus Torvalds 	 * MBGNT signal, so we must have called sa1110_mb_disable()
9491da177e4SLinus Torvalds 	 * beforehand.
9501da177e4SLinus Torvalds 	 */
9511da177e4SLinus Torvalds 	sa1111_configure_smc(sachip, 1,
9521da177e4SLinus Torvalds 			     FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
9531da177e4SLinus Torvalds 			     FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
9541da177e4SLinus Torvalds 
9551da177e4SLinus Torvalds 	/*
9561da177e4SLinus Torvalds 	 * We only need to turn on DCLK whenever we want to use the
9571da177e4SLinus Torvalds 	 * DMA.  It can otherwise be held firmly in the off position.
9581da177e4SLinus Torvalds 	 * (currently, we always enable it.)
9591da177e4SLinus Torvalds 	 */
9601da177e4SLinus Torvalds 	val = sa1111_readl(sachip->base + SA1111_SKPCR);
9611da177e4SLinus Torvalds 	sa1111_writel(val | SKPCR_DCLKEN, sachip->base + SA1111_SKPCR);
9621da177e4SLinus Torvalds 
9631da177e4SLinus Torvalds 	/*
9641da177e4SLinus Torvalds 	 * Enable the SA1110 memory bus request and grant signals.
9651da177e4SLinus Torvalds 	 */
9661da177e4SLinus Torvalds 	sa1110_mb_enable();
967416112f8SDavid Brownell 	}
9681da177e4SLinus Torvalds #endif
9691da177e4SLinus Torvalds 
9701da177e4SLinus Torvalds 	g_sa1111 = sachip;
9711da177e4SLinus Torvalds 
9721da177e4SLinus Torvalds 	has_devs = ~0;
97307be45f5SRussell King 	if (pd)
97407be45f5SRussell King 		has_devs &= ~pd->disable_devs;
9751da177e4SLinus Torvalds 
9761da177e4SLinus Torvalds 	for (i = 0; i < ARRAY_SIZE(sa1111_devices); i++)
977e5c0fc41SRussell King 		if (sa1111_devices[i].devid & has_devs)
9781da177e4SLinus Torvalds 			sa1111_init_one_child(sachip, mem, &sa1111_devices[i]);
9791da177e4SLinus Torvalds 
9801da177e4SLinus Torvalds 	return 0;
9811da177e4SLinus Torvalds 
982*17cf5011SRussell King  err_irq:
983*17cf5011SRussell King 	sa1111_remove_irq(sachip);
98487d5dd62SRussell King  err_clk:
98587d5dd62SRussell King 	clk_disable(sachip->clk);
98697d654f8SRussell King  err_unmap:
9871da177e4SLinus Torvalds 	iounmap(sachip->base);
98872ae00c9SRussell King  err_clk_unprep:
98972ae00c9SRussell King 	clk_unprepare(sachip->clk);
9901da177e4SLinus Torvalds 	return ret;
9911da177e4SLinus Torvalds }
9921da177e4SLinus Torvalds 
993522c37b9SRussell King static int sa1111_remove_one(struct device *dev, void *data)
994522c37b9SRussell King {
995924e1d49SRussell King 	struct sa1111_dev *sadev = SA1111_DEV(dev);
996eac8dbf7SRussell King 	if (dev->bus != &sa1111_bus_type)
997eac8dbf7SRussell King 		return 0;
998924e1d49SRussell King 	device_del(&sadev->dev);
999924e1d49SRussell King 	release_resource(&sadev->res);
1000924e1d49SRussell King 	put_device(&sadev->dev);
1001522c37b9SRussell King 	return 0;
1002522c37b9SRussell King }
1003522c37b9SRussell King 
10041da177e4SLinus Torvalds static void __sa1111_remove(struct sa1111 *sachip)
10051da177e4SLinus Torvalds {
1006522c37b9SRussell King 	device_for_each_child(sachip->dev, NULL, sa1111_remove_one);
10071da177e4SLinus Torvalds 
1008ccb7d854SRussell King 	sa1111_remove_irq(sachip);
10091da177e4SLinus Torvalds 
101097d654f8SRussell King 	clk_disable(sachip->clk);
101172ae00c9SRussell King 	clk_unprepare(sachip->clk);
101297d654f8SRussell King 
10131da177e4SLinus Torvalds 	iounmap(sachip->base);
10141da177e4SLinus Torvalds }
10151da177e4SLinus Torvalds 
10161da177e4SLinus Torvalds struct sa1111_save_data {
10171da177e4SLinus Torvalds 	unsigned int	skcr;
10181da177e4SLinus Torvalds 	unsigned int	skpcr;
10191da177e4SLinus Torvalds 	unsigned int	skcdr;
10201da177e4SLinus Torvalds 	unsigned char	skaud;
10211da177e4SLinus Torvalds 	unsigned char	skpwm0;
10221da177e4SLinus Torvalds 	unsigned char	skpwm1;
10231da177e4SLinus Torvalds 
10241da177e4SLinus Torvalds 	/*
10251da177e4SLinus Torvalds 	 * Interrupt controller
10261da177e4SLinus Torvalds 	 */
10271da177e4SLinus Torvalds 	unsigned int	intpol0;
10281da177e4SLinus Torvalds 	unsigned int	intpol1;
10291da177e4SLinus Torvalds 	unsigned int	inten0;
10301da177e4SLinus Torvalds 	unsigned int	inten1;
10311da177e4SLinus Torvalds 	unsigned int	wakepol0;
10321da177e4SLinus Torvalds 	unsigned int	wakepol1;
10331da177e4SLinus Torvalds 	unsigned int	wakeen0;
10341da177e4SLinus Torvalds 	unsigned int	wakeen1;
10351da177e4SLinus Torvalds };
10361da177e4SLinus Torvalds 
10371da177e4SLinus Torvalds #ifdef CONFIG_PM
10381da177e4SLinus Torvalds 
103906dfe5ccSRussell King static int sa1111_suspend_noirq(struct device *dev)
10401da177e4SLinus Torvalds {
104106dfe5ccSRussell King 	struct sa1111 *sachip = dev_get_drvdata(dev);
10421da177e4SLinus Torvalds 	struct sa1111_save_data *save;
10431da177e4SLinus Torvalds 	unsigned long flags;
10441da177e4SLinus Torvalds 	unsigned int val;
10451da177e4SLinus Torvalds 	void __iomem *base;
10461da177e4SLinus Torvalds 
10471da177e4SLinus Torvalds 	save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
10481da177e4SLinus Torvalds 	if (!save)
10491da177e4SLinus Torvalds 		return -ENOMEM;
105093160c63SRafael J. Wysocki 	sachip->saved_state = save;
10511da177e4SLinus Torvalds 
10521da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
10531da177e4SLinus Torvalds 
10541da177e4SLinus Torvalds 	/*
10551da177e4SLinus Torvalds 	 * Save state.
10561da177e4SLinus Torvalds 	 */
10571da177e4SLinus Torvalds 	base = sachip->base;
10581da177e4SLinus Torvalds 	save->skcr     = sa1111_readl(base + SA1111_SKCR);
10591da177e4SLinus Torvalds 	save->skpcr    = sa1111_readl(base + SA1111_SKPCR);
10601da177e4SLinus Torvalds 	save->skcdr    = sa1111_readl(base + SA1111_SKCDR);
10611da177e4SLinus Torvalds 	save->skaud    = sa1111_readl(base + SA1111_SKAUD);
10621da177e4SLinus Torvalds 	save->skpwm0   = sa1111_readl(base + SA1111_SKPWM0);
10631da177e4SLinus Torvalds 	save->skpwm1   = sa1111_readl(base + SA1111_SKPWM1);
10641da177e4SLinus Torvalds 
1065a22db0f3SRussell King 	sa1111_writel(0, sachip->base + SA1111_SKPWM0);
1066a22db0f3SRussell King 	sa1111_writel(0, sachip->base + SA1111_SKPWM1);
1067a22db0f3SRussell King 
10681da177e4SLinus Torvalds 	base = sachip->base + SA1111_INTC;
10691da177e4SLinus Torvalds 	save->intpol0  = sa1111_readl(base + SA1111_INTPOL0);
10701da177e4SLinus Torvalds 	save->intpol1  = sa1111_readl(base + SA1111_INTPOL1);
10711da177e4SLinus Torvalds 	save->inten0   = sa1111_readl(base + SA1111_INTEN0);
10721da177e4SLinus Torvalds 	save->inten1   = sa1111_readl(base + SA1111_INTEN1);
10731da177e4SLinus Torvalds 	save->wakepol0 = sa1111_readl(base + SA1111_WAKEPOL0);
10741da177e4SLinus Torvalds 	save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1);
10751da177e4SLinus Torvalds 	save->wakeen0  = sa1111_readl(base + SA1111_WAKEEN0);
10761da177e4SLinus Torvalds 	save->wakeen1  = sa1111_readl(base + SA1111_WAKEEN1);
10771da177e4SLinus Torvalds 
10781da177e4SLinus Torvalds 	/*
10791da177e4SLinus Torvalds 	 * Disable.
10801da177e4SLinus Torvalds 	 */
10811da177e4SLinus Torvalds 	val = sa1111_readl(sachip->base + SA1111_SKCR);
10821da177e4SLinus Torvalds 	sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
10831da177e4SLinus Torvalds 
108497d654f8SRussell King 	clk_disable(sachip->clk);
108597d654f8SRussell King 
10861da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
10871da177e4SLinus Torvalds 
108829c140b6SRussell King #ifdef CONFIG_ARCH_SA1100
108929c140b6SRussell King 	sa1110_mb_disable();
109029c140b6SRussell King #endif
109129c140b6SRussell King 
10921da177e4SLinus Torvalds 	return 0;
10931da177e4SLinus Torvalds }
10941da177e4SLinus Torvalds 
10951da177e4SLinus Torvalds /*
10961da177e4SLinus Torvalds  *	sa1111_resume - Restore the SA1111 device state.
10971da177e4SLinus Torvalds  *	@dev: device to restore
10981da177e4SLinus Torvalds  *
10991da177e4SLinus Torvalds  *	Restore the general state of the SA1111; clock control and
11001da177e4SLinus Torvalds  *	interrupt controller.  Other parts of the SA1111 must be
11011da177e4SLinus Torvalds  *	restored by their respective drivers, and must be called
11021da177e4SLinus Torvalds  *	via LDM after this function.
11031da177e4SLinus Torvalds  */
110406dfe5ccSRussell King static int sa1111_resume_noirq(struct device *dev)
11051da177e4SLinus Torvalds {
110606dfe5ccSRussell King 	struct sa1111 *sachip = dev_get_drvdata(dev);
11071da177e4SLinus Torvalds 	struct sa1111_save_data *save;
11081da177e4SLinus Torvalds 	unsigned long flags, id;
11091da177e4SLinus Torvalds 	void __iomem *base;
11101da177e4SLinus Torvalds 
111193160c63SRafael J. Wysocki 	save = sachip->saved_state;
11121da177e4SLinus Torvalds 	if (!save)
11131da177e4SLinus Torvalds 		return 0;
11141da177e4SLinus Torvalds 
11151da177e4SLinus Torvalds 	/*
11161da177e4SLinus Torvalds 	 * Ensure that the SA1111 is still here.
11171da177e4SLinus Torvalds 	 * FIXME: shouldn't do this here.
11181da177e4SLinus Torvalds 	 */
11191da177e4SLinus Torvalds 	id = sa1111_readl(sachip->base + SA1111_SKID);
11201da177e4SLinus Torvalds 	if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
11211da177e4SLinus Torvalds 		__sa1111_remove(sachip);
112206dfe5ccSRussell King 		dev_set_drvdata(dev, NULL);
11231da177e4SLinus Torvalds 		kfree(save);
11241da177e4SLinus Torvalds 		return 0;
11251da177e4SLinus Torvalds 	}
11261da177e4SLinus Torvalds 
11271da177e4SLinus Torvalds 	/*
11281da177e4SLinus Torvalds 	 * First of all, wake up the chip.
11291da177e4SLinus Torvalds 	 */
11301da177e4SLinus Torvalds 	sa1111_wake(sachip);
11313defb247SMarek Vašut 
113229c140b6SRussell King #ifdef CONFIG_ARCH_SA1100
113329c140b6SRussell King 	/* Enable the memory bus request/grant signals */
113429c140b6SRussell King 	sa1110_mb_enable();
113529c140b6SRussell King #endif
113629c140b6SRussell King 
11373defb247SMarek Vašut 	/*
11383defb247SMarek Vašut 	 * Only lock for write ops. Also, sa1111_wake must be called with
11393defb247SMarek Vašut 	 * released spinlock!
11403defb247SMarek Vašut 	 */
11413defb247SMarek Vašut 	spin_lock_irqsave(&sachip->lock, flags);
11423defb247SMarek Vašut 
11431da177e4SLinus Torvalds 	sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0);
11441da177e4SLinus Torvalds 	sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1);
11451da177e4SLinus Torvalds 
11461da177e4SLinus Torvalds 	base = sachip->base;
11471da177e4SLinus Torvalds 	sa1111_writel(save->skcr,     base + SA1111_SKCR);
11481da177e4SLinus Torvalds 	sa1111_writel(save->skpcr,    base + SA1111_SKPCR);
11491da177e4SLinus Torvalds 	sa1111_writel(save->skcdr,    base + SA1111_SKCDR);
11501da177e4SLinus Torvalds 	sa1111_writel(save->skaud,    base + SA1111_SKAUD);
11511da177e4SLinus Torvalds 	sa1111_writel(save->skpwm0,   base + SA1111_SKPWM0);
11521da177e4SLinus Torvalds 	sa1111_writel(save->skpwm1,   base + SA1111_SKPWM1);
11531da177e4SLinus Torvalds 
11541da177e4SLinus Torvalds 	base = sachip->base + SA1111_INTC;
11551da177e4SLinus Torvalds 	sa1111_writel(save->intpol0,  base + SA1111_INTPOL0);
11561da177e4SLinus Torvalds 	sa1111_writel(save->intpol1,  base + SA1111_INTPOL1);
11571da177e4SLinus Torvalds 	sa1111_writel(save->inten0,   base + SA1111_INTEN0);
11581da177e4SLinus Torvalds 	sa1111_writel(save->inten1,   base + SA1111_INTEN1);
11591da177e4SLinus Torvalds 	sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
11601da177e4SLinus Torvalds 	sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
11611da177e4SLinus Torvalds 	sa1111_writel(save->wakeen0,  base + SA1111_WAKEEN0);
11621da177e4SLinus Torvalds 	sa1111_writel(save->wakeen1,  base + SA1111_WAKEEN1);
11631da177e4SLinus Torvalds 
11641da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
11651da177e4SLinus Torvalds 
116693160c63SRafael J. Wysocki 	sachip->saved_state = NULL;
11671da177e4SLinus Torvalds 	kfree(save);
11681da177e4SLinus Torvalds 
11691da177e4SLinus Torvalds 	return 0;
11701da177e4SLinus Torvalds }
11711da177e4SLinus Torvalds 
11721da177e4SLinus Torvalds #else
117306dfe5ccSRussell King #define sa1111_suspend_noirq NULL
117406dfe5ccSRussell King #define sa1111_resume_noirq  NULL
11751da177e4SLinus Torvalds #endif
11761da177e4SLinus Torvalds 
1177351a102dSGreg Kroah-Hartman static int sa1111_probe(struct platform_device *pdev)
11781da177e4SLinus Torvalds {
11791da177e4SLinus Torvalds 	struct resource *mem;
11801da177e4SLinus Torvalds 	int irq;
11811da177e4SLinus Torvalds 
11821da177e4SLinus Torvalds 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
11831da177e4SLinus Torvalds 	if (!mem)
11841da177e4SLinus Torvalds 		return -EINVAL;
11851da177e4SLinus Torvalds 	irq = platform_get_irq(pdev, 0);
118648944738SDavid Vrabel 	if (irq < 0)
1187cb034407SRussell King 		return irq;
11881da177e4SLinus Torvalds 
11893ae5eaecSRussell King 	return __sa1111_probe(&pdev->dev, mem, irq);
11901da177e4SLinus Torvalds }
11911da177e4SLinus Torvalds 
11923ae5eaecSRussell King static int sa1111_remove(struct platform_device *pdev)
11931da177e4SLinus Torvalds {
11943ae5eaecSRussell King 	struct sa1111 *sachip = platform_get_drvdata(pdev);
11951da177e4SLinus Torvalds 
11961da177e4SLinus Torvalds 	if (sachip) {
11971da177e4SLinus Torvalds #ifdef CONFIG_PM
119893160c63SRafael J. Wysocki 		kfree(sachip->saved_state);
119993160c63SRafael J. Wysocki 		sachip->saved_state = NULL;
12001da177e4SLinus Torvalds #endif
1201f2d2420bSJulia Lawall 		__sa1111_remove(sachip);
1202f2d2420bSJulia Lawall 		platform_set_drvdata(pdev, NULL);
12031da177e4SLinus Torvalds 	}
12041da177e4SLinus Torvalds 
12051da177e4SLinus Torvalds 	return 0;
12061da177e4SLinus Torvalds }
12071da177e4SLinus Torvalds 
120806dfe5ccSRussell King static struct dev_pm_ops sa1111_pm_ops = {
120906dfe5ccSRussell King 	.suspend_noirq = sa1111_suspend_noirq,
121006dfe5ccSRussell King 	.resume_noirq = sa1111_resume_noirq,
121106dfe5ccSRussell King };
121206dfe5ccSRussell King 
12131da177e4SLinus Torvalds /*
12141da177e4SLinus Torvalds  *	Not sure if this should be on the system bus or not yet.
12151da177e4SLinus Torvalds  *	We really want some way to register a system device at
12161da177e4SLinus Torvalds  *	the per-machine level, and then have this driver pick
12171da177e4SLinus Torvalds  *	up the registered devices.
12181da177e4SLinus Torvalds  *
12191da177e4SLinus Torvalds  *	We also need to handle the SDRAM configuration for
12201da177e4SLinus Torvalds  *	PXA250/SA1110 machine classes.
12211da177e4SLinus Torvalds  */
12223ae5eaecSRussell King static struct platform_driver sa1111_device_driver = {
12231da177e4SLinus Torvalds 	.probe		= sa1111_probe,
12241da177e4SLinus Torvalds 	.remove		= sa1111_remove,
12253ae5eaecSRussell King 	.driver		= {
12263ae5eaecSRussell King 		.name	= "sa1111",
122706dfe5ccSRussell King 		.pm	= &sa1111_pm_ops,
12283ae5eaecSRussell King 	},
12291da177e4SLinus Torvalds };
12301da177e4SLinus Torvalds 
12311da177e4SLinus Torvalds /*
12321da177e4SLinus Torvalds  *	Get the parent device driver (us) structure
12331da177e4SLinus Torvalds  *	from a child function device
12341da177e4SLinus Torvalds  */
12351da177e4SLinus Torvalds static inline struct sa1111 *sa1111_chip_driver(struct sa1111_dev *sadev)
12361da177e4SLinus Torvalds {
12371da177e4SLinus Torvalds 	return (struct sa1111 *)dev_get_drvdata(sadev->dev.parent);
12381da177e4SLinus Torvalds }
12391da177e4SLinus Torvalds 
12401da177e4SLinus Torvalds /*
12411da177e4SLinus Torvalds  * The bits in the opdiv field are non-linear.
12421da177e4SLinus Torvalds  */
12431da177e4SLinus Torvalds static unsigned char opdiv_table[] = { 1, 4, 2, 8 };
12441da177e4SLinus Torvalds 
12451da177e4SLinus Torvalds static unsigned int __sa1111_pll_clock(struct sa1111 *sachip)
12461da177e4SLinus Torvalds {
12471da177e4SLinus Torvalds 	unsigned int skcdr, fbdiv, ipdiv, opdiv;
12481da177e4SLinus Torvalds 
12491da177e4SLinus Torvalds 	skcdr = sa1111_readl(sachip->base + SA1111_SKCDR);
12501da177e4SLinus Torvalds 
12511da177e4SLinus Torvalds 	fbdiv = (skcdr & 0x007f) + 2;
12521da177e4SLinus Torvalds 	ipdiv = ((skcdr & 0x0f80) >> 7) + 2;
12531da177e4SLinus Torvalds 	opdiv = opdiv_table[(skcdr & 0x3000) >> 12];
12541da177e4SLinus Torvalds 
12551da177e4SLinus Torvalds 	return 3686400 * fbdiv / (ipdiv * opdiv);
12561da177e4SLinus Torvalds }
12571da177e4SLinus Torvalds 
12581da177e4SLinus Torvalds /**
12591da177e4SLinus Torvalds  *	sa1111_pll_clock - return the current PLL clock frequency.
12601da177e4SLinus Torvalds  *	@sadev: SA1111 function block
12611da177e4SLinus Torvalds  *
12621da177e4SLinus Torvalds  *	BUG: we should look at SKCR.  We also blindly believe that
12631da177e4SLinus Torvalds  *	the chip is being fed with the 3.6864MHz clock.
12641da177e4SLinus Torvalds  *
12651da177e4SLinus Torvalds  *	Returns the PLL clock in Hz.
12661da177e4SLinus Torvalds  */
12671da177e4SLinus Torvalds unsigned int sa1111_pll_clock(struct sa1111_dev *sadev)
12681da177e4SLinus Torvalds {
12691da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
12701da177e4SLinus Torvalds 
12711da177e4SLinus Torvalds 	return __sa1111_pll_clock(sachip);
12721da177e4SLinus Torvalds }
12730a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_pll_clock);
12741da177e4SLinus Torvalds 
12751da177e4SLinus Torvalds /**
12761da177e4SLinus Torvalds  *	sa1111_select_audio_mode - select I2S or AC link mode
12771da177e4SLinus Torvalds  *	@sadev: SA1111 function block
12781da177e4SLinus Torvalds  *	@mode: One of %SA1111_AUDIO_ACLINK or %SA1111_AUDIO_I2S
12791da177e4SLinus Torvalds  *
12801da177e4SLinus Torvalds  *	Frob the SKCR to select AC Link mode or I2S mode for
12811da177e4SLinus Torvalds  *	the audio block.
12821da177e4SLinus Torvalds  */
12831da177e4SLinus Torvalds void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode)
12841da177e4SLinus Torvalds {
12851da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
12861da177e4SLinus Torvalds 	unsigned long flags;
12871da177e4SLinus Torvalds 	unsigned int val;
12881da177e4SLinus Torvalds 
12891da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
12901da177e4SLinus Torvalds 
12911da177e4SLinus Torvalds 	val = sa1111_readl(sachip->base + SA1111_SKCR);
12921da177e4SLinus Torvalds 	if (mode == SA1111_AUDIO_I2S) {
12931da177e4SLinus Torvalds 		val &= ~SKCR_SELAC;
12941da177e4SLinus Torvalds 	} else {
12951da177e4SLinus Torvalds 		val |= SKCR_SELAC;
12961da177e4SLinus Torvalds 	}
12971da177e4SLinus Torvalds 	sa1111_writel(val, sachip->base + SA1111_SKCR);
12981da177e4SLinus Torvalds 
12991da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
13001da177e4SLinus Torvalds }
13010a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_select_audio_mode);
13021da177e4SLinus Torvalds 
13031da177e4SLinus Torvalds /**
13041da177e4SLinus Torvalds  *	sa1111_set_audio_rate - set the audio sample rate
13051da177e4SLinus Torvalds  *	@sadev: SA1111 SAC function block
13061da177e4SLinus Torvalds  *	@rate: sample rate to select
13071da177e4SLinus Torvalds  */
13081da177e4SLinus Torvalds int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate)
13091da177e4SLinus Torvalds {
13101da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
13111da177e4SLinus Torvalds 	unsigned int div;
13121da177e4SLinus Torvalds 
13131da177e4SLinus Torvalds 	if (sadev->devid != SA1111_DEVID_SAC)
13141da177e4SLinus Torvalds 		return -EINVAL;
13151da177e4SLinus Torvalds 
13161da177e4SLinus Torvalds 	div = (__sa1111_pll_clock(sachip) / 256 + rate / 2) / rate;
13171da177e4SLinus Torvalds 	if (div == 0)
13181da177e4SLinus Torvalds 		div = 1;
13191da177e4SLinus Torvalds 	if (div > 128)
13201da177e4SLinus Torvalds 		div = 128;
13211da177e4SLinus Torvalds 
13221da177e4SLinus Torvalds 	sa1111_writel(div - 1, sachip->base + SA1111_SKAUD);
13231da177e4SLinus Torvalds 
13241da177e4SLinus Torvalds 	return 0;
13251da177e4SLinus Torvalds }
13260a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_set_audio_rate);
13271da177e4SLinus Torvalds 
13281da177e4SLinus Torvalds /**
13291da177e4SLinus Torvalds  *	sa1111_get_audio_rate - get the audio sample rate
13301da177e4SLinus Torvalds  *	@sadev: SA1111 SAC function block device
13311da177e4SLinus Torvalds  */
13321da177e4SLinus Torvalds int sa1111_get_audio_rate(struct sa1111_dev *sadev)
13331da177e4SLinus Torvalds {
13341da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
13351da177e4SLinus Torvalds 	unsigned long div;
13361da177e4SLinus Torvalds 
13371da177e4SLinus Torvalds 	if (sadev->devid != SA1111_DEVID_SAC)
13381da177e4SLinus Torvalds 		return -EINVAL;
13391da177e4SLinus Torvalds 
13401da177e4SLinus Torvalds 	div = sa1111_readl(sachip->base + SA1111_SKAUD) + 1;
13411da177e4SLinus Torvalds 
13421da177e4SLinus Torvalds 	return __sa1111_pll_clock(sachip) / (256 * div);
13431da177e4SLinus Torvalds }
13440a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_get_audio_rate);
13451da177e4SLinus Torvalds 
13461da177e4SLinus Torvalds void sa1111_set_io_dir(struct sa1111_dev *sadev,
13471da177e4SLinus Torvalds 		       unsigned int bits, unsigned int dir,
13481da177e4SLinus Torvalds 		       unsigned int sleep_dir)
13491da177e4SLinus Torvalds {
13501da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
13511da177e4SLinus Torvalds 	unsigned long flags;
13521da177e4SLinus Torvalds 	unsigned int val;
13531da177e4SLinus Torvalds 	void __iomem *gpio = sachip->base + SA1111_GPIO;
13541da177e4SLinus Torvalds 
13551da177e4SLinus Torvalds #define MODIFY_BITS(port, mask, dir)		\
13561da177e4SLinus Torvalds 	if (mask) {				\
13571da177e4SLinus Torvalds 		val = sa1111_readl(port);	\
13581da177e4SLinus Torvalds 		val &= ~(mask);			\
13591da177e4SLinus Torvalds 		val |= (dir) & (mask);		\
13601da177e4SLinus Torvalds 		sa1111_writel(val, port);	\
13611da177e4SLinus Torvalds 	}
13621da177e4SLinus Torvalds 
13631da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
13641da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PADDR, bits & 15, dir);
13651da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PBDDR, (bits >> 8) & 255, dir >> 8);
13661da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PCDDR, (bits >> 16) & 255, dir >> 16);
13671da177e4SLinus Torvalds 
13681da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PASDR, bits & 15, sleep_dir);
13691da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PBSDR, (bits >> 8) & 255, sleep_dir >> 8);
13701da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PCSDR, (bits >> 16) & 255, sleep_dir >> 16);
13711da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
13721da177e4SLinus Torvalds }
13730a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_set_io_dir);
13741da177e4SLinus Torvalds 
13751da177e4SLinus Torvalds void sa1111_set_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v)
13761da177e4SLinus Torvalds {
13771da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
13781da177e4SLinus Torvalds 	unsigned long flags;
13791da177e4SLinus Torvalds 	unsigned int val;
13801da177e4SLinus Torvalds 	void __iomem *gpio = sachip->base + SA1111_GPIO;
13811da177e4SLinus Torvalds 
13821da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
13831da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PADWR, bits & 15, v);
13841da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PBDWR, (bits >> 8) & 255, v >> 8);
13851da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PCDWR, (bits >> 16) & 255, v >> 16);
13861da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
13871da177e4SLinus Torvalds }
13880a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_set_io);
13891da177e4SLinus Torvalds 
13901da177e4SLinus Torvalds void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned int v)
13911da177e4SLinus Torvalds {
13921da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
13931da177e4SLinus Torvalds 	unsigned long flags;
13941da177e4SLinus Torvalds 	unsigned int val;
13951da177e4SLinus Torvalds 	void __iomem *gpio = sachip->base + SA1111_GPIO;
13961da177e4SLinus Torvalds 
13971da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
13981da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PASSR, bits & 15, v);
13991da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PBSSR, (bits >> 8) & 255, v >> 8);
14001da177e4SLinus Torvalds 	MODIFY_BITS(gpio + SA1111_GPIO_PCSSR, (bits >> 16) & 255, v >> 16);
14011da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
14021da177e4SLinus Torvalds }
14030a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_set_sleep_io);
14041da177e4SLinus Torvalds 
14051da177e4SLinus Torvalds /*
14061da177e4SLinus Torvalds  * Individual device operations.
14071da177e4SLinus Torvalds  */
14081da177e4SLinus Torvalds 
14091da177e4SLinus Torvalds /**
14101da177e4SLinus Torvalds  *	sa1111_enable_device - enable an on-chip SA1111 function block
14111da177e4SLinus Torvalds  *	@sadev: SA1111 function block device to enable
14121da177e4SLinus Torvalds  */
1413ae99ddbcSRussell King int sa1111_enable_device(struct sa1111_dev *sadev)
14141da177e4SLinus Torvalds {
14151da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
14161da177e4SLinus Torvalds 	unsigned long flags;
14171da177e4SLinus Torvalds 	unsigned int val;
1418ae99ddbcSRussell King 	int ret = 0;
14191da177e4SLinus Torvalds 
1420ae99ddbcSRussell King 	if (sachip->pdata && sachip->pdata->enable)
1421ae99ddbcSRussell King 		ret = sachip->pdata->enable(sachip->pdata->data, sadev->devid);
1422ae99ddbcSRussell King 
1423ae99ddbcSRussell King 	if (ret == 0) {
14241da177e4SLinus Torvalds 		spin_lock_irqsave(&sachip->lock, flags);
14251da177e4SLinus Torvalds 		val = sa1111_readl(sachip->base + SA1111_SKPCR);
14261da177e4SLinus Torvalds 		sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
14271da177e4SLinus Torvalds 		spin_unlock_irqrestore(&sachip->lock, flags);
14281da177e4SLinus Torvalds 	}
1429ae99ddbcSRussell King 	return ret;
1430ae99ddbcSRussell King }
14310a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_enable_device);
14321da177e4SLinus Torvalds 
14331da177e4SLinus Torvalds /**
14341da177e4SLinus Torvalds  *	sa1111_disable_device - disable an on-chip SA1111 function block
14351da177e4SLinus Torvalds  *	@sadev: SA1111 function block device to disable
14361da177e4SLinus Torvalds  */
14371da177e4SLinus Torvalds void sa1111_disable_device(struct sa1111_dev *sadev)
14381da177e4SLinus Torvalds {
14391da177e4SLinus Torvalds 	struct sa1111 *sachip = sa1111_chip_driver(sadev);
14401da177e4SLinus Torvalds 	unsigned long flags;
14411da177e4SLinus Torvalds 	unsigned int val;
14421da177e4SLinus Torvalds 
14431da177e4SLinus Torvalds 	spin_lock_irqsave(&sachip->lock, flags);
14441da177e4SLinus Torvalds 	val = sa1111_readl(sachip->base + SA1111_SKPCR);
14451da177e4SLinus Torvalds 	sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
14461da177e4SLinus Torvalds 	spin_unlock_irqrestore(&sachip->lock, flags);
1447ae99ddbcSRussell King 
1448ae99ddbcSRussell King 	if (sachip->pdata && sachip->pdata->disable)
1449ae99ddbcSRussell King 		sachip->pdata->disable(sachip->pdata->data, sadev->devid);
14501da177e4SLinus Torvalds }
14510a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_disable_device);
14521da177e4SLinus Torvalds 
14531da177e4SLinus Torvalds /*
14541da177e4SLinus Torvalds  *	SA1111 "Register Access Bus."
14551da177e4SLinus Torvalds  *
14561da177e4SLinus Torvalds  *	We model this as a regular bus type, and hang devices directly
14571da177e4SLinus Torvalds  *	off this.
14581da177e4SLinus Torvalds  */
14591da177e4SLinus Torvalds static int sa1111_match(struct device *_dev, struct device_driver *_drv)
14601da177e4SLinus Torvalds {
14611da177e4SLinus Torvalds 	struct sa1111_dev *dev = SA1111_DEV(_dev);
14621da177e4SLinus Torvalds 	struct sa1111_driver *drv = SA1111_DRV(_drv);
14631da177e4SLinus Torvalds 
146417f29d36SMarek Szyprowski 	return !!(dev->devid & drv->devid);
14651da177e4SLinus Torvalds }
14661da177e4SLinus Torvalds 
14671da177e4SLinus Torvalds static int sa1111_bus_suspend(struct device *dev, pm_message_t state)
14681da177e4SLinus Torvalds {
14691da177e4SLinus Torvalds 	struct sa1111_dev *sadev = SA1111_DEV(dev);
14701da177e4SLinus Torvalds 	struct sa1111_driver *drv = SA1111_DRV(dev->driver);
14711da177e4SLinus Torvalds 	int ret = 0;
14721da177e4SLinus Torvalds 
14731da177e4SLinus Torvalds 	if (drv && drv->suspend)
14741da177e4SLinus Torvalds 		ret = drv->suspend(sadev, state);
14751da177e4SLinus Torvalds 	return ret;
14761da177e4SLinus Torvalds }
14771da177e4SLinus Torvalds 
14781da177e4SLinus Torvalds static int sa1111_bus_resume(struct device *dev)
14791da177e4SLinus Torvalds {
14801da177e4SLinus Torvalds 	struct sa1111_dev *sadev = SA1111_DEV(dev);
14811da177e4SLinus Torvalds 	struct sa1111_driver *drv = SA1111_DRV(dev->driver);
14821da177e4SLinus Torvalds 	int ret = 0;
14831da177e4SLinus Torvalds 
14841da177e4SLinus Torvalds 	if (drv && drv->resume)
14851da177e4SLinus Torvalds 		ret = drv->resume(sadev);
14861da177e4SLinus Torvalds 	return ret;
14871da177e4SLinus Torvalds }
14881da177e4SLinus Torvalds 
14896bd72f05SRussell King static void sa1111_bus_shutdown(struct device *dev)
14906bd72f05SRussell King {
14916bd72f05SRussell King 	struct sa1111_driver *drv = SA1111_DRV(dev->driver);
14926bd72f05SRussell King 
14936bd72f05SRussell King 	if (drv && drv->shutdown)
14946bd72f05SRussell King 		drv->shutdown(SA1111_DEV(dev));
14956bd72f05SRussell King }
14966bd72f05SRussell King 
14971da177e4SLinus Torvalds static int sa1111_bus_probe(struct device *dev)
14981da177e4SLinus Torvalds {
14991da177e4SLinus Torvalds 	struct sa1111_dev *sadev = SA1111_DEV(dev);
15001da177e4SLinus Torvalds 	struct sa1111_driver *drv = SA1111_DRV(dev->driver);
15011da177e4SLinus Torvalds 	int ret = -ENODEV;
15021da177e4SLinus Torvalds 
15031da177e4SLinus Torvalds 	if (drv->probe)
15041da177e4SLinus Torvalds 		ret = drv->probe(sadev);
15051da177e4SLinus Torvalds 	return ret;
15061da177e4SLinus Torvalds }
15071da177e4SLinus Torvalds 
15081da177e4SLinus Torvalds static int sa1111_bus_remove(struct device *dev)
15091da177e4SLinus Torvalds {
15101da177e4SLinus Torvalds 	struct sa1111_dev *sadev = SA1111_DEV(dev);
15111da177e4SLinus Torvalds 	struct sa1111_driver *drv = SA1111_DRV(dev->driver);
15121da177e4SLinus Torvalds 	int ret = 0;
15131da177e4SLinus Torvalds 
15141da177e4SLinus Torvalds 	if (drv->remove)
15151da177e4SLinus Torvalds 		ret = drv->remove(sadev);
15161da177e4SLinus Torvalds 	return ret;
15171da177e4SLinus Torvalds }
15181da177e4SLinus Torvalds 
15191da177e4SLinus Torvalds struct bus_type sa1111_bus_type = {
15201da177e4SLinus Torvalds 	.name		= "sa1111-rab",
15211da177e4SLinus Torvalds 	.match		= sa1111_match,
15222876ba43SRussell King 	.probe		= sa1111_bus_probe,
15232876ba43SRussell King 	.remove		= sa1111_bus_remove,
15241da177e4SLinus Torvalds 	.suspend	= sa1111_bus_suspend,
15251da177e4SLinus Torvalds 	.resume		= sa1111_bus_resume,
15266bd72f05SRussell King 	.shutdown	= sa1111_bus_shutdown,
15271da177e4SLinus Torvalds };
15280a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_bus_type);
15291da177e4SLinus Torvalds 
15301da177e4SLinus Torvalds int sa1111_driver_register(struct sa1111_driver *driver)
15311da177e4SLinus Torvalds {
15321da177e4SLinus Torvalds 	driver->drv.bus = &sa1111_bus_type;
15331da177e4SLinus Torvalds 	return driver_register(&driver->drv);
15341da177e4SLinus Torvalds }
15350a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_driver_register);
15361da177e4SLinus Torvalds 
15371da177e4SLinus Torvalds void sa1111_driver_unregister(struct sa1111_driver *driver)
15381da177e4SLinus Torvalds {
15391da177e4SLinus Torvalds 	driver_unregister(&driver->drv);
15401da177e4SLinus Torvalds }
15410a4bc5e8SHartley Sweeten EXPORT_SYMBOL(sa1111_driver_unregister);
15421da177e4SLinus Torvalds 
154309a2ba2fSRussell King #ifdef CONFIG_DMABOUNCE
154409a2ba2fSRussell King /*
154509a2ba2fSRussell King  * According to the "Intel StrongARM SA-1111 Microprocessor Companion
154609a2ba2fSRussell King  * Chip Specification Update" (June 2000), erratum #7, there is a
154709a2ba2fSRussell King  * significant bug in the SA1111 SDRAM shared memory controller.  If
154809a2ba2fSRussell King  * an access to a region of memory above 1MB relative to the bank base,
154909a2ba2fSRussell King  * it is important that address bit 10 _NOT_ be asserted. Depending
155009a2ba2fSRussell King  * on the configuration of the RAM, bit 10 may correspond to one
155109a2ba2fSRussell King  * of several different (processor-relative) address bits.
155209a2ba2fSRussell King  *
155309a2ba2fSRussell King  * This routine only identifies whether or not a given DMA address
155409a2ba2fSRussell King  * is susceptible to the bug.
155509a2ba2fSRussell King  *
155609a2ba2fSRussell King  * This should only get called for sa1111_device types due to the
155709a2ba2fSRussell King  * way we configure our device dma_masks.
155809a2ba2fSRussell King  */
155909a2ba2fSRussell King static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
156009a2ba2fSRussell King {
156109a2ba2fSRussell King 	/*
156209a2ba2fSRussell King 	 * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
156309a2ba2fSRussell King 	 * User's Guide" mentions that jumpers R51 and R52 control the
156409a2ba2fSRussell King 	 * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
156509a2ba2fSRussell King 	 * SDRAM bank 1 on Neponset). The default configuration selects
156609a2ba2fSRussell King 	 * Assabet, so any address in bank 1 is necessarily invalid.
156709a2ba2fSRussell King 	 */
156809a2ba2fSRussell King 	return (machine_is_assabet() || machine_is_pfs168()) &&
156909a2ba2fSRussell King 		(addr >= 0xc8000000 || (addr + size) >= 0xc8000000);
157009a2ba2fSRussell King }
157109a2ba2fSRussell King 
157209a2ba2fSRussell King static int sa1111_notifier_call(struct notifier_block *n, unsigned long action,
157309a2ba2fSRussell King 	void *data)
157409a2ba2fSRussell King {
157509a2ba2fSRussell King 	struct sa1111_dev *dev = SA1111_DEV(data);
157609a2ba2fSRussell King 
157709a2ba2fSRussell King 	switch (action) {
157809a2ba2fSRussell King 	case BUS_NOTIFY_ADD_DEVICE:
157909a2ba2fSRussell King 		if (dev->dev.dma_mask && dev->dma_mask < 0xffffffffUL) {
158009a2ba2fSRussell King 			int ret = dmabounce_register_dev(&dev->dev, 1024, 4096,
158109a2ba2fSRussell King 					sa1111_needs_bounce);
158209a2ba2fSRussell King 			if (ret)
158309a2ba2fSRussell King 				dev_err(&dev->dev, "failed to register with dmabounce: %d\n", ret);
158409a2ba2fSRussell King 		}
158509a2ba2fSRussell King 		break;
158609a2ba2fSRussell King 
158709a2ba2fSRussell King 	case BUS_NOTIFY_DEL_DEVICE:
158809a2ba2fSRussell King 		if (dev->dev.dma_mask && dev->dma_mask < 0xffffffffUL)
158909a2ba2fSRussell King 			dmabounce_unregister_dev(&dev->dev);
159009a2ba2fSRussell King 		break;
159109a2ba2fSRussell King 	}
159209a2ba2fSRussell King 	return NOTIFY_OK;
159309a2ba2fSRussell King }
159409a2ba2fSRussell King 
159509a2ba2fSRussell King static struct notifier_block sa1111_bus_notifier = {
159609a2ba2fSRussell King 	.notifier_call = sa1111_notifier_call,
159709a2ba2fSRussell King };
159809a2ba2fSRussell King #endif
159909a2ba2fSRussell King 
16001da177e4SLinus Torvalds static int __init sa1111_init(void)
16011da177e4SLinus Torvalds {
16021da177e4SLinus Torvalds 	int ret = bus_register(&sa1111_bus_type);
160309a2ba2fSRussell King #ifdef CONFIG_DMABOUNCE
160409a2ba2fSRussell King 	if (ret == 0)
160509a2ba2fSRussell King 		bus_register_notifier(&sa1111_bus_type, &sa1111_bus_notifier);
160609a2ba2fSRussell King #endif
16071da177e4SLinus Torvalds 	if (ret == 0)
16083ae5eaecSRussell King 		platform_driver_register(&sa1111_device_driver);
16091da177e4SLinus Torvalds 	return ret;
16101da177e4SLinus Torvalds }
16111da177e4SLinus Torvalds 
16121da177e4SLinus Torvalds static void __exit sa1111_exit(void)
16131da177e4SLinus Torvalds {
16143ae5eaecSRussell King 	platform_driver_unregister(&sa1111_device_driver);
161509a2ba2fSRussell King #ifdef CONFIG_DMABOUNCE
161609a2ba2fSRussell King 	bus_unregister_notifier(&sa1111_bus_type, &sa1111_bus_notifier);
161709a2ba2fSRussell King #endif
16181da177e4SLinus Torvalds 	bus_unregister(&sa1111_bus_type);
16191da177e4SLinus Torvalds }
16201da177e4SLinus Torvalds 
162172724382SRussell King subsys_initcall(sa1111_init);
16221da177e4SLinus Torvalds module_exit(sa1111_exit);
16231da177e4SLinus Torvalds 
16241da177e4SLinus Torvalds MODULE_DESCRIPTION("Intel Corporation SA1111 core driver");
16251da177e4SLinus Torvalds MODULE_LICENSE("GPL");
1626