aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/common/sa1111.c281
-rw-r--r--arch/arm/include/asm/hardware/sa1111.h156
-rw-r--r--arch/arm/mach-pxa/lubbock.c1
-rw-r--r--arch/arm/mach-sa1100/Makefile2
-rw-r--r--arch/arm/mach-sa1100/assabet.c54
-rw-r--r--arch/arm/mach-sa1100/badge4.c40
-rw-r--r--arch/arm/mach-sa1100/cerf.c13
-rw-r--r--arch/arm/mach-sa1100/collie.c24
-rw-r--r--arch/arm/mach-sa1100/dma.c348
-rw-r--r--arch/arm/mach-sa1100/generic.c122
-rw-r--r--arch/arm/mach-sa1100/h3xxx.c13
-rw-r--r--arch/arm/mach-sa1100/hackkit.c7
-rw-r--r--arch/arm/mach-sa1100/include/mach/SA-1100.h219
-rw-r--r--arch/arm/mach-sa1100/include/mach/dma.h117
-rw-r--r--arch/arm/mach-sa1100/include/mach/irqs.h8
-rw-r--r--arch/arm/mach-sa1100/include/mach/neponset.h52
-rw-r--r--arch/arm/mach-sa1100/irq.c7
-rw-r--r--arch/arm/mach-sa1100/jornada720.c39
-rw-r--r--arch/arm/mach-sa1100/nanoengine.c11
-rw-r--r--arch/arm/mach-sa1100/neponset.c545
-rw-r--r--arch/arm/mach-sa1100/pci-nanoengine.c8
-rw-r--r--arch/arm/mach-sa1100/pleb.c24
-rw-r--r--arch/arm/mach-sa1100/shannon.c7
-rw-r--r--arch/arm/mach-sa1100/simpad.c11
-rw-r--r--arch/arm/mach-sa1100/sleep.S37
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]