All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Clocklib: generic clocks framework
@ 2008-04-13 14:41 Dmitry Baryshkov
  2008-04-13 14:43 ` [PATCH 1/5] Clocklib: add generic framework for managing clocks Dmitry Baryshkov
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Dmitry Baryshkov @ 2008-04-13 14:41 UTC (permalink / raw
  To: linux-kernel
  Cc: akpm, Haavard Skinnemoen, Russell King, Paul Mundt, pHilipp Zabel,
	Pavel Machek, tony, paul, David Brownell

Hi,

Here is my current version of the patchset.
Changes since last repost:

 * Clean up stuff noted by akpm.
 * Provide debugfs file description
 * Drop SIRCLK name, bind pxaficp driver to the STUARTCLK
 * Drop 3.6MHz clock renames
 * Rebase pxa part to latest Russel's arm:devel patchset

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/5] Clocklib: add generic framework for managing clocks.
  2008-04-13 14:41 [PATCH 0/5] Clocklib: generic clocks framework Dmitry Baryshkov
@ 2008-04-13 14:43 ` Dmitry Baryshkov
  2008-04-15  6:13   ` Andrew Morton
  2008-04-13 14:43 ` [PATCH 2/5] Clocklib: debugfs support Dmitry Baryshkov
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Dmitry Baryshkov @ 2008-04-13 14:43 UTC (permalink / raw
  To: linux-kernel
  Cc: akpm, Haavard Skinnemoen, Russell King, Paul Mundt, pHilipp Zabel,
	Pavel Machek, tony, paul, David Brownell

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>
---
 MAINTAINERS            |    5 +
 include/linux/clklib.h |  144 +++++++++++++++++++++
 init/Kconfig           |    7 +
 kernel/Makefile        |    1 +
 kernel/clklib.c        |  334 ++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 491 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/clklib.h
 create mode 100644 kernel/clklib.c

diff --git a/MAINTAINERS b/MAINTAINERS
index aaca5cc..a8fbac3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1083,6 +1083,11 @@ P:	Joel Schopp
 M:	jschopp@austin.ibm.com
 S:	Supported
 
+CLOCKLIB INFRASTRUCTURE
+P:	Dmitry Baryshkov
+M:	dbaryshkov@gmail.com
+S:	Maintained
+
 COMMON INTERNET FILE SYSTEM (CIFS)
 P:	Steve French
 M:	sfrench@samba.org
diff --git a/include/linux/clklib.h b/include/linux/clklib.h
new file mode 100644
index 0000000..9545159
--- /dev/null
+++ b/include/linux/clklib.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2008 Dmitry Baryshkov
+ *
+ * This file is released under the GPL v2.
+ */
+
+#ifndef CLKLIB_H
+#define CLKLIB_H
+
+#include <linux/list.h>
+
+struct seq_file;
+
+/**
+ * struct clk_ops - generic clock management operations
+ * @can_get: checks whether passed device can get this clock
+ * @set_parent: reconfigures the clock to use specified parent
+ * @set_mode: enable or disable specified clock
+ * @get_rate: obtain the current clock rate of a specified clock
+ * @set_rate: set the clock rate for a specified clock
+ * @round_rate: adjust a reate to the exact rate a clock can provide
+ *
+ * This structure specifies clock operations that are used to configure
+ * specific clock.
+ */
+struct clk_ops {
+	int (*can_get)(struct clk *clk, struct device *dev);
+	int (*set_parent)(struct clk *clk, struct clk *parent);
+	int (*set_mode)(struct clk *clk, bool enable);
+	unsigned long (*get_rate)(struct clk *clk);
+	int (*set_rate)(struct clk *, unsigned long);
+	long (*round_rate)(struct clk *, unsigned long);
+};
+
+/**
+ * struct clk - generic struct clk implementation used in the clocklib
+ * @node: used to place all clocks in a list
+ * @parent: the parent clock
+ * @owner: module holding all the functions
+ * @name: the name of this clock
+ * @users: count how many users have enabled this clock
+ * @ops: a pointer to clock management operations
+ */
+struct clk {
+	struct list_head node;
+	struct clk	*parent;
+	struct module *owner;
+
+	const char	*name;
+	int		users;
+
+	const struct clk_ops *ops;
+};
+
+int __must_check clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+
+static inline void clks_unregister(struct clk **clks, size_t num)
+{
+	int i;
+	for (i = num - 1; i >= 0;  i++)
+		clk_unregister(clks[i]);
+}
+
+static inline int __must_check clks_register(struct clk **clks, size_t num)
+{
+	int i;
+	int ret;
+	for (i = 0; i < num; i++) {
+		ret = clk_register(clks[i]);
+		if (ret != 0)
+			goto cleanup;
+	}
+
+	return 0;
+
+cleanup:
+	clks_unregister(clks, i);
+
+	return ret;
+}
+
+int __must_check clk_alloc_function(const char *parent, struct clk *clk);
+
+/*
+ * struct clk_function - helper that allows easy registration of clock "functions"
+ * @parent: the name of the parent clock
+ * @clk: the clock that will be set up and installed
+ *
+ * Sometimes single clock will have multiple users or several clocks
+ * will be bound to similar devices. This allows one to register
+ * simple wrapper clocks that serve only naming purposes.
+ */
+struct clk_function {
+	const char *parent;
+	void *priv;
+	struct clk clk;
+};
+
+#define CLK_FUNC(_clock, _function, _ops, _data)	\
+	{						\
+		.parent = _clock,			\
+		.priv	= _data,			\
+		.clk = {				\
+			.name = _function,		\
+			.owner = THIS_MODULE,		\
+			.ops = _ops,			\
+		},					\
+	}
+#define FUNC_TO_CLK(func)	&(&(struct clk_function) func)->clk
+
+static inline void clk_free_functions(
+		struct clk_function *funcs,
+		int num)
+{
+	int i;
+
+	for (i = num - 1; i >= 0; i--)
+		clk_unregister(&funcs[i].clk);
+}
+
+static inline int __must_check 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);
+			clk_free_functions(funcs, i);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+#endif
diff --git a/init/Kconfig b/init/Kconfig
index a97924b..1dd9ce2 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -504,6 +504,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 6c584c5..afaed51 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -68,6 +68,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..024a232
--- /dev/null
+++ b/kernel/clklib.c
@@ -0,0 +1,334 @@
+/*
+ * kernel/clklib.c
+ *
+ * Copyright (C) 2008 Dmitry Baryshkov
+ *
+ * Generic clocks API implementation
+ *
+ * This file is released under the GPL v2.
+ */
+#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 __must_check 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->ops && p->ops->can_get && p->ops->can_get(p, dev)) &&
+		    try_module_get(p->owner)) {
+			clk = p;
+			break;
+		}
+	}
+
+	list_for_each_entry(p, &clocks, node) {
+		if (strcmp(id, p->name) == 0 &&
+		    (!p->ops || !p->ops->can_get) &&
+		    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) || !clk->ops || !clk->ops->set_parent)
+		return -EINVAL;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+
+	rc = clk->ops->set_parent(clk, parent);
+	if (!rc)
+		clk->parent = parent;
+
+	spin_unlock_irqrestore(&clocks_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	struct clk *parent;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+
+	parent = clk->parent;
+
+	spin_unlock_irqrestore(&clocks_lock, flags);
+
+	return parent;
+
+}
+
+static void __clk_disable(struct clk *clk)
+{
+	if (clk->users <= 0) {
+		WARN_ON(1);
+		return;
+	}
+
+	if (--clk->users == 0)
+		if (clk->ops && clk->ops->set_mode)
+			clk->ops->set_mode(clk, false);
+
+	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 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)
+		return 0;
+
+	if (clk->ops && clk->ops->set_mode) {
+		rc = clk->ops->set_mode(clk, true);
+		if (rc) {
+			if (clk->parent)
+				__clk_disable(clk->parent);
+
+			return rc;
+		}
+	}
+
+	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 unsigned long __clk_get_rate(struct clk *clk)
+{
+	unsigned long rate = 0;
+
+	while (clk) {
+		if (clk->ops && clk->ops->get_rate) {
+			rate = clk->ops->get_rate(clk);
+			break;
+		} else
+			clk = clk->parent;
+	}
+
+	return rate;
+}
+
+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 = 0;
+	unsigned long flags;
+	struct clk *pclk;
+
+	if (!clk || IS_ERR(clk))
+		return -EINVAL;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+
+	for (pclk = clk; !res && pclk ; pclk = pclk->parent) {
+		if (pclk->ops && pclk->ops->round_rate)
+			res = pclk->ops->round_rate(clk, rate);
+	}
+
+	if (!res)
+		res = __clk_get_rate(clk);
+
+	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 = -EINVAL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+
+	while (clk && !IS_ERR(clk)) {
+		if (clk->ops && clk->ops->set_rate) {
+			rc = clk->ops->set_rate(clk, rate);
+			break;
+		}
+
+		clk = clk->parent;
+	}
+
+	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.4.4


