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