]> err.no Git - linux-2.6/commitdiff
[ARM] Convert SA1111 to use clock architecture
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Wed, 15 Mar 2006 15:54:37 +0000 (15:54 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Tue, 21 Mar 2006 22:05:53 +0000 (22:05 +0000)
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/common/sa1111.c
arch/arm/mach-pxa/Makefile
arch/arm/mach-pxa/clock.c [new file with mode: 0644]
arch/arm/mach-sa1100/Makefile
arch/arm/mach-sa1100/clock.c [new file with mode: 0644]

index 93352f6097c1b387d799b025653147994fbdbbda..5ba1ee042349eab9a5b606737c988b4abc2f54dc 100644 (file)
@@ -26,6 +26,7 @@
 #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/hardware/sa1111.h>
 
-#ifdef CONFIG_ARCH_PXA
-#include <asm/arch/pxa-regs.h>
-#endif
-
 extern void __init sa1110_mb_enable(void);
 
 /*
@@ -51,6 +48,7 @@ extern void __init sa1110_mb_enable(void);
  */
 struct sa1111 {
        struct device   *dev;
+       struct clk      *clk;
        unsigned long   phys;
        int             irq;
        spinlock_t      lock;
@@ -451,19 +449,7 @@ static void sa1111_wake(struct sa1111 *sachip)
 
        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.
@@ -641,6 +627,12 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
 
        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->dev = me;
@@ -656,7 +648,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
        sachip->base = ioremap(mem->start, PAGE_SIZE * 2);
        if (!sachip->base) {
                ret = -ENOMEM;
-               goto out;
+               goto err_clkput;
        }
 
        /*
@@ -666,7 +658,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
        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: "
@@ -726,9 +718,11 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
 
        return 0;
 
- unmap:
err_unmap:
        iounmap(sachip->base);
- out:
+ err_clkput:
+       clk_put(sachip->clk);
+ err_free:
        kfree(sachip);
        return ret;
 }
@@ -751,6 +745,8 @@ static void __sa1111_remove(struct sa1111 *sachip)
        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);
@@ -759,6 +755,7 @@ static void __sa1111_remove(struct sa1111 *sachip)
        }
 
        iounmap(sachip->base);
+       clk_put(sachip->clk);
        kfree(sachip);
 }
 
@@ -857,6 +854,8 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
        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;
index 32526a0a6f861241089db559937b579e49d18960..382644401a4df47b5691c90810324e3b91ffe42b 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support (must be linked before board specific support)
-obj-y += generic.o irq.o dma.o time.o
+obj-y += clock.o generic.o irq.o dma.o time.o
 obj-$(CONFIG_PXA25x) += pxa25x.o
 obj-$(CONFIG_PXA27x) += pxa27x.o
 
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
new file mode 100644 (file)
index 0000000..8f7c90a
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  linux/arch/arm/mach-sa1100/clock.c
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/hardware.h>
+#include <asm/semaphore.h>
+
+struct clk {
+       struct list_head        node;
+       unsigned long           rate;
+       struct module           *owner;
+       const char              *name;
+       unsigned int            enabled;
+       void                    (*enable)(void);
+       void                    (*disable)(void);
+};
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+static DEFINE_SPINLOCK(clocks_lock);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+       down(&clocks_sem);
+       list_for_each_entry(p, &clocks, node) {
+               if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+                       clk = p;
+                       break;
+               }
+       }
+       up(&clocks_sem);
+
+       return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+       module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable(struct clk *clk)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&clocks_lock, flags);
+       if (clk->enabled++ == 0)
+               clk->enable();
+       spin_unlock_irqrestore(&clocks_lock, flags);
+       return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+       unsigned long flags;
+
+       WARN_ON(clk->enabled == 0);
+
+       spin_lock_irqsave(&clocks_lock, flags);
+       if (--clk->enabled == 0)
+               clk->disable();
+       spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+
+static void clk_gpio27_enable(void)
+{
+       pxa_gpio_mode(GPIO11_3_6MHz_MD);
+}
+
+static void clk_gpio27_disable(void)
+{
+}
+
+static struct clk clk_gpio27 = {
+       .name           = "GPIO27_CLK",
+       .rate           = 3686400,
+       .enable         = clk_gpio27_enable,
+       .disable        = clk_gpio27_disable,
+};
+
+int clk_register(struct clk *clk)
+{
+       down(&clocks_sem);
+       list_add(&clk->node, &clocks);
+       up(&clocks_sem);
+       return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+       down(&clocks_sem);
+       list_del(&clk->node);
+       up(&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static int __init clk_init(void)
+{
+       clk_register(&clk_gpio27);
+       return 0;
+}
+arch_initcall(clk_init);
index e4a4a3e8aa8f40393a3b35a4df3f074b9e5354e9..e27f15042a22dfec7e492f0fa6d965fec139cf5d 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common support
-obj-y := generic.o irq.o dma.o time.o
+obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o
 obj-m :=
 obj-n :=
 obj-  :=
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
new file mode 100644 (file)
index 0000000..b1e8fd7
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ *  linux/arch/arm/mach-sa1100/clock.c
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+
+#include <asm/hardware.h>
+#include <asm/semaphore.h>
+
+struct clk {
+       struct list_head        node;
+       unsigned long           rate;
+       struct module           *owner;
+       const char              *name;
+       unsigned int            enabled;
+       void                    (*enable)(void);
+       void                    (*disable)(void);
+};
+
+static LIST_HEAD(clocks);
+static DECLARE_MUTEX(clocks_sem);
+static DEFINE_SPINLOCK(clocks_lock);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       struct clk *p, *clk = ERR_PTR(-ENOENT);
+
+       down(&clocks_sem);
+       list_for_each_entry(p, &clocks, node) {
+               if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+                       clk = p;
+                       break;
+               }
+       }
+       up(&clocks_sem);
+
+       return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+       module_put(clk->owner);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_enable(struct clk *clk)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&clocks_lock, flags);
+       if (clk->enabled++ == 0)
+               clk->enable();
+       spin_unlock_irqrestore(&clocks_lock, flags);
+       return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+       unsigned long flags;
+
+       WARN_ON(clk->enabled == 0);
+
+       spin_lock_irqsave(&clocks_lock, flags);
+       if (--clk->enabled == 0)
+               clk->disable();
+       spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+
+static void clk_gpio27_enable(void)
+{
+       /*
+        * 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;
+}
+
+static void clk_gpio27_disable(void)
+{
+       TUCR = 0;
+       GPDR &= ~GPIO_32_768kHz;
+       GAFR &= ~GPIO_32_768kHz;
+}
+
+static struct clk clk_gpio27 = {
+       .name           = "GPIO27_CLK",
+       .rate           = 3686400,
+       .enable         = clk_gpio27_enable,
+       .disable        = clk_gpio27_disable,
+};
+
+int clk_register(struct clk *clk)
+{
+       down(&clocks_sem);
+       list_add(&clk->node, &clocks);
+       up(&clocks_sem);
+       return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+       down(&clocks_sem);
+       list_del(&clk->node);
+       up(&clocks_sem);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+static int __init clk_init(void)
+{
+       clk_register(&clk_gpio27);
+       return 0;
+}
+arch_initcall(clk_init);