-- 
With best wishes
Dmitry


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/5] Clocklib: debugfs support
  2008-04-13 14:41 [PATCH 0/5] Clocklib: generic clocks framework Dmitry Baryshkov
  2008-04-13 14:43 ` [PATCH 1/5] Clocklib: add generic framework for managing clocks Dmitry Baryshkov
@ 2008-04-13 14:43 ` Dmitry Baryshkov
  2008-04-13 14:43 ` [PATCH 3/5] Clocklib: support sa1100 sub-arch Dmitry Baryshkov
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 13+ messages in thread
From: Dmitry Baryshkov @ 2008-04-13 14:43 UTC (permalink / raw
  To: linux-kernel
  Cc: akpm, Haavard Skinnemoen, Russell King, Paul Mundt, pHilipp Zabel,
	Pavel Machek, tony, paul, David Brownell

Provide /sys/kernel/debug/clock to ease debugging.

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
 Documentation/ABI/testing/debugfs-clock |   49 ++++++++++++++++++++
 include/linux/clklib.h                  |    2 +
 kernel/clklib.c                         |   74 +++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/ABI/testing/debugfs-clock

diff --git a/Documentation/ABI/testing/debugfs-clock b/Documentation/ABI/testing/debugfs-clock
new file mode 100644
index 0000000..79196e9
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-clock
@@ -0,0 +1,49 @@
+What:           /debug/clock
+Date:           Apr. 2008
+KernelVersion:  2.6.26
+Contact:        Dmitry Baryshkov <dbaryshkov@gmail.com>
+Description:
+
+debugfs interface
+-----------------
+		The /debug/clock file displays information about registered
+		clocks, their rates, usage counters, etc.
+
+Example:
+-------
+cat /sys/kernel/debug/clock
+
+GPIO11_CLK            use=4 rate=   3686400 Hz
+  3_6MHz_CLK          use=4 rate=   3686400 Hz
+    32K_CLK           use=1 rate=     32768 Hz
+      MMCCLK          use=1 rate=     32768 Hz for cell tmio-mmc
+    TMIOUSBCLK        use=1 rate=         0 Hz
+      USBCLK          use=1 rate=         0 Hz for cell tmio-ohci
+    TMIOMCLK          use=1 rate=  48000000 Hz
+      FBCLK           use=1 rate=  48000000 Hz for cell tmio-fb
+HWUARTCLK             use=0 rate=  14745600 Hz
+  UARTCLK             use=0 rate=  14745600 Hz for device pxa2xx-uart.3
+LCDCLK                use=0 rate=  99530000 Hz
+FFUARTCLK             use=1 rate=  14745600 Hz
+  UARTCLK             use=1 rate=  14745600 Hz for device pxa2xx-uart.0
+BTUARTCLK             use=0 rate=  14745600 Hz
+  UARTCLK             use=0 rate=  14745600 Hz for device pxa2xx-uart.1
+STUARTCLK             use=0 rate=  14745600 Hz
+  UARTCLK             use=0 rate=  14745600 Hz for device pxa2xx-uart.2
+  SIRCLK              use=0 rate=  14745600 Hz
+UDCCLK                use=0 rate=  47923000 Hz
+PXAMMCCLK             use=0 rate=  19169000 Hz
+  MMCCLK              use=0 rate=  19169000 Hz for device pxa2xx-mci.0
+I2CCLK                use=1 rate=  31949000 Hz
+SSP_CLK               use=0 rate=   3686400 Hz
+  SSPCLK              use=0 rate=   3686400 Hz for device pxa25x-ssp.0
+NSSPCLK               use=1 rate=   3686400 Hz
+  SSPCLK              use=1 rate=   3686400 Hz for device pxa25x-nssp.1
+ASSPCLK               use=0 rate=   3686400 Hz
+  SSPCLK              use=0 rate=   3686400 Hz for device pxa25x-nssp.2
+PWM0CLK               use=0 rate=   3686400 Hz
+  PWMCLK              use=0 rate=   3686400 Hz for device pxa25x-pwm.0
+PWM1CLK               use=0 rate=   3686400 Hz
+  PWMCLK              use=0 rate=   3686400 Hz for device pxa25x-pwm.1
+AC97CLK               use=0 rate=  24576000 Hz
+FICPCLK               use=0 rate=  47923000 Hz
diff --git a/include/linux/clklib.h b/include/linux/clklib.h
index 9545159..46c6977 100644
--- a/include/linux/clklib.h
+++ b/include/linux/clklib.h
@@ -19,6 +19,7 @@ struct seq_file;
  * @get_rate: obtain the current clock rate of a specified clock
  * @set_rate: set the clock rate for a specified clock
  * @round_rate: adjust a reate to the exact rate a clock can provide
+ * @format: output any additional information for a clock
  *
  * This structure specifies clock operations that are used to configure
  * specific clock.
@@ -30,6 +31,7 @@ struct clk_ops {
 	unsigned long (*get_rate)(struct clk *clk);
 	int (*set_rate)(struct clk *, unsigned long);
 	long (*round_rate)(struct clk *, unsigned long);
+	int (*format)(struct clk *, struct seq_file *);
 };
 
 /**
diff --git a/kernel/clklib.c b/kernel/clklib.c
index 024a232..29174c9 100644
--- a/kernel/clklib.c
+++ b/kernel/clklib.c
@@ -332,3 +332,77 @@ out:
 	return rc;
 }
 EXPORT_SYMBOL(clk_alloc_function);
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#define NAME_FIELD_LEN	20
+
+static void dump_clocks(struct seq_file *s, struct clk *parent, int nest)
+{
+	struct clk *clk;
+	int i;
+
+	list_for_each_entry(clk, &clocks, node) {
+		if (clk->parent == parent) {
+			for (i = 0; i < nest; i++) {
+				seq_putc(s, ' ');
+				seq_putc(s, ' ');
+			}
+			seq_puts(s, clk->name);
+
+			i = 2 * nest + strlen(clk->name);
+			if (i >= NAME_FIELD_LEN)
+				i = NAME_FIELD_LEN - 1;
+			for (; i < NAME_FIELD_LEN; i++) {
+				seq_putc(s, ' ');
+			}
+			seq_printf(s, "%c use=%d rate=%10lu Hz",
+				clk->ops && clk->ops->set_parent ? '*' : ' ',
+				clk->users,
+				__clk_get_rate(clk));
+			if (clk->ops && clk->ops->format)
+				clk->ops->format(clk, s);
+			seq_putc(s, '\n');
+
+			dump_clocks(s, clk, nest + 1);
+		}
+	}
+}
+
+static int clocklib_show(struct seq_file *s, void *unused)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+
+	dump_clocks(s, NULL, 0);
+
+	spin_unlock_irqrestore(&clocks_lock, flags);
+
+	return 0;
+}
+
+static int clocklib_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clocklib_show, NULL);
+}
+
+static struct file_operations clocklib_operations = {
+	.open		= clocklib_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init clocklib_debugfs_init(void)
+{
+	debugfs_create_file("clock", S_IFREG | S_IRUGO,
+				NULL, NULL, &clocklib_operations);
+	return 0;
+}
+subsys_initcall(clocklib_debugfs_init);
+
+#endif /* DEBUG_FS */
-- 
1.5.4.4


-- 
With best wishes
Dmitry


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 3/5] Clocklib: support sa1100 sub-arch.
  2008-04-13 14:41 [PATCH 0/5] Clocklib: generic clocks framework Dmitry Baryshkov
  2008-04-13 14:43 ` [PATCH 1/5] Clocklib: add generic framework for managing clocks Dmitry Baryshkov
  2008-04-13 14:43 ` [PATCH 2/5] Clocklib: debugfs support Dmitry Baryshkov
@ 2008-04-13 14:43 ` Dmitry Baryshkov
  2008-04-13 14:43 ` [PATCH 4/5] Clocklib: support ARM pxa sub-arch Dmitry Baryshkov
  2008-04-13 14:43 ` [PATCH 5/5] Clocklib: Use correct clock for IrDA on pxa Dmitry Baryshkov
  4 siblings, 0 replies; 13+ messages in thread
From: Dmitry Baryshkov @ 2008-04-13 14:43 UTC (permalink / raw
  To: linux-kernel
  Cc: akpm, Haavard Skinnemoen, Russell King, Paul Mundt, pHilipp Zabel,
	Pavel Machek, tony, paul, David Brownell

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
 arch/arm/Kconfig             |    1 +
 arch/arm/mach-sa1100/clock.c |  124 ++++++++----------------------------------
 2 files changed, 24 insertions(+), 101 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index cb79d50..113ead3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -416,6 +416,7 @@ config ARCH_RPC
 	select ISA_DMA_API
 	select NO_IOPORT
 	select HAVE_IDE
+	select HAVE_CLOCK_LIB
 	help
 	  On the Acorn Risc-PC, Linux can support the internal IDE disk and
 	  CD-ROM interface, serial and parallel port, and the floppy drive.
diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index fc97fe5..715d91c 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -8,127 +8,49 @@
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/clk.h>
+#include <linux/clklib.h>
 #include <linux/spinlock.h>
 #include <linux/mutex.h>
 
 #include <asm/hardware.h>
 
-/*
- * Very simple clock implementation - we only have one clock to
- * deal with at the moment, so we only match using the "name".
- */
-struct clk {
-	struct list_head	node;
-	unsigned long		rate;
-	const char		*name;
-	unsigned int		enabled;
-	void			(*enable)(void);
-	void			(*disable)(void);
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clocks_lock);
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-
-	mutex_lock(&clocks_mutex);
-	list_for_each_entry(p, &clocks, node) {
-		if (strcmp(id, p->name) == 0) {
-			clk = p;
-			break;
-		}
-	}
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-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)
+static int clk_gpio27_set_enable(struct clk *clk, bool enable)
 {
 	/*
 	 * 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;
+	if (enable) {
+		GAFR |= GPIO_32_768kHz;
+		GPDR |= GPIO_32_768kHz;
+		TUCR = TUCR_3_6864MHz;
+	} else {
+		TUCR = 0;
+		GPDR &= ~GPIO_32_768kHz;
+		GAFR &= ~GPIO_32_768kHz;
+	}
+
+	return 0;
 }
 
-static void clk_gpio27_disable(void)
+static unsigned long clk_gpio27_get_rate(struct clk *clk)
 {
-	TUCR = 0;
-	GPDR &= ~GPIO_32_768kHz;
-	GAFR &= ~GPIO_32_768kHz;
+	return 3686400;
 }
 
+static struct clk_ops clk_gpio27_ops = {
+	.get_rate	= clk_gpio27_get_rate,
+	.set_mode	= clk_gpio27_set_enable,
+};
+
 static struct clk clk_gpio27 = {
 	.name		= "GPIO27_CLK",
-	.rate		= 3686400,
-	.enable		= clk_gpio27_enable,
-	.disable	= clk_gpio27_disable,
+	.ops		= &clk_gpio27_ops,
+	.owner		= THIS_MODULE,
 };
 
-int clk_register(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_add(&clk->node, &clocks);
-	mutex_unlock(&clocks_mutex);
-	return 0;
-}
-EXPORT_SYMBOL(clk_register);
-
-void clk_unregister(struct clk *clk)
-{
-	mutex_lock(&clocks_mutex);
-	list_del(&clk->node);
-	mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clk_unregister);
-
 static int __init clk_init(void)
 {
-	clk_register(&clk_gpio27);
-	return 0;
+	return clk_register(&clk_gpio27);
 }
 arch_initcall(clk_init);
-- 
1.5.4.4


-- 
With best wishes
Dmitry


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 4/5] Clocklib: support ARM pxa sub-arch.
  2008-04-13 14:41 [PATCH 0/5] Clocklib: generic clocks framework Dmitry Baryshkov
                   ` (2 preceding siblings ...)
  2008-04-13 14:43 ` [PATCH 3/5] Clocklib: support sa1100 sub-arch Dmitry Baryshkov
@ 2008-04-13 14:43 ` Dmitry Baryshkov
  2008-04-13 14:43 ` [PATCH 5/5] Clocklib: Use correct clock for IrDA on pxa Dmitry Baryshkov
  4 siblings, 0 replies; 13+ messages in thread
From: Dmitry Baryshkov @ 2008-04-13 14:43 UTC (permalink / raw
  To: linux-kernel
  Cc: akpm, Haavard Skinnemoen, Russell King, Paul Mundt, pHilipp Zabel,
	Pavel Machek, tony, paul, David Brownell

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
 arch/arm/Kconfig           |    1 +
 arch/arm/mach-pxa/clock.c  |  147 ++++++++++++------------------------
 arch/arm/mach-pxa/clock.h  |   63 +++++++---------
 arch/arm/mach-pxa/pxa25x.c |   79 ++++++++++++-------
 arch/arm/mach-pxa/pxa27x.c |   74 ++++++++++--------
 arch/arm/mach-pxa/pxa3xx.c |  182 ++++++++++++++++++++++++-------------------
 6 files changed, 271 insertions(+), 275 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 113ead3..7ade486 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -404,6 +404,7 @@ config ARCH_PXA
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select TICK_ONESHOT
+	select HAVE_CLOCK_LIB
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index e97dc59..8f7fcdd 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -8,6 +8,7 @@
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/clk.h>
+#include <linux/clklib.h>
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
@@ -20,135 +21,83 @@
 #include "generic.h"
 #include "clock.h"
 
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clocks_lock);
-
-static struct clk *clk_lookup(struct device *dev, const char *id)
+static int clk_gpio11_set_mode(struct clk *clk, bool enable)
 {
-	struct clk *p;
-
-	list_for_each_entry(p, &clocks, node)
-		if (strcmp(id, p->name) == 0 && p->dev == dev)
-			return p;
+	if (enable)
+		pxa_gpio_mode(GPIO11_3_6MHz_MD);
 
-	return NULL;
-}
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-
-	mutex_lock(&clocks_mutex);
-	p = clk_lookup(dev, id);
-	if (!p)
-		p = clk_lookup(NULL, id);
-	if (p)
-		clk = p;
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
+	return 0;
 }
-EXPORT_SYMBOL(clk_get);
 
-void clk_put(struct clk *clk)
+static unsigned long clk_gpio11_get_rate(struct clk *clk)
 {
+	return 3686400;
 }
-EXPORT_SYMBOL(clk_put);
 
-int clk_enable(struct clk *clk)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (clk->enabled++ == 0)
-		clk->ops->enable(clk);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-
-	if (clk->delay)
-		udelay(clk->delay);
+static const struct clk_ops clk_gpio11_ops = {
+	.get_rate	= clk_gpio11_get_rate,
+	.set_mode	= clk_gpio11_set_mode,
+};
 
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
+static struct clk clk_gpio11 = {
+	/* For backwards compatibility untill sa1111 and boards are fixed */
+	.name		= "GPIO27_CLK",
+	.ops		= &clk_gpio11_ops,
+	.owner		= THIS_MODULE,
+};
 
