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