diff options
Diffstat (limited to 'packages/kexecboot/linux-kexecboot-2.6.24/tosa/0039-Add-generic-framework-for-managing-clocks.patch')
-rw-r--r-- | packages/kexecboot/linux-kexecboot-2.6.24/tosa/0039-Add-generic-framework-for-managing-clocks.patch | 446 |
1 files changed, 0 insertions, 446 deletions
diff --git a/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0039-Add-generic-framework-for-managing-clocks.patch b/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0039-Add-generic-framework-for-managing-clocks.patch deleted file mode 100644 index c09c208c6a..0000000000 --- a/packages/kexecboot/linux-kexecboot-2.6.24/tosa/0039-Add-generic-framework-for-managing-clocks.patch +++ /dev/null @@ -1,446 +0,0 @@ -From 62c9a23cfa7181369637d0b61a8e90c83c562f03 Mon Sep 17 00:00:00 2001 -From: Dmitry Baryshkov <dbaryshkov@gmail.com> -Date: Mon, 4 Feb 2008 03:01:06 +0300 -Subject: [PATCH 39/64] Add generic framework for managing clocks. - -Provide a generic framework that platform may choose -to support clocks api. In particular this provides -platform-independant struct clk definition, a full -implementation of clocks api and a set of functions -for registering and unregistering clocks in a safe way. - -Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> ---- - include/linux/clklib.h | 85 ++++++++++++++ - init/Kconfig | 7 + - kernel/Makefile | 1 + - kernel/clklib.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 388 insertions(+), 0 deletions(-) - create mode 100644 include/linux/clklib.h - create mode 100644 kernel/clklib.c - -diff --git a/include/linux/clklib.h b/include/linux/clklib.h -new file mode 100644 -index 0000000..4bd9b4a ---- /dev/null -+++ b/include/linux/clklib.h -@@ -0,0 +1,85 @@ -+/* -+ * Copyright (C) 2008 Dmitry Baryshkov -+ * -+ * This file is released under the GPL v2. -+ */ -+ -+#ifndef CLKLIB_H -+#define CLKLIB_H -+ -+#include <linux/list.h> -+ -+struct clk { -+ struct list_head node; -+ struct clk *parent; -+ -+ const char *name; -+ struct module *owner; -+ -+ int users; -+ unsigned long rate; -+ int delay; -+ -+ int (*can_get) (struct clk *, struct device *); -+ int (*set_parent) (struct clk *, struct clk *); -+ int (*enable) (struct clk *); -+ void (*disable) (struct clk *); -+ unsigned long (*getrate) (struct clk*); -+ int (*setrate) (struct clk *, unsigned long); -+ long (*roundrate) (struct clk *, unsigned long); -+ -+ void *priv; -+}; -+ -+int clk_register(struct clk *clk); -+void clk_unregister(struct clk *clk); -+static void __maybe_unused clks_register(struct clk *clks, size_t num) -+{ -+ int i; -+ for (i = 0; i < num; i++) { -+ clk_register(&clks[i]); -+ } -+} -+ -+ -+int clk_alloc_function(const char *parent, struct clk *clk); -+ -+struct clk_function { -+ const char *parent; -+ struct clk *clk; -+}; -+ -+#define CLK_FUNC(_clock, _function, _can_get, _data, _format) \ -+ { \ -+ .parent = _clock, \ -+ .clk = &(struct clk) { \ -+ .name= _function, \ -+ .owner = THIS_MODULE, \ -+ .can_get = _can_get, \ -+ .priv = _data, \ -+ .format = _format, \ -+ }, \ -+ } -+ -+static int __maybe_unused clk_alloc_functions( -+ struct clk_function *funcs, -+ int num) -+{ -+ int i; -+ int rc; -+ -+ for (i = 0; i < num; i++) { -+ rc = clk_alloc_function(funcs[i].parent, funcs[i].clk); -+ -+ if (rc) { -+ printk(KERN_ERR "Error allocating %s.%s function.\n", -+ funcs[i].parent, -+ funcs[i].clk->name); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+#endif -diff --git a/init/Kconfig b/init/Kconfig -index b9d11a8..05b62ba 100644 ---- a/init/Kconfig -+++ b/init/Kconfig -@@ -435,6 +435,13 @@ config CC_OPTIMIZE_FOR_SIZE - config SYSCTL - bool - -+config HAVE_CLOCK_LIB -+ bool -+ help -+ Platforms select clocklib if they use this infrastructure -+ for managing their clocks both built into SoC and provided -+ by external devices. -+ - menuconfig EMBEDDED - bool "Configure standard kernel features (for small systems)" - help -diff --git a/kernel/Makefile b/kernel/Makefile -index 6d9a87c..0b2ade7 100644 ---- a/kernel/Makefile -+++ b/kernel/Makefile -@@ -58,6 +58,7 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o - obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o - obj-$(CONFIG_MARKERS) += marker.o - obj-$(CONFIG_LATENCYTOP) += latencytop.o -+obj-$(CONFIG_HAVE_CLOCK_LIB) += clklib.o - - ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) - # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is -diff --git a/kernel/clklib.c b/kernel/clklib.c -new file mode 100644 -index 0000000..203af3d ---- /dev/null -+++ b/kernel/clklib.c -@@ -0,0 +1,295 @@ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/clk.h> -+#include <linux/clklib.h> -+#include <linux/spinlock.h> -+#include <linux/err.h> -+#include <linux/delay.h> -+ -+static LIST_HEAD(clocks); -+static DEFINE_SPINLOCK(clocks_lock); -+ -+static int __clk_register(struct clk *clk) -+{ -+ if (clk->parent && -+ !try_module_get(clk->parent->owner)) -+ return -EINVAL; -+ -+ list_add_tail(&clk->node, &clocks); -+ -+ return 0; -+} -+ -+int clk_register(struct clk *clk) -+{ -+ unsigned long flags; -+ int rc; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ rc = __clk_register(clk); -+ -+ spin_unlock_irqrestore(&clocks_lock, flags); -+ -+ return rc; -+} -+EXPORT_SYMBOL(clk_register); -+ -+void clk_unregister(struct clk *clk) -+{ -+ unsigned long flags; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ list_del(&clk->node); -+ if (clk->parent) -+ module_put(clk->parent->owner); -+ spin_unlock_irqrestore(&clocks_lock, flags); -+} -+EXPORT_SYMBOL(clk_unregister); -+ -+struct clk *clk_get(struct device *dev, const char *id) -+{ -+ struct clk *p, *clk = ERR_PTR(-ENOENT); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ list_for_each_entry(p, &clocks, node) { -+ if (strcmp(id, p->name) == 0 && -+ (!p->can_get || p->can_get(p, dev)) && -+ try_module_get(p->owner)) { -+ clk = p; -+ break; -+ } -+ } -+ -+ spin_unlock_irqrestore(&clocks_lock, flags); -+ -+ return clk; -+} -+EXPORT_SYMBOL(clk_get); -+ -+void clk_put(struct clk *clk) -+{ -+ unsigned long flags; -+ -+ if (!clk || IS_ERR(clk)) -+ return; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ module_put(clk->owner); -+ -+ spin_unlock_irqrestore(&clocks_lock, flags); -+} -+EXPORT_SYMBOL(clk_put); -+ -+int clk_set_parent(struct clk *clk, struct clk *parent) -+{ -+ int rc; -+ unsigned long flags; -+ -+ if (!clk || IS_ERR(clk)) -+ return -EINVAL; -+ -+ if (!clk->set_parent) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ rc = clk->set_parent(clk, parent); -+ if (!rc) -+ clk->parent = parent; -+ -+ spin_unlock_irqrestore(&clocks_lock, flags); -+ -+ return rc; -+} -+EXPORT_SYMBOL(clk_set_parent); -+ -+static int __clk_enable(struct clk *clk) -+{ -+ int rc = 0; -+ -+ if (clk->parent) { -+ rc = __clk_enable(clk->parent); -+ -+ if (rc) -+ return rc; -+ } -+ -+ if (clk->users++ == 0) -+ if (clk->enable) -+ rc = clk->enable(clk); -+ -+ if (clk->delay) -+ udelay(clk->delay); -+ -+ return rc; -+} -+ -+int clk_enable(struct clk *clk) -+{ -+ unsigned long flags; -+ int rc; -+ -+ if (!clk || IS_ERR(clk)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ rc = __clk_enable(clk); -+ -+ spin_unlock_irqrestore(&clocks_lock, flags); -+ -+ return rc; -+} -+EXPORT_SYMBOL(clk_enable); -+ -+static void __clk_disable(struct clk *clk) -+{ -+ if (clk->users <= 0) { -+ WARN_ON(1); -+ return; -+ } -+ -+ if (--clk->users == 0) -+ if (clk->disable) -+ clk->disable(clk); -+ -+ if (clk->parent) -+ __clk_disable(clk->parent); -+} -+ -+void clk_disable(struct clk *clk) -+{ -+ unsigned long flags; -+ -+ if (!clk || IS_ERR(clk)) -+ return; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ __clk_disable(clk); -+ -+ spin_unlock_irqrestore(&clocks_lock, flags); -+} -+EXPORT_SYMBOL(clk_disable); -+ -+static unsigned long __clk_get_rate(struct clk *clk) -+{ -+ unsigned long rate = 0; -+ -+ for (;;) { -+ if (rate || !clk) -+ return rate; -+ -+ if (clk->getrate) -+ rate = clk->getrate(clk); -+ else if (clk->rate) -+ rate = clk->rate; -+ else -+ clk = clk->parent; -+ } -+} -+ -+unsigned long clk_get_rate(struct clk *clk) -+{ -+ unsigned long rate = 0; -+ unsigned long flags; -+ -+ if (!clk || IS_ERR(clk)) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ rate = __clk_get_rate(clk); -+ -+ spin_unlock_irqrestore(&clocks_lock, flags); -+ -+ return rate; -+} -+EXPORT_SYMBOL(clk_get_rate); -+ -+long clk_round_rate(struct clk *clk, unsigned long rate) -+{ -+ long res; -+ unsigned long flags; -+ -+ if (!clk || IS_ERR(clk)) -+ return -EINVAL; -+ -+ if (!clk->roundrate) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ res = clk->roundrate(clk, rate); -+ -+ spin_unlock_irqrestore(&clocks_lock, flags); -+ -+ return res; -+} -+EXPORT_SYMBOL(clk_round_rate); -+ -+int clk_set_rate(struct clk *clk, unsigned long rate) -+{ -+ int rc; -+ unsigned long flags; -+ -+ if (!clk || IS_ERR(clk)) -+ return -EINVAL; -+ -+ if (!clk->setrate) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ rc = clk->setrate(clk, rate); -+ -+ spin_unlock_irqrestore(&clocks_lock, flags); -+ -+ return rc; -+} -+EXPORT_SYMBOL(clk_set_rate); -+ -+int clk_alloc_function(const char *parent, struct clk *clk) -+{ -+ int rc = 0; -+ unsigned long flags; -+ struct clk *pclk; -+ bool found = false; -+ -+ spin_lock_irqsave(&clocks_lock, flags); -+ -+ list_for_each_entry(pclk, &clocks, node) { -+ if (strcmp(parent, pclk->name) == 0 && -+ try_module_get(pclk->owner)) { -+ found = true; -+ break; -+ } -+ } -+ -+ if (!found) { -+ rc = -ENODEV; -+ goto out; -+ } -+ -+ clk->parent = pclk; -+ -+ __clk_register(clk); -+ /* -+ * We locked parent owner during search -+ * and also in __clk_register. Free one reference -+ */ -+ module_put(pclk->owner); -+ -+out: -+ if (rc) { -+ kfree(clk); -+ } -+ spin_unlock_irqrestore(&clocks_lock, flags); -+ -+ return rc; -+} -+EXPORT_SYMBOL(clk_alloc_function); --- -1.5.3.8 - |