-void clk_disable(struct clk *clk)
+int clk_cken_set_mode(struct clk *clk, bool enable)
 {
-	unsigned long flags;
+	struct clk_cken *cclk = container_of(clk, struct clk_cken, clk);
+	int cken = cclk->cken;
 
-	WARN_ON(clk->enabled == 0);
+	if (enable) {
+		CKEN |= 1 << cken;
+		if (cclk->delay)
+			udelay(cclk->delay);
+	} else
+		CKEN &= ~(1 << cken);
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (--clk->enabled == 0)
-		clk->ops->disable(clk);
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
 }
-EXPORT_SYMBOL(clk_disable);
 
-unsigned long clk_get_rate(struct clk *clk)
+unsigned long clk_cken_get_rate(struct clk *clk)
 {
-	unsigned long rate;
-
-	rate = clk->rate;
-	if (clk->ops->getrate)
-		rate = clk->ops->getrate(clk);
+	struct clk_cken *cclk = container_of(clk, struct clk_cken, clk);
 
-	return rate;
+	return cclk->rate;
 }
-EXPORT_SYMBOL(clk_get_rate);
 
+const struct clk_ops clk_cken_ops = {
+	.set_mode = clk_cken_set_mode,
+	.get_rate = clk_cken_get_rate,
+};
 
-static void clk_gpio27_enable(struct clk *clk)
+static int clk_dev_can_get(struct clk *clk, struct device *dev)
 {
-	pxa_gpio_mode(GPIO11_3_6MHz_MD);
-}
+	struct clk_function *cfunc = container_of(clk, struct clk_function, clk);
 
-static void clk_gpio27_disable(struct clk *clk)
-{
+	return (dev == cfunc->priv);
 }
 
-static const struct clkops clk_gpio27_ops = {
-	.enable		= clk_gpio27_enable,
-	.disable	= clk_gpio27_disable,
-};
-
-
-void clk_cken_enable(struct clk *clk)
+static int clk_dev_format(struct clk *clk, struct seq_file *s)
 {
-	CKEN |= 1 << clk->cken;
-}
+	struct clk_function *cfunc = container_of(clk, struct clk_function, clk);
 
-void clk_cken_disable(struct clk *clk)
-{
-	CKEN &= ~(1 << clk->cken);
-}
+	BUG_ON(!cfunc->priv);
 
-const struct clkops clk_cken_ops = {
-	.enable		= clk_cken_enable,
-	.disable	= clk_cken_disable,
-};
+	seq_puts(s, " for device ");
+	seq_puts(s, ((struct device *)cfunc->priv)->bus_id);
+	return 0;
+}
 
-static struct clk common_clks[] = {
-	{
-		.name		= "GPIO27_CLK",
-		.ops		= &clk_gpio27_ops,
-		.rate		= 3686400,
-	},
+const struct clk_ops clk_dev_ops = {
+	.can_get = clk_dev_can_get,
+	.format = clk_dev_format,
 };
 
-void clks_register(struct clk *clks, size_t num)
-{
-	int i;
-
-	mutex_lock(&clocks_mutex);
-	for (i = 0; i < num; i++)
-		list_add(&clks[i].node, &clocks);
-	mutex_unlock(&clocks_mutex);
-}
-
 static int __init clk_init(void)
 {
-	clks_register(common_clks, ARRAY_SIZE(common_clks));
-	return 0;
+	return clk_register(clk_gpio11);
 }
 arch_initcall(clk_init);
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index bc6b77e..db645d8 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -1,43 +1,36 @@
-struct clk;
+#include <linux/clk.h>
+#include <linux/clklib.h>
+#include <linux/seq_file.h>
 
-struct clkops {
-	void			(*enable)(struct clk *);
-	void			(*disable)(struct clk *);
-	unsigned long		(*getrate)(struct clk *);
-};
+extern int clk_cken_set_mode(struct clk *clk, bool enable);
+extern unsigned long clk_cken_get_rate(struct clk *clk);
+extern const struct clk_ops clk_cken_ops;
 
-struct clk {
-	struct list_head	node;
-	const char		*name;
-	struct device		*dev;
-	const struct clkops	*ops;
-	unsigned long		rate;
-	unsigned int		cken;
-	unsigned int		delay;
-	unsigned int		enabled;
+struct clk_cken {
+	unsigned int	cken;
+	unsigned long	rate;
+	int		delay;
+	struct clk	clk;
 };
 
-#define INIT_CKEN(_name, _cken, _rate, _delay, _dev)	\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= &clk_cken_ops,		\
+#define INIT_CKEN(_name, _cken, _rate, _delay)		\
+	&(&(struct clk_cken) {				\
+		.cken = CKEN_##_cken,			\
 		.rate	= _rate,			\
-		.cken	= CKEN_##_cken,			\
 		.delay	= _delay,			\
-	}
-
-#define INIT_CK(_name, _cken, _ops, _dev)		\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= _ops,				\
-		.cken	= CKEN_##_cken,			\
-	}
-
-extern const struct clkops clk_cken_ops;
+		.clk = {				\
+			.name	= _name,		\
+			.ops	= &clk_cken_ops,	\
+		},					\
+	})->clk
 
-void clk_cken_enable(struct clk *clk);
-void clk_cken_disable(struct clk *clk);
+#define INIT_CK(_name, _cken, _ops)			\
+	&(&(struct clk_cken) {				\
+		.cken = CKEN_##_cken,			\
+		.clk = {				\
+			.name	= _name,		\
+			.ops	= _ops,			\
+		},					\
+	})->clk
 
-void clks_register(struct clk *clks, size_t num);
+extern const struct clk_ops clk_dev_ops;
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index e802c79..9f25ca3 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -102,10 +102,9 @@ static unsigned long clk_pxa25x_lcd_getrate(struct clk *clk)
 	return pxa25x_get_memclk_frequency_10khz() * 10000;
 }
 
-static const struct clkops clk_pxa25x_lcd_ops = {
-	.enable		= clk_cken_enable,
-	.disable	= clk_cken_disable,
-	.getrate	= clk_pxa25x_lcd_getrate,
+static const struct clk_ops clk_pxa25x_lcd_ops = {
+	.set_mode = clk_cken_set_mode,
+	.get_rate = clk_pxa25x_lcd_getrate,
 };
 
 /*
@@ -113,31 +112,46 @@ static const struct clkops clk_pxa25x_lcd_ops = {
  * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
  * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly)
  */
-static struct clk pxa25x_hwuart_clk =
-	INIT_CKEN("UARTCLK", HWUART, 14745600, 1, &pxa_device_hwuart.dev)
-;
-
-static struct clk pxa25x_clks[] = {
-	INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
-	INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
-	INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
-	INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL),
-	INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa_device_udc.dev),
-	INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev),
-	INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev),
-
-	INIT_CKEN("SSPCLK",  SSP, 3686400, 0, &pxa25x_device_ssp.dev),
-	INIT_CKEN("SSPCLK", NSSP, 3686400, 0, &pxa25x_device_nssp.dev),
-	INIT_CKEN("SSPCLK", ASSP, 3686400, 0, &pxa25x_device_assp.dev),
-	INIT_CKEN("PWMCLK", PWM0, 3686400, 0, &pxa25x_device_pwm0.dev),
-	INIT_CKEN("PWMCLK", PWM1, 3686400, 0, &pxa25x_device_pwm1.dev),
-
-	INIT_CKEN("AC97CLK",     AC97,     24576000, 0, NULL),
+static struct clk *pxa25x_hwuart_cken_clk =
+	INIT_CKEN("HWUARTCLK", HWUART, 14745600, 1);
+
+static struct clk_function pxa25x_hwuart_func =
+	CLK_FUNC("HWUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_hwuart.dev);
+
+
+static struct clk *pxa25x_clks[] = {
+	INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops),
+	INIT_CKEN("FFUARTCLK", FFUART, 14745600, 1),
+	INIT_CKEN("BTUARTCLK", BTUART, 14745600, 1),
+	INIT_CKEN("STUARTCLK", STUART, 14745600, 1),
+	INIT_CKEN("UDCCLK", USB, 47923000, 5),
+	INIT_CKEN("PXAMMCCLK", MMC, 19169000, 0),
+	INIT_CKEN("I2CCLK", I2C, 31949000, 0),
+
+	INIT_CKEN("SSP_CLK",  SSP, 3686400, 0),
+	INIT_CKEN("NSSPCLK", NSSP, 3686400, 0),
+	INIT_CKEN("ASSPCLK", ASSP, 3686400, 0),
+	INIT_CKEN("PWM0CLK", PWM0, 3686400, 0),
+	INIT_CKEN("PWM1CLK", PWM1, 3686400, 0),
+
+	INIT_CKEN("AC97CLK",     AC97,     24576000, 0),
 
 	/*
-	INIT_CKEN("I2SCLK",  I2S,  14745600, 0, NULL),
+	INIT_CKEN("I2SCLK",  I2S,  14745600, 0),
 	*/
-	INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
+	INIT_CKEN("FICPCLK", FICP, 47923000, 0),
+};
+
+static struct clk_function pxa25x_clk_funcs[] = {
+	CLK_FUNC("FFUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_ffuart.dev),
+	CLK_FUNC("BTUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_btuart.dev),
+	CLK_FUNC("STUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_stuart.dev),
+	CLK_FUNC("PXAMMCCLK", "MMCCLK", &clk_dev_ops, &pxa_device_mci.dev),
+	CLK_FUNC("SSP_CLK", "SSPCLK", &clk_dev_ops, &pxa25x_device_ssp.dev),
+	CLK_FUNC("NSSPCLK", "SSPCLK", &clk_dev_ops, &pxa25x_device_nssp.dev),
+	CLK_FUNC("ASSPCLK", "SSPCLK", &clk_dev_ops, &pxa25x_device_assp.dev),
+	CLK_FUNC("PWM0CLK", "PWMCLK", &clk_dev_ops, &pxa25x_device_pwm0.dev),
+	CLK_FUNC("PWM1CLK", "PWMCLK", &clk_dev_ops, &pxa25x_device_pwm1.dev),
 };
 
 #ifdef CONFIG_PM
@@ -279,17 +293,22 @@ static struct sys_device pxa25x_sysdev[] = {
 		.cls	= &pxa_gpio_sysclass,
 	},
 };
-
 static int __init pxa25x_init(void)
 {
 	int i, ret = 0;
 
 	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
-	if (cpu_is_pxa25x())
-		clks_register(&pxa25x_hwuart_clk, 1);
+	if (cpu_is_pxa25x()) {
+		ret = clk_register(pxa25x_hwuart_cken_clk);
+		if (!ret)
+			ret = clk_alloc_function(
+					pxa25x_hwuart_func.parent,
+					&pxa25x_hwuart_func.clk);
+	}
 
 	if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
-		clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks));
+		ret = clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks));
+		ret = clk_alloc_functions(pxa25x_clk_funcs, ARRAY_SIZE(pxa25x_clk_funcs));
 
 		if ((ret = pxa_init_dma(16)))
 			return ret;
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 3291d6f..ecfe887 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -130,48 +130,59 @@ static unsigned long clk_pxa27x_lcd_getrate(struct clk *clk)
 	return pxa27x_get_lcdclk_frequency_10khz() * 10000;
 }
 
