[PATCH 2/3] VIA/Wondermedia clock support

Linux Mailing List Email Account linux at prisktech.co.nz
Sat Feb 26 19:05:15 EST 2011


Signed-off-by: Tony Prisk (linux at prisktech.co.nz)
--- /dev/null   2011-02-26 19:04:30.530140059 +1300
+++ arch/arm/mach-vt8500/clock.c     2011-02-27 12:12:39.000000000 +1300
@@ -0,0 +1,164 @@
+/*
+ *  arch/arm/mach-vt8500/clock.c
+ *
+ *  Copyright (C) 2011 Tony Prisk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+
+#include "clock.h"
+
+static LIST_HEAD(clocks);
+
+static DEFINE_SPINLOCK(clocks_lock);
+static DEFINE_MUTEX(clocks_mutex);
+
+static void __clk_enable(struct clk *clk)
+{
+    if (clk->parent)
+          __clk_enable(clk->parent);
+    if (clk->usecount++ == 0)
+          if (clk->type & CLK_ENABLE)
+               clk->ops->enable(clk);
+}
+
+static void __clk_disable(struct clk *clk)
+{
+    if (--clk->usecount == 0)
+          if (clk->type & CLK_ENABLE)
+               clk->ops->disable(clk);
+    if (clk->parent)
+          __clk_disable(clk->parent);
+}
+
+int clk_enable(struct clk *clk)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&clocks_lock, flags);
+    __clk_enable(clk);
+    spin_unlock_irqrestore(&clocks_lock, flags);
+
+    if (clk->delay)
+          udelay(clk->delay);
+
+    return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+    unsigned long flags;
+
+    WARN_ON(clk->usecount == 0);
+
+    spin_lock_irqsave(&clocks_lock, flags);
+    __clk_disable(clk);
+    spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+    unsigned long rate;
+
+    if (clk == NULL || IS_ERR(clk))
+          return -EINVAL;
+
+    rate = clk->rate;
+    if ((clk->ops->getrate) && (clk->type & CLK_PROGRAMABLE))
+          rate = clk->ops->getrate(clk);
+
+    return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static void propagate_rate(struct clk *root)
+{
+    struct clk *clk;
+
+    list_for_each_entry(clk, &root->children, childnode) {
+          if (clk->ops->setrate)
+               clk->ops->setrate(clk, clk->rate);
+          if (clk->ops->getrate)
+               clk->rate = clk->ops->getrate(clk);
+          propagate_rate(clk);
+    }
+}
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+    unsigned long flags;
+
+    if (clk == NULL || IS_ERR(clk))
+          return -EINVAL;
+
+    if (!(clk->type & CLK_PROGRAMABLE))
+          return -EINVAL;
+
+    if (clk->ops->setrate)
+          clk->ops->setrate(clk, rate);
+
+    if (clk->ops->getrate)
+          clk->rate = clk->ops->getrate(clk);
+
+    spin_lock_irqsave(&clocks_lock, flags);
+    if (!(clk->type & CLK_NO_PROPAGATE))
+          propagate_rate(clk);
+    spin_unlock_irqrestore(&clocks_lock, flags);
+
+    return 0;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_register(struct clk *clk)
+{
+    if (clk == NULL || IS_ERR(clk))
+          return -EINVAL;
+
+    if (clk->parent && !clk->parent->rate)
+          return -EINVAL;
+
+    INIT_LIST_HEAD(&clk->children);
+
+    mutex_lock(&clocks_mutex);
+    list_add_tail(&clk->node, &clocks);
+    if (clk->parent)
+          list_add_tail(&clk->childnode, &clk->parent->children);
+    mutex_unlock(&clocks_mutex);
+
+    /* if rate already set, use it */
+    if (clk->rate)
+          return 0;
+
+    /* see if we can calculate the rate */
+    if (clk->ops->getrate)
+          clk->ops->getrate(clk);
+    /* otherwise use the parents rate */
+    else if (clk->parent)
+          clk->rate = clk->parent->rate;
+
+    return 0;
+}


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110227/1fe5ec4a/attachment.html>


More information about the linux-arm-kernel mailing list