Merge branch 'fixes-jgarzik' of git://git.kernel.org/pub/scm/linux/kernel/git/linvill...
[pandora-kernel.git] / arch / arm / mach-pxa / clock.c
index 34a31ca..83ef5ec 100644 (file)
@@ -9,19 +9,15 @@
 #include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/hardware.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);
-};
+#include "devices.h"
+#include "generic.h"
+#include "clock.h"
 
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
@@ -33,7 +29,8 @@ struct clk *clk_get(struct device *dev, const char *id)
 
        mutex_lock(&clocks_mutex);
        list_for_each_entry(p, &clocks, node) {
-               if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
+               if (strcmp(id, p->name) == 0 &&
+                   (p->dev == NULL || p->dev == dev)) {
                        clk = p;
                        break;
                }
@@ -46,7 +43,6 @@ EXPORT_SYMBOL(clk_get);
 
 void clk_put(struct clk *clk)
 {
-       module_put(clk->owner);
 }
 EXPORT_SYMBOL(clk_put);
 
@@ -56,8 +52,12 @@ int clk_enable(struct clk *clk)
 
        spin_lock_irqsave(&clocks_lock, flags);
        if (clk->enabled++ == 0)
-               clk->enable();
+               clk->ops->enable(clk);
        spin_unlock_irqrestore(&clocks_lock, flags);
+
+       if (clk->delay)
+               udelay(clk->delay);
+
        return 0;
 }
 EXPORT_SYMBOL(clk_enable);
@@ -70,54 +70,75 @@ void clk_disable(struct clk *clk)
 
        spin_lock_irqsave(&clocks_lock, flags);
        if (--clk->enabled == 0)
-               clk->disable();
+               clk->ops->disable(clk);
        spin_unlock_irqrestore(&clocks_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
 unsigned long clk_get_rate(struct clk *clk)
 {
-       return clk->rate;
+       unsigned long rate;
+
+       rate = clk->rate;
+       if (clk->ops->getrate)
+               rate = clk->ops->getrate(clk);
+
+       return rate;
 }
 EXPORT_SYMBOL(clk_get_rate);
 
 
-static void clk_gpio27_enable(void)
+static void clk_gpio27_enable(struct clk *clk)
 {
        pxa_gpio_mode(GPIO11_3_6MHz_MD);
 }
 
-static void clk_gpio27_disable(void)
+static void clk_gpio27_disable(struct clk *clk)
 {
 }
 
-static struct clk clk_gpio27 = {
-       .name           = "GPIO27_CLK",
-       .rate           = 3686400,
+static const struct clkops clk_gpio27_ops = {
        .enable         = clk_gpio27_enable,
        .disable        = clk_gpio27_disable,
 };
 
-int clk_register(struct clk *clk)
+
+void clk_cken_enable(struct clk *clk)
 {
-       mutex_lock(&clocks_mutex);
-       list_add(&clk->node, &clocks);
-       mutex_unlock(&clocks_mutex);
-       return 0;
+       CKEN |= 1 << clk->cken;
 }
-EXPORT_SYMBOL(clk_register);
 
-void clk_unregister(struct clk *clk)
+void clk_cken_disable(struct clk *clk)
 {
+       CKEN &= ~(1 << clk->cken);
+}
+
+const struct clkops clk_cken_ops = {
+       .enable         = clk_cken_enable,
+       .disable        = clk_cken_disable,
+};
+
+static struct clk common_clks[] = {
+       {
+               .name           = "GPIO27_CLK",
+               .ops            = &clk_gpio27_ops,
+               .rate           = 3686400,
+       },
+};
+
+void clks_register(struct clk *clks, size_t num)
+{
+       int i;
+
        mutex_lock(&clocks_mutex);
-       list_del(&clk->node);
+       for (i = 0; i < num; i++)
+               list_add(&clks[i].node, &clocks);
        mutex_unlock(&clocks_mutex);
 }
-EXPORT_SYMBOL(clk_unregister);
 
 static int __init clk_init(void)
 {
-       clk_register(&clk_gpio27);
+       clks_register(common_clks, ARRAY_SIZE(common_clks));
        return 0;
 }
 arch_initcall(clk_init);