-static const struct clkops clk_pxa27x_lcd_ops = {
-	.enable		= clk_cken_enable,
-	.disable	= clk_cken_disable,
-	.getrate	= clk_pxa27x_lcd_getrate,
+static const struct clk_ops clk_pxa27x_lcd_ops = {
+	.set_mode	= clk_cken_set_mode,
+	.get_rate	= clk_pxa27x_lcd_getrate,
 };
 
-static struct clk pxa27x_clks[] = {
-	INIT_CK("LCDCLK", LCD,    &clk_pxa27x_lcd_ops, &pxa_device_fb.dev),
-	INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops, NULL),
+static struct clk *pxa27x_clks[] = {
+	INIT_CK("LCDCLK", LCD,    &clk_pxa27x_lcd_ops),
+	INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops),
 
-	INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
-	INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
-	INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
+	INIT_CKEN("FFUARTCLK", FFUART, 14857000, 1),
+	INIT_CKEN("BTUARTCLK", BTUART, 14857000, 1),
+	INIT_CKEN("STUARTCLK", STUART, 14857000, 1),
 
-	INIT_CKEN("I2SCLK",  I2S,  14682000, 0, &pxa_device_i2s.dev),
-	INIT_CKEN("I2CCLK",  I2C,  32842000, 0, &pxa_device_i2c.dev),
-	INIT_CKEN("UDCCLK",  USB,  48000000, 5, &pxa_device_udc.dev),
-	INIT_CKEN("MMCCLK",  MMC,  19500000, 0, &pxa_device_mci.dev),
-	INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev),
+	INIT_CKEN("I2SCLK",  I2S,  14682000, 0),
+	INIT_CKEN("I2CCLK",  I2C,  32842000, 0),
+	INIT_CKEN("UDCCLK",  USB,  48000000, 5),
+	INIT_CKEN("PXAMMCCLK",  MMC,  19500000, 0),
+	INIT_CKEN("FICPCLK", FICP, 48000000, 0),
 
-	INIT_CKEN("USBCLK", USBHOST, 48000000, 0, &pxa27x_device_ohci.dev),
-	INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
-	INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, &pxa27x_device_keypad.dev),
+	INIT_CKEN("USBCLK", USBHOST, 48000000, 0),
+	INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0),
+	INIT_CKEN("KBDCLK", KEYPAD, 32768, 0),
 
-	INIT_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
-	INIT_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
-	INIT_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
-	INIT_CKEN("PWMCLK", PWM0, 13000000, 0, &pxa27x_device_pwm0.dev),
-	INIT_CKEN("PWMCLK", PWM1, 13000000, 0, &pxa27x_device_pwm1.dev),
+	INIT_CKEN("SSP1CLK", SSP1, 13000000, 0),
+	INIT_CKEN("SSP2CLK", SSP2, 13000000, 0),
+	INIT_CKEN("SSP3CLK", SSP3, 13000000, 0),
+	INIT_CKEN("PWM0CLK", PWM0, 13000000, 0),
+	INIT_CKEN("PWM1CLK", PWM1, 13000000, 0),
 
-	INIT_CKEN("AC97CLK",     AC97,     24576000, 0, NULL),
-	INIT_CKEN("AC97CONFCLK", AC97CONF, 24576000, 0, NULL),
+	INIT_CKEN("AC97CLK",     AC97,     24576000, 0),
+	INIT_CKEN("AC97CONFCLK", AC97CONF, 24576000, 0),
 
 	/*
-	INIT_CKEN("MSLCLK",  MSL,  48000000, 0, NULL),
-	INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL),
-	INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL),
-	INIT_CKEN("IMCLK",   IM,   0, 0, NULL),
-	INIT_CKEN("MEMCLK",  MEMC, 0, 0, NULL),
+	INIT_CKEN("MSLCLK",  MSL,  48000000, 0),
+	INIT_CKEN("USIMCLK", USIM, 48000000, 0),
+	INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0),
+	INIT_CKEN("IMCLK",   IM,   0, 0),
+	INIT_CKEN("MEMCLK",  MEMC, 0, 0),
 	*/
 };
 
