/*
- * linux/arch/arm/mach-sa1100/sa1111.c
+ * linux/arch/arm/common/sa1111.c
*
* SA1111 support
*
* All initialization functions provided here are intended to be called
* from machine specific code with proper arguments when required.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
+#include <linux/clk.h>
#include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
+#include <asm/sizes.h>
#include <asm/hardware/sa1111.h>
-#ifdef CONFIG_ARCH_PXA
-#include <asm/arch/pxa-regs.h>
-#endif
-
extern void __init sa1110_mb_enable(void);
/*
*/
struct sa1111 {
struct device *dev;
+ struct clk *clk;
unsigned long phys;
int irq;
spinlock_t lock;
},
};
+void __init sa1111_adjust_zones(int node, unsigned long *size, unsigned long *holes)
+{
+ unsigned int sz = SZ_1M >> PAGE_SHIFT;
+
+ if (node != 0)
+ sz = 0;
+
+ size[1] = size[0] - sz;
+ size[0] = sz;
+}
+
/*
* SA1111 interrupt support. Since clearing an IRQ while there are
* active IRQs causes the interrupt output to pulse, the upper levels
* will call us again if there are more interrupts to process.
*/
static void
-sa1111_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
+sa1111_irq_handler(unsigned int irq, struct irq_desc *desc)
{
unsigned int stat0, stat1, i;
- void __iomem *base = desc->data;
+ void __iomem *base = get_irq_data(irq);
stat0 = sa1111_readl(base + SA1111_INTSTATCLR0);
stat1 = sa1111_readl(base + SA1111_INTSTATCLR1);
sa1111_writel(stat1, base + SA1111_INTSTATCLR1);
if (stat0 == 0 && stat1 == 0) {
- do_bad_IRQ(irq, desc, regs);
+ do_bad_IRQ(irq, desc);
return;
}
for (i = IRQ_SA1111_START; stat0; i++, stat0 >>= 1)
if (stat0 & 1)
- do_edge_IRQ(i, irq_desc + i, regs);
+ handle_edge_irq(i, irq_desc + i);
for (i = IRQ_SA1111_START + 32; stat1; i++, stat1 >>= 1)
if (stat1 & 1)
- do_edge_IRQ(i, irq_desc + i, regs);
+ handle_edge_irq(i, irq_desc + i);
/* For level-based interrupts */
desc->chip->unmask(irq);
static void sa1111_mask_lowirq(unsigned int irq)
{
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ie0;
ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
static void sa1111_unmask_lowirq(unsigned int irq)
{
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ie0;
ie0 = sa1111_readl(mapbase + SA1111_INTEN0);
static int sa1111_retrigger_lowirq(unsigned int irq)
{
unsigned int mask = SA1111_IRQMASK_LO(irq);
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ip0;
int i;
static int sa1111_type_lowirq(unsigned int irq, unsigned int flags)
{
unsigned int mask = SA1111_IRQMASK_LO(irq);
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ip0;
if (flags == IRQT_PROBE)
static int sa1111_wake_lowirq(unsigned int irq, unsigned int on)
{
unsigned int mask = SA1111_IRQMASK_LO(irq);
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long we0;
we0 = sa1111_readl(mapbase + SA1111_WAKEEN0);
return 0;
}
-static struct irqchip sa1111_low_chip = {
+static struct irq_chip sa1111_low_chip = {
+ .name = "SA1111-l",
.ack = sa1111_ack_irq,
.mask = sa1111_mask_lowirq,
.unmask = sa1111_unmask_lowirq,
.retrigger = sa1111_retrigger_lowirq,
- .type = sa1111_type_lowirq,
- .wake = sa1111_wake_lowirq,
+ .set_type = sa1111_type_lowirq,
+ .set_wake = sa1111_wake_lowirq,
};
static void sa1111_mask_highirq(unsigned int irq)
{
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ie1;
ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
static void sa1111_unmask_highirq(unsigned int irq)
{
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ie1;
ie1 = sa1111_readl(mapbase + SA1111_INTEN1);
static int sa1111_retrigger_highirq(unsigned int irq)
{
unsigned int mask = SA1111_IRQMASK_HI(irq);
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ip1;
int i;
static int sa1111_type_highirq(unsigned int irq, unsigned int flags)
{
unsigned int mask = SA1111_IRQMASK_HI(irq);
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long ip1;
if (flags == IRQT_PROBE)
static int sa1111_wake_highirq(unsigned int irq, unsigned int on)
{
unsigned int mask = SA1111_IRQMASK_HI(irq);
- void __iomem *mapbase = get_irq_chipdata(irq);
+ void __iomem *mapbase = get_irq_chip_data(irq);
unsigned long we1;
we1 = sa1111_readl(mapbase + SA1111_WAKEEN1);
return 0;
}
-static struct irqchip sa1111_high_chip = {
+static struct irq_chip sa1111_high_chip = {
+ .name = "SA1111-h",
.ack = sa1111_ack_irq,
.mask = sa1111_mask_highirq,
.unmask = sa1111_unmask_highirq,
.retrigger = sa1111_retrigger_highirq,
- .type = sa1111_type_highirq,
- .wake = sa1111_wake_highirq,
+ .set_type = sa1111_type_highirq,
+ .set_wake = sa1111_wake_highirq,
};
static void sa1111_setup_irq(struct sa1111 *sachip)
for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
set_irq_chip(irq, &sa1111_low_chip);
- set_irq_chipdata(irq, irqbase);
- set_irq_handler(irq, do_edge_IRQ);
+ set_irq_chip_data(irq, irqbase);
+ set_irq_handler(irq, handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) {
set_irq_chip(irq, &sa1111_high_chip);
- set_irq_chipdata(irq, irqbase);
- set_irq_handler(irq, do_edge_IRQ);
+ set_irq_chip_data(irq, irqbase);
+ set_irq_handler(irq, handle_edge_irq);
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
spin_lock_irqsave(&sachip->lock, flags);
-#ifdef CONFIG_ARCH_SA1100
- /*
- * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
- * (SA-1110 Developer's Manual, section 9.1.2.1)
- */
- GAFR |= GPIO_32_768kHz;
- GPDR |= GPIO_32_768kHz;
- TUCR = TUCR_3_6864MHz;
-#elif CONFIG_ARCH_PXA
- pxa_gpio_mode(GPIO11_3_6MHz_MD);
-#else
-#error missing clock setup
-#endif
+ clk_enable(sachip->clk);
/*
* Turn VCO on, and disable PLL Bypass.
struct sa1111_dev *dev;
int ret;
- dev = kmalloc(sizeof(struct sa1111_dev), GFP_KERNEL);
+ dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL);
if (!dev) {
ret = -ENOMEM;
goto out;
}
- memset(dev, 0, sizeof(struct sa1111_dev));
snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
"%4.4lx", info->offset);
{
struct sa1111 *sachip;
unsigned long id;
- unsigned int has_devs, val;
+ unsigned int has_devs;
int i, ret = -ENODEV;
- sachip = kmalloc(sizeof(struct sa1111), GFP_KERNEL);
+ sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL);
if (!sachip)
return -ENOMEM;
- memset(sachip, 0, sizeof(struct sa1111));
+ sachip->clk = clk_get(me, "GPIO27_CLK");
+ if (!sachip->clk) {
+ ret = PTR_ERR(sachip->clk);
+ goto err_free;
+ }
spin_lock_init(&sachip->lock);
sachip->base = ioremap(mem->start, PAGE_SIZE * 2);
if (!sachip->base) {
ret = -ENOMEM;
- goto out;
+ goto err_clkput;
}
/*
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id);
ret = -ENODEV;
- goto unmap;
+ goto err_unmap;
}
printk(KERN_INFO "SA1111 Microprocessor Companion Chip: "
sa1111_wake(sachip);
#ifdef CONFIG_ARCH_SA1100
+ {
+ unsigned int val;
+
/*
* The SDRAM configuration of the SA1110 and the SA1111 must
* match. This is very important to ensure that SA1111 accesses
* Enable the SA1110 memory bus request and grant signals.
*/
sa1110_mb_enable();
+ }
#endif
/*
return 0;
- unmap:
+ err_unmap:
iounmap(sachip->base);
- out:
+ err_clkput:
+ clk_put(sachip->clk);
+ err_free:
kfree(sachip);
return ret;
}
+static int sa1111_remove_one(struct device *dev, void *data)
+{
+ device_unregister(dev);
+ return 0;
+}
+
static void __sa1111_remove(struct sa1111 *sachip)
{
- struct list_head *l, *n;
void __iomem *irqbase = sachip->base + SA1111_INTC;
- list_for_each_safe(l, n, &sachip->dev->children) {
- struct device *d = list_to_dev(l);
-
- device_unregister(d);
- }
+ device_for_each_child(sachip->dev, NULL, sa1111_remove_one);
/* disable all IRQs */
sa1111_writel(0, irqbase + SA1111_INTEN0);
sa1111_writel(0, irqbase + SA1111_WAKEEN0);
sa1111_writel(0, irqbase + SA1111_WAKEEN1);
+ clk_disable(sachip->clk);
+
if (sachip->irq != NO_IRQ) {
set_irq_chained_handler(sachip->irq, NULL);
set_irq_data(sachip->irq, NULL);
}
iounmap(sachip->base);
+ clk_put(sachip->clk);
kfree(sachip);
}
#ifdef CONFIG_PM
-static int sa1111_suspend(struct device *dev, u32 state, u32 level)
+static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
{
- struct sa1111 *sachip = dev_get_drvdata(dev);
+ struct sa1111 *sachip = platform_get_drvdata(dev);
struct sa1111_save_data *save;
unsigned long flags;
unsigned int val;
void __iomem *base;
- if (level != SUSPEND_DISABLE)
- return 0;
-
save = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
if (!save)
return -ENOMEM;
- dev->power.saved_state = save;
+ dev->dev.power.saved_state = save;
spin_lock_irqsave(&sachip->lock, flags);
sa1111_writel(0, sachip->base + SA1111_SKPWM0);
sa1111_writel(0, sachip->base + SA1111_SKPWM1);
+ clk_disable(sachip->clk);
+
spin_unlock_irqrestore(&sachip->lock, flags);
return 0;
/*
* sa1111_resume - Restore the SA1111 device state.
* @dev: device to restore
- * @level: resume level
*
* Restore the general state of the SA1111; clock control and
* interrupt controller. Other parts of the SA1111 must be
* restored by their respective drivers, and must be called
* via LDM after this function.
*/
-static int sa1111_resume(struct device *dev, u32 level)
+static int sa1111_resume(struct platform_device *dev)
{
- struct sa1111 *sachip = dev_get_drvdata(dev);
+ struct sa1111 *sachip = platform_get_drvdata(dev);
struct sa1111_save_data *save;
unsigned long flags, id;
void __iomem *base;
- if (level != RESUME_ENABLE)
- return 0;
-
- save = (struct sa1111_save_data *)dev->power.saved_state;
+ save = (struct sa1111_save_data *)dev->dev.power.saved_state;
if (!save)
return 0;
id = sa1111_readl(sachip->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
__sa1111_remove(sachip);
- dev_set_drvdata(dev, NULL);
+ platform_set_drvdata(dev, NULL);
kfree(save);
return 0;
}
spin_unlock_irqrestore(&sachip->lock, flags);
- dev->power.saved_state = NULL;
+ dev->dev.power.saved_state = NULL;
kfree(save);
return 0;
#define sa1111_resume NULL
#endif
-static int sa1111_probe(struct device *dev)
+static int sa1111_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = to_platform_device(dev);
struct resource *mem;
int irq;
if (!mem)
return -EINVAL;
irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENXIO;
- return __sa1111_probe(dev, mem, irq);
+ return __sa1111_probe(&pdev->dev, mem, irq);
}
-static int sa1111_remove(struct device *dev)
+static int sa1111_remove(struct platform_device *pdev)
{
- struct sa1111 *sachip = dev_get_drvdata(dev);
+ struct sa1111 *sachip = platform_get_drvdata(pdev);
if (sachip) {
__sa1111_remove(sachip);
- dev_set_drvdata(dev, NULL);
+ platform_set_drvdata(pdev, NULL);
#ifdef CONFIG_PM
- kfree(dev->power.saved_state);
- dev->power.saved_state = NULL;
+ kfree(pdev->dev.power.saved_state);
+ pdev->dev.power.saved_state = NULL;
#endif
}
* We also need to handle the SDRAM configuration for
* PXA250/SA1110 machine classes.
*/
-static struct device_driver sa1111_device_driver = {
- .name = "sa1111",
- .bus = &platform_bus_type,
+static struct platform_driver sa1111_device_driver = {
.probe = sa1111_probe,
.remove = sa1111_remove,
.suspend = sa1111_suspend,
.resume = sa1111_resume,
+ .driver = {
+ .name = "sa1111",
+ },
};
/*
struct bus_type sa1111_bus_type = {
.name = "sa1111-rab",
.match = sa1111_match,
+ .probe = sa1111_bus_probe,
+ .remove = sa1111_bus_remove,
.suspend = sa1111_bus_suspend,
.resume = sa1111_bus_resume,
};
int sa1111_driver_register(struct sa1111_driver *driver)
{
- driver->drv.probe = sa1111_bus_probe;
- driver->drv.remove = sa1111_bus_remove;
driver->drv.bus = &sa1111_bus_type;
return driver_register(&driver->drv);
}
{
int ret = bus_register(&sa1111_bus_type);
if (ret == 0)
- driver_register(&sa1111_device_driver);
+ platform_driver_register(&sa1111_device_driver);
return ret;
}
static void __exit sa1111_exit(void)
{
- driver_unregister(&sa1111_device_driver);
+ platform_driver_unregister(&sa1111_device_driver);
bus_unregister(&sa1111_bus_type);
}
-module_init(sa1111_init);
+subsys_initcall(sa1111_init);
module_exit(sa1111_exit);
MODULE_DESCRIPTION("Intel Corporation SA1111 core driver");