diff options
Diffstat (limited to 'arch')
25 files changed, 679 insertions, 1467 deletions
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 61691cdbdcf2..9173d112ea01 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c @@ -16,6 +16,7 @@ */ #include <linux/module.h> #include <linux/init.h> +#include <linux/irq.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/errno.h> @@ -28,9 +29,8 @@ #include <linux/io.h> #include <mach/hardware.h> -#include <asm/mach-types.h> -#include <asm/irq.h> #include <asm/mach/irq.h> +#include <asm/mach-types.h> #include <asm/sizes.h> #include <asm/hardware/sa1111.h> @@ -86,8 +86,10 @@ #define IRQ_S1_CD_VALID (52) #define IRQ_S0_BVD1_STSCHG (53) #define IRQ_S1_BVD1_STSCHG (54) +#define SA1111_IRQ_NR (55) -extern void __init sa1110_mb_enable(void); +extern void sa1110_mb_enable(void); +extern void sa1110_mb_disable(void); /* * We keep the following data for the overall SA1111. Note that the @@ -104,6 +106,7 @@ struct sa1111 { int irq_base; /* base for cascaded on-chip IRQs */ spinlock_t lock; void __iomem *base; + struct sa1111_platform_data *pdata; #ifdef CONFIG_PM void *saved_state; #endif @@ -118,6 +121,7 @@ static struct sa1111 *g_sa1111; struct sa1111_dev_info { unsigned long offset; unsigned long skpcr_mask; + bool dma; unsigned int devid; unsigned int irq[6]; }; @@ -126,6 +130,7 @@ static struct sa1111_dev_info sa1111_devices[] = { { .offset = SA1111_USB, .skpcr_mask = SKPCR_UCLKEN, + .dma = true, .devid = SA1111_DEVID_USB, .irq = { IRQ_USBPWR, @@ -139,6 +144,7 @@ static struct sa1111_dev_info sa1111_devices[] = { { .offset = 0x0600, .skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN, + .dma = true, .devid = SA1111_DEVID_SAC, .irq = { AUDXMTDMADONEA, @@ -155,7 +161,7 @@ static struct sa1111_dev_info sa1111_devices[] = { { .offset = SA1111_KBD, .skpcr_mask = SKPCR_PTCLKEN, - .devid = SA1111_DEVID_PS2, + .devid = SA1111_DEVID_PS2_KBD, .irq = { IRQ_TPRXINT, IRQ_TPTXINT @@ -164,7 +170,7 @@ static struct sa1111_dev_info sa1111_devices[] = { { .offset = SA1111_MSE, .skpcr_mask = SKPCR_PMCLKEN, - .devid = SA1111_DEVID_PS2, + .devid = SA1111_DEVID_PS2_MSE, .irq = { IRQ_MSRXINT, IRQ_MSTXINT @@ -434,16 +440,28 @@ static struct irq_chip sa1111_high_chip = { .irq_set_wake = sa1111_wake_highirq, }; -static void sa1111_setup_irq(struct sa1111 *sachip) +static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base) { void __iomem *irqbase = sachip->base + SA1111_INTC; - unsigned int irq; + unsigned i, irq; + int ret; /* * We're guaranteed that this region hasn't been taken. */ request_mem_region(sachip->phys + SA1111_INTC, 512, "irq"); + ret = irq_alloc_descs(-1, irq_base, SA1111_IRQ_NR, -1); + if (ret <= 0) { + dev_err(sachip->dev, "unable to allocate %u irqs: %d\n", + SA1111_IRQ_NR, ret); + if (ret == 0) + ret = -EINVAL; + return ret; + } + + sachip->irq_base = ret; + /* disable all IRQs */ sa1111_writel(0, irqbase + SA1111_INTEN0); sa1111_writel(0, irqbase + SA1111_INTEN1); @@ -463,14 +481,16 @@ static void sa1111_setup_irq(struct sa1111 *sachip) sa1111_writel(~0, irqbase + SA1111_INTSTATCLR0); sa1111_writel(~0, irqbase + SA1111_INTSTATCLR1); - for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { + for (i = IRQ_GPAIN0; i <= SSPROR; i++) { + irq = sachip->irq_base + i; irq_set_chip_and_handler(irq, &sa1111_low_chip, handle_edge_irq); irq_set_chip_data(irq, sachip); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) { + for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) { + irq = sachip->irq_base + i; irq_set_chip_and_handler(irq, &sa1111_high_chip, handle_edge_irq); irq_set_chip_data(irq, sachip); @@ -483,6 +503,11 @@ static void sa1111_setup_irq(struct sa1111 *sachip) irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING); irq_set_handler_data(sachip->irq, sachip); irq_set_chained_handler(sachip->irq, sa1111_irq_handler); + + dev_info(sachip->dev, "Providing IRQ%u-%u\n", + sachip->irq_base, sachip->irq_base + SA1111_IRQ_NR - 1); + + return 0; } /* @@ -581,41 +606,10 @@ sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac, } #endif -#ifdef CONFIG_DMABOUNCE -/* - * According to the "Intel StrongARM SA-1111 Microprocessor Companion - * Chip Specification Update" (June 2000), erratum #7, there is a - * significant bug in the SA1111 SDRAM shared memory controller. If - * an access to a region of memory above 1MB relative to the bank base, - * it is important that address bit 10 _NOT_ be asserted. Depending - * on the configuration of the RAM, bit 10 may correspond to one - * of several different (processor-relative) address bits. - * - * This routine only identifies whether or not a given DMA address - * is susceptible to the bug. - * - * This should only get called for sa1111_device types due to the - * way we configure our device dma_masks. - */ -static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size) -{ - /* - * Section 4.6 of the "Intel StrongARM SA-1111 Development Module - * User's Guide" mentions that jumpers R51 and R52 control the - * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or - * SDRAM bank 1 on Neponset). The default configuration selects - * Assabet, so any address in bank 1 is necessarily invalid. - */ - return (machine_is_assabet() || machine_is_pfs168()) && - (addr >= 0xc8000000 || (addr + size) >= 0xc8000000); -} -#endif - static void sa1111_dev_release(struct device *_dev) { struct sa1111_dev *dev = SA1111_DEV(_dev); - release_resource(&dev->res); kfree(dev); } @@ -624,67 +618,58 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent, struct sa1111_dev_info *info) { struct sa1111_dev *dev; + unsigned i; int ret; dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL); if (!dev) { ret = -ENOMEM; - goto out; + goto err_alloc; } + device_initialize(&dev->dev); dev_set_name(&dev->dev, "%4.4lx", info->offset); dev->devid = info->devid; dev->dev.parent = sachip->dev; dev->dev.bus = &sa1111_bus_type; dev->dev.release = sa1111_dev_release; - dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask; dev->res.start = sachip->phys + info->offset; dev->res.end = dev->res.start + 511; dev->res.name = dev_name(&dev->dev); dev->res.flags = IORESOURCE_MEM; dev->mapbase = sachip->base + info->offset; dev->skpcr_mask = info->skpcr_mask; - memmove(dev->irq, info->irq, sizeof(dev->irq)); - - ret = request_resource(parent, &dev->res); - if (ret) { - printk("SA1111: failed to allocate resource for %s\n", - dev->res.name); - dev_set_name(&dev->dev, NULL); - kfree(dev); - goto out; - } - - ret = device_register(&dev->dev); - if (ret) { - release_resource(&dev->res); - kfree(dev); - goto out; - } + for (i = 0; i < ARRAY_SIZE(info->irq); i++) + dev->irq[i] = sachip->irq_base + info->irq[i]; -#ifdef CONFIG_DMABOUNCE /* - * If the parent device has a DMA mask associated with it, - * propagate it down to the children. + * If the parent device has a DMA mask associated with it, and + * this child supports DMA, propagate it down to the children. */ - if (sachip->dev->dma_mask) { + if (info->dma && sachip->dev->dma_mask) { dev->dma_mask = *sachip->dev->dma_mask; dev->dev.dma_mask = &dev->dma_mask; + dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask; + } - if (dev->dma_mask != 0xffffffffUL) { - ret = dmabounce_register_dev(&dev->dev, 1024, 4096, - sa1111_needs_bounce); - if (ret) { - dev_err(&dev->dev, "SA1111: Failed to register" - " with dmabounce\n"); - device_unregister(&dev->dev); - } - } + ret = request_resource(parent, &dev->res); + if (ret) { + dev_err(sachip->dev, "failed to allocate resource for %s\n", + dev->res.name); + goto err_resource; } -#endif -out: + ret = device_add(&dev->dev); + if (ret) + goto err_add; + return 0; + + err_add: + release_resource(&dev->res); + err_resource: + put_device(&dev->dev); + err_alloc: return ret; } @@ -698,16 +683,21 @@ out: * Returns: * %-ENODEV device not found. * %-EBUSY physical address already marked in-use. + * %-EINVAL no platform data passed * %0 successful. */ static int __devinit __sa1111_probe(struct device *me, struct resource *mem, int irq) { + struct sa1111_platform_data *pd = me->platform_data; struct sa1111 *sachip; unsigned long id; unsigned int has_devs; int i, ret = -ENODEV; + if (!pd) + return -EINVAL; + sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL); if (!sachip) return -ENOMEM; @@ -727,6 +717,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) sachip->dev = me; dev_set_drvdata(sachip->dev, sachip); + sachip->pdata = pd; sachip->phys = mem->start; sachip->irq = irq; @@ -759,6 +750,16 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) */ sa1111_wake(sachip); + /* + * The interrupt controller must be initialised before any + * other device to ensure that the interrupts are available. + */ + if (sachip->irq != NO_IRQ) { + ret = sa1111_setup_irq(sachip, pd->irq_base); + if (ret) + goto err_unmap; + } + #ifdef CONFIG_ARCH_SA1100 { unsigned int val; @@ -789,24 +790,14 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) } #endif - /* - * The interrupt controller must be initialised before any - * other device to ensure that the interrupts are available. - */ - if (sachip->irq != NO_IRQ) - sa1111_setup_irq(sachip); - g_sa1111 = sachip; has_devs = ~0; - if (machine_is_assabet() || machine_is_jornada720() || - machine_is_badge4()) - has_devs &= ~(1 << 4); - else - has_devs &= ~(1 << 1); + if (pd) + has_devs &= ~pd->disable_devs; for (i = 0; i < ARRAY_SIZE(sa1111_devices); i++) - if (has_devs & (1 << i)) + if (sa1111_devices[i].devid & has_devs) sa1111_init_one_child(sachip, mem, &sa1111_devices[i]); return 0; @@ -824,7 +815,10 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) static int sa1111_remove_one(struct device *dev, void *data) { - device_unregister(dev); + struct sa1111_dev *sadev = SA1111_DEV(dev); + device_del(&sadev->dev); + release_resource(&sadev->res); + put_device(&sadev->dev); return 0; } @@ -846,6 +840,7 @@ static void __sa1111_remove(struct sa1111 *sachip) if (sachip->irq != NO_IRQ) { irq_set_chained_handler(sachip->irq, NULL); irq_set_handler_data(sachip->irq, NULL); + irq_free_descs(sachip->irq_base, SA1111_IRQ_NR); release_mem_region(sachip->phys + SA1111_INTC, 512); } @@ -904,6 +899,9 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state) save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0); save->skpwm1 = sa1111_readl(base + SA1111_SKPWM1); + sa1111_writel(0, sachip->base + SA1111_SKPWM0); + sa1111_writel(0, sachip->base + SA1111_SKPWM1); + base = sachip->base + SA1111_INTC; save->intpol0 = sa1111_readl(base + SA1111_INTPOL0); save->intpol1 = sa1111_readl(base + SA1111_INTPOL1); @@ -919,13 +917,15 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state) */ val = sa1111_readl(sachip->base + SA1111_SKCR); sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR); - sa1111_writel(0, sachip->base + SA1111_SKPWM0); - sa1111_writel(0, sachip->base + SA1111_SKPWM1); clk_disable(sachip->clk); spin_unlock_irqrestore(&sachip->lock, flags); +#ifdef CONFIG_ARCH_SA1100 + sa1110_mb_disable(); +#endif + return 0; } @@ -966,6 +966,11 @@ static int sa1111_resume(struct platform_device *dev) */ sa1111_wake(sachip); +#ifdef CONFIG_ARCH_SA1100 + /* Enable the memory bus request/grant signals */ + sa1110_mb_enable(); +#endif + /* * Only lock for write ops. Also, sa1111_wake must be called with * released spinlock! @@ -1053,6 +1058,7 @@ static struct platform_driver sa1111_device_driver = { .resume = sa1111_resume, .driver = { .name = "sa1111", + .owner = THIS_MODULE, }, }; @@ -1238,16 +1244,23 @@ EXPORT_SYMBOL(sa1111_set_sleep_io); * sa1111_enable_device - enable an on-chip SA1111 function block * @sadev: SA1111 function block device to enable */ -void sa1111_enable_device(struct sa1111_dev *sadev) +int sa1111_enable_device(struct sa1111_dev *sadev) { struct sa1111 *sachip = sa1111_chip_driver(sadev); unsigned long flags; unsigned int val; + int ret = 0; - spin_lock_irqsave(&sachip->lock, flags); - val = sa1111_readl(sachip->base + SA1111_SKPCR); - sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR); - spin_unlock_irqrestore(&sachip->lock, flags); + if (sachip->pdata && sachip->pdata->enable) + ret = sachip->pdata->enable(sachip->pdata->data, sadev->devid); + + if (ret == 0) { + spin_lock_irqsave(&sachip->lock, flags); + val = sa1111_readl(sachip->base + SA1111_SKPCR); + sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR); + spin_unlock_irqrestore(&sachip->lock, flags); + } + return ret; } EXPORT_SYMBOL(sa1111_enable_device); @@ -1265,6 +1278,9 @@ void sa1111_disable_device(struct sa1111_dev *sadev) val = sa1111_readl(sachip->base + SA1111_SKPCR); sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR); spin_unlock_irqrestore(&sachip->lock, flags); + + if (sachip->pdata && sachip->pdata->disable) + sachip->pdata->disable(sachip->pdata->data, sadev->devid); } EXPORT_SYMBOL(sa1111_disable_device); @@ -1279,7 +1295,7 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv) struct sa1111_dev *dev = SA1111_DEV(_dev); struct sa1111_driver *drv = SA1111_DRV(_drv); - return dev->devid == drv->devid; + return dev->devid & drv->devid; } static int sa1111_bus_suspend(struct device *dev, pm_message_t state) @@ -1304,6 +1320,14 @@ static int sa1111_bus_resume(struct device *dev) return ret; } +static void sa1111_bus_shutdown(struct device *dev) +{ + struct sa1111_driver *drv = SA1111_DRV(dev->driver); + + if (drv && drv->shutdown) + drv->shutdown(SA1111_DEV(dev)); +} + static int sa1111_bus_probe(struct device *dev) { struct sa1111_dev *sadev = SA1111_DEV(dev); @@ -1333,6 +1357,7 @@ struct bus_type sa1111_bus_type = { .remove = sa1111_bus_remove, .suspend = sa1111_bus_suspend, .resume = sa1111_bus_resume, + .shutdown = sa1111_bus_shutdown, }; EXPORT_SYMBOL(sa1111_bus_type); @@ -1349,9 +1374,70 @@ void sa1111_driver_unregister(struct sa1111_driver *driver) } EXPORT_SYMBOL(sa1111_driver_unregister); +#ifdef CONFIG_DMABOUNCE +/* + * According to the "Intel StrongARM SA-1111 Microprocessor Companion + * Chip Specification Update" (June 2000), erratum #7, there is a + * significant bug in the SA1111 SDRAM shared memory controller. If + * an access to a region of memory above 1MB relative to the bank base, + * it is important that address bit 10 _NOT_ be asserted. Depending + * on the configuration of the RAM, bit 10 may correspond to one + * of several different (processor-relative) address bits. + * + * This routine only identifies whether or not a given DMA address + * is susceptible to the bug. + * + * This should only get called for sa1111_device types due to the + * way we configure our device dma_masks. + */ +static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size) +{ + /* + * Section 4.6 of the "Intel StrongARM SA-1111 Development Module + * User's Guide" mentions that jumpers R51 and R52 control the + * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or + * SDRAM bank 1 on Neponset). The default configuration selects + * Assabet, so any address in bank 1 is necessarily invalid. + */ + return (machine_is_assabet() || machine_is_pfs168()) && + (addr >= 0xc8000000 || (addr + size) >= 0xc8000000); +} + +static int sa1111_notifier_call(struct notifier_block *n, unsigned long action, + void *data) +{ + struct sa1111_dev *dev = SA1111_DEV(data); + + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: + if (dev->dev.dma_mask && dev->dma_mask < 0xffffffffUL) { + int ret = dmabounce_register_dev(&dev->dev, 1024, 4096, + sa1111_needs_bounce); + if (ret) + dev_err(&dev->dev, "failed to register with dmabounce: %d\n", ret); + } + break; + + case BUS_NOTIFY_DEL_DEVICE: + if (dev->dev.dma_mask && dev->dma_mask < 0xffffffffUL) + dmabounce_unregister_dev(&dev->dev); + break; + } + return NOTIFY_OK; +} + +static struct notifier_block sa1111_bus_notifier = { + .notifier_call = sa1111_notifier_call, +}; +#endif + static int __init sa1111_init(void) { int ret = bus_register(&sa1111_bus_type); +#ifdef CONFIG_DMABOUNCE + if (ret == 0) + bus_register_notifier(&sa1111_bus_type, &sa1111_bus_notifier); +#endif if (ret == 0) platform_driver_register(&sa1111_device_driver); return ret; @@ -1360,6 +1446,9 @@ static int __init sa1111_init(void) static void __exit sa1111_exit(void) { platform_driver_unregister(&sa1111_device_driver); +#ifdef CONFIG_DMABOUNCE + bus_unregister_notifier(&sa1111_bus_type, &sa1111_bus_notifier); +#endif bus_unregister(&sa1111_bus_type); } diff --git a/arch/arm/include/asm/hardware/sa1111.h b/arch/arm/include/asm/hardware/sa1111.h index 92ed254c175b..7c2bbc7f0be1 100644 --- a/arch/arm/include/asm/hardware/sa1111.h +++ b/arch/arm/include/asm/hardware/sa1111.h @@ -132,34 +132,10 @@ #define SKPCR_DCLKEN (1<<7) #define SKPCR_PWMCLKEN (1<<8) -/* - * USB Host controller - */ +/* USB Host controller */ #define SA1111_USB 0x0400 /* - * Offsets from SA1111_USB_BASE - */ -#define SA1111_USB_STATUS 0x0118 -#define SA1111_USB_RESET 0x011c -#define SA1111_USB_IRQTEST 0x0120 - -#define USB_RESET_FORCEIFRESET (1 << 0) -#define USB_RESET_FORCEHCRESET (1 << 1) -#define USB_RESET_CLKGENRESET (1 << 2) -#define USB_RESET_SIMSCALEDOWN (1 << 3) -#define USB_RESET_USBINTTEST (1 << 4) -#define USB_RESET_SLEEPSTBYEN (1 << 5) -#define USB_RESET_PWRSENSELOW (1 << 6) -#define USB_RESET_PWRCTRLLOW (1 << 7) - -#define USB_STATUS_IRQHCIRMTWKUP (1 << 7) -#define USB_STATUS_IRQHCIBUFFACC (1 << 8) -#define USB_STATUS_NIRQHCIM (1 << 9) -#define USB_STATUS_NHCIMFCLR (1 << 10) -#define USB_STATUS_USBPWRSENSE (1 << 11) - -/* * Serial Audio Controller * * Registers @@ -327,22 +303,6 @@ * PC_SSR GPIO Block C Sleep State */ -#define _PA_DDR _SA1111( 0x1000 ) -#define _PA_DRR _SA1111( 0x1004 ) -#define _PA_DWR _SA1111( 0x1004 ) -#define _PA_SDR _SA1111( 0x1008 ) -#define _PA_SSR _SA1111( 0x100c ) -#define _PB_DDR _SA1111( 0x1010 ) -#define _PB_DRR _SA1111( 0x1014 ) -#define _PB_DWR _SA1111( 0x1014 ) -#define _PB_SDR _SA1111( 0x1018 ) -#define _PB_SSR _SA1111( 0x101c ) -#define _PC_DDR _SA1111( 0x1020 ) -#define _PC_DRR _SA1111( 0x1024 ) -#define _PC_DWR _SA1111( 0x1024 ) -#define _PC_SDR _SA1111( 0x1028 ) -#define _PC_SSR _SA1111( 0x102c ) - #define SA1111_GPIO 0x1000 #define SA1111_GPIO_PADDR (0x000) @@ -425,106 +385,30 @@ #define SA1111_WAKEPOL0 0x0034 #define SA1111_WAKEPOL1 0x0038 -/* - * PS/2 Trackpad and Mouse Interfaces - * - * Registers - * PS2CR Control Register - * PS2STAT Status Register - * PS2DATA Transmit/Receive Data register - * PS2CLKDIV Clock Division Register - * PS2PRECNT Clock Precount Register - * PS2TEST1 Test register 1 - * PS2TEST2 Test register 2 - * PS2TEST3 Test register 3 - * PS2TEST4 Test register 4 - */ - +/* PS/2 Trackpad and Mouse Interfaces */ #define SA1111_KBD 0x0a00 #define SA1111_MSE 0x0c00 -/* - * These are offsets from the above bases. - */ -#define SA1111_PS2CR 0x0000 -#define SA1111_PS2STAT 0x0004 -#define SA1111_PS2DATA 0x0008 -#define SA1111_PS2CLKDIV 0x000c -#define SA1111_PS2PRECNT 0x0010 - -#define PS2CR_ENA 0x08 -#define PS2CR_FKD 0x02 -#define PS2CR_FKC 0x01 - -#define PS2STAT_STP 0x0100 -#define PS2STAT_TXE 0x0080 -#define PS2STAT_TXB 0x0040 -#define PS2STAT_RXF 0x0020 -#define PS2STAT_RXB 0x0010 -#define PS2STAT_ENA 0x0008 -#define PS2STAT_RXP 0x0004 -#define PS2STAT_KBD 0x0002 -#define PS2STAT_KBC 0x0001 +/* PCMCIA Interface */ +#define SA1111_PCMCIA 0x1600 -/* - * PCMCIA Interface - * - * Registers - * PCSR Status Register - * PCCR Control Register - * PCSSR Sleep State Register - */ - -#define SA1111_PCMCIA 0x1600 - -/* - * These are offsets from the above base. - */ -#define SA1111_PCCR 0x0000 -#define SA1111_PCSSR 0x0004 -#define SA1111_PCSR 0x0008 - -#define PCSR_S0_READY (1<<0) -#define PCSR_S1_READY (1<<1) -#define PCSR_S0_DETECT (1<<2) -#define PCSR_S1_DETECT (1<<3) -#define PCSR_S0_VS1 (1<<4) -#define PCSR_S0_VS2 (1<<5) -#define PCSR_S1_VS1 (1<<6) -#define PCSR_S1_VS2 (1<<7) -#define PCSR_S0_WP (1<<8) -#define PCSR_S1_WP (1<<9) -#define PCSR_S0_BVD1 (1<<10) -#define PCSR_S0_BVD2 (1<<11) -#define PCSR_S1_BVD1 (1<<12) -#define PCSR_S1_BVD2 (1<<13) - -#define PCCR_S0_RST (1<<0) -#define PCCR_S1_RST (1<<1) -#define PCCR_S0_FLT (1<<2) -#define PCCR_S1_FLT (1<<3) -#define PCCR_S0_PWAITEN (1<<4) -#define PCCR_S1_PWAITEN (1<<5) -#define PCCR_S0_PSE (1<<6) -#define PCCR_S1_PSE (1<<7) - -#define PCSSR_S0_SLEEP (1<<0) -#define PCSSR_S1_SLEEP (1<<1) extern struct bus_type sa1111_bus_type; -#define SA1111_DEVID_SBI 0 -#define SA1111_DEVID_SK 1 -#define SA1111_DEVID_USB 2 -#define SA1111_DEVID_SAC 3 -#define SA1111_DEVID_SSP 4 -#define SA1111_DEVID_PS2 5 -#define SA1111_DEVID_GPIO 6 -#define SA1111_DEVID_INT 7 -#define SA1111_DEVID_PCMCIA 8 +#define SA1111_DEVID_SBI (1 << 0) +#define SA1111_DEVID_SK (1 << 1) +#define SA1111_DEVID_USB (1 << 2) +#define SA1111_DEVID_SAC (1 << 3) +#define SA1111_DEVID_SSP (1 << 4) +#define SA1111_DEVID_PS2 (3 << 5) +#define SA1111_DEVID_PS2_KBD (1 << 5) +#define SA1111_DEVID_PS2_MSE (1 << 6) +#define SA1111_DEVID_GPIO (1 << 7) +#define SA1111_DEVID_INT (1 << 8) +#define SA1111_DEVID_PCMCIA (1 << 9) struct sa1111_dev { struct device dev; @@ -548,6 +432,7 @@ struct sa1111_driver { int (*remove)(struct sa1111_dev *); int (*suspend)(struct sa1111_dev *, pm_message_t); int (*resume)(struct sa1111_dev *); + void (*shutdown)(struct sa1111_dev *); }; #define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv) @@ -555,9 +440,10 @@ struct sa1111_driver { #define SA1111_DRIVER_NAME(_sadev) ((_sadev)->dev.driver->name) /* - * These frob the SKPCR register. + * These frob the SKPCR register, and call platform specific + * enable/disable functions. */ -void sa1111_enable_device(struct sa1111_dev *); +int sa1111_enable_device(struct sa1111_dev *); void sa1111_disable_device(struct sa1111_dev *); unsigned int sa1111_pll_clock(struct sa1111_dev *); @@ -580,6 +466,10 @@ void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned i struct sa1111_platform_data { int irq_base; /* base for cascaded on-chip IRQs */ + unsigned disable_devs; + void *data; + int (*enable)(void *, unsigned); + void (*disable)(void *, unsigned); }; #endif /* _ASM_ARCH_SA1111 */ diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 6ebd276aebeb..6bb3f47b1f14 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -223,6 +223,7 @@ static struct resource sa1111_resources[] = { static struct sa1111_platform_data sa1111_info = { .irq_base = LUBBOCK_SA1111_IRQ_BASE, + .disable_devs = SA1111_DEVID_SAC, }; static struct platform_device sa1111_device = { diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile index ed7408d3216c..60b97ec01676 100644 --- a/arch/arm/mach-sa1100/Makefile +++ b/arch/arm/mach-sa1100/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o +obj-y := clock.o generic.o irq.o time.o #nmi-oopser.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 0c4b76ab4d8e..e2d411a8d4ce 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -40,13 +40,13 @@ #include "generic.h" #define ASSABET_BCR_DB1110 \ - (ASSABET_BCR_SPK_OFF | ASSABET_BCR_QMUTE | \ + (ASSABET_BCR_SPK_OFF | \ ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \ ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \ ASSABET_BCR_IRDA_MD0) #define ASSABET_BCR_DB1111 \ - (ASSABET_BCR_SPK_OFF | ASSABET_BCR_QMUTE | \ + (ASSABET_BCR_SPK_OFF | \ ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \ ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \ ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \ @@ -152,15 +152,8 @@ static struct flash_platform_data assabet_flash_data = { }; static struct resource assabet_flash_resources[] = { - { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_32M - 1, - .flags = IORESOURCE_MEM, - }, { - .start = SA1100_CS1_PHYS, - .end = SA1100_CS1_PHYS + SZ_32M - 1, - .flags = IORESOURCE_MEM, - } + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M), + DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_32M), }; @@ -204,13 +197,22 @@ static struct mcp_plat_data assabet_mcp_data = { .sclk_rate = 11981000, }; +#ifdef CONFIG_ASSABET_NEPONSET +static struct resource neponset_resources[] = { + DEFINE_RES_MEM(0x10000000, 0x08000000), + DEFINE_RES_MEM(0x18000000, 0x04000000), + DEFINE_RES_MEM(0x40000000, SZ_8K), + DEFINE_RES_IRQ(IRQ_GPIO25), +}; +#endif + static void __init assabet_init(void) { /* * Ensure that the power supply is in "high power" mode. */ - GPDR |= GPIO_GPIO16; GPSR = GPIO_GPIO16; + GPDR |= GPIO_GPIO16; /* * Ensure that these pins are set as outputs and are driving @@ -218,8 +220,16 @@ static void __init assabet_init(void) * the WS latch in the CPLD, and we don't float causing * excessive power drain. --rmk */ - GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM; GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM; + GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM; + + /* + * Also set GPIO27 as an output; this is used to clock UART3 + * via the FPGA and as otherwise has no pullups or pulldowns, + * so stop it floating. + */ + GPCR = GPIO_GPIO27; + GPDR |= GPIO_GPIO27; /* * Set up registers for sleep mode. @@ -246,6 +256,9 @@ static void __init assabet_init(void) #ifndef CONFIG_ASSABET_NEPONSET printk( "Warning: Neponset detected but full support " "hasn't been configured in the kernel\n" ); +#else + platform_device_register_simple("neponset", 0, + neponset_resources, ARRAY_SIZE(neponset_resources)); #endif } @@ -412,21 +425,8 @@ static void __init assabet_map_io(void) */ Ser1SDCR0 |= SDCR0_SUS; - if (machine_has_neponset()) { -#ifdef CONFIG_ASSABET_NEPONSET - extern void neponset_map_io(void); - - /* - * We map Neponset registers even if it isn't present since - * many drivers will try to probe their stuff (and fail). - * This is still more friendly than a kernel paging request - * crash. - */ - neponset_map_io(); -#endif - } else { + if (!machine_has_neponset()) sa1100_register_uart_fns(&assabet_port_fns); - } /* * When Neponset is attached, the first UART should be diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c index b07a2c024cb7..5839c9d8bb92 100644 --- a/arch/arm/mach-sa1100/badge4.c +++ b/arch/arm/mach-sa1100/badge4.c @@ -39,20 +39,28 @@ #include "generic.h" static struct resource sa1111_resources[] = { - [0] = { - .start = BADGE4_SA1111_BASE, - .end = BADGE4_SA1111_BASE + 0x00001fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = BADGE4_IRQ_GPIO_SA1111, - .end = BADGE4_IRQ_GPIO_SA1111, - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(BADGE4_SA1111_BASE, 0x2000), + [1] = DEFINE_RES_IRQ(BADGE4_IRQ_GPIO_SA1111), }; +static int badge4_sa1111_enable(void *data, unsigned devid) +{ + if (devid == SA1111_DEVID_USB) + badge4_set_5V(BADGE4_5V_USB, 1); + return 0; +} + +static void badge4_sa1111_disable(void *data, unsigned devid) +{ + if (devid == SA1111_DEVID_USB) + badge4_set_5V(BADGE4_5V_USB, 0); +} + static struct sa1111_platform_data sa1111_info = { .irq_base = IRQ_BOARD_END, + .disable_devs = SA1111_DEVID_PS2_MSE, + .enable = badge4_sa1111_enable, + .disable = badge4_sa1111_disable, }; static u64 sa1111_dmamask = 0xffffffffUL; @@ -121,11 +129,8 @@ static struct flash_platform_data badge4_flash_data = { .nr_parts = ARRAY_SIZE(badge4_partitions), }; -static struct resource badge4_flash_resource = { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_64M - 1, - .flags = IORESOURCE_MEM, -}; +static struct resource badge4_flash_resource = + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_64M); static int five_v_on __initdata = 0; @@ -269,11 +274,6 @@ static struct map_desc badge4_io_desc[] __initdata = { .pfn = __phys_to_pfn(0x10000000), .length = 0x00100000, .type = MT_DEVICE - }, { /* SA-1111 */ - .virtual = 0xf4000000, - .pfn = __phys_to_pfn(0x48000000), - .length = 0x00100000, - .type = MT_DEVICE } }; diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c index 11bb6d0b9be3..c2f9ba3a9578 100644 --- a/arch/arm/mach-sa1100/cerf.c +++ b/arch/arm/mach-sa1100/cerf.c @@ -33,11 +33,7 @@ #include "generic.h" static struct resource cerfuart2_resources[] = { - [0] = { - .start = 0x80030000, - .end = 0x8003ffff, - .flags = IORESOURCE_MEM, - }, + [0] = DEFINE_RES_MEM(0x80030000, SZ_64K), }; static struct platform_device cerfuart2_device = { @@ -87,11 +83,8 @@ static struct flash_platform_data cerf_flash_data = { .nr_parts = ARRAY_SIZE(cerf_partitions), }; -static struct resource cerf_flash_resource = { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_32M - 1, - .flags = IORESOURCE_MEM, -}; +static struct resource cerf_flash_resource = + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M); static void __init cerf_init_irq(void) { diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index fd5652118ed1..dbe5cf719f7e 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -48,11 +48,7 @@ #include "generic.h" static struct resource collie_scoop_resources[] = { - [0] = { - .start = 0x40800000, - .end = 0x40800fff, - .flags = IORESOURCE_MEM, - }, + [0] = DEFINE_RES_MEM(0x40800000, SZ_4K), }; static struct scoop_config collie_scoop_setup = { @@ -221,16 +217,8 @@ device_initcall(collie_uart_init); static struct resource locomo_resources[] = { - [0] = { - .start = 0x40000000, - .end = 0x40001fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_GPIO25, - .end = IRQ_GPIO25, - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(0x40000000, SZ_8K), + [1] = DEFINE_RES_IRQ(IRQ_GPIO25), }; static struct locomo_platform_data locomo_info = { @@ -303,11 +291,7 @@ static struct flash_platform_data collie_flash_data = { }; static struct resource collie_flash_resources[] = { - { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_32M - 1, - .flags = IORESOURCE_MEM, - } + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M), }; static void __init collie_init(void) diff --git a/arch/arm/mach-sa1100/dma.c b/arch/arm/mach-sa1100/dma.c deleted file mode 100644 index ad660350c296..000000000000 --- a/arch/arm/mach-sa1100/dma.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * arch/arm/mach-sa1100/dma.c - * - * Support functions for the SA11x0 internal DMA channels. - * - * Copyright (C) 2000, 2001 by Nicolas Pitre - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/spinlock.h> -#include <linux/errno.h> - -#include <asm/system.h> -#include <asm/irq.h> -#include <mach/hardware.h> -#include <mach/dma.h> - - -#undef DEBUG -#ifdef DEBUG -#define DPRINTK( s, arg... ) printk( "dma<%p>: " s, regs , ##arg ) -#else -#define DPRINTK( x... ) -#endif - - -typedef struct { - const char *device_id; /* device name */ - u_long device; /* this channel device, 0 if unused*/ - dma_callback_t callback; /* to call when DMA completes */ - void *data; /* ... with private data ptr */ -} sa1100_dma_t; - -static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS]; - -static DEFINE_SPINLOCK(dma_list_lock); - - -static irqreturn_t dma_irq_handler(int irq, void *dev_id) -{ - dma_regs_t *dma_regs = dev_id; - sa1100_dma_t *dma = dma_chan + (((u_int)dma_regs >> 5) & 7); - int status = dma_regs->RdDCSR; - - if (status & (DCSR_ERROR)) { - printk(KERN_CRIT "DMA on \"%s\" caused an error\n", dma->device_id); - dma_regs->ClrDCSR = DCSR_ERROR; - } - - dma_regs->ClrDCSR = status & (DCSR_DONEA | DCSR_DONEB); - if (dma->callback) { - if (status & DCSR_DONEA) - dma->callback(dma->data); - if (status & DCSR_DONEB) - dma->callback(dma->data); - } - return IRQ_HANDLED; -} - - -/** - * sa1100_request_dma - allocate one of the SA11x0's DMA channels - * @device: The SA11x0 peripheral targeted by this request - * @device_id: An ascii name for the claiming device - * @callback: Function to be called when the DMA completes - * @data: A cookie passed back to the callback function - * @dma_regs: Pointer to the location of the allocated channel's identifier - * - * This function will search for a free DMA channel and returns the - * address of the hardware registers for that channel as the channel - * identifier. This identifier is written to the location pointed by - * @dma_regs. The list of possible values for @device are listed into - * arch/arm/mach-sa1100/include/mach/dma.h as a dma_device_t enum. - * - * Note that reading from a port and writing to the same port are - * actually considered as two different streams requiring separate - * DMA registrations. - * - * The @callback function is called from interrupt context when one - * of the two possible DMA buffers in flight has terminated. That - * function has to be small and efficient while posponing more complex - * processing to a lower priority execution context. - * - * If no channels are available, or if the desired @device is already in - * use by another DMA channel, then an error code is returned. This - * function must be called before any other DMA calls. - **/ - -int sa1100_request_dma (dma_device_t device, const char *device_id, - dma_callback_t callback, void *data, - dma_regs_t **dma_regs) -{ - sa1100_dma_t *dma = NULL; - dma_regs_t *regs; - int i, err; - - *dma_regs = NULL; - - err = 0; - spin_lock(&dma_list_lock); - for (i = 0; i < SA1100_DMA_CHANNELS; i++) { - if (dma_chan[i].device == device) { - err = -EBUSY; - break; - } else if (!dma_chan[i].device && !dma) { - dma = &dma_chan[i]; - } - } - if (!err) { - if (dma) - dma->device = device; - else - err = -ENOSR; - } - spin_unlock(&dma_list_lock); - if (err) - return err; - - i = dma - dma_chan; - regs = (dma_regs_t *)&DDAR(i); - err = request_irq(IRQ_DMA0 + i, dma_irq_handler, IRQF_DISABLED, - device_id, regs); - if (err) { - printk(KERN_ERR - "%s: unable to request IRQ %d for %s\n", - __func__, IRQ_DMA0 + i, device_id); - dma->device = 0; - return err; - } - - *dma_regs = regs; - dma->device_id = device_id; - dma->callback = callback; - dma->data = data; - - regs->ClrDCSR = - (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB | - DCSR_IE | DCSR_ERROR | DCSR_RUN); - regs->DDAR = device; - - return 0; -} - - -/** - * sa1100_free_dma - free a SA11x0 DMA channel - * @regs: identifier for the channel to free - * - * This clears all activities on a given DMA channel and releases it - * for future requests. The @regs identifier is provided by a - * successful call to sa1100_request_dma(). - **/ - -void sa1100_free_dma(dma_regs_t *regs) -{ - int i; - - for (i = 0; i < SA1100_DMA_CHANNELS; i++) - if (regs == (dma_regs_t *)&DDAR(i)) - break; - if (i >= SA1100_DMA_CHANNELS) { - printk(KERN_ERR "%s: bad DMA identifier\n", __func__); - return; - } - - if (!dma_chan[i].device) { - printk(KERN_ERR "%s: Trying to free free DMA\n", __func__); - return; - } - - regs->ClrDCSR = - (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB | - DCSR_IE | DCSR_ERROR | DCSR_RUN); - free_irq(IRQ_DMA0 + i, regs); - dma_chan[i].device = 0; -} - - -/** - * sa1100_start_dma - submit a data buffer for DMA - * @regs: identifier for the channel to use - * @dma_ptr: buffer physical (or bus) start address - * @size: buffer size - * - * This function hands the given data buffer to the hardware for DMA - * access. If another buffer is already in flight then this buffer - * will be queued so the DMA engine will switch to it automatically - * when the previous one is done. The DMA engine is actually toggling - * between two buffers so at most 2 successful calls can be made before - * one of them terminates and the callback function is called. - * - * The @regs identifier is provided by a successful call to - * sa1100_request_dma(). - * - * The @size must not be larger than %MAX_DMA_SIZE. If a given buffer - * is larger than that then it's the caller's responsibility to split - * it into smaller chunks and submit them separately. If this is the - * case then a @size of %CUT_DMA_SIZE is recommended to avoid ending - * up with too small chunks. The callback function can be used to chain - * submissions of buffer chunks. - * - * Error return values: - * %-EOVERFLOW: Given buffer size is too big. - * %-EBUSY: Both DMA buffers are already in use. - * %-EAGAIN: Both buffers were busy but one of them just completed - * but the interrupt handler has to execute first. - * - * This function returs 0 on success. - **/ - -int sa1100_start_dma(dma_regs_t *regs, dma_addr_t dma_ptr, u_int size) -{ - unsigned long flags; - u_long status; - int ret; - - if (dma_ptr & 3) - printk(KERN_WARNING "DMA: unaligned start address (0x%08lx)\n", - (unsigned long)dma_ptr); - - if (size > MAX_DMA_SIZE) - return -EOVERFLOW; - - local_irq_save(flags); - status = regs->RdDCSR; - - /* If both DMA buffers are started, there's nothing else we can do. */ - if ((status & (DCSR_STRTA | DCSR_STRTB)) == (DCSR_STRTA | DCSR_STRTB)) { - DPRINTK("start: st %#x busy\n", status); - ret = -EBUSY; - goto out; - } - - if (((status & DCSR_BIU) && (status & DCSR_STRTB)) || - (!(status & DCSR_BIU) && !(status & DCSR_STRTA))) { - if (status & DCSR_DONEA) { - /* give a chance for the interrupt to be processed */ - ret = -EAGAIN; - goto out; - } - regs->DBSA = dma_ptr; - regs->DBTA = size; - regs->SetDCSR = DCSR_STRTA | DCSR_IE | DCSR_RUN; - DPRINTK("start a=%#x s=%d on A\n", dma_ptr, size); - } else { - if (status & DCSR_DONEB) { - /* give a chance for the interrupt to be processed */ - ret = -EAGAIN; - goto out; - } - regs->DBSB = dma_ptr; - regs->DBTB = size; - regs->SetDCSR = DCSR_STRTB | DCSR_IE | DCSR_RUN; - DPRINTK("start a=%#x s=%d on B\n", dma_ptr, size); - } - ret = 0; - -out: - local_irq_restore(flags); - return ret; -} - - -/** - * sa1100_get_dma_pos - return current DMA position - * @regs: identifier for the channel to use - * - * This function returns the current physical (or bus) address for the - * given DMA channel. If the channel is running i.e. not in a stopped - * state then the caller must disable interrupts prior calling this - * function and process the returned value before re-enabling them to - * prevent races with the completion interrupt handler and the callback - * function. The validation of the returned value is the caller's - * responsibility as well -- the hardware seems to return out of range - * values when the DMA engine completes a buffer. - * - * The @regs identifier is provided by a successful call to - * sa1100_request_dma(). - **/ - -dma_addr_t sa1100_get_dma_pos(dma_regs_t *regs) -{ - int status; - - /* - * We must determine whether buffer A or B is active. - * Two possibilities: either we are in the middle of - * a buffer, or the DMA controller just switched to the - * next toggle but the interrupt hasn't been serviced yet. - * The former case is straight forward. In the later case, - * we'll do like if DMA is just at the end of the previous - * toggle since all registers haven't been reset yet. - * This goes around the edge case and since we're always - * a little behind anyways it shouldn't make a big difference. - * If DMA has been stopped prior calling this then the - * position is exact. - */ - status = regs->RdDCSR; - if ((!(status & DCSR_BIU) && (status & DCSR_STRTA)) || - ( (status & DCSR_BIU) && !(status & DCSR_STRTB))) - return regs->DBSA; - else - return regs->DBSB; -} - - -/** - * sa1100_reset_dma - reset a DMA channel - * @regs: identifier for the channel to use - * - * This function resets and reconfigure the given DMA channel. This is - * particularly useful after a sleep/wakeup event. - * - * The @regs identifier is provided by a successful call to - * sa1100_request_dma(). - **/ - -void sa1100_reset_dma(dma_regs_t *regs) -{ - int i; - - for (i = 0; i < SA1100_DMA_CHANNELS; i++) - if (regs == (dma_regs_t *)&DDAR(i)) - break; - if (i >= SA1100_DMA_CHANNELS) { - printk(KERN_ERR "%s: bad DMA identifier\n", __func__); - return; - } - - regs->ClrDCSR = - (DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB | - DCSR_IE | DCSR_ERROR | DCSR_RUN); - regs->DDAR = dma_chan[i].device; -} - - -EXPORT_SYMBOL(sa1100_request_dma); -EXPORT_SYMBOL(sa1100_free_dma); -EXPORT_SYMBOL(sa1100_start_dma); -EXPORT_SYMBOL(sa1100_get_dma_pos); -EXPORT_SYMBOL(sa1100_reset_dma); - diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c index bb10ee2cb89f..01a20ea35b53 100644 --- a/arch/arm/mach-sa1100/generic.c +++ b/arch/arm/mach-sa1100/generic.c @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/dma-mapping.h> #include <linux/pm.h> #include <linux/cpufreq.h> #include <linux/ioport.h> @@ -149,16 +150,8 @@ static void sa11x0_register_device(struct platform_device *dev, void *data) static struct resource sa11x0udc_resources[] = { - [0] = { - .start = __PREG(Ser0UDCCR), - .end = __PREG(Ser0UDCCR) + 0xffff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_Ser0UDC, - .end = IRQ_Ser0UDC, - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(__PREG(Ser0UDCCR), SZ_64K), + [1] = DEFINE_RES_IRQ(IRQ_Ser0UDC), }; static u64 sa11x0udc_dma_mask = 0xffffffffUL; @@ -175,16 +168,8 @@ static struct platform_device sa11x0udc_device = { }; static struct resource sa11x0uart1_resources[] = { - [0] = { - .start = __PREG(Ser1UTCR0), - .end = __PREG(Ser1UTCR0) + 0xffff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_Ser1UART, - .end = IRQ_Ser1UART, - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(__PREG(Ser1UTCR0), SZ_64K), + [1] = DEFINE_RES_IRQ(IRQ_Ser1UART), }; static struct platform_device sa11x0uart1_device = { @@ -195,16 +180,8 @@ static struct platform_device sa11x0uart1_device = { }; static struct resource sa11x0uart3_resources[] = { - [0] = { - .start = __PREG(Ser3UTCR0), - .end = __PREG(Ser3UTCR0) + 0xffff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_Ser3UART, - .end = IRQ_Ser3UART, - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(__PREG(Ser3UTCR0), SZ_64K), + [1] = DEFINE_RES_IRQ(IRQ_Ser3UART), }; static struct platform_device sa11x0uart3_device = { @@ -215,16 +192,8 @@ static struct platform_device sa11x0uart3_device = { }; static struct resource sa11x0mcp_resources[] = { - [0] = { - .start = __PREG(Ser4MCCR0), - .end = __PREG(Ser4MCCR0) + 0xffff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_Ser4MCP, - .end = IRQ_Ser4MCP, - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(__PREG(Ser4MCCR0), SZ_64K), + [1] = DEFINE_RES_IRQ(IRQ_Ser4MCP), }; static u64 sa11x0mcp_dma_mask = 0xffffffffUL; @@ -246,16 +215,8 @@ void sa11x0_register_mcp(struct mcp_plat_data *data) } static struct resource sa11x0ssp_resources[] = { - [0] = { - .start = 0x80070000, - .end = 0x8007ffff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_Ser4SSP, - .end = IRQ_Ser4SSP, - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(0x80070000, SZ_64K), + [1] = DEFINE_RES_IRQ(IRQ_Ser4SSP), }; static u64 sa11x0ssp_dma_mask = 0xffffffffUL; @@ -272,16 +233,8 @@ static struct platform_device sa11x0ssp_device = { }; static struct resource sa11x0fb_resources[] = { - [0] = { - .start = 0xb0100000, - .end = 0xb010ffff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_LCD, - .end = IRQ_LCD, - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(0xb0100000, SZ_64K), + [1] = DEFINE_RES_IRQ(IRQ_LCD), }; static struct platform_device sa11x0fb_device = { @@ -314,23 +267,10 @@ void sa11x0_register_mtd(struct flash_platform_data *flash, } static struct resource sa11x0ir_resources[] = { - { - .start = __PREG(Ser2UTCR0), - .end = __PREG(Ser2UTCR0) + 0x24 - 1, - .flags = IORESOURCE_MEM, - }, { - .start = __PREG(Ser2HSCR0), - .end = __PREG(Ser2HSCR0) + 0x1c - 1, - .flags = IORESOURCE_MEM, - }, { - .start = __PREG(Ser2HSCR2), - .end = __PREG(Ser2HSCR2) + 0x04 - 1, - .flags = IORESOURCE_MEM, - }, { - .start = IRQ_Ser2ICP, - .end = IRQ_Ser2ICP, - .flags = IORESOURCE_IRQ, - } + DEFINE_RES_MEM(__PREG(Ser2UTCR0), 0x24), + DEFINE_RES_MEM(__PREG(Ser2HSCR0), 0x1c), + DEFINE_RES_MEM(__PREG(Ser2HSCR2), 0x04), + DEFINE_RES_IRQ(IRQ_Ser2ICP), }; static struct platform_device sa11x0ir_device = { @@ -350,6 +290,29 @@ static struct platform_device sa11x0rtc_device = { .id = -1, }; +static struct resource sa11x0dma_resources[] = { + DEFINE_RES_MEM(DMA_PHYS, DMA_SIZE), + DEFINE_RES_IRQ(IRQ_DMA0), + DEFINE_RES_IRQ(IRQ_DMA1), + DEFINE_RES_IRQ(IRQ_DMA2), + DEFINE_RES_IRQ(IRQ_DMA3), + DEFINE_RES_IRQ(IRQ_DMA4), + DEFINE_RES_IRQ(IRQ_DMA5), +}; + +static u64 sa11x0dma_dma_mask = DMA_BIT_MASK(32); + +static struct platform_device sa11x0dma_device = { + .name = "sa11x0-dma", + .id = -1, + .dev = { + .dma_mask = &sa11x0dma_dma_mask, + .coherent_dma_mask = 0xffffffff, + }, + .num_resources = ARRAY_SIZE(sa11x0dma_resources), + .resource = sa11x0dma_resources, +}; + static struct platform_device *sa11x0_devices[] __initdata = { &sa11x0udc_device, &sa11x0uart1_device, @@ -358,6 +321,7 @@ static struct platform_device *sa11x0_devices[] __initdata = { &sa11x0pcmcia_device, &sa11x0fb_device, &sa11x0rtc_device, + &sa11x0dma_device, }; static int __init sa1100_init(void) @@ -428,7 +392,7 @@ void __init sa1100_map_io(void) * the MBGNT signal false to ensure the SA1111 doesn't own the * SDRAM bus. */ -void __init sa1110_mb_disable(void) +void sa1110_mb_disable(void) { unsigned long flags; @@ -447,7 +411,7 @@ void __init sa1110_mb_disable(void) * If the system is going to use the SA-1111 DMA engines, set up * the memory bus request/grant pins. */ -void __devinit sa1110_mb_enable(void) +void sa1110_mb_enable(void) { unsigned long flags; diff --git a/arch/arm/mach-sa1100/h3xxx.c b/arch/arm/mach-sa1100/h3xxx.c index b0784c974c2d..63150e1ffe9e 100644 --- a/arch/arm/mach-sa1100/h3xxx.c +++ b/arch/arm/mach-sa1100/h3xxx.c @@ -109,11 +109,8 @@ static struct flash_platform_data h3xxx_flash_data = { .nr_parts = ARRAY_SIZE(h3xxx_partitions), }; -static struct resource h3xxx_flash_resource = { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_32M - 1, - .flags = IORESOURCE_MEM, -}; +static struct resource h3xxx_flash_resource = + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M); /* @@ -186,11 +183,7 @@ static struct sa1100_port_fns h3xxx_port_fns __initdata = { */ static struct resource egpio_resources[] = { - [0] = { - .start = H3600_EGPIO_PHYS, - .end = H3600_EGPIO_PHYS + 0x4 - 1, - .flags = IORESOURCE_MEM, - }, + [0] = DEFINE_RES_MEM(H3600_EGPIO_PHYS, 0x4), }; static struct htc_egpio_chip egpio_chips[] = { diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c index c01bb36db940..37d381ad5464 100644 --- a/arch/arm/mach-sa1100/hackkit.c +++ b/arch/arm/mach-sa1100/hackkit.c @@ -179,11 +179,8 @@ static struct flash_platform_data hackkit_flash_data = { .nr_parts = ARRAY_SIZE(hackkit_partitions), }; -static struct resource hackkit_flash_resource = { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_32M, - .flags = IORESOURCE_MEM, -}; +static struct resource hackkit_flash_resource = + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M); static void __init hackkit_init(void) { diff --git a/arch/arm/mach-sa1100/include/mach/SA-1100.h b/arch/arm/mach-sa1100/include/mach/SA-1100.h index bae8296f5dbf..335a1ff21faf 100644 --- a/arch/arm/mach-sa1100/include/mach/SA-1100.h +++ b/arch/arm/mach-sa1100/include/mach/SA-1100.h @@ -1590,224 +1590,9 @@ /* * Direct Memory Access (DMA) control registers - * - * Registers - * DDAR0 Direct Memory Access (DMA) Device Address Register - * channel 0 (read/write). - * DCSR0 Direct Memory Access (DMA) Control and Status - * Register channel 0 (read/write). - * DBSA0 Direct Memory Access (DMA) Buffer Start address - * register A channel 0 (read/write). - * DBTA0 Direct Memory Access (DMA) Buffer Transfer count - * register A channel 0 (read/write). - * DBSB0 Direct Memory Access (DMA) Buffer Start address - * register B channel 0 (read/write). - * DBTB0 Direct Memory Access (DMA) Buffer Transfer count - * register B channel 0 (read/write). - * - * DDAR1 Direct Memory Access (DMA) Device Address Register - * channel 1 (read/write). - * DCSR1 Direct Memory Access (DMA) Control and Status - * Register channel 1 (read/write). - * DBSA1 Direct Memory Access (DMA) Buffer Start address - * register A channel 1 (read/write). - * DBTA1 Direct Memory Access (DMA) Buffer Transfer count - * register A channel 1 (read/write). - * DBSB1 Direct Memory Access (DMA) Buffer Start address - * register B channel 1 (read/write). - * DBTB1 Direct Memory Access (DMA) Buffer Transfer count - * register B channel 1 (read/write). - * - * DDAR2 Direct Memory Access (DMA) Device Address Register - * channel 2 (read/write). - * DCSR2 Direct Memory Access (DMA) Control and Status - * Register channel 2 (read/write). - * DBSA2 Direct Memory Access (DMA) Buffer Start address - * register A channel 2 (read/write). - * DBTA2 Direct Memory Access (DMA) Buffer Transfer count - * register A channel 2 (read/write). - * DBSB2 Direct Memory Access (DMA) Buffer Start address - * register B channel 2 (read/write). - * DBTB2 Direct Memory Access (DMA) Buffer Transfer count - * register B channel 2 (read/write). - * - * DDAR3 Direct Memory Access (DMA) Device Address Register - * channel 3 (read/write). - * DCSR3 Direct Memory Access (DMA) Control and Status - * Register channel 3 (read/write). - * DBSA3 Direct Memory Access (DMA) Buffer Start address - * register A channel 3 (read/write). - * DBTA3 Direct Memory Access (DMA) Buffer Transfer count - * register A channel 3 (read/write). - * DBSB3 Direct Memory Access (DMA) Buffer Start address - * register B channel 3 (read/write). - * DBTB3 Direct Memory Access (DMA) Buffer Transfer count - * register B channel 3 (read/write). - * - * DDAR4 Direct Memory Access (DMA) Device Address Register - * channel 4 (read/write). - * DCSR4 Direct Memory Access (DMA) Control and Status - * Register channel 4 (read/write). - * DBSA4 Direct Memory Access (DMA) Buffer Start address - * register A channel 4 (read/write). - * DBTA4 Direct Memory Access (DMA) Buffer Transfer count - * register A channel 4 (read/write). - * DBSB4 Direct Memory Access (DMA) Buffer Start address - * register B channel 4 (read/write). - * DBTB4 Direct Memory Access (DMA) Buffer Transfer count - * register B channel 4 (read/write). - * - * DDAR5 Direct Memory Access (DMA) Device Address Register - * channel 5 (read/write). - * DCSR5 Direct Memory Access (DMA) Control and Status - * Register channel 5 (read/write). - * DBSA5 Direct Memory Access (DMA) Buffer Start address - * register A channel 5 (read/write). - * DBTA5 Direct Memory Access (DMA) Buffer Transfer count - * register A channel 5 (read/write). - * DBSB5 Direct Memory Access (DMA) Buffer Start address - * register B channel 5 (read/write). - * DBTB5 Direct Memory Access (DMA) Buffer Transfer count - * register B channel 5 (read/write). */ - -#define DMASp 0x00000020 /* DMA control reg. Space [byte] */ - -#define DDAR(Nb) __REG(0xB0000000 + (Nb)*DMASp) /* DMA Device Address Reg. channel [0..5] */ -#define SetDCSR(Nb) __REG(0xB0000004 + (Nb)*DMASp) /* Set DMA Control & Status Reg. channel [0..5] (write) */ -#define ClrDCSR(Nb) __REG(0xB0000008 + (Nb)*DMASp) /* Clear DMA Control & Status Reg. channel [0..5] (write) */ -#define RdDCSR(Nb) __REG(0xB000000C + (Nb)*DMASp) /* Read DMA Control & Status Reg. channel [0..5] (read) */ -#define DBSA(Nb) __REG(0xB0000010 + (Nb)*DMASp) /* DMA Buffer Start address reg. A channel [0..5] */ -#define DBTA(Nb) __REG(0xB0000014 + (Nb)*DMASp) /* DMA Buffer Transfer count reg. A channel [0..5] */ -#define DBSB(Nb) __REG(0xB0000018 + (Nb)*DMASp) /* DMA Buffer Start address reg. B channel [0..5] */ -#define DBTB(Nb) __REG(0xB000001C + (Nb)*DMASp) /* DMA Buffer Transfer count reg. B channel [0..5] */ - -#define DDAR_RW 0x00000001 /* device data Read/Write */ -#define DDAR_DevWr (DDAR_RW*0) /* Device data Write */ - /* (memory -> device) */ -#define DDAR_DevRd (DDAR_RW*1) /* Device data Read */ - /* (device -> memory) */ -#define DDAR_E 0x00000002 /* big/little Endian device */ -#define DDAR_LtlEnd (DDAR_E*0) /* Little Endian device */ -#define DDAR_BigEnd (DDAR_E*1) /* Big Endian device */ -#define DDAR_BS 0x00000004 /* device Burst Size */ -#define DDAR_Brst4 (DDAR_BS*0) /* Burst-of-4 device */ -#define DDAR_Brst8 (DDAR_BS*1) /* Burst-of-8 device */ -#define DDAR_DW 0x00000008 /* device Data Width */ -#define DDAR_8BitDev (DDAR_DW*0) /* 8-Bit Device */ -#define DDAR_16BitDev (DDAR_DW*1) /* 16-Bit Device */ -#define DDAR_DS Fld (4, 4) /* Device Select */ -#define DDAR_Ser0UDCTr /* Ser. port 0 UDC Transmit */ \ - (0x0 << FShft (DDAR_DS)) -#define DDAR_Ser0UDCRc /* Ser. port 0 UDC Receive */ \ - (0x1 << FShft (DDAR_DS)) -#define DDAR_Ser1SDLCTr /* Ser. port 1 SDLC Transmit */ \ - (0x2 << FShft (DDAR_DS)) -#define DDAR_Ser1SDLCRc /* Ser. port 1 SDLC Receive */ \ - (0x3 << FShft (DDAR_DS)) -#define DDAR_Ser1UARTTr /* Ser. port 1 UART Transmit */ \ - (0x4 << FShft (DDAR_DS)) -#define DDAR_Ser1UARTRc /* Ser. port 1 UART Receive */ \ - (0x5 << FShft (DDAR_DS)) -#define DDAR_Ser2ICPTr /* Ser. port 2 ICP Transmit */ \ - (0x6 << FShft (DDAR_DS)) -#define DDAR_Ser2ICPRc /* Ser. port 2 ICP Receive */ \ - (0x7 << FShft (DDAR_DS)) -#define DDAR_Ser3UARTTr /* Ser. port 3 UART Transmit */ \ - (0x8 << FShft (DDAR_DS)) -#define DDAR_Ser3UARTRc /* Ser. port 3 UART Receive */ \ - (0x9 << FShft (DDAR_DS)) -#define DDAR_Ser4MCP0Tr /* Ser. port 4 MCP 0 Transmit */ \ - /* (audio) */ \ - (0xA << FShft (DDAR_DS)) -#define DDAR_Ser4MCP0Rc /* Ser. port 4 MCP 0 Receive */ \ - /* (audio) */ \ - (0xB << FShft (DDAR_DS)) -#define DDAR_Ser4MCP1Tr /* Ser. port 4 MCP 1 Transmit */ \ - /* (telecom) */ \ - (0xC << FShft (DDAR_DS)) -#define DDAR_Ser4MCP1Rc /* Ser. port 4 MCP 1 Receive */ \ - /* (telecom) */ \ - (0xD << FShft (DDAR_DS)) -#define DDAR_Ser4SSPTr /* Ser. port 4 SSP Transmit */ \ - (0xE << FShft (DDAR_DS)) -#define DDAR_Ser4SSPRc /* Ser. port 4 SSP Receive */ \ - (0xF << FShft (DDAR_DS)) -#define DDAR_DA Fld (24, 8) /* Device Address */ -#define DDAR_DevAdd(Add) /* Device Address */ \ - (((Add) & 0xF0000000) | \ - (((Add) & 0X003FFFFC) << (FShft (DDAR_DA) - 2))) -#define DDAR_Ser0UDCWr /* Ser. port 0 UDC Write */ \ - (DDAR_DevWr + DDAR_Brst8 + DDAR_8BitDev + \ - DDAR_Ser0UDCTr + DDAR_DevAdd (__PREG(Ser0UDCDR))) -#define DDAR_Ser0UDCRd /* Ser. port 0 UDC Read */ \ - (DDAR_DevRd + DDAR_Brst8 + DDAR_8BitDev + \ - DDAR_Ser0UDCRc + DDAR_DevAdd (__PREG(Ser0UDCDR))) -#define DDAR_Ser1UARTWr /* Ser. port 1 UART Write */ \ - (DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \ - DDAR_Ser1UARTTr + DDAR_DevAdd (__PREG(Ser1UTDR))) -#define DDAR_Ser1UARTRd /* Ser. port 1 UART Read */ \ - (DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \ - DDAR_Ser1UARTRc + DDAR_DevAdd (__PREG(Ser1UTDR))) -#define DDAR_Ser1SDLCWr /* Ser. port 1 SDLC Write */ \ - (DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \ - DDAR_Ser1SDLCTr + DDAR_DevAdd (__PREG(Ser1SDDR))) -#define DDAR_Ser1SDLCRd /* Ser. port 1 SDLC Read */ \ - (DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \ - DDAR_Ser1SDLCRc + DDAR_DevAdd (__PREG(Ser1SDDR))) -#define DDAR_Ser2UARTWr /* Ser. port 2 UART Write */ \ - (DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \ - DDAR_Ser2ICPTr + DDAR_DevAdd (__PREG(Ser2UTDR))) -#define DDAR_Ser2UARTRd /* Ser. port 2 UART Read */ \ - (DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \ - DDAR_Ser2ICPRc + DDAR_DevAdd (__PREG(Ser2UTDR))) -#define DDAR_Ser2HSSPWr /* Ser. port 2 HSSP Write */ \ - (DDAR_DevWr + DDAR_Brst8 + DDAR_8BitDev + \ - DDAR_Ser2ICPTr + DDAR_DevAdd (__PREG(Ser2HSDR))) -#define DDAR_Ser2HSSPRd /* Ser. port 2 HSSP Read */ \ - (DDAR_DevRd + DDAR_Brst8 + DDAR_8BitDev + \ - DDAR_Ser2ICPRc + DDAR_DevAdd (__PREG(Ser2HSDR))) -#define DDAR_Ser3UARTWr /* Ser. port 3 UART Write */ \ - (DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \ - DDAR_Ser3UARTTr + DDAR_DevAdd (__PREG(Ser3UTDR))) -#define DDAR_Ser3UARTRd /* Ser. port 3 UART Read */ \ - (DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \ - DDAR_Ser3UARTRc + DDAR_DevAdd (__PREG(Ser3UTDR))) -#define DDAR_Ser4MCP0Wr /* Ser. port 4 MCP 0 Write (audio) */ \ - (DDAR_DevWr + DDAR_Brst4 + DDAR_16BitDev + \ - DDAR_Ser4MCP0Tr + DDAR_DevAdd (__PREG(Ser4MCDR0))) -#define DDAR_Ser4MCP0Rd /* Ser. port 4 MCP 0 Read (audio) */ \ - (DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \ - DDAR_Ser4MCP0Rc + DDAR_DevAdd (__PREG(Ser4MCDR0))) -#define DDAR_Ser4MCP1Wr /* Ser. port 4 MCP 1 Write */ \ - /* (telecom) */ \ - (DDAR_DevWr + DDAR_Brst4 + DDAR_16BitDev + \ - DDAR_Ser4MCP1Tr + DDAR_DevAdd (__PREG(Ser4MCDR1))) -#define DDAR_Ser4MCP1Rd /* Ser. port 4 MCP 1 Read */ \ - /* (telecom) */ \ - (DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \ - DDAR_Ser4MCP1Rc + DDAR_DevAdd (__PREG(Ser4MCDR1))) -#define DDAR_Ser4SSPWr /* Ser. port 4 SSP Write (16 bits) */ \ - (DDAR_DevWr + DDAR_Brst4 + DDAR_16BitDev + \ - DDAR_Ser4SSPTr + DDAR_DevAdd (__PREG(Ser4SSDR))) -#define DDAR_Ser4SSPRd /* Ser. port 4 SSP Read (16 bits) */ \ - (DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \ - DDAR_Ser4SSPRc + DDAR_DevAdd (__PREG(Ser4SSDR))) - -#define DCSR_RUN 0x00000001 /* DMA running */ -#define DCSR_IE 0x00000002 /* DMA Interrupt Enable */ -#define DCSR_ERROR 0x00000004 /* DMA ERROR */ -#define DCSR_DONEA 0x00000008 /* DONE DMA transfer buffer A */ -#define DCSR_STRTA 0x00000010 /* STaRTed DMA transfer buffer A */ -#define DCSR_DONEB 0x00000020 /* DONE DMA transfer buffer B */ -#define DCSR_STRTB 0x00000040 /* STaRTed DMA transfer buffer B */ -#define DCSR_BIU 0x00000080 /* DMA Buffer In Use */ -#define DCSR_BufA (DCSR_BIU*0) /* DMA Buffer A in use */ -#define DCSR_BufB (DCSR_BIU*1) /* DMA Buffer B in use */ - -#define DBT_TC Fld (13, 0) /* Transfer Count */ -#define DBTA_TCA DBT_TC /* Transfer Count buffer A */ -#define DBTB_TCB DBT_TC /* Transfer Count buffer B */ +#define DMA_SIZE (6 * 0x20) +#define DMA_PHYS 0xb0000000 /* diff --git a/arch/arm/mach-sa1100/include/mach/dma.h b/arch/arm/mach-sa1100/include/mach/dma.h deleted file mode 100644 index dda1b351310d..000000000000 --- a/arch/arm/mach-sa1100/include/mach/dma.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * arch/arm/mach-sa1100/include/mach/dma.h - * - * Generic SA1100 DMA support - * - * Copyright (C) 2000 Nicolas Pitre - * - */ - -#ifndef __ASM_ARCH_DMA_H -#define __ASM_ARCH_DMA_H - -#include "hardware.h" - - -/* - * The SA1100 has six internal DMA channels. - */ -#define SA1100_DMA_CHANNELS 6 - -/* - * Maximum physical DMA buffer size - */ -#define MAX_DMA_SIZE 0x1fff -#define CUT_DMA_SIZE 0x1000 - -/* - * All possible SA1100 devices a DMA channel can be attached to. - */ -typedef enum { - DMA_Ser0UDCWr = DDAR_Ser0UDCWr, /* Ser. port 0 UDC Write */ - DMA_Ser0UDCRd = DDAR_Ser0UDCRd, /* Ser. port 0 UDC Read */ - DMA_Ser1UARTWr = DDAR_Ser1UARTWr, /* Ser. port 1 UART Write */ - DMA_Ser1UARTRd = DDAR_Ser1UARTRd, /* Ser. port 1 UART Read */ - DMA_Ser1SDLCWr = DDAR_Ser1SDLCWr, /* Ser. port 1 SDLC Write */ - DMA_Ser1SDLCRd = DDAR_Ser1SDLCRd, /* Ser. port 1 SDLC Read */ - DMA_Ser2UARTWr = DDAR_Ser2UARTWr, /* Ser. port 2 UART Write */ - DMA_Ser2UARTRd = DDAR_Ser2UARTRd, /* Ser. port 2 UART Read */ - DMA_Ser2HSSPWr = DDAR_Ser2HSSPWr, /* Ser. port 2 HSSP Write */ - DMA_Ser2HSSPRd = DDAR_Ser2HSSPRd, /* Ser. port 2 HSSP Read */ - DMA_Ser3UARTWr = DDAR_Ser3UARTWr, /* Ser. port 3 UART Write */ - DMA_Ser3UARTRd = DDAR_Ser3UARTRd, /* Ser. port 3 UART Read */ - DMA_Ser4MCP0Wr = DDAR_Ser4MCP0Wr, /* Ser. port 4 MCP 0 Write (audio) */ - DMA_Ser4MCP0Rd = DDAR_Ser4MCP0Rd, /* Ser. port 4 MCP 0 Read (audio) */ - DMA_Ser4MCP1Wr = DDAR_Ser4MCP1Wr, /* Ser. port 4 MCP 1 Write */ - DMA_Ser4MCP1Rd = DDAR_Ser4MCP1Rd, /* Ser. port 4 MCP 1 Read */ - DMA_Ser4SSPWr = DDAR_Ser4SSPWr, /* Ser. port 4 SSP Write (16 bits) */ - DMA_Ser4SSPRd = DDAR_Ser4SSPRd /* Ser. port 4 SSP Read (16 bits) */ -} dma_device_t; - -typedef struct { - volatile u_long DDAR; - volatile u_long SetDCSR; - volatile u_long ClrDCSR; - volatile u_long RdDCSR; - volatile dma_addr_t DBSA; - volatile u_long DBTA; - volatile dma_addr_t DBSB; - volatile u_long DBTB; -} dma_regs_t; - -typedef void (*dma_callback_t)(void *data); - -/* - * DMA function prototypes - */ - -extern int sa1100_request_dma( dma_device_t device, const char *device_id, - dma_callback_t callback, void *data, - dma_regs_t **regs ); -extern void sa1100_free_dma( dma_regs_t *regs ); -extern int sa1100_start_dma( dma_regs_t *regs, dma_addr_t dma_ptr, u_int size ); -extern dma_addr_t sa1100_get_dma_pos(dma_regs_t *regs); -extern void sa1100_reset_dma(dma_regs_t *regs); - -/** - * sa1100_stop_dma - stop DMA in progress - * @regs: identifier for the channel to use - * - * This stops DMA without clearing buffer pointers. Unlike - * sa1100_clear_dma() this allows subsequent use of sa1100_resume_dma() - * or sa1100_get_dma_pos(). - * - * The @regs identifier is provided by a successful call to - * sa1100_request_dma(). - **/ - -#define sa1100_stop_dma(regs) ((regs)->ClrDCSR = DCSR_IE|DCSR_RUN) - -/** - * sa1100_resume_dma - resume DMA on a stopped channel - * @regs: identifier for the channel to use - * - * This resumes DMA on a channel previously stopped with - * sa1100_stop_dma(). - * - * The @regs identifier is provided by a successful call to - * sa1100_request_dma(). - **/ - -#define sa1100_resume_dma(regs) ((regs)->SetDCSR = DCSR_IE|DCSR_RUN) - -/** - * sa1100_clear_dma - clear DMA pointers - * @regs: identifier for the channel to use - * - * This clear any DMA state so the DMA engine is ready to restart - * with new buffers through sa1100_start_dma(). Any buffers in flight - * are discarded. - * - * The @regs identifier is provided by a successful call to - * sa1100_request_dma(). - **/ - -#define sa1100_clear_dma(regs) ((regs)->ClrDCSR = DCSR_IE|DCSR_RUN|DCSR_STRTA|DCSR_STRTB) - -#endif /* _ASM_ARCH_DMA_H */ diff --git a/arch/arm/mach-sa1100/include/mach/irqs.h b/arch/arm/mach-sa1100/include/mach/irqs.h index d18f21abef80..9e07634a4670 100644 --- a/arch/arm/mach-sa1100/include/mach/irqs.h +++ b/arch/arm/mach-sa1100/include/mach/irqs.h @@ -82,11 +82,3 @@ #else #define NR_IRQS (IRQ_BOARD_START) #endif - -/* - * Board specific IRQs. Define them here. - * Do not surround them with ifdefs. - */ -#define IRQ_NEPONSET_SMC9196 (IRQ_BOARD_START + 0) -#define IRQ_NEPONSET_USAR (IRQ_BOARD_START + 1) -#define IRQ_NEPONSET_SA1111 (IRQ_BOARD_START + 2) diff --git a/arch/arm/mach-sa1100/include/mach/neponset.h b/arch/arm/mach-sa1100/include/mach/neponset.h index ffe2bc45eed0..5516a52a329d 100644 --- a/arch/arm/mach-sa1100/include/mach/neponset.h +++ b/arch/arm/mach-sa1100/include/mach/neponset.h @@ -15,54 +15,6 @@ /* * Neponset definitions: */ - -#define NEPONSET_CPLD_BASE (0x10000000) -#define Nep_p2v( x ) ((x) - NEPONSET_CPLD_BASE + 0xf3000000) -#define Nep_v2p( x ) ((x) - 0xf3000000 + NEPONSET_CPLD_BASE) - -#define _IRR 0x10000024 /* Interrupt Reason Register */ -#define _AUD_CTL 0x100000c0 /* Audio controls (RW) */ -#define _MDM_CTL_0 0x100000b0 /* Modem control 0 (RW) */ -#define _MDM_CTL_1 0x100000b4 /* Modem control 1 (RW) */ -#define _NCR_0 0x100000a0 /* Control Register (RW) */ -#define _KP_X_OUT 0x10000090 /* Keypad row write (RW) */ -#define _KP_Y_IN 0x10000080 /* Keypad column read (RO) */ -#define _SWPK 0x10000020 /* Switch pack (RO) */ -#define _WHOAMI 0x10000000 /* System ID Register (RO) */ - -#define _LEDS 0x10000010 /* LEDs [31:0] (WO) */ - -#define IRR (*((volatile u_char *) Nep_p2v(_IRR))) -#define AUD_CTL (*((volatile u_char *) Nep_p2v(_AUD_CTL))) -#define MDM_CTL_0 (*((volatile u_char *) Nep_p2v(_MDM_CTL_0))) -#define MDM_CTL_1 (*((volatile u_char *) Nep_p2v(_MDM_CTL_1))) -#define NCR_0 (*((volatile u_char *) Nep_p2v(_NCR_0))) -#define KP_X_OUT (*((volatile u_char *) Nep_p2v(_KP_X_OUT))) -#define KP_Y_IN (*((volatile u_char *) Nep_p2v(_KP_Y_IN))) -#define SWPK (*((volatile u_char *) Nep_p2v(_SWPK))) -#define WHOAMI (*((volatile u_char *) Nep_p2v(_WHOAMI))) - -#define LEDS (*((volatile Word *) Nep_p2v(_LEDS))) - -#define IRR_ETHERNET (1<<0) -#define IRR_USAR (1<<1) -#define IRR_SA1111 (1<<2) - -#define AUD_SEL_1341 (1<<0) -#define AUD_MUTE_1341 (1<<1) - -#define MDM_CTL0_RTS1 (1 << 0) -#define MDM_CTL0_DTR1 (1 << 1) -#define MDM_CTL0_RTS2 (1 << 2) -#define MDM_CTL0_DTR2 (1 << 3) - -#define MDM_CTL1_CTS1 (1 << 0) -#define MDM_CTL1_DSR1 (1 << 1) -#define MDM_CTL1_DCD1 (1 << 2) -#define MDM_CTL1_CTS2 (1 << 3) -#define MDM_CTL1_DSR2 (1 << 4) -#define MDM_CTL1_DCD2 (1 << 5) - #define NCR_GP01_OFF (1<<0) #define NCR_TP_PWR_EN (1<<1) #define NCR_MS_PWR_EN (1<<2) @@ -71,4 +23,8 @@ #define NCR_A0VPP (1<<5) #define NCR_A1VPP (1<<6) +void neponset_ncr_frob(unsigned int, unsigned int); +#define neponset_ncr_set(v) neponset_ncr_frob(0, v) +#define neponset_ncr_clear(v) neponset_ncr_frob(v, 0) + #endif diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c index dfbf824a69fa..5d12a305f53e 100644 --- a/arch/arm/mach-sa1100/irq.c +++ b/arch/arm/mach-sa1100/irq.c @@ -221,11 +221,8 @@ static struct irq_chip sa1100_normal_chip = { .irq_set_wake = sa1100_set_wake, }; -static struct resource irq_resource = { - .name = "irqs", - .start = 0x90050000, - .end = 0x9005ffff, -}; +static struct resource irq_resource = + DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs"); static struct sa1100irq_state { unsigned int saved; diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c index ee121d6f0480..8be8130baf63 100644 --- a/arch/arm/mach-sa1100/jornada720.c +++ b/arch/arm/mach-sa1100/jornada720.c @@ -46,7 +46,7 @@ /* memory space (line 52 of HP's doc) */ #define SA1111REGSTART 0x40000000 -#define SA1111REGLEN 0x00001fff +#define SA1111REGLEN 0x00002000 #define EPSONREGSTART 0x48000000 #define EPSONREGLEN 0x00100000 #define EPSONFBSTART 0x48200000 @@ -174,16 +174,8 @@ static struct s1d13xxxfb_pdata s1d13xxxfb_data = { }; static struct resource s1d13xxxfb_resources[] = { - [0] = { - .start = EPSONFBSTART, - .end = EPSONFBSTART + EPSONFBLEN, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = EPSONREGSTART, - .end = EPSONREGSTART + EPSONREGLEN, - .flags = IORESOURCE_MEM, - } + [0] = DEFINE_RES_MEM(EPSONFBSTART, EPSONFBLEN), + [1] = DEFINE_RES_MEM(EPSONREGSTART, EPSONREGLEN), }; static struct platform_device s1d13xxxfb_device = { @@ -197,20 +189,13 @@ static struct platform_device s1d13xxxfb_device = { }; static struct resource sa1111_resources[] = { - [0] = { - .start = SA1111REGSTART, - .end = SA1111REGSTART + SA1111REGLEN, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_GPIO1, - .end = IRQ_GPIO1, - .flags = IORESOURCE_IRQ, - }, + [0] = DEFINE_RES_MEM(SA1111REGSTART, SA1111REGLEN), + [1] = DEFINE_RES_IRQ(IRQ_GPIO1), }; static struct sa1111_platform_data sa1111_info = { .irq_base = IRQ_BOARD_END, + .disable_devs = SA1111_DEVID_PS2_MSE, }; static u64 sa1111_dmamask = 0xffffffffUL; @@ -284,11 +269,6 @@ static struct map_desc jornada720_io_desc[] __initdata = { .pfn = __phys_to_pfn(EPSONFBSTART), .length = EPSONFBLEN, .type = MT_DEVICE - }, { /* SA-1111 */ - .virtual = 0xf4000000, - .pfn = __phys_to_pfn(SA1111REGSTART), - .length = SA1111REGLEN, - .type = MT_DEVICE } }; @@ -352,11 +332,8 @@ static struct flash_platform_data jornada720_flash_data = { .nr_parts = ARRAY_SIZE(jornada720_partitions), }; -static struct resource jornada720_flash_resource = { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_32M - 1, - .flags = IORESOURCE_MEM, -}; +static struct resource jornada720_flash_resource = + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M); static void __init jornada720_mach_init(void) { diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c index 85f6ee672225..3923911000de 100644 --- a/arch/arm/mach-sa1100/nanoengine.c +++ b/arch/arm/mach-sa1100/nanoengine.c @@ -58,15 +58,8 @@ static struct flash_platform_data nanoengine_flash_data = { }; static struct resource nanoengine_flash_resources[] = { - { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_32M - 1, - .flags = IORESOURCE_MEM, - }, { - .start = SA1100_CS1_PHYS, - .end = SA1100_CS1_PHYS + SZ_32M - 1, - .flags = IORESOURCE_MEM, - } + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M), + DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_32M), }; static struct map_desc nanoengine_io_desc[] __initdata = { diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index b4fa53a1427e..3297aa22cd77 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -1,89 +1,103 @@ /* * linux/arch/arm/mach-sa1100/neponset.c - * */ -#include <linux/kernel.h> +#include <linux/err.h> #include <linux/init.h> -#include <linux/tty.h> #include <linux/ioport.h> -#include <linux/serial_core.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/serial_core.h> +#include <linux/slab.h> -#include <mach/hardware.h> #include <asm/mach-types.h> -#include <asm/irq.h> #include <asm/mach/map.h> -#include <asm/mach/irq.h> #include <asm/mach/serial_sa1100.h> -#include <mach/assabet.h> -#include <mach/neponset.h> #include <asm/hardware/sa1111.h> #include <asm/sizes.h> -/* - * Install handler for Neponset IRQ. Note that we have to loop here - * since the ETHERNET and USAR IRQs are level based, and we need to - * ensure that the IRQ signal is deasserted before returning. This - * is rather unfortunate. - */ -static void -neponset_irq_handler(unsigned int irq, struct irq_desc *desc) -{ - unsigned int irr; - - while (1) { - /* - * Acknowledge the parent IRQ. - */ - desc->irq_data.chip->irq_ack(&desc->irq_data); - - /* - * Read the interrupt reason register. Let's have all - * active IRQ bits high. Note: there is a typo in the - * Neponset user's guide for the SA1111 IRR level. - */ - irr = IRR ^ (IRR_ETHERNET | IRR_USAR); - - if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0) - break; - - /* - * Since there is no individual mask, we have to - * mask the parent IRQ. This is safe, since we'll - * recheck the register for any pending IRQs. - */ - if (irr & (IRR_ETHERNET | IRR_USAR)) { - desc->irq_data.chip->irq_mask(&desc->irq_data); +#include <mach/hardware.h> +#include <mach/assabet.h> +#include <mach/neponset.h> - /* - * Ack the interrupt now to prevent re-entering - * this neponset handler. Again, this is safe - * since we'll check the IRR register prior to - * leaving. - */ - desc->irq_data.chip->irq_ack(&desc->irq_data); +#define NEP_IRQ_SMC91X 0 +#define NEP_IRQ_USAR 1 +#define NEP_IRQ_SA1111 2 +#define NEP_IRQ_NR 3 + +#define WHOAMI 0x00 +#define LEDS 0x10 +#define SWPK 0x20 +#define IRR 0x24 +#define KP_Y_IN 0x80 +#define KP_X_OUT 0x90 +#define NCR_0 0xa0 +#define MDM_CTL_0 0xb0 +#define MDM_CTL_1 0xb4 +#define AUD_CTL 0xc0 + +#define IRR_ETHERNET (1 << 0) +#define IRR_USAR (1 << 1) +#define IRR_SA1111 (1 << 2) + +#define MDM_CTL0_RTS1 (1 << 0) +#define MDM_CTL0_DTR1 (1 << 1) +#define MDM_CTL0_RTS2 (1 << 2) +#define MDM_CTL0_DTR2 (1 << 3) + +#define MDM_CTL1_CTS1 (1 << 0) +#define MDM_CTL1_DSR1 (1 << 1) +#define MDM_CTL1_DCD1 (1 << 2) +#define MDM_CTL1_CTS2 (1 << 3) +#define MDM_CTL1_DSR2 (1 << 4) +#define MDM_CTL1_DCD2 (1 << 5) + +#define AUD_SEL_1341 (1 << 0) +#define AUD_MUTE_1341 (1 << 1) - if (irr & IRR_ETHERNET) { - generic_handle_irq(IRQ_NEPONSET_SMC9196); - } +extern void sa1110_mb_disable(void); - if (irr & IRR_USAR) { - generic_handle_irq(IRQ_NEPONSET_USAR); - } +struct neponset_drvdata { + void __iomem *base; + struct platform_device *sa1111; + struct platform_device *smc91x; + unsigned irq_base; +#ifdef CONFIG_PM_SLEEP + u32 ncr0; + u32 mdm_ctl_0; +#endif +}; - desc->irq_data.chip->irq_unmask(&desc->irq_data); - } +static void __iomem *nep_base; - if (irr & IRR_SA1111) { - generic_handle_irq(IRQ_NEPONSET_SA1111); - } +void neponset_ncr_frob(unsigned int mask, unsigned int val) +{ + void __iomem *base = nep_base; + + if (base) { + unsigned long flags; + unsigned v; + + local_irq_save(flags); + v = readb_relaxed(base + NCR_0); + writeb_relaxed((v & ~mask) | val, base + NCR_0); + local_irq_restore(flags); + } else { + WARN(1, "nep_base unset\n"); } } static void neponset_set_mctrl(struct uart_port *port, u_int mctrl) { - u_int mdm_ctl0 = MDM_CTL_0; + void __iomem *base = nep_base; + u_int mdm_ctl0; + + if (!base) + return; + mdm_ctl0 = readb_relaxed(base + MDM_CTL_0); if (port->mapbase == _Ser1UTCR0) { if (mctrl & TIOCM_RTS) mdm_ctl0 &= ~MDM_CTL0_RTS2; @@ -106,14 +120,19 @@ static void neponset_set_mctrl(struct uart_port *port, u_int mctrl) mdm_ctl0 |= MDM_CTL0_DTR1; } - MDM_CTL_0 = mdm_ctl0; + writeb_relaxed(mdm_ctl0, base + MDM_CTL_0); } static u_int neponset_get_mctrl(struct uart_port *port) { + void __iomem *base = nep_base; u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; - u_int mdm_ctl1 = MDM_CTL_1; + u_int mdm_ctl1; + if (!base) + return ret; + + mdm_ctl1 = readb_relaxed(base + MDM_CTL_1); if (port->mapbase == _Ser1UTCR0) { if (mdm_ctl1 & MDM_CTL1_DCD2) ret &= ~TIOCM_CD; @@ -138,209 +157,279 @@ static struct sa1100_port_fns neponset_port_fns __devinitdata = { .get_mctrl = neponset_get_mctrl, }; -static int __devinit neponset_probe(struct platform_device *dev) +/* + * Install handler for Neponset IRQ. Note that we have to loop here + * since the ETHERNET and USAR IRQs are level based, and we need to + * ensure that the IRQ signal is deasserted before returning. This + * is rather unfortunate. + */ +static void neponset_irq_handler(unsigned int irq, struct irq_desc *desc) { - sa1100_register_uart_fns(&neponset_port_fns); + struct neponset_drvdata *d = irq_desc_get_handler_data(desc); + unsigned int irr; - /* - * Install handler for GPIO25. - */ - irq_set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING); - irq_set_chained_handler(IRQ_GPIO25, neponset_irq_handler); + while (1) { + /* + * Acknowledge the parent IRQ. + */ + desc->irq_data.chip->irq_ack(&desc->irq_data); - /* - * We would set IRQ_GPIO25 to be a wake-up IRQ, but - * unfortunately something on the Neponset activates - * this IRQ on sleep (ethernet?) - */ -#if 0 - enable_irq_wake(IRQ_GPIO25); -#endif + /* + * Read the interrupt reason register. Let's have all + * active IRQ bits high. Note: there is a typo in the + * Neponset user's guide for the SA1111 IRR level. + */ + irr = readb_relaxed(d->base + IRR); + irr ^= IRR_ETHERNET | IRR_USAR; - /* - * Setup other Neponset IRQs. SA1111 will be done by the - * generic SA1111 code. - */ - irq_set_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq); - set_irq_flags(IRQ_NEPONSET_SMC9196, IRQF_VALID | IRQF_PROBE); - irq_set_handler(IRQ_NEPONSET_USAR, handle_simple_irq); - set_irq_flags(IRQ_NEPONSET_USAR, IRQF_VALID | IRQF_PROBE); + if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0) + break; - /* - * Disable GPIO 0/1 drivers so the buttons work on the module. - */ - NCR_0 = NCR_GP01_OFF; + /* + * Since there is no individual mask, we have to + * mask the parent IRQ. This is safe, since we'll + * recheck the register for any pending IRQs. + */ + if (irr & (IRR_ETHERNET | IRR_USAR)) { + desc->irq_data.chip->irq_mask(&desc->irq_data); - return 0; -} + /* + * Ack the interrupt now to prevent re-entering + * this neponset handler. Again, this is safe + * since we'll check the IRR register prior to + * leaving. + */ + desc->irq_data.chip->irq_ack(&desc->irq_data); -#ifdef CONFIG_PM + if (irr & IRR_ETHERNET) + generic_handle_irq(d->irq_base + NEP_IRQ_SMC91X); -/* - * LDM power management. - */ -static unsigned int neponset_saved_state; + if (irr & IRR_USAR) + generic_handle_irq(d->irq_base + NEP_IRQ_USAR); -static int neponset_suspend(struct platform_device *dev, pm_message_t state) -{ - /* - * Save state. - */ - neponset_saved_state = NCR_0; + desc->irq_data.chip->irq_unmask(&desc->irq_data); + } - return 0; + if (irr & IRR_SA1111) + generic_handle_irq(d->irq_base + NEP_IRQ_SA1111); + } } -static int neponset_resume(struct platform_device *dev) +/* Yes, we really do not have any kind of masking or unmasking */ +static void nochip_noop(struct irq_data *irq) { - NCR_0 = neponset_saved_state; - - return 0; } -#else -#define neponset_suspend NULL -#define neponset_resume NULL -#endif - -static struct platform_driver neponset_device_driver = { - .probe = neponset_probe, - .suspend = neponset_suspend, - .resume = neponset_resume, - .driver = { - .name = "neponset", - }, -}; - -static struct resource neponset_resources[] = { - [0] = { - .start = 0x10000000, - .end = 0x17ffffff, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device neponset_device = { - .name = "neponset", - .id = 0, - .num_resources = ARRAY_SIZE(neponset_resources), - .resource = neponset_resources, -}; - -static struct resource sa1111_resources[] = { - [0] = { - .start = 0x40000000, - .end = 0x40001fff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_NEPONSET_SA1111, - .end = IRQ_NEPONSET_SA1111, - .flags = IORESOURCE_IRQ, - }, +static struct irq_chip nochip = { + .name = "neponset", + .irq_ack = nochip_noop, + .irq_mask = nochip_noop, + .irq_unmask = nochip_noop, }; static struct sa1111_platform_data sa1111_info = { .irq_base = IRQ_BOARD_END, + .disable_devs = SA1111_DEVID_PS2_MSE, }; -static u64 sa1111_dmamask = 0xffffffffUL; +static int __devinit neponset_probe(struct platform_device *dev) +{ + struct neponset_drvdata *d; + struct resource *nep_res, *sa1111_res, *smc91x_res; + struct resource sa1111_resources[] = { + DEFINE_RES_MEM(0x40000000, SZ_8K), + { .flags = IORESOURCE_IRQ }, + }; + struct platform_device_info sa1111_devinfo = { + .parent = &dev->dev, + .name = "sa1111", + .id = 0, + .res = sa1111_resources, + .num_res = ARRAY_SIZE(sa1111_resources), + .data = &sa1111_info, + .size_data = sizeof(sa1111_info), + .dma_mask = 0xffffffffUL, + }; + struct resource smc91x_resources[] = { + DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS, + 0x02000000, "smc91x-regs"), + DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS + 0x02000000, + 0x02000000, "smc91x-attrib"), + { .flags = IORESOURCE_IRQ }, + }; + struct platform_device_info smc91x_devinfo = { + .parent = &dev->dev, + .name = "smc91x", + .id = 0, + .res = smc91x_resources, + .num_res = ARRAY_SIZE(smc91x_resources), + }; + int ret, irq; + + if (nep_base) + return -EBUSY; + + irq = ret = platform_get_irq(dev, 0); + if (ret < 0) + goto err_alloc; + + nep_res = platform_get_resource(dev, IORESOURCE_MEM, 0); + smc91x_res = platform_get_resource(dev, IORESOURCE_MEM, 1); + sa1111_res = platform_get_resource(dev, IORESOURCE_MEM, 2); + if (!nep_res || !smc91x_res || !sa1111_res) { + ret = -ENXIO; + goto err_alloc; + } -static struct platform_device sa1111_device = { - .name = "sa1111", - .id = 0, - .dev = { - .dma_mask = &sa1111_dmamask, - .coherent_dma_mask = 0xffffffff, - .platform_data = &sa1111_info, - }, - .num_resources = ARRAY_SIZE(sa1111_resources), - .resource = sa1111_resources, -}; + d = kzalloc(sizeof(*d), GFP_KERNEL); + if (!d) { + ret = -ENOMEM; + goto err_alloc; + } -static struct resource smc91x_resources[] = { - [0] = { - .name = "smc91x-regs", - .start = SA1100_CS3_PHYS, - .end = SA1100_CS3_PHYS + 0x01ffffff, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_NEPONSET_SMC9196, - .end = IRQ_NEPONSET_SMC9196, - .flags = IORESOURCE_IRQ, - }, - [2] = { - .name = "smc91x-attrib", - .start = SA1100_CS3_PHYS + 0x02000000, - .end = SA1100_CS3_PHYS + 0x03ffffff, - .flags = IORESOURCE_MEM, - }, -}; + d->base = ioremap(nep_res->start, SZ_4K); + if (!d->base) { + ret = -ENOMEM; + goto err_ioremap; + } -static struct platform_device smc91x_device = { - .name = "smc91x", - .id = 0, - .num_resources = ARRAY_SIZE(smc91x_resources), - .resource = smc91x_resources, -}; + if (readb_relaxed(d->base + WHOAMI) != 0x11) { + dev_warn(&dev->dev, "Neponset board detected, but wrong ID: %02x\n", + readb_relaxed(d->base + WHOAMI)); + ret = -ENODEV; + goto err_id; + } -static struct platform_device *devices[] __initdata = { - &neponset_device, - &sa1111_device, - &smc91x_device, -}; + ret = irq_alloc_descs(-1, IRQ_BOARD_START, NEP_IRQ_NR, -1); + if (ret <= 0) { + dev_err(&dev->dev, "unable to allocate %u irqs: %d\n", + NEP_IRQ_NR, ret); + if (ret == 0) + ret = -ENOMEM; + goto err_irq_alloc; + } -extern void sa1110_mb_disable(void); + d->irq_base = ret; -static int __init neponset_init(void) -{ - platform_driver_register(&neponset_device_driver); + irq_set_chip_and_handler(d->irq_base + NEP_IRQ_SMC91X, &nochip, + handle_simple_irq); + set_irq_flags(d->irq_base + NEP_IRQ_SMC91X, IRQF_VALID | IRQF_PROBE); + irq_set_chip_and_handler(d->irq_base + NEP_IRQ_USAR, &nochip, + handle_simple_irq); + set_irq_flags(d->irq_base + NEP_IRQ_USAR, IRQF_VALID | IRQF_PROBE); + irq_set_chip(d->irq_base + NEP_IRQ_SA1111, &nochip); - /* - * The Neponset is only present on the Assabet machine type. - */ - if (!machine_is_assabet()) - return -ENODEV; + irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); + irq_set_handler_data(irq, d); + irq_set_chained_handler(irq, neponset_irq_handler); /* - * Ensure that the memory bus request/grant signals are setup, - * and the grant is held in its inactive state, whether or not - * we actually have a Neponset attached. + * We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately + * something on the Neponset activates this IRQ on sleep (eth?) */ +#if 0 + enable_irq_wake(irq); +#endif + + dev_info(&dev->dev, "Neponset daughter board, providing IRQ%u-%u\n", + d->irq_base, d->irq_base + NEP_IRQ_NR - 1); + nep_base = d->base; + + sa1100_register_uart_fns(&neponset_port_fns); + + /* Ensure that the memory bus request/grant signals are setup */ sa1110_mb_disable(); - if (!machine_has_neponset()) { - printk(KERN_DEBUG "Neponset expansion board not present\n"); - return -ENODEV; - } + /* Disable GPIO 0/1 drivers so the buttons work on the Assabet */ + writeb_relaxed(NCR_GP01_OFF, d->base + NCR_0); - if (WHOAMI != 0x11) { - printk(KERN_WARNING "Neponset board detected, but " - "wrong ID: %02x\n", WHOAMI); - return -ENODEV; - } + sa1111_resources[0].parent = sa1111_res; + sa1111_resources[1].start = d->irq_base + NEP_IRQ_SA1111; + sa1111_resources[1].end = d->irq_base + NEP_IRQ_SA1111; + d->sa1111 = platform_device_register_full(&sa1111_devinfo); + + smc91x_resources[0].parent = smc91x_res; + smc91x_resources[1].parent = smc91x_res; + smc91x_resources[2].start = d->irq_base + NEP_IRQ_SMC91X; + smc91x_resources[2].end = d->irq_base + NEP_IRQ_SMC91X; + d->smc91x = platform_device_register_full(&smc91x_devinfo); + + platform_set_drvdata(dev, d); - return platform_add_devices(devices, ARRAY_SIZE(devices)); + return 0; + + err_irq_alloc: + err_id: + iounmap(d->base); + err_ioremap: + kfree(d); + err_alloc: + return ret; } -subsys_initcall(neponset_init); +static int __devexit neponset_remove(struct platform_device *dev) +{ + struct neponset_drvdata *d = platform_get_drvdata(dev); + int irq = platform_get_irq(dev, 0); + + if (!IS_ERR(d->sa1111)) + platform_device_unregister(d->sa1111); + if (!IS_ERR(d->smc91x)) + platform_device_unregister(d->smc91x); + irq_set_chained_handler(irq, NULL); + irq_free_descs(d->irq_base, NEP_IRQ_NR); + nep_base = NULL; + iounmap(d->base); + kfree(d); -static struct map_desc neponset_io_desc[] __initdata = { - { /* System Registers */ - .virtual = 0xf3000000, - .pfn = __phys_to_pfn(0x10000000), - .length = SZ_1M, - .type = MT_DEVICE - }, { /* SA-1111 */ - .virtual = 0xf4000000, - .pfn = __phys_to_pfn(0x40000000), - .length = SZ_1M, - .type = MT_DEVICE - } + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int neponset_suspend(struct device *dev) +{ + struct neponset_drvdata *d = dev_get_drvdata(dev); + + d->ncr0 = readb_relaxed(d->base + NCR_0); + d->mdm_ctl_0 = readb_relaxed(d->base + MDM_CTL_0); + + return 0; +} + +static int neponset_resume(struct device *dev) +{ + struct neponset_drvdata *d = dev_get_drvdata(dev); + + writeb_relaxed(d->ncr0, d->base + NCR_0); + writeb_relaxed(d->mdm_ctl_0, d->base + MDM_CTL_0); + + return 0; +} + +static const struct dev_pm_ops neponset_pm_ops = { + .suspend_noirq = neponset_suspend, + .resume_noirq = neponset_resume, + .freeze_noirq = neponset_suspend, + .restore_noirq = neponset_resume, +}; +#define PM_OPS &neponset_pm_ops +#else +#define PM_OPS NULL +#endif + +static struct platform_driver neponset_device_driver = { + .probe = neponset_probe, + .remove = __devexit_p(neponset_remove), + .driver = { + .name = "neponset", + .owner = THIS_MODULE, + .pm = PM_OPS, + }, }; -void __init neponset_map_io(void) +static int __init neponset_init(void) { - iotable_init(neponset_io_desc, ARRAY_SIZE(neponset_io_desc)); + return platform_driver_register(&neponset_device_driver); } + +subsys_initcall(neponset_init); diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c index 0d01ca788922..41bb018b3103 100644 --- a/arch/arm/mach-sa1100/pci-nanoengine.c +++ b/arch/arm/mach-sa1100/pci-nanoengine.c @@ -135,12 +135,8 @@ struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys &sys->resources); } -static struct resource pci_io_ports = { - .name = "PCI IO", - .start = 0x400, - .end = 0x7FF, - .flags = IORESOURCE_IO, -}; +static struct resource pci_io_ports = + DEFINE_RES_IO_NAMED(0x400, 0x400, "PCI IO"); static struct resource pci_non_prefetchable_memory = { .name = "PCI non-prefetchable", diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c index 9307df053533..ca5d33b6041a 100644 --- a/arch/arm/mach-sa1100/pleb.c +++ b/arch/arm/mach-sa1100/pleb.c @@ -37,17 +37,9 @@ #define IRQ_GPIO_ETH0_IRQ IRQ_GPIO21 static struct resource smc91x_resources[] = { - [0] = { - .start = PLEB_ETH0_P, - .end = PLEB_ETH0_P | 0x03ffffff, - .flags = IORESOURCE_MEM, - }, + [0] = DEFINE_RES_MEM(PLEB_ETH0_P, 0x04000000), #if 0 /* Autoprobe instead, to get rising/falling edge characteristic right */ - [1] = { - .start = IRQ_GPIO_ETH0_IRQ, - .end = IRQ_GPIO_ETH0_IRQ, - .flags = IORESOURCE_IRQ, - }, + [1] = DEFINE_RES_IRQ(IRQ_GPIO_ETH0_IRQ), #endif }; @@ -70,16 +62,8 @@ static struct platform_device *devices[] __initdata = { * the two SA1100 lowest chip select outputs. */ static struct resource pleb_flash_resources[] = { - [0] = { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_8M - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = SA1100_CS1_PHYS, - .end = SA1100_CS1_PHYS + SZ_8M - 1, - .flags = IORESOURCE_MEM, - } + [0] = DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_8M), + [1] = DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_8M), }; diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c index 318b2b766a0b..5fd615649847 100644 --- a/arch/arm/mach-sa1100/shannon.c +++ b/arch/arm/mach-sa1100/shannon.c @@ -46,11 +46,8 @@ static struct flash_platform_data shannon_flash_data = { .nr_parts = ARRAY_SIZE(shannon_partitions), }; -static struct resource shannon_flash_resource = { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_4M - 1, - .flags = IORESOURCE_MEM, -}; +static struct resource shannon_flash_resource = + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_4M); static struct mcp_plat_data shannon_mcp_data = { .mccr0 = MCCR0_ADM, diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index e17c04d6e324..cdb9d197c092 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c @@ -176,15 +176,8 @@ static struct flash_platform_data simpad_flash_data = { static struct resource simpad_flash_resources [] = { - { - .start = SA1100_CS0_PHYS, - .end = SA1100_CS0_PHYS + SZ_16M -1, - .flags = IORESOURCE_MEM, - }, { - .start = SA1100_CS1_PHYS, - .end = SA1100_CS1_PHYS + SZ_16M -1, - .flags = IORESOURCE_MEM, - } + DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_16M), + DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_16M), }; static struct mcp_plat_data simpad_mcp_data = { diff --git a/arch/arm/mach-sa1100/sleep.S b/arch/arm/mach-sa1100/sleep.S index e8223315b442..30cc6721665b 100644 --- a/arch/arm/mach-sa1100/sleep.S +++ b/arch/arm/mach-sa1100/sleep.S @@ -26,27 +26,36 @@ * * Causes sa11x0 to enter sleep state * + * Must be aligned to a cacheline. */ - + .balign 32 ENTRY(sa1100_finish_suspend) @ disable clock switching mcr p15, 0, r1, c15, c2, 2 - @ Adjust memory timing before lowering CPU clock - @ Clock speed adjustment without changing memory timing makes - @ CPU hang in some cases - ldr r0, =MDREFR - ldr r1, [r0] - orr r1, r1, #MDREFR_K1DB2 - str r1, [r0] + ldr r6, =MDREFR + ldr r4, [r6] + orr r4, r4, #MDREFR_K1DB2 + ldr r5, =PPCR + + @ Pre-load __udelay into the I-cache + mov r0, #1 + bl __udelay + mov r0, r0 + + @ The following must all exist in a single cache line to + @ avoid accessing memory until this sequence is complete, + @ otherwise we occasionally hang. + + @ Adjust memory timing before lowering CPU clock + str r4, [r6] @ delay 90us and set CPU PLL to lowest speed @ fixes resume problem on high speed SA1110 mov r0, #90 bl __udelay - ldr r0, =PPCR mov r1, #0 - str r1, [r0] + str r1, [r5] mov r0, #90 bl __udelay @@ -85,12 +94,10 @@ ENTRY(sa1100_finish_suspend) bic r5, r5, #FMsk(MSC_RT) bic r5, r5, #FMsk(MSC_RT)<<16 - ldr r6, =MDREFR - ldr r7, [r6] -bic r7, r7, #0x0000FF00 -bic r7, r7, #0x000000F0 -orr r8, r7, #MDREFR_SLFRSH + bic r7, r7, #0x0000FF00 + bic r7, r7, #0x000000F0 + orr r8, r7, #MDREFR_SLFRSH ldr r9, =MDCNFG ldr r10, [r9] |