+static struct clk_function pxa27x_clk_funcs[] = {
+	CLK_FUNC("FFUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_ffuart.dev),
+	CLK_FUNC("BTUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_btuart.dev),
+	CLK_FUNC("STUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_stuart.dev),
+	CLK_FUNC("PXAMMCCLK", "MMCCLK", &clk_dev_ops, &pxa_device_mci.dev),
+	CLK_FUNC("SSP1CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp1.dev),
+	CLK_FUNC("SSP2CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp2.dev),
+	CLK_FUNC("SSP3CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp3.dev),
+	CLK_FUNC("PWM0CLK", "PWMCLK", &clk_dev_ops, &pxa27x_device_pwm0.dev),
+	CLK_FUNC("PWM1CLK", "PWMCLK", &clk_dev_ops, &pxa27x_device_pwm1.dev),
+};
+
 #ifdef CONFIG_PM
 
 #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
@@ -380,7 +391,8 @@ static int __init pxa27x_init(void)
 	int i, ret = 0;
 
 	if (cpu_is_pxa27x()) {
-		clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
+		ret = clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
+		ret = clk_alloc_functions(pxa27x_clk_funcs, ARRAY_SIZE(pxa27x_clk_funcs));
 
 		if ((ret = pxa_init_dma(32)))
 			return ret;
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 7c061af..3568c31 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/delay.h>
 #include <linux/sysdev.h>
 
 #include <asm/hardware.h>
@@ -144,107 +145,127 @@ static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
 	return hsio_clk;
 }
 
-static void clk_pxa3xx_cken_enable(struct clk *clk)
+static int clk_pxa3xx_cken_set_mode(struct clk *clk, bool enable)
 {
-	unsigned long mask = 1ul << (clk->cken & 0x1f);
-
-	if (clk->cken < 32)
-		CKENA |= mask;
+	struct clk_cken *cclk = container_of(clk, struct clk_cken, clk);
+	int cken = cclk->cken;
+	unsigned long mask = 1ul << (cken & 0x1f);
+
+	if (cken < 32)
+		if (enable)
+			CKENA |= mask;
+		else
+			CKENA &= ~mask;
 	else
-		CKENB |= mask;
-}
+		if (enable)
+			CKENB |= mask;
+		else
+			CKENB &= ~mask;
 
-static void clk_pxa3xx_cken_disable(struct clk *clk)
-{
-	unsigned long mask = 1ul << (clk->cken & 0x1f);
-
-	if (clk->cken < 32)
-		CKENA &= ~mask;
-	else
-		CKENB &= ~mask;
+	return 0;
 }
 
-static const struct clkops clk_pxa3xx_cken_ops = {
-	.enable		= clk_pxa3xx_cken_enable,
-	.disable	= clk_pxa3xx_cken_disable,
+static const struct clk_ops clk_pxa3xx_cken_ops = {
+	.set_mode	= clk_pxa3xx_cken_set_mode,
+	.get_rate	= clk_cken_get_rate,
 };
 
-static const struct clkops clk_pxa3xx_hsio_ops = {
-	.enable		= clk_pxa3xx_cken_enable,
-	.disable	= clk_pxa3xx_cken_disable,
-	.getrate	= clk_pxa3xx_hsio_getrate,
+static const struct clk_ops clk_pxa3xx_hsio_ops = {
+	.set_mode	= clk_pxa3xx_cken_set_mode,
+	.get_rate	= clk_pxa3xx_hsio_getrate,
 };
 
-static const struct clkops clk_pxa3xx_ac97_ops = {
-	.enable		= clk_pxa3xx_cken_enable,
-	.disable	= clk_pxa3xx_cken_disable,
-	.getrate	= clk_pxa3xx_ac97_getrate,
+static const struct clk_ops clk_pxa3xx_ac97_ops = {
+	.set_mode	= clk_pxa3xx_cken_set_mode,
+	.get_rate	= clk_pxa3xx_ac97_getrate,
 };
 
-static void clk_pout_enable(struct clk *clk)
+static int clk_pout_set_mode(struct clk *clk, bool enable)
 {
-	OSCC |= OSCC_PEN;
-}
+	struct clk_cken *cclk = container_of(clk, struct clk_cken, clk);
+	if (enable) {
+		OSCC |= OSCC_PEN;
+		if (cclk->delay)
+			udelay(cclk->delay);
+	} else
+		OSCC &= ~OSCC_PEN;
 
-static void clk_pout_disable(struct clk *clk)
-{
-	OSCC &= ~OSCC_PEN;
+	return 0;
 }
 
-static const struct clkops clk_pout_ops = {
-	.enable		= clk_pout_enable,
-	.disable	= clk_pout_disable,
+static const struct clk_ops clk_pout_ops = {
+	.set_mode	= clk_pout_set_mode,
+	.get_rate	= clk_cken_get_rate,
 };
 
-#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev)	\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= &clk_pxa3xx_cken_ops,		\
+#define PXA3xx_CKEN(_name, _cken, _rate, _delay)	\
+	&(&(struct clk_cken) {				\
+		.clk	= {				\
+			.name	= _name,		\
+			.ops	= &clk_pxa3xx_cken_ops,	\
+		},					\
 		.rate	= _rate,			\
 		.cken	= CKEN_##_cken,			\
 		.delay	= _delay,			\
-	}
-
-#define PXA3xx_CK(_name, _cken, _ops, _dev)		\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= _ops,				\
-		.cken	= CKEN_##_cken,			\
-	}
-
-static struct clk pxa3xx_clks[] = {
-	{
-		.name           = "CLK_POUT",
-		.ops            = &clk_pout_ops,
+	})->clk
+
+#define PXA3xx_CK(_name, _cken, _ops)			\
+	&(&(struct clk_cken) {				\
+		.cken = CKEN_##_cken,			\
+		.clk = {				\
+			.name	= _name,		\
+			.ops	= _ops,			\
+		},					\
+	})->clk
+
+static struct clk *pxa3xx_clks[] = {
+	&(&(struct clk_cken) {
+		.clk	= {
+			.name	= "CLK_POUT",
+			.ops	= &clk_pout_ops,
+		},
 		.rate           = 13000000,
-		.delay          = 70,
-	},
+		.delay		= 70,
+	})->clk,
+
+	PXA3xx_CK("LCDCLK",  LCD,    &clk_pxa3xx_hsio_ops),
+	PXA3xx_CK("CAMCLK",  CAMERA, &clk_pxa3xx_hsio_ops),
+	PXA3xx_CK("AC97CLK", AC97,   &clk_pxa3xx_ac97_ops),
+
+	PXA3xx_CKEN("FFUARTCLK", FFUART, 14857000, 1),
+	PXA3xx_CKEN("BTUARTCLK", BTUART, 14857000, 1),
+	PXA3xx_CKEN("STUARTCLK", STUART, 14857000, 1),
+
+	PXA3xx_CKEN("I2CCLK", I2C,  32842000, 0),
+	PXA3xx_CKEN("UDCCLK", UDC,  48000000, 5),
+	PXA3xx_CKEN("USBCLK", USBH, 48000000, 0),
+	PXA3xx_CKEN("KBDCLK", KEYPAD,  32768, 0),
+
+	PXA3xx_CKEN("SSP1CLK", SSP1, 13000000, 0),
+	PXA3xx_CKEN("SSP2CLK", SSP2, 13000000, 0),
+	PXA3xx_CKEN("SSP3CLK", SSP3, 13000000, 0),
+	PXA3xx_CKEN("SSP4CLK", SSP4, 13000000, 0),
+	PXA3xx_CKEN("PWM0CLK", PWM0, 13000000, 0),
+	PXA3xx_CKEN("PWM1CLK", PWM1, 13000000, 0),
+
+	PXA3xx_CKEN("MMC1CLK", MMC1, 19500000, 0),
+	PXA3xx_CKEN("MMC2CLK", MMC2, 19500000, 0),
+	PXA3xx_CKEN("MMC3CLK", MMC3, 19500000, 0),
+};
 
-	PXA3xx_CK("LCDCLK",  LCD,    &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
-	PXA3xx_CK("CAMCLK",  CAMERA, &clk_pxa3xx_hsio_ops, NULL),
-	PXA3xx_CK("AC97CLK", AC97,   &clk_pxa3xx_ac97_ops, NULL),
-
-	PXA3xx_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
-	PXA3xx_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
-	PXA3xx_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
-
-	PXA3xx_CKEN("I2CCLK", I2C,  32842000, 0, &pxa_device_i2c.dev),
-	PXA3xx_CKEN("UDCCLK", UDC,  48000000, 5, &pxa_device_udc.dev),
-	PXA3xx_CKEN("USBCLK", USBH, 48000000, 0, &pxa27x_device_ohci.dev),
-	PXA3xx_CKEN("KBDCLK", KEYPAD,  32768, 0, &pxa27x_device_keypad.dev),
-
-	PXA3xx_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
-	PXA3xx_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
-	PXA3xx_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
-	PXA3xx_CKEN("SSPCLK", SSP4, 13000000, 0, &pxa3xx_device_ssp4.dev),
-	PXA3xx_CKEN("PWMCLK", PWM0, 13000000, 0, &pxa27x_device_pwm0.dev),
-	PXA3xx_CKEN("PWMCLK", PWM1, 13000000, 0, &pxa27x_device_pwm1.dev),
-
-	PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev),
-	PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev),
-	PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
+static struct clk_function pxa3xx_clk_funcs[] = {
+	CLK_FUNC("FFUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_ffuart.dev),
+	CLK_FUNC("BTUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_btuart.dev),
+	CLK_FUNC("STUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_stuart.dev),
+	CLK_FUNC("SSP1CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp1.dev),
+	CLK_FUNC("SSP2CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp2.dev),
+	CLK_FUNC("SSP3CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp3.dev),
+	CLK_FUNC("SSP4CLK", "SSPCLK", &clk_dev_ops, &pxa3xx_device_ssp4.dev),
+	CLK_FUNC("MMC1CLK", "MMCCLK", &clk_dev_ops, &pxa_device_mci.dev),
+	CLK_FUNC("MMC2CLK", "MMCCLK", &clk_dev_ops, &pxa3xx_device_mci2.dev),
+	CLK_FUNC("MMC3CLK", "MMCCLK", &clk_dev_ops, &pxa3xx_device_mci3.dev),
+	CLK_FUNC("PWM0CLK", "PWMCLK", &clk_dev_ops, &pxa27x_device_pwm0.dev),
+	CLK_FUNC("PWM1CLK", "PWMCLK", &clk_dev_ops, &pxa27x_device_pwm1.dev),
 };
 
 #ifdef CONFIG_PM
@@ -556,7 +577,8 @@ static int __init pxa3xx_init(void)
 		 */
 		ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
 
-		clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
+		ret = clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
+		ret = clk_alloc_functions(pxa3xx_clk_funcs, ARRAY_SIZE(pxa3xx_clk_funcs));
 
 		if ((ret = pxa_init_dma(32)))
 			return ret;
-- 
1.5.4.4


-- 
With best wishes
Dmitry


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 5/5] Clocklib: Use correct clock for IrDA on pxa
  2008-04-13 14:41 [PATCH 0/5] Clocklib: generic clocks framework Dmitry Baryshkov
                   ` (3 preceding siblings ...)
  2008-04-13 14:43 ` [PATCH 4/5] Clocklib: support ARM pxa sub-arch Dmitry Baryshkov
@ 2008-04-13 14:43 ` Dmitry Baryshkov
  4 siblings, 0 replies; 13+ messages in thread
From: Dmitry Baryshkov @ 2008-04-13 14:43 UTC (permalink / raw
  To: linux-kernel
  Cc: akpm, Haavard Skinnemoen, Russell King, Paul Mundt, pHilipp Zabel,
	Pavel Machek, tony, paul, David Brownell

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
 drivers/net/irda/pxaficp_ir.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 8db71ab..1aae2d6 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -815,7 +815,7 @@ static int pxa_irda_probe(struct platform_device *pdev)
 	si->dev = &pdev->dev;
 	si->pdata = pdev->dev.platform_data;
 
-	si->sir_clk = clk_get(&pdev->dev, "UARTCLK");
+	si->sir_clk = clk_get(&pdev->dev, "STUARTCLK");
 	si->fir_clk = clk_get(&pdev->dev, "FICPCLK");
 	if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) {
 		err = PTR_ERR(IS_ERR(si->sir_clk) ? si->sir_clk : si->fir_clk);
-- 
1.5.4.4


-- 
With best wishes
Dmitry


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/5] Clocklib: add generic framework for managing clocks.
  2008-04-13 14:43 ` [PATCH 1/5] Clocklib: add generic framework for managing clocks Dmitry Baryshkov
@ 2008-04-15  6:13   ` Andrew Morton
  2008-04-15  9:34     ` Dmitry Baryshkov
  2008-04-16  5:21     ` Haavard Skinnemoen
  0 siblings, 2 replies; 13+ messages in thread
From: Andrew Morton @ 2008-04-15  6:13 UTC (permalink / raw
  To: Dmitry Baryshkov
  Cc: linux-kernel, Haavard Skinnemoen, Russell King, Paul Mundt,
	pHilipp Zabel, Pavel Machek, tony, paul, David Brownell

On Sun, 13 Apr 2008 18:43:12 +0400 Dmitry Baryshkov <dbaryshkov@gmail.com> wrote:

> +#define FUNC_TO_CLK(func)	&(&(struct clk_function) func)->clk

scratched my head for a while, was unable to work out what this does.
It is unused, so I think it can be zapped?

All the inlined functions in clklib.h are waaaaaaaaaaaay too big
to be inlined.  Did I fail to notice that last time around?

Anyway, this patchset is basically an arm-only thing, so I'll need
guidance, please...

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/5] Clocklib: add generic framework for managing clocks.
  2008-04-15  6:13   ` Andrew Morton
@ 2008-04-15  9:34     ` Dmitry Baryshkov
  2008-04-15  9:47       ` Andrew Morton
  2008-04-16  5:21     ` Haavard Skinnemoen
  1 sibling, 1 reply; 13+ messages in thread
From: Dmitry Baryshkov @ 2008-04-15  9:34 UTC (permalink / raw
  To: Andrew Morton
  Cc: linux-kernel, Haavard Skinnemoen, Russell King, Paul Mundt,
	pHilipp Zabel, Pavel Machek, tony, paul, David Brownell

On Mon, Apr 14, 2008 at 11:13:30PM -0700, Andrew Morton wrote:
> On Sun, 13 Apr 2008 18:43:12 +0400 Dmitry Baryshkov <dbaryshkov@gmail.com> wrote:
> 
> > +#define FUNC_TO_CLK(func)	&(&(struct clk_function) func)->clk
> 
> scratched my head for a while, was unable to work out what this does.
> It is unused, so I think it can be zapped?

It take clk_function and returns pointer to the contained struct clk.
It's unused in the submitted code, but it's used in the yet-in-progress
drivers for Toshiba companion chips. I used it to be able to write
things like:

static struct clk *clks[] = {
        [TC6387XB_CLK_MMC] = FUNC_TO_CLK(MFD_CLK_FUNC(NULL, "MMCCLK",
				&tc6387xb_cells[TC6387XB_CELL_MMC])),
};

where MFD_CLK_FUNC instantiates some special sort of clk_function.

> 
> All the inlined functions in clklib.h are waaaaaaaaaaaay too big
> to be inlined.  Did I fail to notice that last time around?

OK.

> 
> Anyway, this patchset is basically an arm-only thing, so I'll need
> guidance, please...

They were posted to the LKML with CC to arch maintainers primary to get
their feedback. I have a hope that it can be used not only for various
arms, but for other arches. As you can see posting it here helped to make
the whole patchset better and less memory hungry.

As currently the patchset only contains the generic and ARM-related
things, I think it can and should go in via Russell, if he agrees.

Russell?

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/5] Clocklib: add generic framework for managing clocks.
  2008-04-15  9:34     ` Dmitry Baryshkov
@ 2008-04-15  9:47       ` Andrew Morton
  2008-04-15  9:53         ` Pavel Machek
  0 siblings, 1 reply; 13+ messages in thread
From: Andrew Morton @ 2008-04-15  9:47 UTC (permalink / raw
  To: Dmitry Baryshkov
  Cc: linux-kernel, Haavard Skinnemoen, Russell King, Paul Mundt,
	pHilipp Zabel, Pavel Machek, tony, paul, David Brownell

On Tue, 15 Apr 2008 13:34:51 +0400 Dmitry Baryshkov <dbaryshkov@gmail.com> wrote:

> On Mon, Apr 14, 2008 at 11:13:30PM -0700, Andrew Morton wrote:
> > On Sun, 13 Apr 2008 18:43:12 +0400 Dmitry Baryshkov <dbaryshkov@gmail.com> wrote:
> > 
> > > +#define FUNC_TO_CLK(func)	&(&(struct clk_function) func)->clk
> > 
> > scratched my head for a while, was unable to work out what this does.
> > It is unused, so I think it can be zapped?
> 
> It take clk_function and returns pointer to the contained struct clk.

Then why does it cast a clk_function to a clk_function?

The innermost `&' hurts my brain.

> I used it to be able to write things like:
> 
> static struct clk *clks[] = {
> 	        [TC6387XB_CLK_MMC] = FUNC_TO_CLK(MFD_CLK_FUNC(NULL, "MMCCLK",
> 					&tc6387xb_cells[TC6387XB_CELL_MMC])),
> };
> 

erm, if you say so.  Is this as simple and clear as we can possibly make it?

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/5] Clocklib: add generic framework for managing clocks.
  2008-04-15  9:47       ` Andrew Morton
@ 2008-04-15  9:53         ` Pavel Machek
  2008-04-15 10:11           ` Dmitry Baryshkov
  0 siblings, 1 reply; 13+ messages in thread
From: Pavel Machek @ 2008-04-15  9:53 UTC (permalink / raw
  To: Andrew Morton
  Cc: Dmitry Baryshkov, linux-kernel, Haavard Skinnemoen, Russell King,
	Paul Mundt, pHilipp Zabel, tony, paul, David Brownell

> On Tue, 15 Apr 2008 13:34:51 +0400 Dmitry Baryshkov <dbaryshkov@gmail.com> wrote:
> 
> > On Mon, Apr 14, 2008 at 11:13:30PM -0700, Andrew Morton wrote:
> > > On Sun, 13 Apr 2008 18:43:12 +0400 Dmitry Baryshkov <dbaryshkov@gmail.com> wrote:
> > > 
> > > > +#define FUNC_TO_CLK(func)	&(&(struct clk_function) func)->clk
> > > 
> > > scratched my head for a while, was unable to work out what this does.
> > > It is unused, so I think it can be zapped?
> > 
> > It take clk_function and returns pointer to the contained struct clk.
> 
> Then why does it cast a clk_function to a clk_function?
> 
> The innermost `&' hurts my brain.

Hmm, is that obfuscated way of writing

&(func.clk)

?
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/5] Clocklib: add generic framework for managing clocks.
  2008-04-15  9:53         ` Pavel Machek
@ 2008-04-15 10:11           ` Dmitry Baryshkov
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry Baryshkov @ 2008-04-15 10:11 UTC (permalink / raw
  To: Pavel Machek
  Cc: Andrew Morton, linux-kernel, Haavard Skinnemoen, Russell King,
	Paul Mundt, pHilipp Zabel, tony, paul, David Brownell

On Tue, Apr 15, 2008 at 11:53:32AM +0200, Pavel Machek wrote:
> > On Tue, 15 Apr 2008 13:34:51 +0400 Dmitry Baryshkov <dbaryshkov@gmail.com> wrote:
> > 
> > > On Mon, Apr 14, 2008 at 11:13:30PM -0700, Andrew Morton wrote:
> > > > On Sun, 13 Apr 2008 18:43:12 +0400 Dmitry Baryshkov <dbaryshkov@gmail.com> wrote:
> > > > 
> > > > > +#define FUNC_TO_CLK(func)	&(&(struct clk_function) func)->clk
> > > > 
> > > > scratched my head for a while, was unable to work out what this does.
> > > > It is unused, so I think it can be zapped?
> > > 
> > > It take clk_function and returns pointer to the contained struct clk.
> > 
> > Then why does it cast a clk_function to a clk_function?
> > 
> > The innermost `&' hurts my brain.
> 
> Hmm, is that obfuscated way of writing
> 
> &(func.clk)

Oops... Yes. Then it really can be dropped.

> 
> ?
> 									Pavel
> 
> -- 
> (english) http://www.livejournal.com/~pavelmachek
> (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

-- 
With best wishes
Dmitry


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/5] Clocklib: add generic framework for managing clocks.
  2008-04-15  6:13   ` Andrew Morton
  2008-04-15  9:34     ` Dmitry Baryshkov
@ 2008-04-16  5:21     ` Haavard Skinnemoen
  1 sibling, 0 replies; 13+ messages in thread
From: Haavard Skinnemoen @ 2008-04-16  5:21 UTC (permalink / raw
  To: Andrew Morton
  Cc: Dmitry Baryshkov, linux-kernel, Russell King, Paul Mundt,
	pHilipp Zabel, Pavel Machek, tony, paul, David Brownell

On Mon, 14 Apr 2008 23:13:30 -0700
Andrew Morton <akpm@linux-foundation.org> wrote:

> Anyway, this patchset is basically an arm-only thing, so I'll need
> guidance, please...

As soon as any drivers starts using the dynamic clock registration API
introduced by these patches, other architectures will be sort of forced
to care about it...

I consider switching to clklib on avr32 regardless of this...though I
haven't really started that work yet.

But if Russell want to merge this initial dump through the ARM tree, I'm
perfectly fine with that, even if this library is intended to be
architecture-neutral.

Haavard

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 4/5] Clocklib: support ARM pxa sub-arch.
  2008-04-20  8:29 [PATCH 0/5] Clocklib: generic clocks framework Dmitry Baryshkov
@ 2008-04-20  8:31 ` Dmitry Baryshkov
  0 siblings, 0 replies; 13+ messages in thread
From: Dmitry Baryshkov @ 2008-04-20  8:31 UTC (permalink / raw
  To: linux-kernel
  Cc: akpm, Haavard Skinnemoen, Russell King, Paul Mundt, pHilipp Zabel,
	Pavel Machek, tony, paul, David Brownell

Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com>
---
 arch/arm/Kconfig           |    1 +
 arch/arm/mach-pxa/clock.c  |  147 ++++++++++++------------------------
 arch/arm/mach-pxa/clock.h  |   63 +++++++---------
 arch/arm/mach-pxa/pxa25x.c |   79 ++++++++++++-------
 arch/arm/mach-pxa/pxa27x.c |   74 ++++++++++--------
 arch/arm/mach-pxa/pxa3xx.c |  182 ++++++++++++++++++++++++-------------------
 6 files changed, 271 insertions(+), 275 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 113ead3..7ade486 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -404,6 +404,7 @@ config ARCH_PXA
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select TICK_ONESHOT
+	select HAVE_CLOCK_LIB
 	help
 	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
 
diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index e97dc59..74fedfb 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -8,6 +8,7 @@
 #include <linux/err.h>
 #include <linux/string.h>
 #include <linux/clk.h>
+#include <linux/clklib.h>
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
@@ -20,135 +21,83 @@
 #include "generic.h"
 #include "clock.h"
 
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clocks_lock);
-
-static struct clk *clk_lookup(struct device *dev, const char *id)
+static int clk_gpio11_set_mode(struct clk *clk, bool enable)
 {
-	struct clk *p;
-
-	list_for_each_entry(p, &clocks, node)
-		if (strcmp(id, p->name) == 0 && p->dev == dev)
-			return p;
+	if (enable)
+		pxa_gpio_mode(GPIO11_3_6MHz_MD);
 
-	return NULL;
-}
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *p, *clk = ERR_PTR(-ENOENT);
-
-	mutex_lock(&clocks_mutex);
-	p = clk_lookup(dev, id);
-	if (!p)
-		p = clk_lookup(NULL, id);
-	if (p)
-		clk = p;
-	mutex_unlock(&clocks_mutex);
-
-	return clk;
+	return 0;
 }
-EXPORT_SYMBOL(clk_get);
 
-void clk_put(struct clk *clk)
+static unsigned long clk_gpio11_get_rate(struct clk *clk)
 {
+	return 3686400;
 }
-EXPORT_SYMBOL(clk_put);
 
-int clk_enable(struct clk *clk)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (clk->enabled++ == 0)
-		clk->ops->enable(clk);
-	spin_unlock_irqrestore(&clocks_lock, flags);
-
-	if (clk->delay)
-		udelay(clk->delay);
+static const struct clk_ops clk_gpio11_ops = {
+	.get_rate	= clk_gpio11_get_rate,
+	.set_mode	= clk_gpio11_set_mode,
+};
 
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
+static struct clk clk_gpio11 = {
+	/* For backwards compatibility untill sa1111 and boards are fixed */
+	.name		= "GPIO27_CLK",
+	.ops		= &clk_gpio11_ops,
+	.owner		= THIS_MODULE,
+};
 
-void clk_disable(struct clk *clk)
+int clk_cken_set_mode(struct clk *clk, bool enable)
 {
-	unsigned long flags;
+	struct clk_cken *cclk = container_of(clk, struct clk_cken, clk);
+	int cken = cclk->cken;
 
-	WARN_ON(clk->enabled == 0);
+	if (enable) {
+		CKEN |= 1 << cken;
+		if (cclk->delay)
+			udelay(cclk->delay);
+	} else
+		CKEN &= ~(1 << cken);
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (--clk->enabled == 0)
-		clk->ops->disable(clk);
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
 }
-EXPORT_SYMBOL(clk_disable);
 
-unsigned long clk_get_rate(struct clk *clk)
+unsigned long clk_cken_get_rate(struct clk *clk)
 {
-	unsigned long rate;
-
-	rate = clk->rate;
-	if (clk->ops->getrate)
-		rate = clk->ops->getrate(clk);
+	struct clk_cken *cclk = container_of(clk, struct clk_cken, clk);
 
-	return rate;
+	return cclk->rate;
 }
-EXPORT_SYMBOL(clk_get_rate);
 
+const struct clk_ops clk_cken_ops = {
+	.set_mode = clk_cken_set_mode,
+	.get_rate = clk_cken_get_rate,
+};
 
-static void clk_gpio27_enable(struct clk *clk)
+static int clk_dev_can_get(struct clk *clk, struct device *dev)
 {
-	pxa_gpio_mode(GPIO11_3_6MHz_MD);
-}
+	struct clk_function *cfunc = container_of(clk, struct clk_function, clk);
 
-static void clk_gpio27_disable(struct clk *clk)
-{
+	return (dev == cfunc->priv);
 }
 
-static const struct clkops clk_gpio27_ops = {
-	.enable		= clk_gpio27_enable,
-	.disable	= clk_gpio27_disable,
-};
-
-
-void clk_cken_enable(struct clk *clk)
+static int clk_dev_format(struct clk *clk, struct seq_file *s)
 {
-	CKEN |= 1 << clk->cken;
-}
+	struct clk_function *cfunc = container_of(clk, struct clk_function, clk);
 
-void clk_cken_disable(struct clk *clk)
-{
-	CKEN &= ~(1 << clk->cken);
-}
+	BUG_ON(!cfunc->priv);
 
-const struct clkops clk_cken_ops = {
-	.enable		= clk_cken_enable,
-	.disable	= clk_cken_disable,
-};
+	seq_puts(s, " for device ");
+	seq_puts(s, ((struct device *)cfunc->priv)->bus_id);
+	return 0;
+}
 
-static struct clk common_clks[] = {
-	{
-		.name		= "GPIO27_CLK",
-		.ops		= &clk_gpio27_ops,
-		.rate		= 3686400,
-	},
+const struct clk_ops clk_dev_ops = {
+	.can_get = clk_dev_can_get,
+	.format = clk_dev_format,
 };
 
-void clks_register(struct clk *clks, size_t num)
-{
-	int i;
-
-	mutex_lock(&clocks_mutex);
-	for (i = 0; i < num; i++)
-		list_add(&clks[i].node, &clocks);
-	mutex_unlock(&clocks_mutex);
-}
-
 static int __init clk_init(void)
 {
-	clks_register(common_clks, ARRAY_SIZE(common_clks));
-	return 0;
+	return clk_register(&clk_gpio11);
 }
 arch_initcall(clk_init);
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index bc6b77e..976cf8a 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -1,43 +1,36 @@
-struct clk;
+#include <linux/clk.h>
+#include <linux/clklib.h>
+#include <linux/seq_file.h>
 
-struct clkops {
-	void			(*enable)(struct clk *);
-	void			(*disable)(struct clk *);
-	unsigned long		(*getrate)(struct clk *);
-};
+extern int clk_cken_set_mode(struct clk *clk, bool enable);
+extern unsigned long clk_cken_get_rate(struct clk *clk);
+extern const struct clk_ops clk_cken_ops;
 
-struct clk {
-	struct list_head	node;
-	const char		*name;
-	struct device		*dev;
-	const struct clkops	*ops;
-	unsigned long		rate;
-	unsigned int		cken;
-	unsigned int		delay;
-	unsigned int		enabled;
+struct clk_cken {
+	unsigned int	cken;
+	unsigned long	rate;
+	int		delay;
+	struct clk	clk;
 };
 
-#define INIT_CKEN(_name, _cken, _rate, _delay, _dev)	\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= &clk_cken_ops,		\
+#define INIT_CKEN(_name, _cken, _rate, _delay)		\
+	&(struct clk_cken) {				\
+		.cken = CKEN_##_cken,			\
 		.rate	= _rate,			\
-		.cken	= CKEN_##_cken,			\
 		.delay	= _delay,			\
-	}
-
-#define INIT_CK(_name, _cken, _ops, _dev)		\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= _ops,				\
-		.cken	= CKEN_##_cken,			\
-	}
-
-extern const struct clkops clk_cken_ops;
+		.clk = {				\
+			.name	= _name,		\
+			.ops	= &clk_cken_ops,	\
+		},					\
+	}.clk
 
-void clk_cken_enable(struct clk *clk);
-void clk_cken_disable(struct clk *clk);
+#define INIT_CK(_name, _cken, _ops)			\
+	&(struct clk_cken) {				\
+		.cken = CKEN_##_cken,			\
+		.clk = {				\
+			.name	= _name,		\
+			.ops	= _ops,			\
+		},					\
+	}.clk
 
-void clks_register(struct clk *clks, size_t num);
+extern const struct clk_ops clk_dev_ops;
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index e802c79..9f25ca3 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -102,10 +102,9 @@ static unsigned long clk_pxa25x_lcd_getrate(struct clk *clk)
 	return pxa25x_get_memclk_frequency_10khz() * 10000;
 }
 
-static const struct clkops clk_pxa25x_lcd_ops = {
-	.enable		= clk_cken_enable,
-	.disable	= clk_cken_disable,
-	.getrate	= clk_pxa25x_lcd_getrate,
+static const struct clk_ops clk_pxa25x_lcd_ops = {
+	.set_mode = clk_cken_set_mode,
+	.get_rate = clk_pxa25x_lcd_getrate,
 };
 
 /*
@@ -113,31 +112,46 @@ static const struct clkops clk_pxa25x_lcd_ops = {
  * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
  * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly)
  */
-static struct clk pxa25x_hwuart_clk =
-	INIT_CKEN("UARTCLK", HWUART, 14745600, 1, &pxa_device_hwuart.dev)
-;
-
-static struct clk pxa25x_clks[] = {
-	INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
-	INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
-	INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
-	INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL),
-	INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa_device_udc.dev),
-	INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev),
-	INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev),
-
-	INIT_CKEN("SSPCLK",  SSP, 3686400, 0, &pxa25x_device_ssp.dev),
-	INIT_CKEN("SSPCLK", NSSP, 3686400, 0, &pxa25x_device_nssp.dev),
-	INIT_CKEN("SSPCLK", ASSP, 3686400, 0, &pxa25x_device_assp.dev),
-	INIT_CKEN("PWMCLK", PWM0, 3686400, 0, &pxa25x_device_pwm0.dev),
-	INIT_CKEN("PWMCLK", PWM1, 3686400, 0, &pxa25x_device_pwm1.dev),
-
-	INIT_CKEN("AC97CLK",     AC97,     24576000, 0, NULL),
+static struct clk *pxa25x_hwuart_cken_clk =
+	INIT_CKEN("HWUARTCLK", HWUART, 14745600, 1);
+
+static struct clk_function pxa25x_hwuart_func =
+	CLK_FUNC("HWUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_hwuart.dev);
+
+
+static struct clk *pxa25x_clks[] = {
+	INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops),
+	INIT_CKEN("FFUARTCLK", FFUART, 14745600, 1),
+	INIT_CKEN("BTUARTCLK", BTUART, 14745600, 1),
+	INIT_CKEN("STUARTCLK", STUART, 14745600, 1),
+	INIT_CKEN("UDCCLK", USB, 47923000, 5),
+	INIT_CKEN("PXAMMCCLK", MMC, 19169000, 0),
+	INIT_CKEN("I2CCLK", I2C, 31949000, 0),
+
+	INIT_CKEN("SSP_CLK",  SSP, 3686400, 0),
+	INIT_CKEN("NSSPCLK", NSSP, 3686400, 0),
+	INIT_CKEN("ASSPCLK", ASSP, 3686400, 0),
+	INIT_CKEN("PWM0CLK", PWM0, 3686400, 0),
+	INIT_CKEN("PWM1CLK", PWM1, 3686400, 0),
+
+	INIT_CKEN("AC97CLK",     AC97,     24576000, 0),
 
 	/*
-	INIT_CKEN("I2SCLK",  I2S,  14745600, 0, NULL),
+	INIT_CKEN("I2SCLK",  I2S,  14745600, 0),
 	*/
-	INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
+	INIT_CKEN("FICPCLK", FICP, 47923000, 0),
+};
+
+static struct clk_function pxa25x_clk_funcs[] = {
+	CLK_FUNC("FFUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_ffuart.dev),
+	CLK_FUNC("BTUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_btuart.dev),
+	CLK_FUNC("STUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_stuart.dev),
+	CLK_FUNC("PXAMMCCLK", "MMCCLK", &clk_dev_ops, &pxa_device_mci.dev),
+	CLK_FUNC("SSP_CLK", "SSPCLK", &clk_dev_ops, &pxa25x_device_ssp.dev),
+	CLK_FUNC("NSSPCLK", "SSPCLK", &clk_dev_ops, &pxa25x_device_nssp.dev),
+	CLK_FUNC("ASSPCLK", "SSPCLK", &clk_dev_ops, &pxa25x_device_assp.dev),
+	CLK_FUNC("PWM0CLK", "PWMCLK", &clk_dev_ops, &pxa25x_device_pwm0.dev),
+	CLK_FUNC("PWM1CLK", "PWMCLK", &clk_dev_ops, &pxa25x_device_pwm1.dev),
 };
 
 #ifdef CONFIG_PM
@@ -279,17 +293,22 @@ static struct sys_device pxa25x_sysdev[] = {
 		.cls	= &pxa_gpio_sysclass,
 	},
 };
-
 static int __init pxa25x_init(void)
 {
 	int i, ret = 0;
 
 	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
-	if (cpu_is_pxa25x())
-		clks_register(&pxa25x_hwuart_clk, 1);
+	if (cpu_is_pxa25x()) {
+		ret = clk_register(pxa25x_hwuart_cken_clk);
+		if (!ret)
+			ret = clk_alloc_function(
+					pxa25x_hwuart_func.parent,
+					&pxa25x_hwuart_func.clk);
+	}
 
 	if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
-		clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks));
+		ret = clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks));
+		ret = clk_alloc_functions(pxa25x_clk_funcs, ARRAY_SIZE(pxa25x_clk_funcs));
 
 		if ((ret = pxa_init_dma(16)))
 			return ret;
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 3291d6f..ecfe887 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -130,48 +130,59 @@ static unsigned long clk_pxa27x_lcd_getrate(struct clk *clk)
 	return pxa27x_get_lcdclk_frequency_10khz() * 10000;
 }
 
-static const struct clkops clk_pxa27x_lcd_ops = {
-	.enable		= clk_cken_enable,
-	.disable	= clk_cken_disable,
-	.getrate	= clk_pxa27x_lcd_getrate,
+static const struct clk_ops clk_pxa27x_lcd_ops = {
+	.set_mode	= clk_cken_set_mode,
+	.get_rate	= clk_pxa27x_lcd_getrate,
 };
 
-static struct clk pxa27x_clks[] = {
-	INIT_CK("LCDCLK", LCD,    &clk_pxa27x_lcd_ops, &pxa_device_fb.dev),
-	INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops, NULL),
+static struct clk *pxa27x_clks[] = {
+	INIT_CK("LCDCLK", LCD,    &clk_pxa27x_lcd_ops),
+	INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops),
 
-	INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
-	INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
-	INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
+	INIT_CKEN("FFUARTCLK", FFUART, 14857000, 1),
+	INIT_CKEN("BTUARTCLK", BTUART, 14857000, 1),
+	INIT_CKEN("STUARTCLK", STUART, 14857000, 1),
 
-	INIT_CKEN("I2SCLK",  I2S,  14682000, 0, &pxa_device_i2s.dev),
-	INIT_CKEN("I2CCLK",  I2C,  32842000, 0, &pxa_device_i2c.dev),
-	INIT_CKEN("UDCCLK",  USB,  48000000, 5, &pxa_device_udc.dev),
-	INIT_CKEN("MMCCLK",  MMC,  19500000, 0, &pxa_device_mci.dev),
-	INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev),
+	INIT_CKEN("I2SCLK",  I2S,  14682000, 0),
+	INIT_CKEN("I2CCLK",  I2C,  32842000, 0),
+	INIT_CKEN("UDCCLK",  USB,  48000000, 5),
+	INIT_CKEN("PXAMMCCLK",  MMC,  19500000, 0),
+	INIT_CKEN("FICPCLK", FICP, 48000000, 0),
 
-	INIT_CKEN("USBCLK", USBHOST, 48000000, 0, &pxa27x_device_ohci.dev),
-	INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
-	INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, &pxa27x_device_keypad.dev),
+	INIT_CKEN("USBCLK", USBHOST, 48000000, 0),
+	INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0),
+	INIT_CKEN("KBDCLK", KEYPAD, 32768, 0),
 
-	INIT_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
-	INIT_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
-	INIT_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
-	INIT_CKEN("PWMCLK", PWM0, 13000000, 0, &pxa27x_device_pwm0.dev),
-	INIT_CKEN("PWMCLK", PWM1, 13000000, 0, &pxa27x_device_pwm1.dev),
+	INIT_CKEN("SSP1CLK", SSP1, 13000000, 0),
+	INIT_CKEN("SSP2CLK", SSP2, 13000000, 0),
+	INIT_CKEN("SSP3CLK", SSP3, 13000000, 0),
+	INIT_CKEN("PWM0CLK", PWM0, 13000000, 0),
+	INIT_CKEN("PWM1CLK", PWM1, 13000000, 0),
 
-	INIT_CKEN("AC97CLK",     AC97,     24576000, 0, NULL),
-	INIT_CKEN("AC97CONFCLK", AC97CONF, 24576000, 0, NULL),
+	INIT_CKEN("AC97CLK",     AC97,     24576000, 0),
+	INIT_CKEN("AC97CONFCLK", AC97CONF, 24576000, 0),
 
 	/*
-	INIT_CKEN("MSLCLK",  MSL,  48000000, 0, NULL),
-	INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL),
-	INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL),
-	INIT_CKEN("IMCLK",   IM,   0, 0, NULL),
-	INIT_CKEN("MEMCLK",  MEMC, 0, 0, NULL),
+	INIT_CKEN("MSLCLK",  MSL,  48000000, 0),
+	INIT_CKEN("USIMCLK", USIM, 48000000, 0),
+	INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0),
+	INIT_CKEN("IMCLK",   IM,   0, 0),
+	INIT_CKEN("MEMCLK",  MEMC, 0, 0),
 	*/
 };
 
+static struct clk_function pxa27x_clk_funcs[] = {
+	CLK_FUNC("FFUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_ffuart.dev),
+	CLK_FUNC("BTUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_btuart.dev),
+	CLK_FUNC("STUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_stuart.dev),
+	CLK_FUNC("PXAMMCCLK", "MMCCLK", &clk_dev_ops, &pxa_device_mci.dev),
+	CLK_FUNC("SSP1CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp1.dev),
+	CLK_FUNC("SSP2CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp2.dev),
+	CLK_FUNC("SSP3CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp3.dev),
+	CLK_FUNC("PWM0CLK", "PWMCLK", &clk_dev_ops, &pxa27x_device_pwm0.dev),
+	CLK_FUNC("PWM1CLK", "PWMCLK", &clk_dev_ops, &pxa27x_device_pwm1.dev),
+};
+
 #ifdef CONFIG_PM
 
 #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
@@ -380,7 +391,8 @@ static int __init pxa27x_init(void)
 	int i, ret = 0;
 
 	if (cpu_is_pxa27x()) {
-		clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
+		ret = clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
+		ret = clk_alloc_functions(pxa27x_clk_funcs, ARRAY_SIZE(pxa27x_clk_funcs));
 
 		if ((ret = pxa_init_dma(32)))
 			return ret;
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 7c061af..cef6d80 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/delay.h>
 #include <linux/sysdev.h>
 
 #include <asm/hardware.h>
@@ -144,107 +145,127 @@ static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
 	return hsio_clk;
 }
 
-static void clk_pxa3xx_cken_enable(struct clk *clk)
+static int clk_pxa3xx_cken_set_mode(struct clk *clk, bool enable)
 {
-	unsigned long mask = 1ul << (clk->cken & 0x1f);
-
-	if (clk->cken < 32)
-		CKENA |= mask;
+	struct clk_cken *cclk = container_of(clk, struct clk_cken, clk);
+	int cken = cclk->cken;
+	unsigned long mask = 1ul << (cken & 0x1f);
+
+	if (cken < 32)
+		if (enable)
+			CKENA |= mask;
+		else
+			CKENA &= ~mask;
 	else
-		CKENB |= mask;
-}
+		if (enable)
+			CKENB |= mask;
+		else
+			CKENB &= ~mask;
 
-static void clk_pxa3xx_cken_disable(struct clk *clk)
-{
-	unsigned long mask = 1ul << (clk->cken & 0x1f);
-
-	if (clk->cken < 32)
-		CKENA &= ~mask;
-	else
-		CKENB &= ~mask;
+	return 0;
 }
 
-static const struct clkops clk_pxa3xx_cken_ops = {
-	.enable		= clk_pxa3xx_cken_enable,
-	.disable	= clk_pxa3xx_cken_disable,
+static const struct clk_ops clk_pxa3xx_cken_ops = {
+	.set_mode	= clk_pxa3xx_cken_set_mode,
+	.get_rate	= clk_cken_get_rate,
 };
 
-static const struct clkops clk_pxa3xx_hsio_ops = {
-	.enable		= clk_pxa3xx_cken_enable,
-	.disable	= clk_pxa3xx_cken_disable,
-	.getrate	= clk_pxa3xx_hsio_getrate,
+static const struct clk_ops clk_pxa3xx_hsio_ops = {
+	.set_mode	= clk_pxa3xx_cken_set_mode,
+	.get_rate	= clk_pxa3xx_hsio_getrate,
 };
 
-static const struct clkops clk_pxa3xx_ac97_ops = {
-	.enable		= clk_pxa3xx_cken_enable,
-	.disable	= clk_pxa3xx_cken_disable,
-	.getrate	= clk_pxa3xx_ac97_getrate,
+static const struct clk_ops clk_pxa3xx_ac97_ops = {
+	.set_mode	= clk_pxa3xx_cken_set_mode,
+	.get_rate	= clk_pxa3xx_ac97_getrate,
 };
 
-static void clk_pout_enable(struct clk *clk)
+static int clk_pout_set_mode(struct clk *clk, bool enable)
 {
-	OSCC |= OSCC_PEN;
-}
+	struct clk_cken *cclk = container_of(clk, struct clk_cken, clk);
+	if (enable) {
+		OSCC |= OSCC_PEN;
+		if (cclk->delay)
+			udelay(cclk->delay);
+	} else
+		OSCC &= ~OSCC_PEN;
 
-static void clk_pout_disable(struct clk *clk)
-{
-	OSCC &= ~OSCC_PEN;
+	return 0;
 }
 
-static const struct clkops clk_pout_ops = {
-	.enable		= clk_pout_enable,
-	.disable	= clk_pout_disable,
+static const struct clk_ops clk_pout_ops = {
+	.set_mode	= clk_pout_set_mode,
+	.get_rate	= clk_cken_get_rate,
 };
 
-#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev)	\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= &clk_pxa3xx_cken_ops,		\
+#define PXA3xx_CKEN(_name, _cken, _rate, _delay)	\
+	&(struct clk_cken) {				\
+		.clk	= {				\
+			.name	= _name,		\
+			.ops	= &clk_pxa3xx_cken_ops,	\
+		},					\
 		.rate	= _rate,			\
 		.cken	= CKEN_##_cken,			\
 		.delay	= _delay,			\
-	}
-
-#define PXA3xx_CK(_name, _cken, _ops, _dev)		\
-	{						\
-		.name	= _name,			\
-		.dev	= _dev,				\
-		.ops	= _ops,				\
-		.cken	= CKEN_##_cken,			\
-	}
-
-static struct clk pxa3xx_clks[] = {
-	{
-		.name           = "CLK_POUT",
-		.ops            = &clk_pout_ops,
+	}.clk
+
+#define PXA3xx_CK(_name, _cken, _ops)			\
+	&(struct clk_cken) {				\
+		.cken = CKEN_##_cken,			\
+		.clk = {				\
+			.name	= _name,		\
+			.ops	= _ops,			\
+		},					\
+	}.clk
+
+static struct clk *pxa3xx_clks[] = {
+	&(&(struct clk_cken) {
+		.clk	= {
+			.name	= "CLK_POUT",
+			.ops	= &clk_pout_ops,
+		},
 		.rate           = 13000000,
-		.delay          = 70,
-	},
+		.delay		= 70,
+	})->clk,
+
+	PXA3xx_CK("LCDCLK",  LCD,    &clk_pxa3xx_hsio_ops),
+	PXA3xx_CK("CAMCLK",  CAMERA, &clk_pxa3xx_hsio_ops),
+	PXA3xx_CK("AC97CLK", AC97,   &clk_pxa3xx_ac97_ops),
+
+	PXA3xx_CKEN("FFUARTCLK", FFUART, 14857000, 1),
+	PXA3xx_CKEN("BTUARTCLK", BTUART, 14857000, 1),
+	PXA3xx_CKEN("STUARTCLK", STUART, 14857000, 1),
+
+	PXA3xx_CKEN("I2CCLK", I2C,  32842000, 0),
+	PXA3xx_CKEN("UDCCLK", UDC,  48000000, 5),
+	PXA3xx_CKEN("USBCLK", USBH, 48000000, 0),
+	PXA3xx_CKEN("KBDCLK", KEYPAD,  32768, 0),
+
+	PXA3xx_CKEN("SSP1CLK", SSP1, 13000000, 0),
+	PXA3xx_CKEN("SSP2CLK", SSP2, 13000000, 0),
+	PXA3xx_CKEN("SSP3CLK", SSP3, 13000000, 0),
+	PXA3xx_CKEN("SSP4CLK", SSP4, 13000000, 0),
+	PXA3xx_CKEN("PWM0CLK", PWM0, 13000000, 0),
+	PXA3xx_CKEN("PWM1CLK", PWM1, 13000000, 0),
+
+	PXA3xx_CKEN("MMC1CLK", MMC1, 19500000, 0),
+	PXA3xx_CKEN("MMC2CLK", MMC2, 19500000, 0),
+	PXA3xx_CKEN("MMC3CLK", MMC3, 19500000, 0),
+};
 
-	PXA3xx_CK("LCDCLK",  LCD,    &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
-	PXA3xx_CK("CAMCLK",  CAMERA, &clk_pxa3xx_hsio_ops, NULL),
-	PXA3xx_CK("AC97CLK", AC97,   &clk_pxa3xx_ac97_ops, NULL),
-
-	PXA3xx_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
-	PXA3xx_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
-	PXA3xx_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
-
-	PXA3xx_CKEN("I2CCLK", I2C,  32842000, 0, &pxa_device_i2c.dev),
-	PXA3xx_CKEN("UDCCLK", UDC,  48000000, 5, &pxa_device_udc.dev),
-	PXA3xx_CKEN("USBCLK", USBH, 48000000, 0, &pxa27x_device_ohci.dev),
-	PXA3xx_CKEN("KBDCLK", KEYPAD,  32768, 0, &pxa27x_device_keypad.dev),
-
-	PXA3xx_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
-	PXA3xx_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
-	PXA3xx_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
-	PXA3xx_CKEN("SSPCLK", SSP4, 13000000, 0, &pxa3xx_device_ssp4.dev),
-	PXA3xx_CKEN("PWMCLK", PWM0, 13000000, 0, &pxa27x_device_pwm0.dev),
-	PXA3xx_CKEN("PWMCLK", PWM1, 13000000, 0, &pxa27x_device_pwm1.dev),
-
-	PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev),
-	PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev),
-	PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
+static struct clk_function pxa3xx_clk_funcs[] = {
+	CLK_FUNC("FFUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_ffuart.dev),
+	CLK_FUNC("BTUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_btuart.dev),
+	CLK_FUNC("STUARTCLK", "UARTCLK", &clk_dev_ops, &pxa_device_stuart.dev),
+	CLK_FUNC("SSP1CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp1.dev),
+	CLK_FUNC("SSP2CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp2.dev),
+	CLK_FUNC("SSP3CLK", "SSPCLK", &clk_dev_ops, &pxa27x_device_ssp3.dev),
+	CLK_FUNC("SSP4CLK", "SSPCLK", &clk_dev_ops, &pxa3xx_device_ssp4.dev),
+	CLK_FUNC("MMC1CLK", "MMCCLK", &clk_dev_ops, &pxa_device_mci.dev),
+	CLK_FUNC("MMC2CLK", "MMCCLK", &clk_dev_ops, &pxa3xx_device_mci2.dev),
+	CLK_FUNC("MMC3CLK", "MMCCLK", &clk_dev_ops, &pxa3xx_device_mci3.dev),
+	CLK_FUNC("PWM0CLK", "PWMCLK", &clk_dev_ops, &pxa27x_device_pwm0.dev),
+	CLK_FUNC("PWM1CLK", "PWMCLK", &clk_dev_ops, &pxa27x_device_pwm1.dev),
 };
 
 #ifdef CONFIG_PM
@@ -556,7 +577,8 @@ static int __init pxa3xx_init(void)
 		 */
 		ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
 
-		clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
+		ret = clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
+		ret = clk_alloc_functions(pxa3xx_clk_funcs, ARRAY_SIZE(pxa3xx_clk_funcs));
 
 		if ((ret = pxa_init_dma(32)))
 			return ret;
-- 
1.5.4.4


-- 
With best wishes
Dmitry


^ permalink raw reply related	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2008-04-20  8:32 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-04-13 14:41 [PATCH 0/5] Clocklib: generic clocks framework Dmitry Baryshkov
2008-04-13 14:43 ` [PATCH 1/5] Clocklib: add generic framework for managing clocks Dmitry Baryshkov
2008-04-15  6:13   ` Andrew Morton
2008-04-15  9:34     ` Dmitry Baryshkov
2008-04-15  9:47       ` Andrew Morton
2008-04-15  9:53         ` Pavel Machek
2008-04-15 10:11           ` Dmitry Baryshkov
2008-04-16  5:21     ` Haavard Skinnemoen
2008-04-13 14:43 ` [PATCH 2/5] Clocklib: debugfs support Dmitry Baryshkov
2008-04-13 14:43 ` [PATCH 3/5] Clocklib: support sa1100 sub-arch Dmitry Baryshkov
2008-04-13 14:43 ` [PATCH 4/5] Clocklib: support ARM pxa sub-arch Dmitry Baryshkov
2008-04-13 14:43 ` [PATCH 5/5] Clocklib: Use correct clock for IrDA on pxa Dmitry Baryshkov
  -- strict thread matches above, loose matches on Subject: below --
2008-04-20  8:29 [PATCH 0/5] Clocklib: generic clocks framework Dmitry Baryshkov
2008-04-20  8:31 ` [PATCH 4/5] Clocklib: support ARM pxa sub-arch Dmitry Baryshkov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.