All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/7] Add a generic struct clk
@ 2011-09-22 22:26 ` Mike Turquette
  0 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Mike Turquette

Hi all,

The goal of this series is to provide a cross-platform clock framework
that platforms can use to model their clock trees and perform common
operations on them.  Currently everyone re-invents their own clock tree
inside platform code which makes it impossible for drivers to use the
clock APIs safely across many platforms and for distro's to compile
multi-platform kernels which all redefine struct clk and its operations.

This is the second version of the common clock patches which were
originally posted by Jeremy Kerr and then re-posted with some additional
patches by Mark Brown.  Mark's re-post didn't have any changes done to
the original four patches from Jeremy which is why this series is "v2".

The changes in this series are minimal: I've folded in some of Mark's
fixes and most of the comments posted to his series as well as rebasing
on top of v3.1-rc7.  The design and functionality hasn't changed much
since Jeremy posted v1 of this series.  Propagating the rate change up
to the parent has been removed from clk_set_rate since that needs some
more thought.  I also dropped Mark's change to append a device's name to
a clk name since device tree might solve this neatly.  Again more
discussion around that would be good.

v1 of the series can be found at,
http://article.gmane.org/gmane.linux.kernel/1143182

Mark's re-post (v1+) can be found at,
http://article.gmane.org/gmane.linux.ports.arm.kernel/129889

Todo in follow-up patches:
clk_set_parent
Implement a *safe* upstream propagation for parent rate changes
Track tree topology and export to userspace (sysfs or debugfs)
Manage root clocks globally
Device tree support
Per-tree locking instead of framework-wide locking
Device driver rate-change notifiers

Jeremy Kerr (4):
  clk: Add a generic clock infrastructure
  clk: Implement clk_set_rate
  clk: Add fixed-rate clock
  clk: Add simple gated clock

Mark Brown (3):
  clk: Add Kconfig option to build all generic clk drivers
  clk: Add initial WM831x clock driver
  x86: Enable generic clk API on x86

 MAINTAINERS              |    1 +
 arch/x86/Kconfig         |    1 +
 drivers/clk/Kconfig      |   27 +++-
 drivers/clk/Makefile     |    4 +
 drivers/clk/clk-fixed.c  |   24 +++
 drivers/clk/clk-gate.c   |   78 ++++++++++
 drivers/clk/clk-wm831x.c |  386 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clk.c        |  291 ++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c     |    7 +
 include/linux/clk.h      |  179 ++++++++++++++++++++--
 10 files changed, 985 insertions(+), 13 deletions(-)
 create mode 100644 drivers/clk/clk-fixed.c
 create mode 100644 drivers/clk/clk-gate.c
 create mode 100644 drivers/clk/clk-wm831x.c
 create mode 100644 drivers/clk/clk.c

-- 
1.7.4.1


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

* [PATCH v2 0/7] Add a generic struct clk
@ 2011-09-22 22:26 ` Mike Turquette
  0 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

The goal of this series is to provide a cross-platform clock framework
that platforms can use to model their clock trees and perform common
operations on them.  Currently everyone re-invents their own clock tree
inside platform code which makes it impossible for drivers to use the
clock APIs safely across many platforms and for distro's to compile
multi-platform kernels which all redefine struct clk and its operations.

This is the second version of the common clock patches which were
originally posted by Jeremy Kerr and then re-posted with some additional
patches by Mark Brown.  Mark's re-post didn't have any changes done to
the original four patches from Jeremy which is why this series is "v2".

The changes in this series are minimal: I've folded in some of Mark's
fixes and most of the comments posted to his series as well as rebasing
on top of v3.1-rc7.  The design and functionality hasn't changed much
since Jeremy posted v1 of this series.  Propagating the rate change up
to the parent has been removed from clk_set_rate since that needs some
more thought.  I also dropped Mark's change to append a device's name to
a clk name since device tree might solve this neatly.  Again more
discussion around that would be good.

v1 of the series can be found at,
http://article.gmane.org/gmane.linux.kernel/1143182

Mark's re-post (v1+) can be found at,
http://article.gmane.org/gmane.linux.ports.arm.kernel/129889

Todo in follow-up patches:
clk_set_parent
Implement a *safe* upstream propagation for parent rate changes
Track tree topology and export to userspace (sysfs or debugfs)
Manage root clocks globally
Device tree support
Per-tree locking instead of framework-wide locking
Device driver rate-change notifiers

Jeremy Kerr (4):
  clk: Add a generic clock infrastructure
  clk: Implement clk_set_rate
  clk: Add fixed-rate clock
  clk: Add simple gated clock

Mark Brown (3):
  clk: Add Kconfig option to build all generic clk drivers
  clk: Add initial WM831x clock driver
  x86: Enable generic clk API on x86

 MAINTAINERS              |    1 +
 arch/x86/Kconfig         |    1 +
 drivers/clk/Kconfig      |   27 +++-
 drivers/clk/Makefile     |    4 +
 drivers/clk/clk-fixed.c  |   24 +++
 drivers/clk/clk-gate.c   |   78 ++++++++++
 drivers/clk/clk-wm831x.c |  386 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clk.c        |  291 ++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c     |    7 +
 include/linux/clk.h      |  179 ++++++++++++++++++++--
 10 files changed, 985 insertions(+), 13 deletions(-)
 create mode 100644 drivers/clk/clk-fixed.c
 create mode 100644 drivers/clk/clk-gate.c
 create mode 100644 drivers/clk/clk-wm831x.c
 create mode 100644 drivers/clk/clk.c

-- 
1.7.4.1

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-22 22:26   ` Mike Turquette
  -1 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Mike Turquette

From: Jeremy Kerr <jeremy.kerr@canonical.com>

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, and a set of clock operations. Different clock
implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

The interface is split into two halves:

 * struct clk, which is the generic-device-driver interface. This
   provides a set of functions which drivers may use to request
   enable/disable, query or manipulate in a hardware-independent manner.

 * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
   interface. Clock drivers implement the ops, which allow the core
   clock code to implement the generic 'struct clk' API.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
common, opaque struct clk, and a set of clock operations (defined per
type of clock):

  struct clk_hw_ops {
  	int		(*prepare)(struct clk_hw *);
  	void		(*unprepare)(struct clk_hw *);
  	int		(*enable)(struct clk_hw *);
  	void		(*disable)(struct clk_hw *);
  	unsigned long	(*recalc_rate)(struct clk_hw *);
  	int		(*set_rate)(struct clk_hw *,
  					unsigned long, unsigned long *);
  	long		(*round_rate)(struct clk_hw *, unsigned long);
  	int		(*set_parent)(struct clk_hw *, struct clk *);
  	struct clk *	(*get_parent)(struct clk_hw *);
  };

Platform clock code can register a clock through clk_register, passing a
set of operations, and a pointer to hardware-specific data:

  struct clk_hw_foo {
  	struct clk_hw clk;
  	void __iomem *enable_reg;
  };

  #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)

  static int clk_foo_enable(struct clk_hw *clk)
  {
  	struct clk_foo *foo = to_clk_foo(clk);
  	raw_writeb(foo->enable_reg, 1);
  	return 0;
  }

  struct clk_hw_ops clk_foo_ops = {
  	.enable = clk_foo_enable,
  };

And in the platform initialisation code:

  struct clk_foo my_clk_foo;

  void init_clocks(void)
  {
  	my_clk_foo.enable_reg = ioremap(...);

  	clk_register(&clk_foo_ops, &my_clk_foo, NULL);
  }

Changes from Thomas Gleixner <tglx@linutronix.de>.

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

TODO:

 * We don't keep any internal reference to the clock topology at present.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Create a dummy clk_unregister and prototype/document it and clk_register
Constify struct clk_hw_ops
Remove spinlock.h header, include kernel.h
Use EOPNOTSUPP instead of ENOTSUPP
Add might_sleep to clk_prepare/clk_unprepare stubs
Properly init children hlist and child_node
Whitespace and typo fixes

 drivers/clk/Kconfig  |    3 +
 drivers/clk/Makefile |    1 +
 drivers/clk/clk.c    |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    7 ++
 include/linux/clk.h  |  140 +++++++++++++++++++++++++++---
 5 files changed, 371 insertions(+), 12 deletions(-)
 create mode 100644 drivers/clk/clk.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 3530927..c53ed59 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
 
 config HAVE_MACH_CLKDEV
 	bool
+
+config GENERIC_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..570d5b9 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_GENERIC_CLK)	+= clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..1cd7315
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct clk {
+	const char		*name;
+	const struct clk_hw_ops	*ops;
+	struct clk_hw		*hw;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	struct clk		*parent;
+	unsigned long		rate;
+};
+
+static DEFINE_SPINLOCK(enable_lock);
+static DEFINE_MUTEX(prepare_lock);
+
+static void __clk_unprepare(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	if (WARN_ON(clk->prepare_count == 0))
+		return;
+
+	if (--clk->prepare_count > 0)
+		return;
+
+	WARN_ON(clk->enable_count > 0);
+
+	if (clk->ops->unprepare)
+		clk->ops->unprepare(clk->hw);
+
+	__clk_unprepare(clk->parent);
+}
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&prepare_lock);
+	__clk_unprepare(clk);
+	mutex_unlock(&prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+static int __clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk)
+		return 0;
+
+	if (clk->prepare_count == 0) {
+		ret = __clk_prepare(clk->parent);
+		if (ret)
+			return ret;
+
+		if (clk->ops->prepare) {
+			ret = clk->ops->prepare(clk->hw);
+			if (ret) {
+				__clk_unprepare(clk->parent);
+				return ret;
+			}
+		}
+	}
+
+	clk->prepare_count++;
+
+	return 0;
+}
+
+int clk_prepare(struct clk *clk)
+{
+	int ret;
+
+	mutex_lock(&prepare_lock);
+	ret = __clk_prepare(clk);
+	mutex_unlock(&prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+static void __clk_disable(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	if (WARN_ON(clk->enable_count == 0))
+		return;
+
+	if (--clk->enable_count > 0)
+		return;
+
+	if (clk->ops->disable)
+		clk->ops->disable(clk->hw);
+	__clk_disable(clk->parent);
+}
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&enable_lock, flags);
+	__clk_disable(clk);
+	spin_unlock_irqrestore(&enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+static int __clk_enable(struct clk *clk)
+{
+	int ret;
+
+	if (!clk)
+		return 0;
+
+	if (WARN_ON(clk->prepare_count == 0))
+		return -ESHUTDOWN;
+
+
+	if (clk->enable_count == 0) {
+		ret = __clk_enable(clk->parent);
+		if (ret)
+			return ret;
+
+		if (clk->ops->enable) {
+			ret = clk->ops->enable(clk->hw);
+			if (ret) {
+				__clk_disable(clk->parent);
+				return ret;
+			}
+		}
+	}
+
+	clk->enable_count++;
+	return 0;
+}
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&enable_lock, flags);
+	ret = __clk_enable(clk);
+	spin_unlock_irqrestore(&enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+	return clk->rate;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk && clk->ops->round_rate)
+		return clk->ops->round_rate(clk->hw, rate);
+	return rate;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	/* not yet implemented */
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (!clk)
+		return NULL;
+
+	return clk->parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	/* not yet implemented */
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
+		const char *name)
+{
+	struct clk *clk;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return NULL;
+
+	INIT_HLIST_HEAD(&clk->children);
+	INIT_HLIST_NODE(&clk->child_node);
+
+	clk->name = name;
+	clk->ops = ops;
+	clk->hw = hw;
+	hw->clk = clk;
+
+	/* Query the hardware for parent and initial rate */
+
+	if (clk->ops->get_parent)
+		/* We don't to lock against prepare/enable here, as
+		 * the clock is not yet accessible from anywhere */
+		clk->parent = clk->ops->get_parent(clk->hw);
+
+	if (clk->ops->recalc_rate)
+		clk->rate = clk->ops->recalc_rate(clk->hw);
+
+
+	return clk;
+}
+EXPORT_SYMBOL_GPL(clk_register);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 6db161f..e2a9719 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -23,6 +23,13 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
+ * through other headers; we don't want them used anywhere but here. */
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..d6ae10b 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,17 +12,137 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
 struct device;
 
-/*
- * The base API.
+struct clk;
+
+#ifdef CONFIG_GENERIC_CLK
+
+struct clk_hw {
+	struct clk *clk;
+};
+
+/**
+ * struct clk_hw_ops -  Callback operations for hardware clocks; these are to
+ * be provided by the clock implementation, and will be called by drivers
+ * through the clk_* API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may sleep. Called with
+ *		prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with enable_lock held. This function must not
+ *		sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with enable_lock held.
+ *		This function must not sleep.
+ *
+ * @recalc_rate	Recalculate the rate of this clock, by quering hardware
+ *		and/or the clock's parent. Called with the global clock mutex
+ *		held. Optional, but recommended - if this op is not set,
+ *		clk_get_rate will return 0.
+ *
+ * @get_parent	Query the parent of this clock; for clocks with multiple
+ *		possible parents, query the hardware for the current
+ *		parent. Currently only called when the clock is first
+ *		registered.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
+ * should be done in clk_prepare. Switching that will not sleep should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
  */
+struct clk_hw_ops {
+	int		(*prepare)(struct clk_hw *);
+	void		(*unprepare)(struct clk_hw *);
+	int		(*enable)(struct clk_hw *);
+	void		(*disable)(struct clk_hw *);
+	unsigned long	(*recalc_rate)(struct clk_hw *);
+	long		(*round_rate)(struct clk_hw *, unsigned long);
+	struct clk *	(*get_parent)(struct clk_hw *);
+};
 
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any possibly sleeping initialisation on @clk, allowing the clock to be
+ * later enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possibly sleeping) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_register - register and initialize a new clock
+ *
+ * @ops: ops for the new clock
+ * @hw: struct clk_hw to be passed to the ops of the new clock
+ * @name: name to use for the new clock
+ *
+ * Register a new clock with the clk subsystem.  Returns either a
+ * struct clk for the new clock or a NULL pointer.
+ */
+struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
+			 const char *name);
+
+/**
+ * clk_unregister - remove a clock
+ *
+ * @clk: clock to unregister
+ *
+ * Remove a clock from the clk subsystem.  This is currently not
+ * implemented but is provided to allow unregistration code to be
+ * written in drivers ready for use when an implementation is
+ * provided.
+ */
+static inline int clk_unregister(struct clk *clk)
+{
+	return -EOPNOTSUPP;
+}
+
+#else /* !CONFIG_GENERIC_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * For !CONFIG_GENERIC_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
  */
-struct clk;
+static inline int clk_prepare(struct clk *clk) {
+	might_sleep();
+	return 0;
+}
+
+static inline void clk_unprepare(struct clk *clk) {
+	might_sleep();
+}
+
+#endif /* !CONFIG_GENERIC_CLK */
 
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
@@ -67,6 +188,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +205,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source
@@ -97,7 +213,7 @@ void clk_put(struct clk *clk);
  * Returns rounded clock rate in Hz, or negative errno.
  */
 long clk_round_rate(struct clk *clk, unsigned long rate);
- 
+
 /**
  * clk_set_rate - set the clock rate for a clock source
  * @clk: clock source
@@ -106,7 +222,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
  * Returns success (0) or negative errno.
  */
 int clk_set_rate(struct clk *clk, unsigned long rate);
- 
+
 /**
  * clk_set_parent - set the parent clock source for this clock
  * @clk: clock source
-- 
1.7.4.1


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-09-22 22:26   ` Mike Turquette
  0 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jeremy Kerr <jeremy.kerr@canonical.com>

We currently have ~21 definitions of struct clk in the ARM architecture,
each defined on a per-platform basis. This makes it difficult to define
platform- (or architecture-) independent clock sources without making
assumptions about struct clk, and impossible to compile two
platforms with different struct clks into a single image.

This change is an effort to unify struct clk where possible, by defining
a common struct clk, and a set of clock operations. Different clock
implementations can set their own operations, and have a standard
interface for generic code. The callback interface is exposed to the
kernel proper, while the clock implementations only need to be seen by
the platform internals.

The interface is split into two halves:

 * struct clk, which is the generic-device-driver interface. This
   provides a set of functions which drivers may use to request
   enable/disable, query or manipulate in a hardware-independent manner.

 * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
   interface. Clock drivers implement the ops, which allow the core
   clock code to implement the generic 'struct clk' API.

This allows us to share clock code among platforms, and makes it
possible to dynamically create clock devices in platform-independent
code.

Platforms can enable the generic struct clock through
CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
common, opaque struct clk, and a set of clock operations (defined per
type of clock):

  struct clk_hw_ops {
  	int		(*prepare)(struct clk_hw *);
  	void		(*unprepare)(struct clk_hw *);
  	int		(*enable)(struct clk_hw *);
  	void		(*disable)(struct clk_hw *);
  	unsigned long	(*recalc_rate)(struct clk_hw *);
  	int		(*set_rate)(struct clk_hw *,
  					unsigned long, unsigned long *);
  	long		(*round_rate)(struct clk_hw *, unsigned long);
  	int		(*set_parent)(struct clk_hw *, struct clk *);
  	struct clk *	(*get_parent)(struct clk_hw *);
  };

Platform clock code can register a clock through clk_register, passing a
set of operations, and a pointer to hardware-specific data:

  struct clk_hw_foo {
  	struct clk_hw clk;
  	void __iomem *enable_reg;
  };

  #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)

  static int clk_foo_enable(struct clk_hw *clk)
  {
  	struct clk_foo *foo = to_clk_foo(clk);
  	raw_writeb(foo->enable_reg, 1);
  	return 0;
  }

  struct clk_hw_ops clk_foo_ops = {
  	.enable = clk_foo_enable,
  };

And in the platform initialisation code:

  struct clk_foo my_clk_foo;

  void init_clocks(void)
  {
  	my_clk_foo.enable_reg = ioremap(...);

  	clk_register(&clk_foo_ops, &my_clk_foo, NULL);
  }

Changes from Thomas Gleixner <tglx@linutronix.de>.

The common clock definitions are based on a development patch from Ben
Herrenschmidt <benh@kernel.crashing.org>.

TODO:

 * We don't keep any internal reference to the clock topology at present.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Create a dummy clk_unregister and prototype/document it and clk_register
Constify struct clk_hw_ops
Remove spinlock.h header, include kernel.h
Use EOPNOTSUPP instead of ENOTSUPP
Add might_sleep to clk_prepare/clk_unprepare stubs
Properly init children hlist and child_node
Whitespace and typo fixes

 drivers/clk/Kconfig  |    3 +
 drivers/clk/Makefile |    1 +
 drivers/clk/clk.c    |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    7 ++
 include/linux/clk.h  |  140 +++++++++++++++++++++++++++---
 5 files changed, 371 insertions(+), 12 deletions(-)
 create mode 100644 drivers/clk/clk.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 3530927..c53ed59 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
 
 config HAVE_MACH_CLKDEV
 	bool
+
+config GENERIC_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..570d5b9 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_GENERIC_CLK)	+= clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..1cd7315
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct clk {
+	const char		*name;
+	const struct clk_hw_ops	*ops;
+	struct clk_hw		*hw;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	struct clk		*parent;
+	unsigned long		rate;
+};
+
+static DEFINE_SPINLOCK(enable_lock);
+static DEFINE_MUTEX(prepare_lock);
+
+static void __clk_unprepare(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	if (WARN_ON(clk->prepare_count == 0))
+		return;
+
+	if (--clk->prepare_count > 0)
+		return;
+
+	WARN_ON(clk->enable_count > 0);
+
+	if (clk->ops->unprepare)
+		clk->ops->unprepare(clk->hw);
+
+	__clk_unprepare(clk->parent);
+}
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&prepare_lock);
+	__clk_unprepare(clk);
+	mutex_unlock(&prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+static int __clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk)
+		return 0;
+
+	if (clk->prepare_count == 0) {
+		ret = __clk_prepare(clk->parent);
+		if (ret)
+			return ret;
+
+		if (clk->ops->prepare) {
+			ret = clk->ops->prepare(clk->hw);
+			if (ret) {
+				__clk_unprepare(clk->parent);
+				return ret;
+			}
+		}
+	}
+
+	clk->prepare_count++;
+
+	return 0;
+}
+
+int clk_prepare(struct clk *clk)
+{
+	int ret;
+
+	mutex_lock(&prepare_lock);
+	ret = __clk_prepare(clk);
+	mutex_unlock(&prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+static void __clk_disable(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	if (WARN_ON(clk->enable_count == 0))
+		return;
+
+	if (--clk->enable_count > 0)
+		return;
+
+	if (clk->ops->disable)
+		clk->ops->disable(clk->hw);
+	__clk_disable(clk->parent);
+}
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&enable_lock, flags);
+	__clk_disable(clk);
+	spin_unlock_irqrestore(&enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+static int __clk_enable(struct clk *clk)
+{
+	int ret;
+
+	if (!clk)
+		return 0;
+
+	if (WARN_ON(clk->prepare_count == 0))
+		return -ESHUTDOWN;
+
+
+	if (clk->enable_count == 0) {
+		ret = __clk_enable(clk->parent);
+		if (ret)
+			return ret;
+
+		if (clk->ops->enable) {
+			ret = clk->ops->enable(clk->hw);
+			if (ret) {
+				__clk_disable(clk->parent);
+				return ret;
+			}
+		}
+	}
+
+	clk->enable_count++;
+	return 0;
+}
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&enable_lock, flags);
+	ret = __clk_enable(clk);
+	spin_unlock_irqrestore(&enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (!clk)
+		return 0;
+	return clk->rate;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk && clk->ops->round_rate)
+		return clk->ops->round_rate(clk->hw, rate);
+	return rate;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	/* not yet implemented */
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (!clk)
+		return NULL;
+
+	return clk->parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	/* not yet implemented */
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
+		const char *name)
+{
+	struct clk *clk;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return NULL;
+
+	INIT_HLIST_HEAD(&clk->children);
+	INIT_HLIST_NODE(&clk->child_node);
+
+	clk->name = name;
+	clk->ops = ops;
+	clk->hw = hw;
+	hw->clk = clk;
+
+	/* Query the hardware for parent and initial rate */
+
+	if (clk->ops->get_parent)
+		/* We don't to lock against prepare/enable here, as
+		 * the clock is not yet accessible from anywhere */
+		clk->parent = clk->ops->get_parent(clk->hw);
+
+	if (clk->ops->recalc_rate)
+		clk->rate = clk->ops->recalc_rate(clk->hw);
+
+
+	return clk;
+}
+EXPORT_SYMBOL_GPL(clk_register);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 6db161f..e2a9719 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -23,6 +23,13 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
+ * through other headers; we don't want them used anywhere but here. */
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..d6ae10b 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,17 +12,137 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/kernel.h>
+#include <linux/errno.h>
+
 struct device;
 
-/*
- * The base API.
+struct clk;
+
+#ifdef CONFIG_GENERIC_CLK
+
+struct clk_hw {
+	struct clk *clk;
+};
+
+/**
+ * struct clk_hw_ops -  Callback operations for hardware clocks; these are to
+ * be provided by the clock implementation, and will be called by drivers
+ * through the clk_* API.
+ *
+ * @prepare:	Prepare the clock for enabling. This must not return until
+ *		the clock is fully prepared, and it's safe to call clk_enable.
+ *		This callback is intended to allow clock implementations to
+ *		do any initialisation that may sleep. Called with
+ *		prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		prepare_lock held.
+ *
+ * @enable:	Enable the clock atomically. This must not return until the
+ *		clock is generating a valid clock signal, usable by consumer
+ *		devices. Called with enable_lock held. This function must not
+ *		sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with enable_lock held.
+ *		This function must not sleep.
+ *
+ * @recalc_rate	Recalculate the rate of this clock, by quering hardware
+ *		and/or the clock's parent. Called with the global clock mutex
+ *		held. Optional, but recommended - if this op is not set,
+ *		clk_get_rate will return 0.
+ *
+ * @get_parent	Query the parent of this clock; for clocks with multiple
+ *		possible parents, query the hardware for the current
+ *		parent. Currently only called when the clock is first
+ *		registered.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
+ * should be done in clk_prepare. Switching that will not sleep should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
  */
+struct clk_hw_ops {
+	int		(*prepare)(struct clk_hw *);
+	void		(*unprepare)(struct clk_hw *);
+	int		(*enable)(struct clk_hw *);
+	void		(*disable)(struct clk_hw *);
+	unsigned long	(*recalc_rate)(struct clk_hw *);
+	long		(*round_rate)(struct clk_hw *, unsigned long);
+	struct clk *	(*get_parent)(struct clk_hw *);
+};
 
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any possibly sleeping initialisation on @clk, allowing the clock to be
+ * later enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possibly sleeping) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_register - register and initialize a new clock
+ *
+ * @ops: ops for the new clock
+ * @hw: struct clk_hw to be passed to the ops of the new clock
+ * @name: name to use for the new clock
+ *
+ * Register a new clock with the clk subsystem.  Returns either a
+ * struct clk for the new clock or a NULL pointer.
+ */
+struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
+			 const char *name);
+
+/**
+ * clk_unregister - remove a clock
+ *
+ * @clk: clock to unregister
+ *
+ * Remove a clock from the clk subsystem.  This is currently not
+ * implemented but is provided to allow unregistration code to be
+ * written in drivers ready for use when an implementation is
+ * provided.
+ */
+static inline int clk_unregister(struct clk *clk)
+{
+	return -EOPNOTSUPP;
+}
+
+#else /* !CONFIG_GENERIC_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * For !CONFIG_GENERIC_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
  */
-struct clk;
+static inline int clk_prepare(struct clk *clk) {
+	might_sleep();
+	return 0;
+}
+
+static inline void clk_unprepare(struct clk *clk) {
+	might_sleep();
+}
+
+#endif /* !CONFIG_GENERIC_CLK */
 
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
@@ -67,6 +188,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +205,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source
@@ -97,7 +213,7 @@ void clk_put(struct clk *clk);
  * Returns rounded clock rate in Hz, or negative errno.
  */
 long clk_round_rate(struct clk *clk, unsigned long rate);
- 
+
 /**
  * clk_set_rate - set the clock rate for a clock source
  * @clk: clock source
@@ -106,7 +222,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
  * Returns success (0) or negative errno.
  */
 int clk_set_rate(struct clk *clk, unsigned long rate);
- 
+
 /**
  * clk_set_parent - set the parent clock source for this clock
  * @clk: clock source
-- 
1.7.4.1

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

* [PATCH v2 2/7] clk: Implement clk_set_rate
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-22 22:26   ` Mike Turquette
  -1 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Mike Turquette

From: Jeremy Kerr <jeremy.kerr@canonical.com>

Implement clk_set_rate by adding a set_rate callback to clk_hw_ops.
Rates are propagated down the clock tree and recalculated.  Also adds a
flag for signaling that parents must change rates to achieve the desired
frequency (upstream propagation).

TODO:
Upstream propagation is not yet implemented.
Device pre-change and post-change notifications are not implemented, but
are marked up as FIXME comments.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Remove upstream propagation (for now)
Rename CLK_SET_RATE_PROPAGATE to CLK_PARENT_RATE_CHANGE

 drivers/clk/clk.c   |   71 ++++++++++++++++++++++++++++++++++++++++++++++----
 include/linux/clk.h |   12 ++++++++
 2 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 1cd7315..86636c2 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -21,6 +21,8 @@ struct clk {
 	unsigned int		enable_count;
 	unsigned int		prepare_count;
 	struct clk		*parent;
+	struct hlist_head	children;
+	struct hlist_node	child_node;
 	unsigned long		rate;
 };
 
@@ -176,10 +178,57 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 }
 EXPORT_SYMBOL_GPL(clk_round_rate);
 
+/*
+ * clk_recalc_rates - Given a clock (with a recently updated clk->rate),
+ *	notify its children that the rate may need to be recalculated, using
+ *	ops->recalc_rate().
+ */
+static void clk_recalc_rates(struct clk *clk)
+{
+	struct hlist_node *tmp;
+	struct clk *child;
+
+	if (clk->ops->recalc_rate)
+		clk->rate = clk->ops->recalc_rate(clk->hw);
+
+	/* FIXME add post-rate change notification here */
+
+	hlist_for_each_entry(child, tmp, &clk->children, child_node)
+		clk_recalc_rates(child);
+}
+
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	/* not yet implemented */
-	return -ENOSYS;
+	unsigned long parent_rate, new_rate;
+	int ret = 0;
+
+	if (!clk->ops->set_rate)
+		return -ENOSYS;
+
+	new_rate = rate;
+
+	/* prevent racing with updates to the clock topology */
+	mutex_lock(&prepare_lock);
+
+	/* FIXME add pre-rate change notification here */
+
+	ret = clk->ops->set_rate(clk->hw, new_rate, &parent_rate);
+
+	/* FIXME ignores CLK_PARENT_RATE_CHANGE */
+	if (ret < 0)
+		/* FIXME add rate change abort notification here */
+		goto out;
+
+	/*
+	 * If successful recalculate the rates of the clock, including
+	 * children.
+	 */
+	clk_recalc_rates(clk);
+
+out:
+	mutex_unlock(&prepare_lock);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_set_rate);
 
@@ -216,16 +265,26 @@ struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
 	clk->hw = hw;
 	hw->clk = clk;
 
-	/* Query the hardware for parent and initial rate */
+	/*
+	 * Query the hardware for parent and initial rate. We may alter
+	 * the clock topology, making this clock available from the parent's
+	 * children list. So, we need to protect against concurrent
+	 * accesses through set_rate
+	 */
+	mutex_lock(&prepare_lock);
 
-	if (clk->ops->get_parent)
-		/* We don't to lock against prepare/enable here, as
-		 * the clock is not yet accessible from anywhere */
+	if (clk->ops->get_parent) {
 		clk->parent = clk->ops->get_parent(clk->hw);
+		if (clk->parent)
+			hlist_add_head(&clk->child_node,
+					&clk->parent->children);
+	}
 
 	if (clk->ops->recalc_rate)
 		clk->rate = clk->ops->recalc_rate(clk->hw);
 
+	mutex_unlock(&prepare_lock);
+
 
 	return clk;
 }
diff --git a/include/linux/clk.h b/include/linux/clk.h
index d6ae10b..0d2cd5e 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -58,6 +58,12 @@ struct clk_hw {
  *		parent. Currently only called when the clock is first
  *		registered.
  *
+ * @set_rate	Change the rate of this clock. If this callback returns
+ *		CLK_SET_RATE_PROPAGATE, the rate change will be propagated to
+ *		the parent clock (which may propagate again). The requested
+ *		rate of the parent is passed back from the callback in the
+ *		second 'unsigned long *' argument.
+ *
  * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
  * implementations to split any work between atomic (enable) and sleepable
  * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
@@ -76,9 +82,15 @@ struct clk_hw_ops {
 	void		(*disable)(struct clk_hw *);
 	unsigned long	(*recalc_rate)(struct clk_hw *);
 	long		(*round_rate)(struct clk_hw *, unsigned long);
+	int		(*set_rate)(struct clk_hw *,
+					unsigned long, unsigned long *);
 	struct clk *	(*get_parent)(struct clk_hw *);
 };
 
+enum {
+	CLK_PARENT_RATE_CHANGE = 1,
+};
+
 /**
  * clk_prepare - prepare clock for atomic enabling.
  *
-- 
1.7.4.1


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

* [PATCH v2 2/7] clk: Implement clk_set_rate
@ 2011-09-22 22:26   ` Mike Turquette
  0 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jeremy Kerr <jeremy.kerr@canonical.com>

Implement clk_set_rate by adding a set_rate callback to clk_hw_ops.
Rates are propagated down the clock tree and recalculated.  Also adds a
flag for signaling that parents must change rates to achieve the desired
frequency (upstream propagation).

TODO:
Upstream propagation is not yet implemented.
Device pre-change and post-change notifications are not implemented, but
are marked up as FIXME comments.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Remove upstream propagation (for now)
Rename CLK_SET_RATE_PROPAGATE to CLK_PARENT_RATE_CHANGE

 drivers/clk/clk.c   |   71 ++++++++++++++++++++++++++++++++++++++++++++++----
 include/linux/clk.h |   12 ++++++++
 2 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 1cd7315..86636c2 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -21,6 +21,8 @@ struct clk {
 	unsigned int		enable_count;
 	unsigned int		prepare_count;
 	struct clk		*parent;
+	struct hlist_head	children;
+	struct hlist_node	child_node;
 	unsigned long		rate;
 };
 
@@ -176,10 +178,57 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 }
 EXPORT_SYMBOL_GPL(clk_round_rate);
 
+/*
+ * clk_recalc_rates - Given a clock (with a recently updated clk->rate),
+ *	notify its children that the rate may need to be recalculated, using
+ *	ops->recalc_rate().
+ */
+static void clk_recalc_rates(struct clk *clk)
+{
+	struct hlist_node *tmp;
+	struct clk *child;
+
+	if (clk->ops->recalc_rate)
+		clk->rate = clk->ops->recalc_rate(clk->hw);
+
+	/* FIXME add post-rate change notification here */
+
+	hlist_for_each_entry(child, tmp, &clk->children, child_node)
+		clk_recalc_rates(child);
+}
+
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	/* not yet implemented */
-	return -ENOSYS;
+	unsigned long parent_rate, new_rate;
+	int ret = 0;
+
+	if (!clk->ops->set_rate)
+		return -ENOSYS;
+
+	new_rate = rate;
+
+	/* prevent racing with updates to the clock topology */
+	mutex_lock(&prepare_lock);
+
+	/* FIXME add pre-rate change notification here */
+
+	ret = clk->ops->set_rate(clk->hw, new_rate, &parent_rate);
+
+	/* FIXME ignores CLK_PARENT_RATE_CHANGE */
+	if (ret < 0)
+		/* FIXME add rate change abort notification here */
+		goto out;
+
+	/*
+	 * If successful recalculate the rates of the clock, including
+	 * children.
+	 */
+	clk_recalc_rates(clk);
+
+out:
+	mutex_unlock(&prepare_lock);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_set_rate);
 
@@ -216,16 +265,26 @@ struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
 	clk->hw = hw;
 	hw->clk = clk;
 
-	/* Query the hardware for parent and initial rate */
+	/*
+	 * Query the hardware for parent and initial rate. We may alter
+	 * the clock topology, making this clock available from the parent's
+	 * children list. So, we need to protect against concurrent
+	 * accesses through set_rate
+	 */
+	mutex_lock(&prepare_lock);
 
-	if (clk->ops->get_parent)
-		/* We don't to lock against prepare/enable here, as
-		 * the clock is not yet accessible from anywhere */
+	if (clk->ops->get_parent) {
 		clk->parent = clk->ops->get_parent(clk->hw);
+		if (clk->parent)
+			hlist_add_head(&clk->child_node,
+					&clk->parent->children);
+	}
 
 	if (clk->ops->recalc_rate)
 		clk->rate = clk->ops->recalc_rate(clk->hw);
 
+	mutex_unlock(&prepare_lock);
+
 
 	return clk;
 }
diff --git a/include/linux/clk.h b/include/linux/clk.h
index d6ae10b..0d2cd5e 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -58,6 +58,12 @@ struct clk_hw {
  *		parent. Currently only called when the clock is first
  *		registered.
  *
+ * @set_rate	Change the rate of this clock. If this callback returns
+ *		CLK_SET_RATE_PROPAGATE, the rate change will be propagated to
+ *		the parent clock (which may propagate again). The requested
+ *		rate of the parent is passed back from the callback in the
+ *		second 'unsigned long *' argument.
+ *
  * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
  * implementations to split any work between atomic (enable) and sleepable
  * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
@@ -76,9 +82,15 @@ struct clk_hw_ops {
 	void		(*disable)(struct clk_hw *);
 	unsigned long	(*recalc_rate)(struct clk_hw *);
 	long		(*round_rate)(struct clk_hw *, unsigned long);
+	int		(*set_rate)(struct clk_hw *,
+					unsigned long, unsigned long *);
 	struct clk *	(*get_parent)(struct clk_hw *);
 };
 
+enum {
+	CLK_PARENT_RATE_CHANGE = 1,
+};
+
 /**
  * clk_prepare - prepare clock for atomic enabling.
  *
-- 
1.7.4.1

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

* [PATCH v2 3/7] clk: Add fixed-rate clock
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-22 22:26   ` Mike Turquette
  -1 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Mike Turquette

From: Jeremy Kerr <jeremy.kerr@canonical.com>

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Add copyright header

 drivers/clk/Kconfig     |    4 ++++
 drivers/clk/Makefile    |    1 +
 drivers/clk/clk-fixed.c |   24 ++++++++++++++++++++++++
 include/linux/clk.h     |   14 ++++++++++++++
 4 files changed, 43 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-fixed.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c53ed59..d8313d7 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -8,3 +8,7 @@ config HAVE_MACH_CLKDEV
 
 config GENERIC_CLK
 	bool
+
+config GENERIC_CLK_FIXED
+	bool
+	depends on GENERIC_CLK
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 570d5b9..9a3325a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,3 +1,4 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_GENERIC_CLK)	+= clk.o
+obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
diff --git a/drivers/clk/clk-fixed.c b/drivers/clk/clk-fixed.c
new file mode 100644
index 0000000..956fb9a
--- /dev/null
+++ b/drivers/clk/clk-fixed.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simple fixed-rate clock implementation
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+#define to_clk_fixed(c) container_of(c, struct clk_hw_fixed, hw)
+
+static unsigned long clk_fixed_recalc_rate(struct clk_hw *hw)
+{
+	return to_clk_fixed(hw)->rate;
+}
+
+struct clk_hw_ops clk_fixed_ops = {
+	.recalc_rate = clk_fixed_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0d2cd5e..1903dd8 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -110,6 +110,20 @@ int clk_prepare(struct clk *clk);
  */
 void clk_unprepare(struct clk *clk);
 
+/* Base clock implementations. Platform clock implementations can use these
+ * directly, or 'subclass' as approprate */
+
+#ifdef CONFIG_GENERIC_CLK_FIXED
+
+struct clk_hw_fixed {
+	struct clk_hw	hw;
+	unsigned long	rate;
+};
+
+extern struct clk_hw_ops clk_fixed_ops;
+
+#endif /* CONFIG_GENERIC_CLK_FIXED */
+
 /**
  * clk_register - register and initialize a new clock
  *
-- 
1.7.4.1


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

* [PATCH v2 3/7] clk: Add fixed-rate clock
@ 2011-09-22 22:26   ` Mike Turquette
  0 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jeremy Kerr <jeremy.kerr@canonical.com>

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Add copyright header

 drivers/clk/Kconfig     |    4 ++++
 drivers/clk/Makefile    |    1 +
 drivers/clk/clk-fixed.c |   24 ++++++++++++++++++++++++
 include/linux/clk.h     |   14 ++++++++++++++
 4 files changed, 43 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-fixed.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c53ed59..d8313d7 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -8,3 +8,7 @@ config HAVE_MACH_CLKDEV
 
 config GENERIC_CLK
 	bool
+
+config GENERIC_CLK_FIXED
+	bool
+	depends on GENERIC_CLK
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 570d5b9..9a3325a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,3 +1,4 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_GENERIC_CLK)	+= clk.o
+obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
diff --git a/drivers/clk/clk-fixed.c b/drivers/clk/clk-fixed.c
new file mode 100644
index 0000000..956fb9a
--- /dev/null
+++ b/drivers/clk/clk-fixed.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simple fixed-rate clock implementation
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+#define to_clk_fixed(c) container_of(c, struct clk_hw_fixed, hw)
+
+static unsigned long clk_fixed_recalc_rate(struct clk_hw *hw)
+{
+	return to_clk_fixed(hw)->rate;
+}
+
+struct clk_hw_ops clk_fixed_ops = {
+	.recalc_rate = clk_fixed_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0d2cd5e..1903dd8 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -110,6 +110,20 @@ int clk_prepare(struct clk *clk);
  */
 void clk_unprepare(struct clk *clk);
 
+/* Base clock implementations. Platform clock implementations can use these
+ * directly, or 'subclass' as approprate */
+
+#ifdef CONFIG_GENERIC_CLK_FIXED
+
+struct clk_hw_fixed {
+	struct clk_hw	hw;
+	unsigned long	rate;
+};
+
+extern struct clk_hw_ops clk_fixed_ops;
+
+#endif /* CONFIG_GENERIC_CLK_FIXED */
+
 /**
  * clk_register - register and initialize a new clock
  *
-- 
1.7.4.1

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

* [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-22 22:26   ` Mike Turquette
  -1 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Jamie Iles, Mike Turquette

From: Jeremy Kerr <jeremy.kerr@canonical.com>

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Add copyright header
Fold in Jamie's patch for set-to-disable clks
Use BIT macro instead of shift

 drivers/clk/Kconfig    |    4 ++
 drivers/clk/Makefile   |    1 +
 drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h    |   13 ++++++++
 4 files changed, 96 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-gate.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index d8313d7..a78967c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -12,3 +12,7 @@ config GENERIC_CLK
 config GENERIC_CLK_FIXED
 	bool
 	depends on GENERIC_CLK
+
+config GENERIC_CLK_GATE
+	bool
+	depends on GENERIC_CLK
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 9a3325a..d186446 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_GENERIC_CLK)	+= clk.o
 obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
+obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
new file mode 100644
index 0000000..a1d8e79
--- /dev/null
+++ b/drivers/clk/clk-gate.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simple clk gate implementation
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
+
+static unsigned long clk_gate_get_rate(struct clk_hw *clk)
+{
+	return clk_get_rate(clk_get_parent(clk->clk));
+}
+
+static void clk_gate_set_bit(struct clk_hw *clk)
+{
+	struct clk_gate *gate = to_clk_gate(clk);
+	u32 reg;
+
+	reg = __raw_readl(gate->reg);
+	reg |= BIT(gate->bit_idx);
+	__raw_writel(reg, gate->reg);
+}
+
+static void clk_gate_clear_bit(struct clk_hw *clk)
+{
+	struct clk_gate *gate = to_clk_gate(clk);
+	u32 reg;
+
+	reg = __raw_readl(gate->reg);
+	reg &= ~BIT(gate->bit_idx);
+	__raw_writel(reg, gate->reg);
+}
+
+static int clk_gate_enable_set(struct clk_hw *clk)
+{
+	clk_gate_set_bit(clk);
+
+	return 0;
+}
+
+static void clk_gate_disable_clear(struct clk_hw *clk)
+{
+	clk_gate_clear_bit(clk);
+}
+
+struct clk_hw_ops clk_gate_set_enable_ops = {
+	.recalc_rate = clk_gate_get_rate,
+	.enable = clk_gate_enable_set,
+	.disable = clk_gate_disable_clear,
+};
+EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
+
+static int clk_gate_enable_clear(struct clk_hw *clk)
+{
+	clk_gate_clear_bit(clk);
+
+	return 0;
+}
+
+static void clk_gate_disable_set(struct clk_hw *clk)
+{
+	clk_gate_set_bit(clk);
+}
+
+struct clk_hw_ops clk_gate_set_disable_ops = {
+	.recalc_rate = clk_gate_get_rate,
+	.enable = clk_gate_enable_clear,
+	.disable = clk_gate_disable_set,
+};
+EXPORT_SYMBOL_GPL(clk_gate_set_disable_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1903dd8..626fd0d 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -124,6 +124,19 @@ extern struct clk_hw_ops clk_fixed_ops;
 
 #endif /* CONFIG_GENERIC_CLK_FIXED */
 
+#ifdef CONFIG_GENERIC_CLK_GATE
+
+struct clk_gate {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		bit_idx;
+};
+
+extern struct clk_hw_ops clk_gate_set_enable_ops;
+extern struct clk_hw_ops clk_gate_set_disable_ops;
+
+#endif /* CONFIG_GENERIC_CLK_GATE */
+
 /**
  * clk_register - register and initialize a new clock
  *
-- 
1.7.4.1


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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-09-22 22:26   ` Mike Turquette
  0 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:26 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jeremy Kerr <jeremy.kerr@canonical.com>

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Jamie Iles <jamie@jamieiles.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Add copyright header
Fold in Jamie's patch for set-to-disable clks
Use BIT macro instead of shift

 drivers/clk/Kconfig    |    4 ++
 drivers/clk/Makefile   |    1 +
 drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h    |   13 ++++++++
 4 files changed, 96 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-gate.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index d8313d7..a78967c 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -12,3 +12,7 @@ config GENERIC_CLK
 config GENERIC_CLK_FIXED
 	bool
 	depends on GENERIC_CLK
+
+config GENERIC_CLK_GATE
+	bool
+	depends on GENERIC_CLK
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 9a3325a..d186446 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_GENERIC_CLK)	+= clk.o
 obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
+obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
new file mode 100644
index 0000000..a1d8e79
--- /dev/null
+++ b/drivers/clk/clk-gate.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Simple clk gate implementation
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <asm/io.h>
+
+#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
+
+static unsigned long clk_gate_get_rate(struct clk_hw *clk)
+{
+	return clk_get_rate(clk_get_parent(clk->clk));
+}
+
+static void clk_gate_set_bit(struct clk_hw *clk)
+{
+	struct clk_gate *gate = to_clk_gate(clk);
+	u32 reg;
+
+	reg = __raw_readl(gate->reg);
+	reg |= BIT(gate->bit_idx);
+	__raw_writel(reg, gate->reg);
+}
+
+static void clk_gate_clear_bit(struct clk_hw *clk)
+{
+	struct clk_gate *gate = to_clk_gate(clk);
+	u32 reg;
+
+	reg = __raw_readl(gate->reg);
+	reg &= ~BIT(gate->bit_idx);
+	__raw_writel(reg, gate->reg);
+}
+
+static int clk_gate_enable_set(struct clk_hw *clk)
+{
+	clk_gate_set_bit(clk);
+
+	return 0;
+}
+
+static void clk_gate_disable_clear(struct clk_hw *clk)
+{
+	clk_gate_clear_bit(clk);
+}
+
+struct clk_hw_ops clk_gate_set_enable_ops = {
+	.recalc_rate = clk_gate_get_rate,
+	.enable = clk_gate_enable_set,
+	.disable = clk_gate_disable_clear,
+};
+EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
+
+static int clk_gate_enable_clear(struct clk_hw *clk)
+{
+	clk_gate_clear_bit(clk);
+
+	return 0;
+}
+
+static void clk_gate_disable_set(struct clk_hw *clk)
+{
+	clk_gate_set_bit(clk);
+}
+
+struct clk_hw_ops clk_gate_set_disable_ops = {
+	.recalc_rate = clk_gate_get_rate,
+	.enable = clk_gate_enable_clear,
+	.disable = clk_gate_disable_set,
+};
+EXPORT_SYMBOL_GPL(clk_gate_set_disable_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1903dd8..626fd0d 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -124,6 +124,19 @@ extern struct clk_hw_ops clk_fixed_ops;
 
 #endif /* CONFIG_GENERIC_CLK_FIXED */
 
+#ifdef CONFIG_GENERIC_CLK_GATE
+
+struct clk_gate {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		bit_idx;
+};
+
+extern struct clk_hw_ops clk_gate_set_enable_ops;
+extern struct clk_hw_ops clk_gate_set_disable_ops;
+
+#endif /* CONFIG_GENERIC_CLK_GATE */
+
 /**
  * clk_register - register and initialize a new clock
  *
-- 
1.7.4.1

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

* [PATCH v2 5/7] clk: Add Kconfig option to build all generic clk drivers
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-22 22:27   ` Mike Turquette
  -1 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:27 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

From: Mark Brown <broonie@opensource.wolfsonmicro.com>

Currently drivers for the generic clk subsystem must be selected by
platforms using them in order to enable build. When doing development on
the API or generic build time testing it is useful to be able to build
unused drivers in order to improve coverage so supply a Kconfig option
which allows this.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
No change since v1

 drivers/clk/Kconfig |   11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a78967c..95b42a3 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -1,4 +1,3 @@
-
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
@@ -9,6 +8,16 @@ config HAVE_MACH_CLKDEV
 config GENERIC_CLK
 	bool
 
+config GENERIC_CLK_BUILD_TEST
+	bool "Build all generic clock drivers"
+	depends on EXPERIMENTAL && GENERIC_CLK
+	select GENERIC_CLK_FIXED
+	select GENERIC_CLK_GATE
+	help
+	   Enable all possible generic clock drivers.  This is only
+	   useful for improving build coverage, it is not useful for
+	   production kernel builds.
+
 config GENERIC_CLK_FIXED
 	bool
 	depends on GENERIC_CLK
-- 
1.7.4.1


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

* [PATCH v2 5/7] clk: Add Kconfig option to build all generic clk drivers
@ 2011-09-22 22:27   ` Mike Turquette
  0 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:27 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Brown <broonie@opensource.wolfsonmicro.com>

Currently drivers for the generic clk subsystem must be selected by
platforms using them in order to enable build. When doing development on
the API or generic build time testing it is useful to be able to build
unused drivers in order to improve coverage so supply a Kconfig option
which allows this.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
No change since v1

 drivers/clk/Kconfig |   11 ++++++++++-
 1 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index a78967c..95b42a3 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -1,4 +1,3 @@
-
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
@@ -9,6 +8,16 @@ config HAVE_MACH_CLKDEV
 config GENERIC_CLK
 	bool
 
+config GENERIC_CLK_BUILD_TEST
+	bool "Build all generic clock drivers"
+	depends on EXPERIMENTAL && GENERIC_CLK
+	select GENERIC_CLK_FIXED
+	select GENERIC_CLK_GATE
+	help
+	   Enable all possible generic clock drivers.  This is only
+	   useful for improving build coverage, it is not useful for
+	   production kernel builds.
+
 config GENERIC_CLK_FIXED
 	bool
 	depends on GENERIC_CLK
-- 
1.7.4.1

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

* [PATCH v2 6/7] clk: Add initial WM831x clock driver
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-22 22:27   ` Mike Turquette
  -1 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:27 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Mike Turquette

From: Mark Brown <broonie@opensource.wolfsonmicro.com>

The WM831x and WM832x series of PMICs contain a flexible clocking
subsystem intended to provide always on and system core clocks.  It
features:

- A 32.768kHz crystal oscillator which can optionally be used to pass
  through an externally generated clock.
- A FLL which can be clocked from either the 32.768kHz oscillator or
  the CLKIN pin.
- A CLKOUT pin which can bring out either the oscillator or the FLL
  output.
- The 32.768kHz clock can also optionally be brought out on the GPIO
  pins of the device.

This driver fully supports the 32.768kHz oscillator and CLKOUT.  The FLL
is supported only in AUTO mode, the full flexibility of the FLL cannot
currently be used.  The use of clock references other than the internal
oscillator is not currently supported, and since clk_set_parent() is not
implemented in the generic clock API the clock tree configuration cannot
be changed at runtime.

Due to a lack of access to systems where the core SoC has been converted
to use the generic clock API this driver has been compile tested only.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Changed CLK_SET_RATE_PROPAGATE to CLK_PARENT_RATE_CHANGE
Converted to clk_register to the original style, without passing in
	struct device *dev.  This is due to Mark's clock name collision
	patch being dropped.

 MAINTAINERS              |    1 +
 drivers/clk/Kconfig      |    5 +
 drivers/clk/Makefile     |    1 +
 drivers/clk/clk-wm831x.c |  386 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 393 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-wm831x.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ae8820e..a100ea0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7208,6 +7208,7 @@ T:	git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
 W:	http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
 S:	Supported
 F:	Documentation/hwmon/wm83??
+F:	drivers/clk/clk-wm83*.c
 F:	drivers/leds/leds-wm83*.c
 F:	drivers/input/misc/wm831x-on.c
 F:	drivers/input/touchscreen/wm831x-ts.c
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 95b42a3..8aca5ab 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -13,6 +13,7 @@ config GENERIC_CLK_BUILD_TEST
 	depends on EXPERIMENTAL && GENERIC_CLK
 	select GENERIC_CLK_FIXED
 	select GENERIC_CLK_GATE
+	select GENERIC_CLK_WM831X if MFD_WM831X=y
 	help
 	   Enable all possible generic clock drivers.  This is only
 	   useful for improving build coverage, it is not useful for
@@ -25,3 +26,7 @@ config GENERIC_CLK_FIXED
 config GENERIC_CLK_GATE
 	bool
 	depends on GENERIC_CLK
+
+config GENERIC_CLK_WM831X
+	tristate
+	depends on GENERIC_CLK && MFD_WM831X
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d186446..6628ad5 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_GENERIC_CLK)	+= clk.o
 obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
 obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
+obj-$(CONFIG_GENERIC_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
new file mode 100644
index 0000000..bfcbcb5
--- /dev/null
+++ b/drivers/clk/clk-wm831x.c
@@ -0,0 +1,386 @@
+/*
+ * WM831x clock control
+ *
+ * Copyright 2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wm831x/core.h>
+
+struct wm831x_clk {
+	struct wm831x *wm831x;
+	struct clk_hw xtal_hw;
+	struct clk_hw fll_hw;
+	struct clk_hw clkout_hw;
+	bool xtal_ena;
+};
+
+static int wm831x_xtal_enable(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  xtal_hw);
+
+	if (clkdata->xtal_ena)
+		return 0;
+	else
+		return -EPERM;
+}
+
+static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  xtal_hw);
+
+	if (clkdata->xtal_ena)
+		return 32768;
+	else
+		return 0;
+}
+
+static long wm831x_xtal_round_rate(struct clk_hw *hw, unsigned long rate)
+{
+	return wm831x_xtal_recalc_rate(hw);
+}
+
+static const struct clk_hw_ops wm831x_xtal_ops = {
+	.enable = wm831x_xtal_enable,
+	.recalc_rate = wm831x_xtal_recalc_rate,
+	.round_rate = wm831x_xtal_round_rate,
+};
+
+static const unsigned long wm831x_fll_auto_rates[] = {
+	 2048000,
+	11289600,
+	12000000,
+	12288000,
+	19200000,
+	22579600,
+	24000000,
+	24576000,
+};
+
+static bool wm831x_fll_enabled(struct wm831x *wm831x)
+{
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_1);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read FLL_CONTROL_1: %d\n",
+			ret);
+		return true;
+	}
+
+	return ret & WM831X_FLL_ENA;
+}
+
+static int wm831x_fll_prepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2,
+			      WM831X_FLL_ENA, WM831X_FLL_ENA);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);
+
+	return ret;
+}
+
+static void wm831x_fll_unprepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2, WM831X_FLL_ENA, 0);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to disaable FLL: %d\n", ret);
+}
+
+static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
+			ret);
+		return 0;
+	}
+
+	if (ret & WM831X_FLL_AUTO)
+		return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK];
+
+	dev_err(wm831x->dev, "FLL only supported in AUTO mode\n");
+	return 0;
+}
+
+static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
+		if (wm831x_fll_auto_rates[i] == rate)
+			break;
+	if (i == ARRAY_SIZE(wm831x_fll_auto_rates))
+		return -EINVAL;
+
+	if (wm831x_fll_enabled(wm831x))
+		return -EPERM;
+
+	return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,
+			       WM831X_FLL_AUTO_FREQ_MASK, i);
+}
+
+static struct clk *wm831x_fll_get_parent(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	/* AUTO mode is always clocked from the crystal */
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
+			ret);
+		return NULL;
+	}
+
+	if (ret & WM831X_FLL_AUTO)
+		return clkdata->xtal_hw.clk;
+
+	ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n",
+			ret);
+		return NULL;
+	}
+
+	switch (ret & WM831X_FLL_CLK_SRC_MASK) {
+	case 0:
+		return clkdata->xtal_hw.clk;
+	case 1:
+		dev_warn(wm831x->dev,
+			 "FLL clocked from CLKIN not yet supported\n");
+		return NULL;
+	default:
+		dev_err(wm831x->dev, "Unsupported FLL clock source %d\n",
+			ret & WM831X_FLL_CLK_SRC_MASK);
+		return NULL;
+	}
+}
+
+static const struct clk_hw_ops wm831x_fll_ops = {
+	.prepare = wm831x_fll_prepare,
+	.unprepare = wm831x_fll_unprepare,
+	.recalc_rate = wm831x_fll_recalc_rate,
+	.set_rate = wm831x_fll_set_rate,
+	.get_parent = wm831x_fll_get_parent,
+};
+
+static int wm831x_clkout_prepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_unlock(wm831x);
+	if (ret != 0) {
+		dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
+		return ret;
+	}
+
+	ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
+			      WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret);
+
+	wm831x_reg_lock(wm831x);
+
+	return ret;
+}
+
+static void wm831x_clkout_unprepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_unlock(wm831x);
+	if (ret != 0) {
+		dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
+		return;
+	}
+
+	ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
+			      WM831X_CLKOUT_ENA, 0);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret);
+
+	wm831x_reg_lock(wm831x);
+}
+
+static unsigned long wm831x_clkout_recalc_rate(struct clk_hw *hw)
+{
+	return clk_get_rate(clk_get_parent(hw->clk));
+}
+
+static long wm831x_clkout_round_rate(struct clk_hw *hw, unsigned long rate)
+{
+	return clk_round_rate(clk_get_parent(hw->clk), rate);
+}
+
+static int wm831x_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *parent_rate)
+{
+	*parent_rate = rate;
+	return CLK_PARENT_RATE_CHANGE;
+}
+
+static struct clk *wm831x_clkout_get_parent(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
+			ret);
+		return NULL;
+	}
+
+	if (ret & WM831X_CLKOUT_SRC)
+		return clkdata->xtal_hw.clk;
+	else
+		return clkdata->fll_hw.clk;
+}
+
+static const struct clk_hw_ops wm831x_clkout_ops = {
+	.prepare = wm831x_clkout_prepare,
+	.unprepare = wm831x_clkout_unprepare,
+	.recalc_rate = wm831x_clkout_recalc_rate,
+	.round_rate = wm831x_clkout_round_rate,
+	.set_rate = wm831x_clkout_set_rate,
+	.get_parent = wm831x_clkout_get_parent,
+};
+
+static __devinit int wm831x_clk_probe(struct platform_device *pdev)
+{
+	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+	struct wm831x_clk *clkdata;
+	int ret;
+
+	clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL);
+	if (!clkdata)
+		return -ENOMEM;
+
+	/* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
+			ret);
+		goto err_alloc;
+	}
+	clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
+
+	if (!clk_register(&wm831x_xtal_ops, &clkdata->xtal_hw,
+			  "xtal")) {
+		ret = -EINVAL;
+		goto err_alloc;
+	}
+
+	if (!clk_register(&wm831x_fll_ops, &clkdata->fll_hw,
+			  "fll")) {
+		ret = -EINVAL;
+		goto err_xtal;
+	}
+
+	if (!clk_register(&wm831x_clkout_ops, &clkdata->clkout_hw,
+			  "clkout")) {
+		ret = -EINVAL;
+		goto err_fll;
+	}
+
+	dev_set_drvdata(&pdev->dev, clkdata);
+
+	return 0;
+
+err_fll:
+	clk_unregister(clkdata->fll_hw.clk);
+err_xtal:
+	clk_unregister(clkdata->xtal_hw.clk);
+err_alloc:
+	kfree(clkdata);
+	return ret;
+}
+
+static __devexit int wm831x_clk_remove(struct platform_device *pdev)
+{
+	struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
+
+	clk_unregister(clkdata->clkout_hw.clk);
+	clk_unregister(clkdata->fll_hw.clk);
+	clk_unregister(clkdata->xtal_hw.clk);
+	kfree(clkdata);
+
+	return 0;
+}
+
+static struct platform_driver wm831x_clk_driver = {
+	.probe = wm831x_clk_probe,
+	.remove = __devexit_p(wm831x_clk_remove),
+	.driver		= {
+		.name	= "wm831x-clk",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init wm831x_clk_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&wm831x_clk_driver);
+	if (ret != 0)
+		pr_err("Failed to register WM831x clock driver: %d\n", ret);
+
+	return ret;
+}
+module_init(wm831x_clk_init);
+
+static void __exit wm831x_clk_exit(void)
+{
+	platform_driver_unregister(&wm831x_clk_driver);
+}
+module_exit(wm831x_clk_exit);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM831x clock driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm831x-clk");
-- 
1.7.4.1


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

* [PATCH v2 6/7] clk: Add initial WM831x clock driver
@ 2011-09-22 22:27   ` Mike Turquette
  0 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:27 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Brown <broonie@opensource.wolfsonmicro.com>

The WM831x and WM832x series of PMICs contain a flexible clocking
subsystem intended to provide always on and system core clocks.  It
features:

- A 32.768kHz crystal oscillator which can optionally be used to pass
  through an externally generated clock.
- A FLL which can be clocked from either the 32.768kHz oscillator or
  the CLKIN pin.
- A CLKOUT pin which can bring out either the oscillator or the FLL
  output.
- The 32.768kHz clock can also optionally be brought out on the GPIO
  pins of the device.

This driver fully supports the 32.768kHz oscillator and CLKOUT.  The FLL
is supported only in AUTO mode, the full flexibility of the FLL cannot
currently be used.  The use of clock references other than the internal
oscillator is not currently supported, and since clk_set_parent() is not
implemented in the generic clock API the clock tree configuration cannot
be changed at runtime.

Due to a lack of access to systems where the core SoC has been converted
to use the generic clock API this driver has been compile tested only.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
Changes since v1:
Changed CLK_SET_RATE_PROPAGATE to CLK_PARENT_RATE_CHANGE
Converted to clk_register to the original style, without passing in
	struct device *dev.  This is due to Mark's clock name collision
	patch being dropped.

 MAINTAINERS              |    1 +
 drivers/clk/Kconfig      |    5 +
 drivers/clk/Makefile     |    1 +
 drivers/clk/clk-wm831x.c |  386 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 393 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-wm831x.c

diff --git a/MAINTAINERS b/MAINTAINERS
index ae8820e..a100ea0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7208,6 +7208,7 @@ T:	git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
 W:	http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
 S:	Supported
 F:	Documentation/hwmon/wm83??
+F:	drivers/clk/clk-wm83*.c
 F:	drivers/leds/leds-wm83*.c
 F:	drivers/input/misc/wm831x-on.c
 F:	drivers/input/touchscreen/wm831x-ts.c
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 95b42a3..8aca5ab 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -13,6 +13,7 @@ config GENERIC_CLK_BUILD_TEST
 	depends on EXPERIMENTAL && GENERIC_CLK
 	select GENERIC_CLK_FIXED
 	select GENERIC_CLK_GATE
+	select GENERIC_CLK_WM831X if MFD_WM831X=y
 	help
 	   Enable all possible generic clock drivers.  This is only
 	   useful for improving build coverage, it is not useful for
@@ -25,3 +26,7 @@ config GENERIC_CLK_FIXED
 config GENERIC_CLK_GATE
 	bool
 	depends on GENERIC_CLK
+
+config GENERIC_CLK_WM831X
+	tristate
+	depends on GENERIC_CLK && MFD_WM831X
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d186446..6628ad5 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_GENERIC_CLK)	+= clk.o
 obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
 obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
+obj-$(CONFIG_GENERIC_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk-wm831x.c b/drivers/clk/clk-wm831x.c
new file mode 100644
index 0000000..bfcbcb5
--- /dev/null
+++ b/drivers/clk/clk-wm831x.c
@@ -0,0 +1,386 @@
+/*
+ * WM831x clock control
+ *
+ * Copyright 2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wm831x/core.h>
+
+struct wm831x_clk {
+	struct wm831x *wm831x;
+	struct clk_hw xtal_hw;
+	struct clk_hw fll_hw;
+	struct clk_hw clkout_hw;
+	bool xtal_ena;
+};
+
+static int wm831x_xtal_enable(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  xtal_hw);
+
+	if (clkdata->xtal_ena)
+		return 0;
+	else
+		return -EPERM;
+}
+
+static unsigned long wm831x_xtal_recalc_rate(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  xtal_hw);
+
+	if (clkdata->xtal_ena)
+		return 32768;
+	else
+		return 0;
+}
+
+static long wm831x_xtal_round_rate(struct clk_hw *hw, unsigned long rate)
+{
+	return wm831x_xtal_recalc_rate(hw);
+}
+
+static const struct clk_hw_ops wm831x_xtal_ops = {
+	.enable = wm831x_xtal_enable,
+	.recalc_rate = wm831x_xtal_recalc_rate,
+	.round_rate = wm831x_xtal_round_rate,
+};
+
+static const unsigned long wm831x_fll_auto_rates[] = {
+	 2048000,
+	11289600,
+	12000000,
+	12288000,
+	19200000,
+	22579600,
+	24000000,
+	24576000,
+};
+
+static bool wm831x_fll_enabled(struct wm831x *wm831x)
+{
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_1);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read FLL_CONTROL_1: %d\n",
+			ret);
+		return true;
+	}
+
+	return ret & WM831X_FLL_ENA;
+}
+
+static int wm831x_fll_prepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2,
+			      WM831X_FLL_ENA, WM831X_FLL_ENA);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);
+
+	return ret;
+}
+
+static void wm831x_fll_unprepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2, WM831X_FLL_ENA, 0);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to disaable FLL: %d\n", ret);
+}
+
+static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
+			ret);
+		return 0;
+	}
+
+	if (ret & WM831X_FLL_AUTO)
+		return wm831x_fll_auto_rates[ret & WM831X_FLL_AUTO_FREQ_MASK];
+
+	dev_err(wm831x->dev, "FLL only supported in AUTO mode\n");
+	return 0;
+}
+
+static int wm831x_fll_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *parent_rate)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(wm831x_fll_auto_rates); i++)
+		if (wm831x_fll_auto_rates[i] == rate)
+			break;
+	if (i == ARRAY_SIZE(wm831x_fll_auto_rates))
+		return -EINVAL;
+
+	if (wm831x_fll_enabled(wm831x))
+		return -EPERM;
+
+	return wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_2,
+			       WM831X_FLL_AUTO_FREQ_MASK, i);
+}
+
+static struct clk *wm831x_fll_get_parent(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  fll_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	/* AUTO mode is always clocked from the crystal */
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
+			ret);
+		return NULL;
+	}
+
+	if (ret & WM831X_FLL_AUTO)
+		return clkdata->xtal_hw.clk;
+
+	ret = wm831x_reg_read(wm831x, WM831X_FLL_CONTROL_5);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read FLL_CONTROL_5: %d\n",
+			ret);
+		return NULL;
+	}
+
+	switch (ret & WM831X_FLL_CLK_SRC_MASK) {
+	case 0:
+		return clkdata->xtal_hw.clk;
+	case 1:
+		dev_warn(wm831x->dev,
+			 "FLL clocked from CLKIN not yet supported\n");
+		return NULL;
+	default:
+		dev_err(wm831x->dev, "Unsupported FLL clock source %d\n",
+			ret & WM831X_FLL_CLK_SRC_MASK);
+		return NULL;
+	}
+}
+
+static const struct clk_hw_ops wm831x_fll_ops = {
+	.prepare = wm831x_fll_prepare,
+	.unprepare = wm831x_fll_unprepare,
+	.recalc_rate = wm831x_fll_recalc_rate,
+	.set_rate = wm831x_fll_set_rate,
+	.get_parent = wm831x_fll_get_parent,
+};
+
+static int wm831x_clkout_prepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_unlock(wm831x);
+	if (ret != 0) {
+		dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
+		return ret;
+	}
+
+	ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
+			      WM831X_CLKOUT_ENA, WM831X_CLKOUT_ENA);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to enable CLKOUT: %d\n", ret);
+
+	wm831x_reg_lock(wm831x);
+
+	return ret;
+}
+
+static void wm831x_clkout_unprepare(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_unlock(wm831x);
+	if (ret != 0) {
+		dev_crit(wm831x->dev, "Failed to lock registers: %d\n", ret);
+		return;
+	}
+
+	ret = wm831x_set_bits(wm831x, WM831X_CLOCK_CONTROL_1,
+			      WM831X_CLKOUT_ENA, 0);
+	if (ret != 0)
+		dev_crit(wm831x->dev, "Failed to disable CLKOUT: %d\n", ret);
+
+	wm831x_reg_lock(wm831x);
+}
+
+static unsigned long wm831x_clkout_recalc_rate(struct clk_hw *hw)
+{
+	return clk_get_rate(clk_get_parent(hw->clk));
+}
+
+static long wm831x_clkout_round_rate(struct clk_hw *hw, unsigned long rate)
+{
+	return clk_round_rate(clk_get_parent(hw->clk), rate);
+}
+
+static int wm831x_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *parent_rate)
+{
+	*parent_rate = rate;
+	return CLK_PARENT_RATE_CHANGE;
+}
+
+static struct clk *wm831x_clkout_get_parent(struct clk_hw *hw)
+{
+	struct wm831x_clk *clkdata = container_of(hw, struct wm831x_clk,
+						  clkout_hw);
+	struct wm831x *wm831x = clkdata->wm831x;
+	int ret;
+
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_1);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_1: %d\n",
+			ret);
+		return NULL;
+	}
+
+	if (ret & WM831X_CLKOUT_SRC)
+		return clkdata->xtal_hw.clk;
+	else
+		return clkdata->fll_hw.clk;
+}
+
+static const struct clk_hw_ops wm831x_clkout_ops = {
+	.prepare = wm831x_clkout_prepare,
+	.unprepare = wm831x_clkout_unprepare,
+	.recalc_rate = wm831x_clkout_recalc_rate,
+	.round_rate = wm831x_clkout_round_rate,
+	.set_rate = wm831x_clkout_set_rate,
+	.get_parent = wm831x_clkout_get_parent,
+};
+
+static __devinit int wm831x_clk_probe(struct platform_device *pdev)
+{
+	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+	struct wm831x_clk *clkdata;
+	int ret;
+
+	clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL);
+	if (!clkdata)
+		return -ENOMEM;
+
+	/* XTAL_ENA can only be set via OTP/InstantConfig so just read once */
+	ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2);
+	if (ret < 0) {
+		dev_err(wm831x->dev, "Unable to read CLOCK_CONTROL_2: %d\n",
+			ret);
+		goto err_alloc;
+	}
+	clkdata->xtal_ena = ret & WM831X_XTAL_ENA;
+
+	if (!clk_register(&wm831x_xtal_ops, &clkdata->xtal_hw,
+			  "xtal")) {
+		ret = -EINVAL;
+		goto err_alloc;
+	}
+
+	if (!clk_register(&wm831x_fll_ops, &clkdata->fll_hw,
+			  "fll")) {
+		ret = -EINVAL;
+		goto err_xtal;
+	}
+
+	if (!clk_register(&wm831x_clkout_ops, &clkdata->clkout_hw,
+			  "clkout")) {
+		ret = -EINVAL;
+		goto err_fll;
+	}
+
+	dev_set_drvdata(&pdev->dev, clkdata);
+
+	return 0;
+
+err_fll:
+	clk_unregister(clkdata->fll_hw.clk);
+err_xtal:
+	clk_unregister(clkdata->xtal_hw.clk);
+err_alloc:
+	kfree(clkdata);
+	return ret;
+}
+
+static __devexit int wm831x_clk_remove(struct platform_device *pdev)
+{
+	struct wm831x_clk *clkdata = dev_get_drvdata(&pdev->dev);
+
+	clk_unregister(clkdata->clkout_hw.clk);
+	clk_unregister(clkdata->fll_hw.clk);
+	clk_unregister(clkdata->xtal_hw.clk);
+	kfree(clkdata);
+
+	return 0;
+}
+
+static struct platform_driver wm831x_clk_driver = {
+	.probe = wm831x_clk_probe,
+	.remove = __devexit_p(wm831x_clk_remove),
+	.driver		= {
+		.name	= "wm831x-clk",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init wm831x_clk_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&wm831x_clk_driver);
+	if (ret != 0)
+		pr_err("Failed to register WM831x clock driver: %d\n", ret);
+
+	return ret;
+}
+module_init(wm831x_clk_init);
+
+static void __exit wm831x_clk_exit(void)
+{
+	platform_driver_unregister(&wm831x_clk_driver);
+}
+module_exit(wm831x_clk_exit);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM831x clock driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm831x-clk");
-- 
1.7.4.1

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

* [PATCH v2 7/7] x86: Enable generic clk API on x86
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-22 22:27   ` Mike Turquette
  -1 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:27 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

From: Mark Brown <broonie@opensource.wolfsonmicro.com>

Enable the generic clk API on x86, enabling use of the API by drivers for
x86 modules and also improving build coverage for clock API using devices.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
No change since v1

 arch/x86/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6a47bb2..571b2c5 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -73,6 +73,7 @@ config X86
 	select HAVE_BPF_JIT if (X86_64 && NET)
 	select CLKEVT_I8253
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
+	select GENERIC_CLK
 
 config INSTRUCTION_DECODER
 	def_bool (KPROBES || PERF_EVENTS)
-- 
1.7.4.1


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

* [PATCH v2 7/7] x86: Enable generic clk API on x86
@ 2011-09-22 22:27   ` Mike Turquette
  0 siblings, 0 replies; 144+ messages in thread
From: Mike Turquette @ 2011-09-22 22:27 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mark Brown <broonie@opensource.wolfsonmicro.com>

Enable the generic clk API on x86, enabling use of the API by drivers for
x86 modules and also improving build coverage for clock API using devices.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
No change since v1

 arch/x86/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6a47bb2..571b2c5 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -73,6 +73,7 @@ config X86
 	select HAVE_BPF_JIT if (X86_64 && NET)
 	select CLKEVT_I8253
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG
+	select GENERIC_CLK
 
 config INSTRUCTION_DECODER
 	def_bool (KPROBES || PERF_EVENTS)
-- 
1.7.4.1

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

* Re: [PATCH v2 0/7] Add a generic struct clk
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-22 23:17   ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-22 23:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Mike Turquette

On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
> Hi all,
>
> The goal of this series is to provide a cross-platform clock framework
> that platforms can use to model their clock trees and perform common
> operations on them.  Currently everyone re-invents their own clock tree
> inside platform code which makes it impossible for drivers to use the
> clock APIs safely across many platforms and for distro's to compile
> multi-platform kernels which all redefine struct clk and its operations.
>
> This is the second version of the common clock patches which were
> originally posted by Jeremy Kerr and then re-posted with some additional
> patches by Mark Brown.  Mark's re-post didn't have any changes done to
> the original four patches from Jeremy which is why this series is "v2".
>
> The changes in this series are minimal: I've folded in some of Mark's
> fixes and most of the comments posted to his series as well as rebasing
> on top of v3.1-rc7.  The design and functionality hasn't changed much
> since Jeremy posted v1 of this series.  Propagating the rate change up
> to the parent has been removed from clk_set_rate since that needs some
> more thought.  I also dropped Mark's change to append a device's name to
> a clk name since device tree might solve this neatly.  Again more
> discussion around that would be good.

For convenience these patches can be found at:
git://git.linaro.org/people/mturquette/linux.git
v3.1-rc7-clkv2

Regards,
Mike

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

* [PATCH v2 0/7] Add a generic struct clk
@ 2011-09-22 23:17   ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-22 23:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
> Hi all,
>
> The goal of this series is to provide a cross-platform clock framework
> that platforms can use to model their clock trees and perform common
> operations on them. ?Currently everyone re-invents their own clock tree
> inside platform code which makes it impossible for drivers to use the
> clock APIs safely across many platforms and for distro's to compile
> multi-platform kernels which all redefine struct clk and its operations.
>
> This is the second version of the common clock patches which were
> originally posted by Jeremy Kerr and then re-posted with some additional
> patches by Mark Brown. ?Mark's re-post didn't have any changes done to
> the original four patches from Jeremy which is why this series is "v2".
>
> The changes in this series are minimal: I've folded in some of Mark's
> fixes and most of the comments posted to his series as well as rebasing
> on top of v3.1-rc7. ?The design and functionality hasn't changed much
> since Jeremy posted v1 of this series. ?Propagating the rate change up
> to the parent has been removed from clk_set_rate since that needs some
> more thought. ?I also dropped Mark's change to append a device's name to
> a clk name since device tree might solve this neatly. ?Again more
> discussion around that would be good.

For convenience these patches can be found at:
git://git.linaro.org/people/mturquette/linux.git
v3.1-rc7-clkv2

Regards,
Mike

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-09-25  3:55     ` Grant Likely
  -1 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-09-25  3:55 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, and a set of clock operations. Different clock
> implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> The interface is split into two halves:
> 
>  * struct clk, which is the generic-device-driver interface. This
>    provides a set of functions which drivers may use to request
>    enable/disable, query or manipulate in a hardware-independent manner.
> 
>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>    interface. Clock drivers implement the ops, which allow the core
>    clock code to implement the generic 'struct clk' API.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
> common, opaque struct clk, and a set of clock operations (defined per
> type of clock):
> 
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };
> 
>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
> 
>   static int clk_foo_enable(struct clk_hw *clk)
>   {
>   	struct clk_foo *foo = to_clk_foo(clk);
>   	raw_writeb(foo->enable_reg, 1);
>   	return 0;
>   }
> 
>   struct clk_hw_ops clk_foo_ops = {
>   	.enable = clk_foo_enable,
>   };
> 
> And in the platform initialisation code:
> 
>   struct clk_foo my_clk_foo;
> 
>   void init_clocks(void)
>   {
>   	my_clk_foo.enable_reg = ioremap(...);
> 
>   	clk_register(&clk_foo_ops, &my_clk_foo, NULL);

Shouldn't this be:

	clk_register(&clk_foo_ops, &my_clk_foo->clk, NULL);

?

Also, this documentation would be good to have in the Documentation
directory instead of lost in a commit header.

Otherwise looks okay to me.

Reviewed-by: Grant Likely <grant.likely@secretlab.ca>


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-09-25  3:55     ` Grant Likely
  0 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-09-25  3:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, and a set of clock operations. Different clock
> implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> The interface is split into two halves:
> 
>  * struct clk, which is the generic-device-driver interface. This
>    provides a set of functions which drivers may use to request
>    enable/disable, query or manipulate in a hardware-independent manner.
> 
>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>    interface. Clock drivers implement the ops, which allow the core
>    clock code to implement the generic 'struct clk' API.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
> common, opaque struct clk, and a set of clock operations (defined per
> type of clock):
> 
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };
> 
>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
> 
>   static int clk_foo_enable(struct clk_hw *clk)
>   {
>   	struct clk_foo *foo = to_clk_foo(clk);
>   	raw_writeb(foo->enable_reg, 1);
>   	return 0;
>   }
> 
>   struct clk_hw_ops clk_foo_ops = {
>   	.enable = clk_foo_enable,
>   };
> 
> And in the platform initialisation code:
> 
>   struct clk_foo my_clk_foo;
> 
>   void init_clocks(void)
>   {
>   	my_clk_foo.enable_reg = ioremap(...);
> 
>   	clk_register(&clk_foo_ops, &my_clk_foo, NULL);

Shouldn't this be:

	clk_register(&clk_foo_ops, &my_clk_foo->clk, NULL);

?

Also, this documentation would be good to have in the Documentation
directory instead of lost in a commit header.

Otherwise looks okay to me.

Reviewed-by: Grant Likely <grant.likely@secretlab.ca>

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-22 22:26   ` Mike Turquette
@ 2011-09-25  4:02     ` Grant Likely
  -1 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-09-25  4:02 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Jamie Iles

On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Add copyright header
> Fold in Jamie's patch for set-to-disable clks
> Use BIT macro instead of shift
> 
>  drivers/clk/Kconfig    |    4 ++
>  drivers/clk/Makefile   |    1 +
>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h    |   13 ++++++++
>  4 files changed, 96 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-gate.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d8313d7..a78967c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -12,3 +12,7 @@ config GENERIC_CLK
>  config GENERIC_CLK_FIXED
>  	bool
>  	depends on GENERIC_CLK
> +
> +config GENERIC_CLK_GATE
> +	bool
> +	depends on GENERIC_CLK

I see zero documentation on what a "gated clock" is supposed to be or
how it works, and there are zero comments in the code.  It's kind of
hard to review that way, and even harder to use.

g.

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-09-25  4:02     ` Grant Likely
  0 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-09-25  4:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Add copyright header
> Fold in Jamie's patch for set-to-disable clks
> Use BIT macro instead of shift
> 
>  drivers/clk/Kconfig    |    4 ++
>  drivers/clk/Makefile   |    1 +
>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h    |   13 ++++++++
>  4 files changed, 96 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-gate.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d8313d7..a78967c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -12,3 +12,7 @@ config GENERIC_CLK
>  config GENERIC_CLK_FIXED
>  	bool
>  	depends on GENERIC_CLK
> +
> +config GENERIC_CLK_GATE
> +	bool
> +	depends on GENERIC_CLK

I see zero documentation on what a "gated clock" is supposed to be or
how it works, and there are zero comments in the code.  It's kind of
hard to review that way, and even harder to use.

g.

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

* Re: [PATCH v2 6/7] clk: Add initial WM831x clock driver
  2011-09-22 22:27   ` Mike Turquette
@ 2011-09-25  4:08     ` Grant Likely
  -1 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-09-25  4:08 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Thu, Sep 22, 2011 at 03:27:01PM -0700, Mike Turquette wrote:
> From: Mark Brown <broonie@opensource.wolfsonmicro.com>
> 
> The WM831x and WM832x series of PMICs contain a flexible clocking
> subsystem intended to provide always on and system core clocks.  It
> features:
> 
> - A 32.768kHz crystal oscillator which can optionally be used to pass
>   through an externally generated clock.
> - A FLL which can be clocked from either the 32.768kHz oscillator or
>   the CLKIN pin.
> - A CLKOUT pin which can bring out either the oscillator or the FLL
>   output.
> - The 32.768kHz clock can also optionally be brought out on the GPIO
>   pins of the device.
> 
> This driver fully supports the 32.768kHz oscillator and CLKOUT.  The FLL
> is supported only in AUTO mode, the full flexibility of the FLL cannot
> currently be used.  The use of clock references other than the internal
> oscillator is not currently supported, and since clk_set_parent() is not
> implemented in the generic clock API the clock tree configuration cannot
> be changed at runtime.
> 
> Due to a lack of access to systems where the core SoC has been converted
> to use the generic clock API this driver has been compile tested only.
> 
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>

A few minor comments below.  Otherwise looks fine to me.

> +static __devinit int wm831x_clk_probe(struct platform_device *pdev)
> +{
> +	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
> +	struct wm831x_clk *clkdata;
> +	int ret;
> +
> +	clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL);

If devm_kzalloc() is used, then all the kfree unwinding can be
dropped.

> +static int __init wm831x_clk_init(void)
> +{
> +	int ret;
> +
> +	ret = platform_driver_register(&wm831x_clk_driver);
> +	if (ret != 0)
> +		pr_err("Failed to register WM831x clock driver: %d\n", ret);
> +
> +	return ret;

No need for this song-and-dance.  The driver core is pretty well
debugged.  Just use "return platform_driver_register(...);"

g.

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

* [PATCH v2 6/7] clk: Add initial WM831x clock driver
@ 2011-09-25  4:08     ` Grant Likely
  0 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-09-25  4:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:27:01PM -0700, Mike Turquette wrote:
> From: Mark Brown <broonie@opensource.wolfsonmicro.com>
> 
> The WM831x and WM832x series of PMICs contain a flexible clocking
> subsystem intended to provide always on and system core clocks.  It
> features:
> 
> - A 32.768kHz crystal oscillator which can optionally be used to pass
>   through an externally generated clock.
> - A FLL which can be clocked from either the 32.768kHz oscillator or
>   the CLKIN pin.
> - A CLKOUT pin which can bring out either the oscillator or the FLL
>   output.
> - The 32.768kHz clock can also optionally be brought out on the GPIO
>   pins of the device.
> 
> This driver fully supports the 32.768kHz oscillator and CLKOUT.  The FLL
> is supported only in AUTO mode, the full flexibility of the FLL cannot
> currently be used.  The use of clock references other than the internal
> oscillator is not currently supported, and since clk_set_parent() is not
> implemented in the generic clock API the clock tree configuration cannot
> be changed at runtime.
> 
> Due to a lack of access to systems where the core SoC has been converted
> to use the generic clock API this driver has been compile tested only.
> 
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>

A few minor comments below.  Otherwise looks fine to me.

> +static __devinit int wm831x_clk_probe(struct platform_device *pdev)
> +{
> +	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
> +	struct wm831x_clk *clkdata;
> +	int ret;
> +
> +	clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL);

If devm_kzalloc() is used, then all the kfree unwinding can be
dropped.

> +static int __init wm831x_clk_init(void)
> +{
> +	int ret;
> +
> +	ret = platform_driver_register(&wm831x_clk_driver);
> +	if (ret != 0)
> +		pr_err("Failed to register WM831x clock driver: %d\n", ret);
> +
> +	return ret;

No need for this song-and-dance.  The driver core is pretty well
debugged.  Just use "return platform_driver_register(...);"

g.

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

* Re: [PATCH v2 0/7] Add a generic struct clk
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-25  4:10   ` Grant Likely
  -1 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-09-25  4:10 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Thu, Sep 22, 2011 at 03:26:55PM -0700, Mike Turquette wrote:
> Hi all,
> 
> The goal of this series is to provide a cross-platform clock framework
> that platforms can use to model their clock trees and perform common
> operations on them.  Currently everyone re-invents their own clock tree
> inside platform code which makes it impossible for drivers to use the
> clock APIs safely across many platforms and for distro's to compile
> multi-platform kernels which all redefine struct clk and its operations.
> 
> This is the second version of the common clock patches which were
> originally posted by Jeremy Kerr and then re-posted with some additional
> patches by Mark Brown.  Mark's re-post didn't have any changes done to
> the original four patches from Jeremy which is why this series is "v2".
> 
> The changes in this series are minimal: I've folded in some of Mark's
> fixes and most of the comments posted to his series as well as rebasing
> on top of v3.1-rc7.  The design and functionality hasn't changed much
> since Jeremy posted v1 of this series.  Propagating the rate change up
> to the parent has been removed from clk_set_rate since that needs some
> more thought.  I also dropped Mark's change to append a device's name to
> a clk name since device tree might solve this neatly.  Again more
> discussion around that would be good.
> 
> v1 of the series can be found at,
> http://article.gmane.org/gmane.linux.kernel/1143182
> 
> Mark's re-post (v1+) can be found at,
> http://article.gmane.org/gmane.linux.ports.arm.kernel/129889

Looks good at first review to me.  I had a few comments, but nothing
major.  It really needs some documentation though.

g.


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

* [PATCH v2 0/7] Add a generic struct clk
@ 2011-09-25  4:10   ` Grant Likely
  0 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-09-25  4:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:55PM -0700, Mike Turquette wrote:
> Hi all,
> 
> The goal of this series is to provide a cross-platform clock framework
> that platforms can use to model their clock trees and perform common
> operations on them.  Currently everyone re-invents their own clock tree
> inside platform code which makes it impossible for drivers to use the
> clock APIs safely across many platforms and for distro's to compile
> multi-platform kernels which all redefine struct clk and its operations.
> 
> This is the second version of the common clock patches which were
> originally posted by Jeremy Kerr and then re-posted with some additional
> patches by Mark Brown.  Mark's re-post didn't have any changes done to
> the original four patches from Jeremy which is why this series is "v2".
> 
> The changes in this series are minimal: I've folded in some of Mark's
> fixes and most of the comments posted to his series as well as rebasing
> on top of v3.1-rc7.  The design and functionality hasn't changed much
> since Jeremy posted v1 of this series.  Propagating the rate change up
> to the parent has been removed from clk_set_rate since that needs some
> more thought.  I also dropped Mark's change to append a device's name to
> a clk name since device tree might solve this neatly.  Again more
> discussion around that would be good.
> 
> v1 of the series can be found at,
> http://article.gmane.org/gmane.linux.kernel/1143182
> 
> Mark's re-post (v1+) can be found at,
> http://article.gmane.org/gmane.linux.ports.arm.kernel/129889

Looks good at first review to me.  I had a few comments, but nothing
major.  It really needs some documentation though.

g.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-25  3:55     ` Grant Likely
@ 2011-09-25  5:26       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-25  5:26 UTC (permalink / raw)
  To: Grant Likely
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Sat, Sep 24, 2011 at 8:55 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>>
>> We currently have ~21 definitions of struct clk in the ARM architecture,
>> each defined on a per-platform basis. This makes it difficult to define
>> platform- (or architecture-) independent clock sources without making
>> assumptions about struct clk, and impossible to compile two
>> platforms with different struct clks into a single image.
>>
>> This change is an effort to unify struct clk where possible, by defining
>> a common struct clk, and a set of clock operations. Different clock
>> implementations can set their own operations, and have a standard
>> interface for generic code. The callback interface is exposed to the
>> kernel proper, while the clock implementations only need to be seen by
>> the platform internals.
>>
>> The interface is split into two halves:
>>
>>  * struct clk, which is the generic-device-driver interface. This
>>    provides a set of functions which drivers may use to request
>>    enable/disable, query or manipulate in a hardware-independent manner.
>>
>>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>>    interface. Clock drivers implement the ops, which allow the core
>>    clock code to implement the generic 'struct clk' API.
>>
>> This allows us to share clock code among platforms, and makes it
>> possible to dynamically create clock devices in platform-independent
>> code.
>>
>> Platforms can enable the generic struct clock through
>> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
>> common, opaque struct clk, and a set of clock operations (defined per
>> type of clock):
>>
>>   struct clk_hw_ops {
>>       int             (*prepare)(struct clk_hw *);
>>       void            (*unprepare)(struct clk_hw *);
>>       int             (*enable)(struct clk_hw *);
>>       void            (*disable)(struct clk_hw *);
>>       unsigned long   (*recalc_rate)(struct clk_hw *);
>>       int             (*set_rate)(struct clk_hw *,
>>                                       unsigned long, unsigned long *);
>>       long            (*round_rate)(struct clk_hw *, unsigned long);
>>       int             (*set_parent)(struct clk_hw *, struct clk *);
>>       struct clk *    (*get_parent)(struct clk_hw *);
>>   };
>>
>> Platform clock code can register a clock through clk_register, passing a
>> set of operations, and a pointer to hardware-specific data:
>>
>>   struct clk_hw_foo {
>>       struct clk_hw clk;
>>       void __iomem *enable_reg;
>>   };
>>
>>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
>>
>>   static int clk_foo_enable(struct clk_hw *clk)
>>   {
>>       struct clk_foo *foo = to_clk_foo(clk);
>>       raw_writeb(foo->enable_reg, 1);
>>       return 0;
>>   }
>>
>>   struct clk_hw_ops clk_foo_ops = {
>>       .enable = clk_foo_enable,
>>   };
>>
>> And in the platform initialisation code:
>>
>>   struct clk_foo my_clk_foo;
>>
>>   void init_clocks(void)
>>   {
>>       my_clk_foo.enable_reg = ioremap(...);
>>
>>       clk_register(&clk_foo_ops, &my_clk_foo, NULL);
>
> Shouldn't this be:
>
>        clk_register(&clk_foo_ops, &my_clk_foo->clk, NULL);
>
> ?
>
> Also, this documentation would be good to have in the Documentation
> directory instead of lost in a commit header.

Thanks for your review Grant.  Will fix the changelog and add proper
Documentation/ in the next round.

Regards,
Mike

> Otherwise looks okay to me.
>
> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
>
>

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-09-25  5:26       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-25  5:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Sep 24, 2011 at 8:55 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>>
>> We currently have ~21 definitions of struct clk in the ARM architecture,
>> each defined on a per-platform basis. This makes it difficult to define
>> platform- (or architecture-) independent clock sources without making
>> assumptions about struct clk, and impossible to compile two
>> platforms with different struct clks into a single image.
>>
>> This change is an effort to unify struct clk where possible, by defining
>> a common struct clk, and a set of clock operations. Different clock
>> implementations can set their own operations, and have a standard
>> interface for generic code. The callback interface is exposed to the
>> kernel proper, while the clock implementations only need to be seen by
>> the platform internals.
>>
>> The interface is split into two halves:
>>
>> ?* struct clk, which is the generic-device-driver interface. This
>> ? ?provides a set of functions which drivers may use to request
>> ? ?enable/disable, query or manipulate in a hardware-independent manner.
>>
>> ?* struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>> ? ?interface. Clock drivers implement the ops, which allow the core
>> ? ?clock code to implement the generic 'struct clk' API.
>>
>> This allows us to share clock code among platforms, and makes it
>> possible to dynamically create clock devices in platform-independent
>> code.
>>
>> Platforms can enable the generic struct clock through
>> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
>> common, opaque struct clk, and a set of clock operations (defined per
>> type of clock):
>>
>> ? struct clk_hw_ops {
>> ? ? ? int ? ? ? ? ? ? (*prepare)(struct clk_hw *);
>> ? ? ? void ? ? ? ? ? ?(*unprepare)(struct clk_hw *);
>> ? ? ? int ? ? ? ? ? ? (*enable)(struct clk_hw *);
>> ? ? ? void ? ? ? ? ? ?(*disable)(struct clk_hw *);
>> ? ? ? unsigned long ? (*recalc_rate)(struct clk_hw *);
>> ? ? ? int ? ? ? ? ? ? (*set_rate)(struct clk_hw *,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long, unsigned long *);
>> ? ? ? long ? ? ? ? ? ?(*round_rate)(struct clk_hw *, unsigned long);
>> ? ? ? int ? ? ? ? ? ? (*set_parent)(struct clk_hw *, struct clk *);
>> ? ? ? struct clk * ? ?(*get_parent)(struct clk_hw *);
>> ? };
>>
>> Platform clock code can register a clock through clk_register, passing a
>> set of operations, and a pointer to hardware-specific data:
>>
>> ? struct clk_hw_foo {
>> ? ? ? struct clk_hw clk;
>> ? ? ? void __iomem *enable_reg;
>> ? };
>>
>> ? #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
>>
>> ? static int clk_foo_enable(struct clk_hw *clk)
>> ? {
>> ? ? ? struct clk_foo *foo = to_clk_foo(clk);
>> ? ? ? raw_writeb(foo->enable_reg, 1);
>> ? ? ? return 0;
>> ? }
>>
>> ? struct clk_hw_ops clk_foo_ops = {
>> ? ? ? .enable = clk_foo_enable,
>> ? };
>>
>> And in the platform initialisation code:
>>
>> ? struct clk_foo my_clk_foo;
>>
>> ? void init_clocks(void)
>> ? {
>> ? ? ? my_clk_foo.enable_reg = ioremap(...);
>>
>> ? ? ? clk_register(&clk_foo_ops, &my_clk_foo, NULL);
>
> Shouldn't this be:
>
> ? ? ? ?clk_register(&clk_foo_ops, &my_clk_foo->clk, NULL);
>
> ?
>
> Also, this documentation would be good to have in the Documentation
> directory instead of lost in a commit header.

Thanks for your review Grant.  Will fix the changelog and add proper
Documentation/ in the next round.

Regards,
Mike

> Otherwise looks okay to me.
>
> Reviewed-by: Grant Likely <grant.likely@secretlab.ca>
>
>

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-25  4:02     ` Grant Likely
@ 2011-09-25  5:27       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-25  5:27 UTC (permalink / raw)
  To: Grant Likely
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Jamie Iles

On Sat, Sep 24, 2011 at 9:02 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>>
>> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> ---
>> Changes since v1:
>> Add copyright header
>> Fold in Jamie's patch for set-to-disable clks
>> Use BIT macro instead of shift
>>
>>  drivers/clk/Kconfig    |    4 ++
>>  drivers/clk/Makefile   |    1 +
>>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/clk.h    |   13 ++++++++
>>  4 files changed, 96 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/clk/clk-gate.c
>>
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index d8313d7..a78967c 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -12,3 +12,7 @@ config GENERIC_CLK
>>  config GENERIC_CLK_FIXED
>>       bool
>>       depends on GENERIC_CLK
>> +
>> +config GENERIC_CLK_GATE
>> +     bool
>> +     depends on GENERIC_CLK
>
> I see zero documentation on what a "gated clock" is supposed to be or
> how it works, and there are zero comments in the code.  It's kind of
> hard to review that way, and even harder to use.

Will add Documentation and re-post.

Thanks,
Mike

> g.
>

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-09-25  5:27       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-25  5:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Sep 24, 2011 at 9:02 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>>
>> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> ---
>> Changes since v1:
>> Add copyright header
>> Fold in Jamie's patch for set-to-disable clks
>> Use BIT macro instead of shift
>>
>> ?drivers/clk/Kconfig ? ?| ? ?4 ++
>> ?drivers/clk/Makefile ? | ? ?1 +
>> ?drivers/clk/clk-gate.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++++
>> ?include/linux/clk.h ? ?| ? 13 ++++++++
>> ?4 files changed, 96 insertions(+), 0 deletions(-)
>> ?create mode 100644 drivers/clk/clk-gate.c
>>
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index d8313d7..a78967c 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -12,3 +12,7 @@ config GENERIC_CLK
>> ?config GENERIC_CLK_FIXED
>> ? ? ? bool
>> ? ? ? depends on GENERIC_CLK
>> +
>> +config GENERIC_CLK_GATE
>> + ? ? bool
>> + ? ? depends on GENERIC_CLK
>
> I see zero documentation on what a "gated clock" is supposed to be or
> how it works, and there are zero comments in the code. ?It's kind of
> hard to review that way, and even harder to use.

Will add Documentation and re-post.

Thanks,
Mike

> g.
>

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

* Re: [PATCH v2 6/7] clk: Add initial WM831x clock driver
  2011-09-25  4:08     ` Grant Likely
@ 2011-09-25  5:29       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-25  5:29 UTC (permalink / raw)
  To: Grant Likely
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Sat, Sep 24, 2011 at 9:08 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Thu, Sep 22, 2011 at 03:27:01PM -0700, Mike Turquette wrote:
>> From: Mark Brown <broonie@opensource.wolfsonmicro.com>
>>
>> The WM831x and WM832x series of PMICs contain a flexible clocking
>> subsystem intended to provide always on and system core clocks.  It
>> features:
>>
>> - A 32.768kHz crystal oscillator which can optionally be used to pass
>>   through an externally generated clock.
>> - A FLL which can be clocked from either the 32.768kHz oscillator or
>>   the CLKIN pin.
>> - A CLKOUT pin which can bring out either the oscillator or the FLL
>>   output.
>> - The 32.768kHz clock can also optionally be brought out on the GPIO
>>   pins of the device.
>>
>> This driver fully supports the 32.768kHz oscillator and CLKOUT.  The FLL
>> is supported only in AUTO mode, the full flexibility of the FLL cannot
>> currently be used.  The use of clock references other than the internal
>> oscillator is not currently supported, and since clk_set_parent() is not
>> implemented in the generic clock API the clock tree configuration cannot
>> be changed at runtime.
>>
>> Due to a lack of access to systems where the core SoC has been converted
>> to use the generic clock API this driver has been compile tested only.
>>
>> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>
> A few minor comments below.  Otherwise looks fine to me.
>
>> +static __devinit int wm831x_clk_probe(struct platform_device *pdev)
>> +{
>> +     struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
>> +     struct wm831x_clk *clkdata;
>> +     int ret;
>> +
>> +     clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL);
>
> If devm_kzalloc() is used, then all the kfree unwinding can be
> dropped.
>
>> +static int __init wm831x_clk_init(void)
>> +{
>> +     int ret;
>> +
>> +     ret = platform_driver_register(&wm831x_clk_driver);
>> +     if (ret != 0)
>> +             pr_err("Failed to register WM831x clock driver: %d\n", ret);
>> +
>> +     return ret;
>
> No need for this song-and-dance.  The driver core is pretty well
> debugged.  Just use "return platform_driver_register(...);"

Grant,

Thanks for the review.

Mark,

I know you're not carrying this whole set of patches but do you want
to rework this and resend or do you just want me to fix it up?
Changes are trivial if you don't want to touch it.

Regards,
Mike

> g.
>

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

* [PATCH v2 6/7] clk: Add initial WM831x clock driver
@ 2011-09-25  5:29       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-25  5:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Sep 24, 2011 at 9:08 PM, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Thu, Sep 22, 2011 at 03:27:01PM -0700, Mike Turquette wrote:
>> From: Mark Brown <broonie@opensource.wolfsonmicro.com>
>>
>> The WM831x and WM832x series of PMICs contain a flexible clocking
>> subsystem intended to provide always on and system core clocks. ?It
>> features:
>>
>> - A 32.768kHz crystal oscillator which can optionally be used to pass
>> ? through an externally generated clock.
>> - A FLL which can be clocked from either the 32.768kHz oscillator or
>> ? the CLKIN pin.
>> - A CLKOUT pin which can bring out either the oscillator or the FLL
>> ? output.
>> - The 32.768kHz clock can also optionally be brought out on the GPIO
>> ? pins of the device.
>>
>> This driver fully supports the 32.768kHz oscillator and CLKOUT. ?The FLL
>> is supported only in AUTO mode, the full flexibility of the FLL cannot
>> currently be used. ?The use of clock references other than the internal
>> oscillator is not currently supported, and since clk_set_parent() is not
>> implemented in the generic clock API the clock tree configuration cannot
>> be changed at runtime.
>>
>> Due to a lack of access to systems where the core SoC has been converted
>> to use the generic clock API this driver has been compile tested only.
>>
>> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>
> A few minor comments below. ?Otherwise looks fine to me.
>
>> +static __devinit int wm831x_clk_probe(struct platform_device *pdev)
>> +{
>> + ? ? struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
>> + ? ? struct wm831x_clk *clkdata;
>> + ? ? int ret;
>> +
>> + ? ? clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL);
>
> If devm_kzalloc() is used, then all the kfree unwinding can be
> dropped.
>
>> +static int __init wm831x_clk_init(void)
>> +{
>> + ? ? int ret;
>> +
>> + ? ? ret = platform_driver_register(&wm831x_clk_driver);
>> + ? ? if (ret != 0)
>> + ? ? ? ? ? ? pr_err("Failed to register WM831x clock driver: %d\n", ret);
>> +
>> + ? ? return ret;
>
> No need for this song-and-dance. ?The driver core is pretty well
> debugged. ?Just use "return platform_driver_register(...);"

Grant,

Thanks for the review.

Mark,

I know you're not carrying this whole set of patches but do you want
to rework this and resend or do you just want me to fix it up?
Changes are trivial if you don't want to touch it.

Regards,
Mike

> g.
>

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

* Re: [PATCH v2 6/7] clk: Add initial WM831x clock driver
  2011-09-25  4:08     ` Grant Likely
@ 2011-09-26  9:38       ` Mark Brown
  -1 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-09-26  9:38 UTC (permalink / raw)
  To: Grant Likely
  Cc: Mike Turquette, linux-kernel, linux-arm-kernel, jeremy.kerr,
	tglx, linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev,
	paul, sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann,
	linux, eric.miao, richard.zhao

On Sat, Sep 24, 2011 at 10:08:36PM -0600, Grant Likely wrote:
> On Thu, Sep 22, 2011 at 03:27:01PM -0700, Mike Turquette wrote:

> > +	ret = platform_driver_register(&wm831x_clk_driver);
> > +	if (ret != 0)
> > +		pr_err("Failed to register WM831x clock driver: %d\n", ret);
> > +
> > +	return ret;

> No need for this song-and-dance.  The driver core is pretty well
> debugged.  Just use "return platform_driver_register(...);"

No, that's not helpful.  The issue isn't the device probe code itself,
the issue is things like module unload not doing what they're supposed
to do and leaving the device lying around or something - there's rather
more going on than just the plain API call.

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

* [PATCH v2 6/7] clk: Add initial WM831x clock driver
@ 2011-09-26  9:38       ` Mark Brown
  0 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-09-26  9:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Sep 24, 2011 at 10:08:36PM -0600, Grant Likely wrote:
> On Thu, Sep 22, 2011 at 03:27:01PM -0700, Mike Turquette wrote:

> > +	ret = platform_driver_register(&wm831x_clk_driver);
> > +	if (ret != 0)
> > +		pr_err("Failed to register WM831x clock driver: %d\n", ret);
> > +
> > +	return ret;

> No need for this song-and-dance.  The driver core is pretty well
> debugged.  Just use "return platform_driver_register(...);"

No, that's not helpful.  The issue isn't the device probe code itself,
the issue is things like module unload not doing what they're supposed
to do and leaving the device lying around or something - there's rather
more going on than just the plain API call.

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-22 22:26   ` Mike Turquette
@ 2011-09-26 18:33     ` Rob Herring
  -1 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-09-26 18:33 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, arnd.bergmann, Jamie Iles,
	skannan, linux, jeremy.kerr, tglx, linux-arm-kernel, sboyd

Mike,

On 09/22/2011 05:26 PM, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Add copyright header
> Fold in Jamie's patch for set-to-disable clks
> Use BIT macro instead of shift
> 
>  drivers/clk/Kconfig    |    4 ++
>  drivers/clk/Makefile   |    1 +
>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h    |   13 ++++++++
>  4 files changed, 96 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-gate.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d8313d7..a78967c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -12,3 +12,7 @@ config GENERIC_CLK
>  config GENERIC_CLK_FIXED
>  	bool
>  	depends on GENERIC_CLK
> +
> +config GENERIC_CLK_GATE
> +	bool
> +	depends on GENERIC_CLK
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 9a3325a..d186446 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -2,3 +2,4 @@
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
>  obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
> +obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> new file mode 100644
> index 0000000..a1d8e79
> --- /dev/null
> +++ b/drivers/clk/clk-gate.c
> @@ -0,0 +1,78 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Simple clk gate implementation
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <asm/io.h>

use linux/io.h

> +
> +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
> +
> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> +{
> +	return clk_get_rate(clk_get_parent(clk->clk));
> +}
> +
> +static void clk_gate_set_bit(struct clk_hw *clk)
> +{
> +	struct clk_gate *gate = to_clk_gate(clk);
> +	u32 reg;
> +
> +	reg = __raw_readl(gate->reg);
> +	reg |= BIT(gate->bit_idx);
> +	__raw_writel(reg, gate->reg);

Don't these read-mod-writes need a spinlock around it?

It's possible to have an enable bits and dividers in the same register.
If you did a set_rate and while doing an enable/disable, there would be
a problem. Also, it may be 2 different clocks in the same register, so
the spinlock needs to be shared and not per clock.

> +}
> +
> +static void clk_gate_clear_bit(struct clk_hw *clk)
> +{
> +	struct clk_gate *gate = to_clk_gate(clk);
> +	u32 reg;
> +
> +	reg = __raw_readl(gate->reg);
> +	reg &= ~BIT(gate->bit_idx);
> +	__raw_writel(reg, gate->reg);
> +}
> +
> +static int clk_gate_enable_set(struct clk_hw *clk)
> +{
> +	clk_gate_set_bit(clk);
> +
> +	return 0;
> +}
> +
> +static void clk_gate_disable_clear(struct clk_hw *clk)
> +{
> +	clk_gate_clear_bit(clk);
> +}
> +
> +struct clk_hw_ops clk_gate_set_enable_ops = {

const?

> +	.recalc_rate = clk_gate_get_rate,
> +	.enable = clk_gate_enable_set,
> +	.disable = clk_gate_disable_clear,
> +};
> +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
> +
> +static int clk_gate_enable_clear(struct clk_hw *clk)
> +{
> +	clk_gate_clear_bit(clk);
> +
> +	return 0;
> +}
> +
> +static void clk_gate_disable_set(struct clk_hw *clk)
> +{
> +	clk_gate_set_bit(clk);
> +}

Are these wrapper functions really needed? Just assign set_bit and
clear_bit functions directly to the ops structs. Only the ops struct
name is exposed to the user.

> +
> +struct clk_hw_ops clk_gate_set_disable_ops = {

const?

Rob


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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-09-26 18:33     ` Rob Herring
  0 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-09-26 18:33 UTC (permalink / raw)
  To: linux-arm-kernel

Mike,

On 09/22/2011 05:26 PM, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Add copyright header
> Fold in Jamie's patch for set-to-disable clks
> Use BIT macro instead of shift
> 
>  drivers/clk/Kconfig    |    4 ++
>  drivers/clk/Makefile   |    1 +
>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h    |   13 ++++++++
>  4 files changed, 96 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-gate.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d8313d7..a78967c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -12,3 +12,7 @@ config GENERIC_CLK
>  config GENERIC_CLK_FIXED
>  	bool
>  	depends on GENERIC_CLK
> +
> +config GENERIC_CLK_GATE
> +	bool
> +	depends on GENERIC_CLK
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 9a3325a..d186446 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -2,3 +2,4 @@
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
>  obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
> +obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> new file mode 100644
> index 0000000..a1d8e79
> --- /dev/null
> +++ b/drivers/clk/clk-gate.c
> @@ -0,0 +1,78 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Simple clk gate implementation
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <asm/io.h>

use linux/io.h

> +
> +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
> +
> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> +{
> +	return clk_get_rate(clk_get_parent(clk->clk));
> +}
> +
> +static void clk_gate_set_bit(struct clk_hw *clk)
> +{
> +	struct clk_gate *gate = to_clk_gate(clk);
> +	u32 reg;
> +
> +	reg = __raw_readl(gate->reg);
> +	reg |= BIT(gate->bit_idx);
> +	__raw_writel(reg, gate->reg);

Don't these read-mod-writes need a spinlock around it?

It's possible to have an enable bits and dividers in the same register.
If you did a set_rate and while doing an enable/disable, there would be
a problem. Also, it may be 2 different clocks in the same register, so
the spinlock needs to be shared and not per clock.

> +}
> +
> +static void clk_gate_clear_bit(struct clk_hw *clk)
> +{
> +	struct clk_gate *gate = to_clk_gate(clk);
> +	u32 reg;
> +
> +	reg = __raw_readl(gate->reg);
> +	reg &= ~BIT(gate->bit_idx);
> +	__raw_writel(reg, gate->reg);
> +}
> +
> +static int clk_gate_enable_set(struct clk_hw *clk)
> +{
> +	clk_gate_set_bit(clk);
> +
> +	return 0;
> +}
> +
> +static void clk_gate_disable_clear(struct clk_hw *clk)
> +{
> +	clk_gate_clear_bit(clk);
> +}
> +
> +struct clk_hw_ops clk_gate_set_enable_ops = {

const?

> +	.recalc_rate = clk_gate_get_rate,
> +	.enable = clk_gate_enable_set,
> +	.disable = clk_gate_disable_clear,
> +};
> +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
> +
> +static int clk_gate_enable_clear(struct clk_hw *clk)
> +{
> +	clk_gate_clear_bit(clk);
> +
> +	return 0;
> +}
> +
> +static void clk_gate_disable_set(struct clk_hw *clk)
> +{
> +	clk_gate_set_bit(clk);
> +}

Are these wrapper functions really needed? Just assign set_bit and
clear_bit functions directly to the ops structs. Only the ops struct
name is exposed to the user.

> +
> +struct clk_hw_ops clk_gate_set_disable_ops = {

const?

Rob

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-26 18:33     ` Rob Herring
@ 2011-09-26 18:40       ` Jamie Iles
  -1 siblings, 0 replies; 144+ messages in thread
From: Jamie Iles @ 2011-09-26 18:40 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mike Turquette, linux-kernel, paul, linaro-dev, linus.walleij,
	patches, eric.miao, broonie, magnus.damm, arnd.bergmann,
	Jamie Iles, skannan, linux, jeremy.kerr, tglx, linux-arm-kernel,
	sboyd

Hi Rob,

On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
> Mike,
> 
> On 09/22/2011 05:26 PM, Mike Turquette wrote:
> > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > 
> > Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> > Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> > Signed-off-by: Mike Turquette <mturquette@ti.com>
> > ---
> > Changes since v1:
> > Add copyright header
> > Fold in Jamie's patch for set-to-disable clks
> > Use BIT macro instead of shift
> > 
> >  drivers/clk/Kconfig    |    4 ++
> >  drivers/clk/Makefile   |    1 +
> >  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk.h    |   13 ++++++++
> >  4 files changed, 96 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/clk/clk-gate.c
> > 
> > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> > index d8313d7..a78967c 100644
> > --- a/drivers/clk/Kconfig
> > +++ b/drivers/clk/Kconfig
> > @@ -12,3 +12,7 @@ config GENERIC_CLK
> >  config GENERIC_CLK_FIXED
> >  	bool
> >  	depends on GENERIC_CLK
> > +
> > +config GENERIC_CLK_GATE
> > +	bool
> > +	depends on GENERIC_CLK
> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> > index 9a3325a..d186446 100644
> > --- a/drivers/clk/Makefile
> > +++ b/drivers/clk/Makefile
> > @@ -2,3 +2,4 @@
> >  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> >  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
> >  obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
> > +obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
> > diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> > new file mode 100644
> > index 0000000..a1d8e79
> > --- /dev/null
> > +++ b/drivers/clk/clk-gate.c
> > @@ -0,0 +1,78 @@
> > +/*
> > + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * Simple clk gate implementation
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/module.h>
> > +#include <asm/io.h>
> 
> use linux/io.h
> 
> > +
> > +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
> > +
> > +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> > +{
> > +	return clk_get_rate(clk_get_parent(clk->clk));
> > +}
> > +
> > +static void clk_gate_set_bit(struct clk_hw *clk)
> > +{
> > +	struct clk_gate *gate = to_clk_gate(clk);
> > +	u32 reg;
> > +
> > +	reg = __raw_readl(gate->reg);
> > +	reg |= BIT(gate->bit_idx);
> > +	__raw_writel(reg, gate->reg);
> 
> Don't these read-mod-writes need a spinlock around it?
> 
> It's possible to have an enable bits and dividers in the same register.
> If you did a set_rate and while doing an enable/disable, there would be
> a problem. Also, it may be 2 different clocks in the same register, so
> the spinlock needs to be shared and not per clock.

Well the prepare lock will be held here and I believe that would be 
sufficient.

> > +}
> > +
> > +static void clk_gate_clear_bit(struct clk_hw *clk)
> > +{
> > +	struct clk_gate *gate = to_clk_gate(clk);
> > +	u32 reg;
> > +
> > +	reg = __raw_readl(gate->reg);
> > +	reg &= ~BIT(gate->bit_idx);
> > +	__raw_writel(reg, gate->reg);
> > +}
> > +
> > +static int clk_gate_enable_set(struct clk_hw *clk)
> > +{
> > +	clk_gate_set_bit(clk);
> > +
> > +	return 0;
> > +}
> > +
> > +static void clk_gate_disable_clear(struct clk_hw *clk)
> > +{
> > +	clk_gate_clear_bit(clk);
> > +}
> > +
> > +struct clk_hw_ops clk_gate_set_enable_ops = {
> 
> const?

Yup.

> > +	.recalc_rate = clk_gate_get_rate,
> > +	.enable = clk_gate_enable_set,
> > +	.disable = clk_gate_disable_clear,
> > +};
> > +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
> > +
> > +static int clk_gate_enable_clear(struct clk_hw *clk)
> > +{
> > +	clk_gate_clear_bit(clk);
> > +
> > +	return 0;
> > +}
> > +
> > +static void clk_gate_disable_set(struct clk_hw *clk)
> > +{
> > +	clk_gate_set_bit(clk);
> > +}
> 
> Are these wrapper functions really needed? Just assign set_bit and
> clear_bit functions directly to the ops structs. Only the ops struct
> name is exposed to the user.

I used the wrappers because the .enable method has to return an int, but 
the disable needs to return void.  It's either that or open code the 
set/clear in each.

> > +
> > +struct clk_hw_ops clk_gate_set_disable_ops = {
> 
> const?

Yes.

Jamie

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-09-26 18:40       ` Jamie Iles
  0 siblings, 0 replies; 144+ messages in thread
From: Jamie Iles @ 2011-09-26 18:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Rob,

On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
> Mike,
> 
> On 09/22/2011 05:26 PM, Mike Turquette wrote:
> > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > 
> > Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> > Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> > Signed-off-by: Mike Turquette <mturquette@ti.com>
> > ---
> > Changes since v1:
> > Add copyright header
> > Fold in Jamie's patch for set-to-disable clks
> > Use BIT macro instead of shift
> > 
> >  drivers/clk/Kconfig    |    4 ++
> >  drivers/clk/Makefile   |    1 +
> >  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk.h    |   13 ++++++++
> >  4 files changed, 96 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/clk/clk-gate.c
> > 
> > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> > index d8313d7..a78967c 100644
> > --- a/drivers/clk/Kconfig
> > +++ b/drivers/clk/Kconfig
> > @@ -12,3 +12,7 @@ config GENERIC_CLK
> >  config GENERIC_CLK_FIXED
> >  	bool
> >  	depends on GENERIC_CLK
> > +
> > +config GENERIC_CLK_GATE
> > +	bool
> > +	depends on GENERIC_CLK
> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> > index 9a3325a..d186446 100644
> > --- a/drivers/clk/Makefile
> > +++ b/drivers/clk/Makefile
> > @@ -2,3 +2,4 @@
> >  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> >  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
> >  obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
> > +obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
> > diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> > new file mode 100644
> > index 0000000..a1d8e79
> > --- /dev/null
> > +++ b/drivers/clk/clk-gate.c
> > @@ -0,0 +1,78 @@
> > +/*
> > + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * Simple clk gate implementation
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/module.h>
> > +#include <asm/io.h>
> 
> use linux/io.h
> 
> > +
> > +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
> > +
> > +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> > +{
> > +	return clk_get_rate(clk_get_parent(clk->clk));
> > +}
> > +
> > +static void clk_gate_set_bit(struct clk_hw *clk)
> > +{
> > +	struct clk_gate *gate = to_clk_gate(clk);
> > +	u32 reg;
> > +
> > +	reg = __raw_readl(gate->reg);
> > +	reg |= BIT(gate->bit_idx);
> > +	__raw_writel(reg, gate->reg);
> 
> Don't these read-mod-writes need a spinlock around it?
> 
> It's possible to have an enable bits and dividers in the same register.
> If you did a set_rate and while doing an enable/disable, there would be
> a problem. Also, it may be 2 different clocks in the same register, so
> the spinlock needs to be shared and not per clock.

Well the prepare lock will be held here and I believe that would be 
sufficient.

> > +}
> > +
> > +static void clk_gate_clear_bit(struct clk_hw *clk)
> > +{
> > +	struct clk_gate *gate = to_clk_gate(clk);
> > +	u32 reg;
> > +
> > +	reg = __raw_readl(gate->reg);
> > +	reg &= ~BIT(gate->bit_idx);
> > +	__raw_writel(reg, gate->reg);
> > +}
> > +
> > +static int clk_gate_enable_set(struct clk_hw *clk)
> > +{
> > +	clk_gate_set_bit(clk);
> > +
> > +	return 0;
> > +}
> > +
> > +static void clk_gate_disable_clear(struct clk_hw *clk)
> > +{
> > +	clk_gate_clear_bit(clk);
> > +}
> > +
> > +struct clk_hw_ops clk_gate_set_enable_ops = {
> 
> const?

Yup.

> > +	.recalc_rate = clk_gate_get_rate,
> > +	.enable = clk_gate_enable_set,
> > +	.disable = clk_gate_disable_clear,
> > +};
> > +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
> > +
> > +static int clk_gate_enable_clear(struct clk_hw *clk)
> > +{
> > +	clk_gate_clear_bit(clk);
> > +
> > +	return 0;
> > +}
> > +
> > +static void clk_gate_disable_set(struct clk_hw *clk)
> > +{
> > +	clk_gate_set_bit(clk);
> > +}
> 
> Are these wrapper functions really needed? Just assign set_bit and
> clear_bit functions directly to the ops structs. Only the ops struct
> name is exposed to the user.

I used the wrappers because the .enable method has to return an int, but 
the disable needs to return void.  It's either that or open code the 
set/clear in each.

> > +
> > +struct clk_hw_ops clk_gate_set_disable_ops = {
> 
> const?

Yes.

Jamie

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-26 18:40       ` Jamie Iles
@ 2011-09-26 19:10         ` Rob Herring
  -1 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-09-26 19:10 UTC (permalink / raw)
  To: Jamie Iles
  Cc: Mike Turquette, linux-kernel, paul, linaro-dev, linus.walleij,
	patches, eric.miao, broonie, magnus.damm, arnd.bergmann, skannan,
	linux, jeremy.kerr, tglx, linux-arm-kernel, sboyd

On 09/26/2011 01:40 PM, Jamie Iles wrote:
> Hi Rob,
> 
> On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
>> Mike,
>>
>> On 09/22/2011 05:26 PM, Mike Turquette wrote:
>>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>>>
>>> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>>> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>>> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
>>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>>> ---
>>> Changes since v1:
>>> Add copyright header
>>> Fold in Jamie's patch for set-to-disable clks
>>> Use BIT macro instead of shift
>>>
>>>  drivers/clk/Kconfig    |    4 ++
>>>  drivers/clk/Makefile   |    1 +
>>>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>>>  include/linux/clk.h    |   13 ++++++++
>>>  4 files changed, 96 insertions(+), 0 deletions(-)
>>>  create mode 100644 drivers/clk/clk-gate.c
>>>
>>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>>> index d8313d7..a78967c 100644
>>> --- a/drivers/clk/Kconfig
>>> +++ b/drivers/clk/Kconfig
>>> @@ -12,3 +12,7 @@ config GENERIC_CLK
>>>  config GENERIC_CLK_FIXED
>>>  	bool
>>>  	depends on GENERIC_CLK
>>> +
>>> +config GENERIC_CLK_GATE
>>> +	bool
>>> +	depends on GENERIC_CLK
>>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>>> index 9a3325a..d186446 100644
>>> --- a/drivers/clk/Makefile
>>> +++ b/drivers/clk/Makefile
>>> @@ -2,3 +2,4 @@
>>>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>>>  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
>>>  obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
>>> +obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
>>> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
>>> new file mode 100644
>>> index 0000000..a1d8e79
>>> --- /dev/null
>>> +++ b/drivers/clk/clk-gate.c
>>> @@ -0,0 +1,78 @@
>>> +/*
>>> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * Simple clk gate implementation
>>> + */
>>> +
>>> +#include <linux/clk.h>
>>> +#include <linux/module.h>
>>> +#include <asm/io.h>
>>
>> use linux/io.h
>>
>>> +
>>> +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
>>> +
>>> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
>>> +{
>>> +	return clk_get_rate(clk_get_parent(clk->clk));
>>> +}
>>> +
>>> +static void clk_gate_set_bit(struct clk_hw *clk)
>>> +{
>>> +	struct clk_gate *gate = to_clk_gate(clk);
>>> +	u32 reg;
>>> +
>>> +	reg = __raw_readl(gate->reg);
>>> +	reg |= BIT(gate->bit_idx);
>>> +	__raw_writel(reg, gate->reg);
>>
>> Don't these read-mod-writes need a spinlock around it?
>>
>> It's possible to have an enable bits and dividers in the same register.
>> If you did a set_rate and while doing an enable/disable, there would be
>> a problem. Also, it may be 2 different clocks in the same register, so
>> the spinlock needs to be shared and not per clock.
> 
> Well the prepare lock will be held here and I believe that would be 
> sufficient.

No, the enable spinlock is protecting enable/disable. But set_rate is
protected by the prepare mutex. So you clearly don't need locking if you
have a register of only 1 bit enables. If you have a register accessed
by both enable/disable and prepare/unprepare/set_rate, then you need
some protection.


> 
>>> +}
>>> +
>>> +static void clk_gate_clear_bit(struct clk_hw *clk)
>>> +{
>>> +	struct clk_gate *gate = to_clk_gate(clk);
>>> +	u32 reg;
>>> +
>>> +	reg = __raw_readl(gate->reg);
>>> +	reg &= ~BIT(gate->bit_idx);
>>> +	__raw_writel(reg, gate->reg);
>>> +}
>>> +
>>> +static int clk_gate_enable_set(struct clk_hw *clk)
>>> +{
>>> +	clk_gate_set_bit(clk);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void clk_gate_disable_clear(struct clk_hw *clk)
>>> +{
>>> +	clk_gate_clear_bit(clk);
>>> +}
>>> +
>>> +struct clk_hw_ops clk_gate_set_enable_ops = {
>>
>> const?
> 
> Yup.
> 
>>> +	.recalc_rate = clk_gate_get_rate,
>>> +	.enable = clk_gate_enable_set,
>>> +	.disable = clk_gate_disable_clear,
>>> +};
>>> +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
>>> +
>>> +static int clk_gate_enable_clear(struct clk_hw *clk)
>>> +{
>>> +	clk_gate_clear_bit(clk);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void clk_gate_disable_set(struct clk_hw *clk)
>>> +{
>>> +	clk_gate_set_bit(clk);
>>> +}
>>
>> Are these wrapper functions really needed? Just assign set_bit and
>> clear_bit functions directly to the ops structs. Only the ops struct
>> name is exposed to the user.
> 
> I used the wrappers because the .enable method has to return an int, but 
> the disable needs to return void.  It's either that or open code the 
> set/clear in each.

Okay. I missed that detail...

Rob

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-09-26 19:10         ` Rob Herring
  0 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-09-26 19:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/26/2011 01:40 PM, Jamie Iles wrote:
> Hi Rob,
> 
> On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
>> Mike,
>>
>> On 09/22/2011 05:26 PM, Mike Turquette wrote:
>>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>>>
>>> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>>> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>>> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
>>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>>> ---
>>> Changes since v1:
>>> Add copyright header
>>> Fold in Jamie's patch for set-to-disable clks
>>> Use BIT macro instead of shift
>>>
>>>  drivers/clk/Kconfig    |    4 ++
>>>  drivers/clk/Makefile   |    1 +
>>>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>>>  include/linux/clk.h    |   13 ++++++++
>>>  4 files changed, 96 insertions(+), 0 deletions(-)
>>>  create mode 100644 drivers/clk/clk-gate.c
>>>
>>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>>> index d8313d7..a78967c 100644
>>> --- a/drivers/clk/Kconfig
>>> +++ b/drivers/clk/Kconfig
>>> @@ -12,3 +12,7 @@ config GENERIC_CLK
>>>  config GENERIC_CLK_FIXED
>>>  	bool
>>>  	depends on GENERIC_CLK
>>> +
>>> +config GENERIC_CLK_GATE
>>> +	bool
>>> +	depends on GENERIC_CLK
>>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>>> index 9a3325a..d186446 100644
>>> --- a/drivers/clk/Makefile
>>> +++ b/drivers/clk/Makefile
>>> @@ -2,3 +2,4 @@
>>>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>>>  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
>>>  obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
>>> +obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
>>> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
>>> new file mode 100644
>>> index 0000000..a1d8e79
>>> --- /dev/null
>>> +++ b/drivers/clk/clk-gate.c
>>> @@ -0,0 +1,78 @@
>>> +/*
>>> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License version 2 as
>>> + * published by the Free Software Foundation.
>>> + *
>>> + * Simple clk gate implementation
>>> + */
>>> +
>>> +#include <linux/clk.h>
>>> +#include <linux/module.h>
>>> +#include <asm/io.h>
>>
>> use linux/io.h
>>
>>> +
>>> +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
>>> +
>>> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
>>> +{
>>> +	return clk_get_rate(clk_get_parent(clk->clk));
>>> +}
>>> +
>>> +static void clk_gate_set_bit(struct clk_hw *clk)
>>> +{
>>> +	struct clk_gate *gate = to_clk_gate(clk);
>>> +	u32 reg;
>>> +
>>> +	reg = __raw_readl(gate->reg);
>>> +	reg |= BIT(gate->bit_idx);
>>> +	__raw_writel(reg, gate->reg);
>>
>> Don't these read-mod-writes need a spinlock around it?
>>
>> It's possible to have an enable bits and dividers in the same register.
>> If you did a set_rate and while doing an enable/disable, there would be
>> a problem. Also, it may be 2 different clocks in the same register, so
>> the spinlock needs to be shared and not per clock.
> 
> Well the prepare lock will be held here and I believe that would be 
> sufficient.

No, the enable spinlock is protecting enable/disable. But set_rate is
protected by the prepare mutex. So you clearly don't need locking if you
have a register of only 1 bit enables. If you have a register accessed
by both enable/disable and prepare/unprepare/set_rate, then you need
some protection.


> 
>>> +}
>>> +
>>> +static void clk_gate_clear_bit(struct clk_hw *clk)
>>> +{
>>> +	struct clk_gate *gate = to_clk_gate(clk);
>>> +	u32 reg;
>>> +
>>> +	reg = __raw_readl(gate->reg);
>>> +	reg &= ~BIT(gate->bit_idx);
>>> +	__raw_writel(reg, gate->reg);
>>> +}
>>> +
>>> +static int clk_gate_enable_set(struct clk_hw *clk)
>>> +{
>>> +	clk_gate_set_bit(clk);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void clk_gate_disable_clear(struct clk_hw *clk)
>>> +{
>>> +	clk_gate_clear_bit(clk);
>>> +}
>>> +
>>> +struct clk_hw_ops clk_gate_set_enable_ops = {
>>
>> const?
> 
> Yup.
> 
>>> +	.recalc_rate = clk_gate_get_rate,
>>> +	.enable = clk_gate_enable_set,
>>> +	.disable = clk_gate_disable_clear,
>>> +};
>>> +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
>>> +
>>> +static int clk_gate_enable_clear(struct clk_hw *clk)
>>> +{
>>> +	clk_gate_clear_bit(clk);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void clk_gate_disable_set(struct clk_hw *clk)
>>> +{
>>> +	clk_gate_set_bit(clk);
>>> +}
>>
>> Are these wrapper functions really needed? Just assign set_bit and
>> clear_bit functions directly to the ops structs. Only the ops struct
>> name is exposed to the user.
> 
> I used the wrappers because the .enable method has to return an int, but 
> the disable needs to return void.  It's either that or open code the 
> set/clear in each.

Okay. I missed that detail...

Rob

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-26 19:10         ` Rob Herring
@ 2011-09-26 19:37           ` Jamie Iles
  -1 siblings, 0 replies; 144+ messages in thread
From: Jamie Iles @ 2011-09-26 19:37 UTC (permalink / raw)
  To: Rob Herring
  Cc: Jamie Iles, Mike Turquette, linux-kernel, paul, linaro-dev,
	linus.walleij, patches, eric.miao, broonie, magnus.damm,
	arnd.bergmann, skannan, linux, jeremy.kerr, tglx,
	linux-arm-kernel, sboyd

On Mon, Sep 26, 2011 at 02:10:32PM -0500, Rob Herring wrote:
> On 09/26/2011 01:40 PM, Jamie Iles wrote:
> > On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
> >>> +static void clk_gate_set_bit(struct clk_hw *clk)
> >>> +{
> >>> +	struct clk_gate *gate = to_clk_gate(clk);
> >>> +	u32 reg;
> >>> +
> >>> +	reg = __raw_readl(gate->reg);
> >>> +	reg |= BIT(gate->bit_idx);
> >>> +	__raw_writel(reg, gate->reg);
> >>
> >> Don't these read-mod-writes need a spinlock around it?
> >>
> >> It's possible to have an enable bits and dividers in the same register.
> >> If you did a set_rate and while doing an enable/disable, there would be
> >> a problem. Also, it may be 2 different clocks in the same register, so
> >> the spinlock needs to be shared and not per clock.
> > 
> > Well the prepare lock will be held here and I believe that would be 
> > sufficient.
> 
> No, the enable spinlock is protecting enable/disable. But set_rate is
> protected by the prepare mutex. So you clearly don't need locking if you
> have a register of only 1 bit enables. If you have a register accessed
> by both enable/disable and prepare/unprepare/set_rate, then you need
> some protection.

OK fair point, but I would guess that if you had a clock like this then 
you probably wouldn't use this simple gated clock would you?  (speaking 
from my world where we have quite simple clocks ;-))

Jamie

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-09-26 19:37           ` Jamie Iles
  0 siblings, 0 replies; 144+ messages in thread
From: Jamie Iles @ 2011-09-26 19:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 26, 2011 at 02:10:32PM -0500, Rob Herring wrote:
> On 09/26/2011 01:40 PM, Jamie Iles wrote:
> > On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
> >>> +static void clk_gate_set_bit(struct clk_hw *clk)
> >>> +{
> >>> +	struct clk_gate *gate = to_clk_gate(clk);
> >>> +	u32 reg;
> >>> +
> >>> +	reg = __raw_readl(gate->reg);
> >>> +	reg |= BIT(gate->bit_idx);
> >>> +	__raw_writel(reg, gate->reg);
> >>
> >> Don't these read-mod-writes need a spinlock around it?
> >>
> >> It's possible to have an enable bits and dividers in the same register.
> >> If you did a set_rate and while doing an enable/disable, there would be
> >> a problem. Also, it may be 2 different clocks in the same register, so
> >> the spinlock needs to be shared and not per clock.
> > 
> > Well the prepare lock will be held here and I believe that would be 
> > sufficient.
> 
> No, the enable spinlock is protecting enable/disable. But set_rate is
> protected by the prepare mutex. So you clearly don't need locking if you
> have a register of only 1 bit enables. If you have a register accessed
> by both enable/disable and prepare/unprepare/set_rate, then you need
> some protection.

OK fair point, but I would guess that if you had a clock like this then 
you probably wouldn't use this simple gated clock would you?  (speaking 
from my world where we have quite simple clocks ;-))

Jamie

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-26 19:37           ` Jamie Iles
@ 2011-09-26 22:37             ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-26 22:37 UTC (permalink / raw)
  To: Jamie Iles
  Cc: Rob Herring, linux-kernel, paul, linaro-dev, linus.walleij,
	patches, eric.miao, broonie, magnus.damm, arnd.bergmann, skannan,
	linux, jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Mon, Sep 26, 2011 at 12:37 PM, Jamie Iles <jamie@jamieiles.com> wrote:
> On Mon, Sep 26, 2011 at 02:10:32PM -0500, Rob Herring wrote:
>> On 09/26/2011 01:40 PM, Jamie Iles wrote:
>> > On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
>> >>> +static void clk_gate_set_bit(struct clk_hw *clk)
>> >>> +{
>> >>> + struct clk_gate *gate = to_clk_gate(clk);
>> >>> + u32 reg;
>> >>> +
>> >>> + reg = __raw_readl(gate->reg);
>> >>> + reg |= BIT(gate->bit_idx);
>> >>> + __raw_writel(reg, gate->reg);
>> >>
>> >> Don't these read-mod-writes need a spinlock around it?
>> >>
>> >> It's possible to have an enable bits and dividers in the same register.
>> >> If you did a set_rate and while doing an enable/disable, there would be
>> >> a problem. Also, it may be 2 different clocks in the same register, so
>> >> the spinlock needs to be shared and not per clock.
>> >
>> > Well the prepare lock will be held here and I believe that would be
>> > sufficient.
>>
>> No, the enable spinlock is protecting enable/disable. But set_rate is
>> protected by the prepare mutex. So you clearly don't need locking if you
>> have a register of only 1 bit enables. If you have a register accessed
>> by both enable/disable and prepare/unprepare/set_rate, then you need
>> some protection.
>
> OK fair point, but I would guess that if you had a clock like this then
> you probably wouldn't use this simple gated clock would you?  (speaking
> from my world where we have quite simple clocks ;-))

I think it is a safe assumption that if a register controls both
enable/disable and some programmable divider then,

1) those controls are probably for the same clock
2) that clock won't be using the cookie-cutter gated-clock
implementation anyways

Rob, do you feel these assumptions are OK and locking can remain the
same in this patch?

Regards,
Mike

> Jamie
>

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-09-26 22:37             ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-09-26 22:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 26, 2011 at 12:37 PM, Jamie Iles <jamie@jamieiles.com> wrote:
> On Mon, Sep 26, 2011 at 02:10:32PM -0500, Rob Herring wrote:
>> On 09/26/2011 01:40 PM, Jamie Iles wrote:
>> > On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
>> >>> +static void clk_gate_set_bit(struct clk_hw *clk)
>> >>> +{
>> >>> + struct clk_gate *gate = to_clk_gate(clk);
>> >>> + u32 reg;
>> >>> +
>> >>> + reg = __raw_readl(gate->reg);
>> >>> + reg |= BIT(gate->bit_idx);
>> >>> + __raw_writel(reg, gate->reg);
>> >>
>> >> Don't these read-mod-writes need a spinlock around it?
>> >>
>> >> It's possible to have an enable bits and dividers in the same register.
>> >> If you did a set_rate and while doing an enable/disable, there would be
>> >> a problem. Also, it may be 2 different clocks in the same register, so
>> >> the spinlock needs to be shared and not per clock.
>> >
>> > Well the prepare lock will be held here and I believe that would be
>> > sufficient.
>>
>> No, the enable spinlock is protecting enable/disable. But set_rate is
>> protected by the prepare mutex. So you clearly don't need locking if you
>> have a register of only 1 bit enables. If you have a register accessed
>> by both enable/disable and prepare/unprepare/set_rate, then you need
>> some protection.
>
> OK fair point, but I would guess that if you had a clock like this then
> you probably wouldn't use this simple gated clock would you? ?(speaking
> from my world where we have quite simple clocks ;-))

I think it is a safe assumption that if a register controls both
enable/disable and some programmable divider then,

1) those controls are probably for the same clock
2) that clock won't be using the cookie-cutter gated-clock
implementation anyways

Rob, do you feel these assumptions are OK and locking can remain the
same in this patch?

Regards,
Mike

> Jamie
>

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-26 22:37             ` Turquette, Mike
@ 2011-09-26 23:30               ` Rob Herring
  -1 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-09-26 23:30 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Jamie Iles, linux-kernel, paul, linaro-dev, linus.walleij,
	patches, eric.miao, broonie, magnus.damm, arnd.bergmann, skannan,
	linux, jeremy.kerr, tglx, linux-arm-kernel, sboyd

On 09/26/2011 05:37 PM, Turquette, Mike wrote:
> On Mon, Sep 26, 2011 at 12:37 PM, Jamie Iles <jamie@jamieiles.com> wrote:
>> On Mon, Sep 26, 2011 at 02:10:32PM -0500, Rob Herring wrote:
>>> On 09/26/2011 01:40 PM, Jamie Iles wrote:
>>>> On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
>>>>>> +static void clk_gate_set_bit(struct clk_hw *clk)
>>>>>> +{
>>>>>> + struct clk_gate *gate = to_clk_gate(clk);
>>>>>> + u32 reg;
>>>>>> +
>>>>>> + reg = __raw_readl(gate->reg);
>>>>>> + reg |= BIT(gate->bit_idx);
>>>>>> + __raw_writel(reg, gate->reg);
>>>>>
>>>>> Don't these read-mod-writes need a spinlock around it?
>>>>>
>>>>> It's possible to have an enable bits and dividers in the same register.
>>>>> If you did a set_rate and while doing an enable/disable, there would be
>>>>> a problem. Also, it may be 2 different clocks in the same register, so
>>>>> the spinlock needs to be shared and not per clock.
>>>>
>>>> Well the prepare lock will be held here and I believe that would be
>>>> sufficient.
>>>
>>> No, the enable spinlock is protecting enable/disable. But set_rate is
>>> protected by the prepare mutex. So you clearly don't need locking if you
>>> have a register of only 1 bit enables. If you have a register accessed
>>> by both enable/disable and prepare/unprepare/set_rate, then you need
>>> some protection.
>>
>> OK fair point, but I would guess that if you had a clock like this then
>> you probably wouldn't use this simple gated clock would you?  (speaking
>> from my world where we have quite simple clocks ;-))
> 
> I think it is a safe assumption that if a register controls both
> enable/disable and some programmable divider then,
> 
> 1) those controls are probably for the same clock
> 2) that clock won't be using the cookie-cutter gated-clock
> implementation anyways

By definition of simple gated clock, the other bits have to be for
another clock. The restriction is that all the other bits can only be
clock gate bits.

> 
> Rob, do you feel these assumptions are OK and locking can remain the
> same in this patch?

Perhaps it is rare enough that it is not worth it use generic code in
this case. If so, the documentation should be clear about this
constraint. It is not something anyone will have hit before because
everyone used a single global lock. Now with the api being split between
2 locks, this adds a new complexity.

I think the simple gated clock code should be usable for any clock
controlled by a single bit in a 32-bit register independent of other
things in that register.

One example is MX1 in (mach-imx/clock-imx1.c). The CSCR register has
single bit enable for clk16m while hclk and clk48m have dividers in that
register.

Rob

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-09-26 23:30               ` Rob Herring
  0 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-09-26 23:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/26/2011 05:37 PM, Turquette, Mike wrote:
> On Mon, Sep 26, 2011 at 12:37 PM, Jamie Iles <jamie@jamieiles.com> wrote:
>> On Mon, Sep 26, 2011 at 02:10:32PM -0500, Rob Herring wrote:
>>> On 09/26/2011 01:40 PM, Jamie Iles wrote:
>>>> On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
>>>>>> +static void clk_gate_set_bit(struct clk_hw *clk)
>>>>>> +{
>>>>>> + struct clk_gate *gate = to_clk_gate(clk);
>>>>>> + u32 reg;
>>>>>> +
>>>>>> + reg = __raw_readl(gate->reg);
>>>>>> + reg |= BIT(gate->bit_idx);
>>>>>> + __raw_writel(reg, gate->reg);
>>>>>
>>>>> Don't these read-mod-writes need a spinlock around it?
>>>>>
>>>>> It's possible to have an enable bits and dividers in the same register.
>>>>> If you did a set_rate and while doing an enable/disable, there would be
>>>>> a problem. Also, it may be 2 different clocks in the same register, so
>>>>> the spinlock needs to be shared and not per clock.
>>>>
>>>> Well the prepare lock will be held here and I believe that would be
>>>> sufficient.
>>>
>>> No, the enable spinlock is protecting enable/disable. But set_rate is
>>> protected by the prepare mutex. So you clearly don't need locking if you
>>> have a register of only 1 bit enables. If you have a register accessed
>>> by both enable/disable and prepare/unprepare/set_rate, then you need
>>> some protection.
>>
>> OK fair point, but I would guess that if you had a clock like this then
>> you probably wouldn't use this simple gated clock would you?  (speaking
>> from my world where we have quite simple clocks ;-))
> 
> I think it is a safe assumption that if a register controls both
> enable/disable and some programmable divider then,
> 
> 1) those controls are probably for the same clock
> 2) that clock won't be using the cookie-cutter gated-clock
> implementation anyways

By definition of simple gated clock, the other bits have to be for
another clock. The restriction is that all the other bits can only be
clock gate bits.

> 
> Rob, do you feel these assumptions are OK and locking can remain the
> same in this patch?

Perhaps it is rare enough that it is not worth it use generic code in
this case. If so, the documentation should be clear about this
constraint. It is not something anyone will have hit before because
everyone used a single global lock. Now with the api being split between
2 locks, this adds a new complexity.

I think the simple gated clock code should be usable for any clock
controlled by a single bit in a 32-bit register independent of other
things in that register.

One example is MX1 in (mach-imx/clock-imx1.c). The CSCR register has
single bit enable for clk16m while hclk and clk48m have dividers in that
register.

Rob

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

* Re: [PATCH v2 0/7] Add a generic struct clk
  2011-09-22 22:26 ` Mike Turquette
@ 2011-09-29 18:54   ` Mark Brown
  -1 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-09-29 18:54 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, magnus.damm, arnd.bergmann, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Thu, Sep 22, 2011 at 03:26:55PM -0700, Mike Turquette wrote:

> more thought.  I also dropped Mark's change to append a device's name to
> a clk name since device tree might solve this neatly.  Again more
> discussion around that would be good.

Some of that was for debugfs type stuff - if we end up providing
information about the clocks via a diagnostic interface being able to
distinguish between things in a textual fashion would be handy (and I'd
guess the struct device may also be needed by any OF bindings to get at
the bindings?).

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

* [PATCH v2 0/7] Add a generic struct clk
@ 2011-09-29 18:54   ` Mark Brown
  0 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-09-29 18:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:55PM -0700, Mike Turquette wrote:

> more thought.  I also dropped Mark's change to append a device's name to
> a clk name since device tree might solve this neatly.  Again more
> discussion around that would be good.

Some of that was for debugfs type stuff - if we end up providing
information about the clocks via a diagnostic interface being able to
distinguish between things in a textual fashion would be handy (and I'd
guess the struct device may also be needed by any OF bindings to get at
the bindings?).

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-03 14:17     ` Rob Herring
  -1 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-10-03 14:17 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

On 09/22/2011 05:26 PM, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, and a set of clock operations. Different clock
> implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> The interface is split into two halves:
> 
>  * struct clk, which is the generic-device-driver interface. This
>    provides a set of functions which drivers may use to request
>    enable/disable, query or manipulate in a hardware-independent manner.
> 
>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>    interface. Clock drivers implement the ops, which allow the core
>    clock code to implement the generic 'struct clk' API.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
> common, opaque struct clk, and a set of clock operations (defined per
> type of clock):
> 
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };
> 
>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
> 
>   static int clk_foo_enable(struct clk_hw *clk)
>   {
>   	struct clk_foo *foo = to_clk_foo(clk);
>   	raw_writeb(foo->enable_reg, 1);
>   	return 0;
>   }
> 
>   struct clk_hw_ops clk_foo_ops = {
>   	.enable = clk_foo_enable,
>   };
> 
> And in the platform initialisation code:
> 
>   struct clk_foo my_clk_foo;
> 
>   void init_clocks(void)
>   {
>   	my_clk_foo.enable_reg = ioremap(...);
> 
>   	clk_register(&clk_foo_ops, &my_clk_foo, NULL);
>   }
> 
> Changes from Thomas Gleixner <tglx@linutronix.de>.
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> TODO:
> 
>  * We don't keep any internal reference to the clock topology at present.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Create a dummy clk_unregister and prototype/document it and clk_register
> Constify struct clk_hw_ops
> Remove spinlock.h header, include kernel.h
> Use EOPNOTSUPP instead of ENOTSUPP
> Add might_sleep to clk_prepare/clk_unprepare stubs
> Properly init children hlist and child_node
> Whitespace and typo fixes
> 
>  drivers/clk/Kconfig  |    3 +
>  drivers/clk/Makefile |    1 +
>  drivers/clk/clk.c    |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    7 ++
>  include/linux/clk.h  |  140 +++++++++++++++++++++++++++---
>  5 files changed, 371 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/clk/clk.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3530927..c53ed59 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
>  
>  config HAVE_MACH_CLKDEV
>  	bool
> +
> +config GENERIC_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..570d5b9 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_GENERIC_CLK)	+= clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..1cd7315
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,232 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +struct clk {
> +	const char		*name;
> +	const struct clk_hw_ops	*ops;
> +	struct clk_hw		*hw;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	struct clk		*parent;
> +	unsigned long		rate;
> +};
> +
> +static DEFINE_SPINLOCK(enable_lock);
> +static DEFINE_MUTEX(prepare_lock);
> +
> +static void __clk_unprepare(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return;
> +
> +	if (--clk->prepare_count > 0)
> +		return;
> +
> +	WARN_ON(clk->enable_count > 0);
> +
> +	if (clk->ops->unprepare)
> +		clk->ops->unprepare(clk->hw);
> +
> +	__clk_unprepare(clk->parent);
> +}
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&prepare_lock);
> +	__clk_unprepare(clk);
> +	mutex_unlock(&prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +static int __clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (clk->prepare_count == 0) {
> +		ret = __clk_prepare(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->prepare) {
> +			ret = clk->ops->prepare(clk->hw);
> +			if (ret) {
> +				__clk_unprepare(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->prepare_count++;
> +
> +	return 0;
> +}
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret;
> +
> +	mutex_lock(&prepare_lock);
> +	ret = __clk_prepare(clk);
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +static void __clk_disable(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->enable_count == 0))
> +		return;
> +
> +	if (--clk->enable_count > 0)
> +		return;
> +
> +	if (clk->ops->disable)
> +		clk->ops->disable(clk->hw);
> +	__clk_disable(clk->parent);
> +}
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	__clk_disable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +static int __clk_enable(struct clk *clk)
> +{
> +	int ret;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return -ESHUTDOWN;
> +
> +
> +	if (clk->enable_count == 0) {
> +		ret = __clk_enable(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->enable) {
> +			ret = clk->ops->enable(clk->hw);
> +			if (ret) {
> +				__clk_disable(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->enable_count++;
> +	return 0;
> +}
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	ret = __clk_enable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (!clk)
> +		return 0;
> +	return clk->rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk && clk->ops->round_rate)
> +		return clk->ops->round_rate(clk->hw, rate);
> +	return rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (!clk)
> +		return NULL;
> +
> +	return clk->parent;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +		const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> +	if (!clk)
> +		return NULL;
> +
> +	INIT_HLIST_HEAD(&clk->children);
> +	INIT_HLIST_NODE(&clk->child_node);
> +
> +	clk->name = name;
> +	clk->ops = ops;
> +	clk->hw = hw;
> +	hw->clk = clk;
> +
> +	/* Query the hardware for parent and initial rate */
> +
> +	if (clk->ops->get_parent)
> +		/* We don't to lock against prepare/enable here, as
> +		 * the clock is not yet accessible from anywhere */
> +		clk->parent = clk->ops->get_parent(clk->hw);

I don't think this is going to work. This implies that the parent clock
is already registered. For simple clk trees, that's probably not an
issue, but for chips with lots of muxing it will be impossible to get
the order correct for all cases. This is not an issue today as most
clocks are statically created.

I think what is needed is a 2 stage init. The 1st stage to create all
the clocks and a 2nd stage to build the tree once all clocks are created.

Tracking the parents using struct clk_hw instead would help as long as
clocks are still statically allocated. However, that won't help for
devicetree.

Rob

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-03 14:17     ` Rob Herring
  0 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-10-03 14:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/22/2011 05:26 PM, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, and a set of clock operations. Different clock
> implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> The interface is split into two halves:
> 
>  * struct clk, which is the generic-device-driver interface. This
>    provides a set of functions which drivers may use to request
>    enable/disable, query or manipulate in a hardware-independent manner.
> 
>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>    interface. Clock drivers implement the ops, which allow the core
>    clock code to implement the generic 'struct clk' API.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
> common, opaque struct clk, and a set of clock operations (defined per
> type of clock):
> 
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };
> 
>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
> 
>   static int clk_foo_enable(struct clk_hw *clk)
>   {
>   	struct clk_foo *foo = to_clk_foo(clk);
>   	raw_writeb(foo->enable_reg, 1);
>   	return 0;
>   }
> 
>   struct clk_hw_ops clk_foo_ops = {
>   	.enable = clk_foo_enable,
>   };
> 
> And in the platform initialisation code:
> 
>   struct clk_foo my_clk_foo;
> 
>   void init_clocks(void)
>   {
>   	my_clk_foo.enable_reg = ioremap(...);
> 
>   	clk_register(&clk_foo_ops, &my_clk_foo, NULL);
>   }
> 
> Changes from Thomas Gleixner <tglx@linutronix.de>.
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> TODO:
> 
>  * We don't keep any internal reference to the clock topology at present.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Create a dummy clk_unregister and prototype/document it and clk_register
> Constify struct clk_hw_ops
> Remove spinlock.h header, include kernel.h
> Use EOPNOTSUPP instead of ENOTSUPP
> Add might_sleep to clk_prepare/clk_unprepare stubs
> Properly init children hlist and child_node
> Whitespace and typo fixes
> 
>  drivers/clk/Kconfig  |    3 +
>  drivers/clk/Makefile |    1 +
>  drivers/clk/clk.c    |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    7 ++
>  include/linux/clk.h  |  140 +++++++++++++++++++++++++++---
>  5 files changed, 371 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/clk/clk.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3530927..c53ed59 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
>  
>  config HAVE_MACH_CLKDEV
>  	bool
> +
> +config GENERIC_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..570d5b9 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_GENERIC_CLK)	+= clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..1cd7315
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,232 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +struct clk {
> +	const char		*name;
> +	const struct clk_hw_ops	*ops;
> +	struct clk_hw		*hw;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	struct clk		*parent;
> +	unsigned long		rate;
> +};
> +
> +static DEFINE_SPINLOCK(enable_lock);
> +static DEFINE_MUTEX(prepare_lock);
> +
> +static void __clk_unprepare(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return;
> +
> +	if (--clk->prepare_count > 0)
> +		return;
> +
> +	WARN_ON(clk->enable_count > 0);
> +
> +	if (clk->ops->unprepare)
> +		clk->ops->unprepare(clk->hw);
> +
> +	__clk_unprepare(clk->parent);
> +}
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&prepare_lock);
> +	__clk_unprepare(clk);
> +	mutex_unlock(&prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +static int __clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (clk->prepare_count == 0) {
> +		ret = __clk_prepare(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->prepare) {
> +			ret = clk->ops->prepare(clk->hw);
> +			if (ret) {
> +				__clk_unprepare(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->prepare_count++;
> +
> +	return 0;
> +}
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret;
> +
> +	mutex_lock(&prepare_lock);
> +	ret = __clk_prepare(clk);
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +static void __clk_disable(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->enable_count == 0))
> +		return;
> +
> +	if (--clk->enable_count > 0)
> +		return;
> +
> +	if (clk->ops->disable)
> +		clk->ops->disable(clk->hw);
> +	__clk_disable(clk->parent);
> +}
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	__clk_disable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +static int __clk_enable(struct clk *clk)
> +{
> +	int ret;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return -ESHUTDOWN;
> +
> +
> +	if (clk->enable_count == 0) {
> +		ret = __clk_enable(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->enable) {
> +			ret = clk->ops->enable(clk->hw);
> +			if (ret) {
> +				__clk_disable(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->enable_count++;
> +	return 0;
> +}
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	ret = __clk_enable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (!clk)
> +		return 0;
> +	return clk->rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk && clk->ops->round_rate)
> +		return clk->ops->round_rate(clk->hw, rate);
> +	return rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (!clk)
> +		return NULL;
> +
> +	return clk->parent;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +		const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> +	if (!clk)
> +		return NULL;
> +
> +	INIT_HLIST_HEAD(&clk->children);
> +	INIT_HLIST_NODE(&clk->child_node);
> +
> +	clk->name = name;
> +	clk->ops = ops;
> +	clk->hw = hw;
> +	hw->clk = clk;
> +
> +	/* Query the hardware for parent and initial rate */
> +
> +	if (clk->ops->get_parent)
> +		/* We don't to lock against prepare/enable here, as
> +		 * the clock is not yet accessible from anywhere */
> +		clk->parent = clk->ops->get_parent(clk->hw);

I don't think this is going to work. This implies that the parent clock
is already registered. For simple clk trees, that's probably not an
issue, but for chips with lots of muxing it will be impossible to get
the order correct for all cases. This is not an issue today as most
clocks are statically created.

I think what is needed is a 2 stage init. The 1st stage to create all
the clocks and a 2nd stage to build the tree once all clocks are created.

Tracking the parents using struct clk_hw instead would help as long as
clocks are still statically allocated. However, that won't help for
devicetree.

Rob

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-03 14:17     ` Rob Herring
@ 2011-10-03 14:25       ` Mark Brown
  -1 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-03 14:25 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mike Turquette, linux-kernel, paul, linaro-dev, linus.walleij,
	patches, eric.miao, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Mon, Oct 03, 2011 at 09:17:30AM -0500, Rob Herring wrote:
> On 09/22/2011 05:26 PM, Mike Turquette wrote:

A lot of stuff that should really have been cut plus...

> > +	if (clk->ops->get_parent)
> > +		/* We don't to lock against prepare/enable here, as
> > +		 * the clock is not yet accessible from anywhere */
> > +		clk->parent = clk->ops->get_parent(clk->hw);

> I don't think this is going to work. This implies that the parent clock
> is already registered. For simple clk trees, that's probably not an
> issue, but for chips with lots of muxing it will be impossible to get
> the order correct for all cases. This is not an issue today as most
> clocks are statically created.

> I think what is needed is a 2 stage init. The 1st stage to create all
> the clocks and a 2nd stage to build the tree once all clocks are created.

> Tracking the parents using struct clk_hw instead would help as long as
> clocks are still statically allocated. However, that won't help for
> devicetree.

This isn't in any way specific to clocks, right now the likely solution
looks to be Grant's changes for retrying probe() as new devices come on
line.  With that devices can return a code from their probe() which
tells the driver core that they couldn't get all the resources they need
and that it should retry the probe() if more devices come on-line.

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-03 14:25       ` Mark Brown
  0 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-03 14:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 03, 2011 at 09:17:30AM -0500, Rob Herring wrote:
> On 09/22/2011 05:26 PM, Mike Turquette wrote:

A lot of stuff that should really have been cut plus...

> > +	if (clk->ops->get_parent)
> > +		/* We don't to lock against prepare/enable here, as
> > +		 * the clock is not yet accessible from anywhere */
> > +		clk->parent = clk->ops->get_parent(clk->hw);

> I don't think this is going to work. This implies that the parent clock
> is already registered. For simple clk trees, that's probably not an
> issue, but for chips with lots of muxing it will be impossible to get
> the order correct for all cases. This is not an issue today as most
> clocks are statically created.

> I think what is needed is a 2 stage init. The 1st stage to create all
> the clocks and a 2nd stage to build the tree once all clocks are created.

> Tracking the parents using struct clk_hw instead would help as long as
> clocks are still statically allocated. However, that won't help for
> devicetree.

This isn't in any way specific to clocks, right now the likely solution
looks to be Grant's changes for retrying probe() as new devices come on
line.  With that devices can return a code from their probe() which
tells the driver core that they couldn't get all the resources they need
and that it should retry the probe() if more devices come on-line.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-03 14:25       ` Mark Brown
@ 2011-10-03 15:24         ` Rob Herring
  -1 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-10-03 15:24 UTC (permalink / raw)
  To: Mark Brown
  Cc: Mike Turquette, linux-kernel, paul, linaro-dev, linus.walleij,
	patches, eric.miao, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

On 10/03/2011 09:25 AM, Mark Brown wrote:
> On Mon, Oct 03, 2011 at 09:17:30AM -0500, Rob Herring wrote:
>> On 09/22/2011 05:26 PM, Mike Turquette wrote:
> 
> A lot of stuff that should really have been cut plus...
> 
>>> +	if (clk->ops->get_parent)
>>> +		/* We don't to lock against prepare/enable here, as
>>> +		 * the clock is not yet accessible from anywhere */
>>> +		clk->parent = clk->ops->get_parent(clk->hw);
> 
>> I don't think this is going to work. This implies that the parent clock
>> is already registered. For simple clk trees, that's probably not an
>> issue, but for chips with lots of muxing it will be impossible to get
>> the order correct for all cases. This is not an issue today as most
>> clocks are statically created.
> 
>> I think what is needed is a 2 stage init. The 1st stage to create all
>> the clocks and a 2nd stage to build the tree once all clocks are created.
> 
>> Tracking the parents using struct clk_hw instead would help as long as
>> clocks are still statically allocated. However, that won't help for
>> devicetree.
> 
> This isn't in any way specific to clocks, right now the likely solution
> looks to be Grant's changes for retrying probe() as new devices come on
> line.  With that devices can return a code from their probe() which
> tells the driver core that they couldn't get all the resources they need
> and that it should retry the probe() if more devices come on-line.

Except SOC clocks are initialized very early before timers are up and
there can be a very high number of dependencies (every clock except
fixed clocks). With the driver probe retry, retrying is the exception,
not the rule.

Retrying would require every caller to maintain a list of clks to
retry. With 2 stages, you can move that into the core clock code.

There are not typically a large number of board-level/driver created
clocks, so ensuring correct register order is not really a problem. In
cases where there is a cross-driver dependency, the probe retry is a
good solution.

Rob

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-03 15:24         ` Rob Herring
  0 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-10-03 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/03/2011 09:25 AM, Mark Brown wrote:
> On Mon, Oct 03, 2011 at 09:17:30AM -0500, Rob Herring wrote:
>> On 09/22/2011 05:26 PM, Mike Turquette wrote:
> 
> A lot of stuff that should really have been cut plus...
> 
>>> +	if (clk->ops->get_parent)
>>> +		/* We don't to lock against prepare/enable here, as
>>> +		 * the clock is not yet accessible from anywhere */
>>> +		clk->parent = clk->ops->get_parent(clk->hw);
> 
>> I don't think this is going to work. This implies that the parent clock
>> is already registered. For simple clk trees, that's probably not an
>> issue, but for chips with lots of muxing it will be impossible to get
>> the order correct for all cases. This is not an issue today as most
>> clocks are statically created.
> 
>> I think what is needed is a 2 stage init. The 1st stage to create all
>> the clocks and a 2nd stage to build the tree once all clocks are created.
> 
>> Tracking the parents using struct clk_hw instead would help as long as
>> clocks are still statically allocated. However, that won't help for
>> devicetree.
> 
> This isn't in any way specific to clocks, right now the likely solution
> looks to be Grant's changes for retrying probe() as new devices come on
> line.  With that devices can return a code from their probe() which
> tells the driver core that they couldn't get all the resources they need
> and that it should retry the probe() if more devices come on-line.

Except SOC clocks are initialized very early before timers are up and
there can be a very high number of dependencies (every clock except
fixed clocks). With the driver probe retry, retrying is the exception,
not the rule.

Retrying would require every caller to maintain a list of clks to
retry. With 2 stages, you can move that into the core clock code.

There are not typically a large number of board-level/driver created
clocks, so ensuring correct register order is not really a problem. In
cases where there is a cross-driver dependency, the probe retry is a
good solution.

Rob

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-03 15:24         ` Rob Herring
@ 2011-10-03 16:31           ` Mark Brown
  -1 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-03 16:31 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mike Turquette, linux-kernel, paul, linaro-dev, linus.walleij,
	patches, eric.miao, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Mon, Oct 03, 2011 at 10:24:52AM -0500, Rob Herring wrote:
> On 10/03/2011 09:25 AM, Mark Brown wrote:

> > This isn't in any way specific to clocks, right now the likely solution
> > looks to be Grant's changes for retrying probe() as new devices come on
> > line.  With that devices can return a code from their probe() which
> > tells the driver core that they couldn't get all the resources they need
> > and that it should retry the probe() if more devices come on-line.

> Except SOC clocks are initialized very early before timers are up and
> there can be a very high number of dependencies (every clock except
> fixed clocks). With the driver probe retry, retrying is the exception,
> not the rule.

> Retrying would require every caller to maintain a list of clks to
> retry. With 2 stages, you can move that into the core clock code.

They don't need to maintain a list of clocks to retry, they need to
unwind when probe() fails.  But yes.

> There are not typically a large number of board-level/driver created
> clocks, so ensuring correct register order is not really a problem. In
> cases where there is a cross-driver dependency, the probe retry is a
> good solution.

I dunno, I get the impression that some of this is due to the current
limitations of the clock API rather than due to a lack of clocks -
perhaps that's specific to the applications I look at, though.
applications 

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-03 16:31           ` Mark Brown
  0 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-03 16:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 03, 2011 at 10:24:52AM -0500, Rob Herring wrote:
> On 10/03/2011 09:25 AM, Mark Brown wrote:

> > This isn't in any way specific to clocks, right now the likely solution
> > looks to be Grant's changes for retrying probe() as new devices come on
> > line.  With that devices can return a code from their probe() which
> > tells the driver core that they couldn't get all the resources they need
> > and that it should retry the probe() if more devices come on-line.

> Except SOC clocks are initialized very early before timers are up and
> there can be a very high number of dependencies (every clock except
> fixed clocks). With the driver probe retry, retrying is the exception,
> not the rule.

> Retrying would require every caller to maintain a list of clks to
> retry. With 2 stages, you can move that into the core clock code.

They don't need to maintain a list of clocks to retry, they need to
unwind when probe() fails.  But yes.

> There are not typically a large number of board-level/driver created
> clocks, so ensuring correct register order is not really a problem. In
> cases where there is a cross-driver dependency, the probe retry is a
> good solution.

I dunno, I get the impression that some of this is due to the current
limitations of the clock API rather than due to a lack of clocks -
perhaps that's specific to the applications I look at, though.
applications 

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-03 16:31           ` Mark Brown
@ 2011-10-03 16:43             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 144+ messages in thread
From: Russell King - ARM Linux @ 2011-10-03 16:43 UTC (permalink / raw)
  To: Mark Brown
  Cc: Rob Herring, Mike Turquette, linux-kernel, paul, linaro-dev,
	linus.walleij, patches, eric.miao, magnus.damm, amit.kucheria,
	richard.zhao, grant.likely, dsaxena, arnd.bergmann, shawn.guo,
	skannan, jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Mon, Oct 03, 2011 at 05:31:08PM +0100, Mark Brown wrote:
> I dunno, I get the impression that some of this is due to the current
> limitations of the clock API rather than due to a lack of clocks -
> perhaps that's specific to the applications I look at, though.
> applications 

The clk API per-se has nothing to do with how clocks are registered.
There are two things that are the clk API:

1. clkdev - which deals with translating devices + connection IDs to
   struct clk.  This has no ordering requirements wrt requiring
   parents to be "initialized" before their children (it has no care
   about that at all because it's not within its definition.)

   For this, registration is about connecting device + connection IDs
   to a struct clk.

2. the driver API, defining how the opaque struct clk is looked up,
   obtained and then manipulated.  This has no 'registration' stuff.

So, whether clocks are a tree or flat is unspecified.  It's unspecified
whether there's any particular order required.

In fact, with a clock tree, it's entirely possible that only the leaf
clocks will be 'registered' with clkdev.  How the rest of the clock tree
is initialized is beyond the scope of the driver clk API.

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-03 16:43             ` Russell King - ARM Linux
  0 siblings, 0 replies; 144+ messages in thread
From: Russell King - ARM Linux @ 2011-10-03 16:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 03, 2011 at 05:31:08PM +0100, Mark Brown wrote:
> I dunno, I get the impression that some of this is due to the current
> limitations of the clock API rather than due to a lack of clocks -
> perhaps that's specific to the applications I look at, though.
> applications 

The clk API per-se has nothing to do with how clocks are registered.
There are two things that are the clk API:

1. clkdev - which deals with translating devices + connection IDs to
   struct clk.  This has no ordering requirements wrt requiring
   parents to be "initialized" before their children (it has no care
   about that at all because it's not within its definition.)

   For this, registration is about connecting device + connection IDs
   to a struct clk.

2. the driver API, defining how the opaque struct clk is looked up,
   obtained and then manipulated.  This has no 'registration' stuff.

So, whether clocks are a tree or flat is unspecified.  It's unspecified
whether there's any particular order required.

In fact, with a clock tree, it's entirely possible that only the leaf
clocks will be 'registered' with clkdev.  How the rest of the clock tree
is initialized is beyond the scope of the driver clk API.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-03 16:43             ` Russell King - ARM Linux
@ 2011-10-03 17:05               ` Mark Brown
  -1 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-03 17:05 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: jeremy.kerr, paul, linaro-dev, linus.walleij, tglx, patches,
	linux-arm-kernel, magnus.damm, linux-kernel, eric.miao,
	grant.likely, dsaxena, amit.kucheria, skannan, arnd.bergmann,
	sboyd, richard.zhao, shawn.guo, Mike Turquette

On Mon, Oct 03, 2011 at 05:43:09PM +0100, Russell King - ARM Linux wrote:
> On Mon, Oct 03, 2011 at 05:31:08PM +0100, Mark Brown wrote:

[Not being many off-SoC clocks]
> > I dunno, I get the impression that some of this is due to the current
> > limitations of the clock API rather than due to a lack of clocks -
> > perhaps that's specific to the applications I look at, though.
> > applications 

> The clk API per-se has nothing to do with how clocks are registered.
> There are two things that are the clk API:

Right, it's consumer side only which is the limitation I'm talking about
- at the minute it's only possible to use the clk API for on-SoC clocks
(or at least clocks that the SoC cares about), we don't have a clock API
for cross platform clock providers.  I don't know if getting a cross
platform implementation will change that situation much.

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-03 17:05               ` Mark Brown
  0 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-03 17:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 03, 2011 at 05:43:09PM +0100, Russell King - ARM Linux wrote:
> On Mon, Oct 03, 2011 at 05:31:08PM +0100, Mark Brown wrote:

[Not being many off-SoC clocks]
> > I dunno, I get the impression that some of this is due to the current
> > limitations of the clock API rather than due to a lack of clocks -
> > perhaps that's specific to the applications I look at, though.
> > applications 

> The clk API per-se has nothing to do with how clocks are registered.
> There are two things that are the clk API:

Right, it's consumer side only which is the limitation I'm talking about
- at the minute it's only possible to use the clk API for on-SoC clocks
(or at least clocks that the SoC cares about), we don't have a clock API
for cross platform clock providers.  I don't know if getting a cross
platform implementation will change that situation much.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-03 22:02     ` Rob Herring
  -1 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-10-03 22:02 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

Mike,

On 09/22/2011 05:26 PM, Mike Turquette wrote:

> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 6db161f..e2a9719 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -23,6 +23,13 @@
>  static LIST_HEAD(clocks);
>  static DEFINE_MUTEX(clocks_mutex);
>  
> +/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
> + * through other headers; we don't want them used anywhere but here. */
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +extern int __clk_get(struct clk *clk);
> +extern void __clk_put(struct clk *clk);
> +#endif
> +

This is dead code left from prior versions.

Rob

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-03 22:02     ` Rob Herring
  0 siblings, 0 replies; 144+ messages in thread
From: Rob Herring @ 2011-10-03 22:02 UTC (permalink / raw)
  To: linux-arm-kernel

Mike,

On 09/22/2011 05:26 PM, Mike Turquette wrote:

> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 6db161f..e2a9719 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -23,6 +23,13 @@
>  static LIST_HEAD(clocks);
>  static DEFINE_MUTEX(clocks_mutex);
>  
> +/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
> + * through other headers; we don't want them used anywhere but here. */
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +extern int __clk_get(struct clk *clk);
> +extern void __clk_put(struct clk *clk);
> +#endif
> +

This is dead code left from prior versions.

Rob

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-03 22:02     ` Rob Herring
@ 2011-10-03 22:15       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-03 22:15 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Mon, Oct 3, 2011 at 3:02 PM, Rob Herring <robherring2@gmail.com> wrote:
> Mike,
>
> On 09/22/2011 05:26 PM, Mike Turquette wrote:
>
>> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
>> index 6db161f..e2a9719 100644
>> --- a/drivers/clk/clkdev.c
>> +++ b/drivers/clk/clkdev.c
>> @@ -23,6 +23,13 @@
>>  static LIST_HEAD(clocks);
>>  static DEFINE_MUTEX(clocks_mutex);
>>
>> +/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
>> + * through other headers; we don't want them used anywhere but here. */
>> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
>> +extern int __clk_get(struct clk *clk);
>> +extern void __clk_put(struct clk *clk);
>> +#endif
>> +
>
> This is dead code left from prior versions.

Indeed it is.  Will pull it out for V3.

Thanks,
Mike

> Rob
>

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-03 22:15       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-03 22:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 3, 2011 at 3:02 PM, Rob Herring <robherring2@gmail.com> wrote:
> Mike,
>
> On 09/22/2011 05:26 PM, Mike Turquette wrote:
>
>> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
>> index 6db161f..e2a9719 100644
>> --- a/drivers/clk/clkdev.c
>> +++ b/drivers/clk/clkdev.c
>> @@ -23,6 +23,13 @@
>> ?static LIST_HEAD(clocks);
>> ?static DEFINE_MUTEX(clocks_mutex);
>>
>> +/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
>> + * through other headers; we don't want them used anywhere but here. */
>> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
>> +extern int __clk_get(struct clk *clk);
>> +extern void __clk_put(struct clk *clk);
>> +#endif
>> +
>
> This is dead code left from prior versions.

Indeed it is.  Will pull it out for V3.

Thanks,
Mike

> Rob
>

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-03 14:17     ` Rob Herring
@ 2011-10-04 18:09       ` Grant Likely
  -1 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-10-04 18:09 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mike Turquette, linux-kernel, paul, linaro-dev, linus.walleij,
	patches, eric.miao, broonie, magnus.damm, amit.kucheria,
	richard.zhao, dsaxena, arnd.bergmann, shawn.guo, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Mon, Oct 03, 2011 at 09:17:30AM -0500, Rob Herring wrote:
> On 09/22/2011 05:26 PM, Mike Turquette wrote:
> > +	/* Query the hardware for parent and initial rate */
> > +
> > +	if (clk->ops->get_parent)
> > +		/* We don't to lock against prepare/enable here, as
> > +		 * the clock is not yet accessible from anywhere */
> > +		clk->parent = clk->ops->get_parent(clk->hw);
> 
> I don't think this is going to work. This implies that the parent clock
> is already registered. For simple clk trees, that's probably not an
> issue, but for chips with lots of muxing it will be impossible to get
> the order correct for all cases. This is not an issue today as most
> clocks are statically created.
> 
> I think what is needed is a 2 stage init. The 1st stage to create all
> the clocks and a 2nd stage to build the tree once all clocks are created.
> 
> Tracking the parents using struct clk_hw instead would help as long as
> clocks are still statically allocated. However, that won't help for
> devicetree.

I disagree.  Clocks really need to be registered in dependency order.
Even in the deferral case, the driver should hold of actually
registering the clk (note: the struct clk, not the struct device)
until the clocks it depends on are available.

I also agree with the point that there are a lot of SoC clocks that
may not even show up in clkdev, and for pragmatic considerations are
better set up all at once early in the init process (ie. as part of
common SoC setup code, and doesn't change between boards).  That code
should be clue-full enough that it can register its own clocks in the
right order.

g.


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-04 18:09       ` Grant Likely
  0 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-10-04 18:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 03, 2011 at 09:17:30AM -0500, Rob Herring wrote:
> On 09/22/2011 05:26 PM, Mike Turquette wrote:
> > +	/* Query the hardware for parent and initial rate */
> > +
> > +	if (clk->ops->get_parent)
> > +		/* We don't to lock against prepare/enable here, as
> > +		 * the clock is not yet accessible from anywhere */
> > +		clk->parent = clk->ops->get_parent(clk->hw);
> 
> I don't think this is going to work. This implies that the parent clock
> is already registered. For simple clk trees, that's probably not an
> issue, but for chips with lots of muxing it will be impossible to get
> the order correct for all cases. This is not an issue today as most
> clocks are statically created.
> 
> I think what is needed is a 2 stage init. The 1st stage to create all
> the clocks and a 2nd stage to build the tree once all clocks are created.
> 
> Tracking the parents using struct clk_hw instead would help as long as
> clocks are still statically allocated. However, that won't help for
> devicetree.

I disagree.  Clocks really need to be registered in dependency order.
Even in the deferral case, the driver should hold of actually
registering the clk (note: the struct clk, not the struct device)
until the clocks it depends on are available.

I also agree with the point that there are a lot of SoC clocks that
may not even show up in clkdev, and for pragmatic considerations are
better set up all at once early in the init process (ie. as part of
common SoC setup code, and doesn't change between boards).  That code
should be clue-full enough that it can register its own clocks in the
right order.

g.

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

* Re: [PATCH v2 6/7] clk: Add initial WM831x clock driver
  2011-09-26  9:38       ` Mark Brown
@ 2011-10-04 18:18         ` Grant Likely
  -1 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-10-04 18:18 UTC (permalink / raw)
  To: Mark Brown
  Cc: Mike Turquette, linux-kernel, linux-arm-kernel, jeremy.kerr,
	tglx, linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev,
	paul, sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann,
	linux, eric.miao, richard.zhao

On Mon, Sep 26, 2011 at 10:38:58AM +0100, Mark Brown wrote:
> On Sat, Sep 24, 2011 at 10:08:36PM -0600, Grant Likely wrote:
> > On Thu, Sep 22, 2011 at 03:27:01PM -0700, Mike Turquette wrote:
> 
> > > +	ret = platform_driver_register(&wm831x_clk_driver);
> > > +	if (ret != 0)
> > > +		pr_err("Failed to register WM831x clock driver: %d\n", ret);
> > > +
> > > +	return ret;
> 
> > No need for this song-and-dance.  The driver core is pretty well
> > debugged.  Just use "return platform_driver_register(...);"
> 
> No, that's not helpful.  The issue isn't the device probe code itself,
> the issue is things like module unload not doing what they're supposed
> to do and leaving the device lying around or something - there's rather
> more going on than just the plain API call.

Then lets fix the core code.  I see this pattern show up again and
again of extra boilerplate going around
platform_driver_{register,unregister}().  That says to me that there
either needs to be a new helper, or the core code needs to be made
more verbose.

In fact, I've been considering adding a macro for
{platform,i2c,spi,...}_drivers that does all the module boilerplate
for the common case of only registering a driver at init time.
Something like:

#define module_platform_driver(__driver) \
int __driver##_init(void) \
{ \
	return platform_driver_register(&(__driver)); \
} \
module_init(__driver##_init); \
void ##__driver##_exit(void) \
{ \
	platform_driver_unregister(&(__driver)); \
} \
module_exit(##__driver##_exit);

It's not a lot of code, but I dislike how much boilerplate every
single driver has to use if it doesn't do anything special.

g.

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

* [PATCH v2 6/7] clk: Add initial WM831x clock driver
@ 2011-10-04 18:18         ` Grant Likely
  0 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-10-04 18:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Sep 26, 2011 at 10:38:58AM +0100, Mark Brown wrote:
> On Sat, Sep 24, 2011 at 10:08:36PM -0600, Grant Likely wrote:
> > On Thu, Sep 22, 2011 at 03:27:01PM -0700, Mike Turquette wrote:
> 
> > > +	ret = platform_driver_register(&wm831x_clk_driver);
> > > +	if (ret != 0)
> > > +		pr_err("Failed to register WM831x clock driver: %d\n", ret);
> > > +
> > > +	return ret;
> 
> > No need for this song-and-dance.  The driver core is pretty well
> > debugged.  Just use "return platform_driver_register(...);"
> 
> No, that's not helpful.  The issue isn't the device probe code itself,
> the issue is things like module unload not doing what they're supposed
> to do and leaving the device lying around or something - there's rather
> more going on than just the plain API call.

Then lets fix the core code.  I see this pattern show up again and
again of extra boilerplate going around
platform_driver_{register,unregister}().  That says to me that there
either needs to be a new helper, or the core code needs to be made
more verbose.

In fact, I've been considering adding a macro for
{platform,i2c,spi,...}_drivers that does all the module boilerplate
for the common case of only registering a driver at init time.
Something like:

#define module_platform_driver(__driver) \
int __driver##_init(void) \
{ \
	return platform_driver_register(&(__driver)); \
} \
module_init(__driver##_init); \
void ##__driver##_exit(void) \
{ \
	platform_driver_unregister(&(__driver)); \
} \
module_exit(##__driver##_exit);

It's not a lot of code, but I dislike how much boilerplate every
single driver has to use if it doesn't do anything special.

g.

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

* Re: [PATCH v2 6/7] clk: Add initial WM831x clock driver
  2011-10-04 18:18         ` Grant Likely
@ 2011-10-04 20:50           ` Mark Brown
  -1 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-04 20:50 UTC (permalink / raw)
  To: Grant Likely
  Cc: Mike Turquette, linux-kernel, linux-arm-kernel, jeremy.kerr,
	tglx, linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev,
	paul, sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann,
	linux, eric.miao, richard.zhao

On Tue, Oct 04, 2011 at 12:18:18PM -0600, Grant Likely wrote:
> On Mon, Sep 26, 2011 at 10:38:58AM +0100, Mark Brown wrote:

> > No, that's not helpful.  The issue isn't the device probe code itself,
> > the issue is things like module unload not doing what they're supposed
> > to do and leaving the device lying around or something - there's rather
> > more going on than just the plain API call.

> Then lets fix the core code.  I see this pattern show up again and
> again of extra boilerplate going around
> platform_driver_{register,unregister}().  That says to me that there
> either needs to be a new helper, or the core code needs to be made
> more verbose.

I'd go with the latter, it's pretty much the approach the subsystems I
help maintain have been taking.  In fast paths it's a bit different but
in slow paths it tends to be helpful to know why things just fell over.

> In fact, I've been considering adding a macro for
> {platform,i2c,spi,...}_drivers that does all the module boilerplate
> for the common case of only registering a driver at init time.
> Something like:

> #define module_platform_driver(__driver) \
> int __driver##_init(void) \
> { \
> 	return platform_driver_register(&(__driver)); \
> } \
> module_init(__driver##_init); \
> void ##__driver##_exit(void) \
> { \
> 	platform_driver_unregister(&(__driver)); \
> } \
> module_exit(##__driver##_exit);

> It's not a lot of code, but I dislike how much boilerplate every
> single driver has to use if it doesn't do anything special.

Yeah, this sort of stuff would be helpful - there's quite a bit of
boilerplate you end up having to write to get drivers going.

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

* [PATCH v2 6/7] clk: Add initial WM831x clock driver
@ 2011-10-04 20:50           ` Mark Brown
  0 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-04 20:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 04, 2011 at 12:18:18PM -0600, Grant Likely wrote:
> On Mon, Sep 26, 2011 at 10:38:58AM +0100, Mark Brown wrote:

> > No, that's not helpful.  The issue isn't the device probe code itself,
> > the issue is things like module unload not doing what they're supposed
> > to do and leaving the device lying around or something - there's rather
> > more going on than just the plain API call.

> Then lets fix the core code.  I see this pattern show up again and
> again of extra boilerplate going around
> platform_driver_{register,unregister}().  That says to me that there
> either needs to be a new helper, or the core code needs to be made
> more verbose.

I'd go with the latter, it's pretty much the approach the subsystems I
help maintain have been taking.  In fast paths it's a bit different but
in slow paths it tends to be helpful to know why things just fell over.

> In fact, I've been considering adding a macro for
> {platform,i2c,spi,...}_drivers that does all the module boilerplate
> for the common case of only registering a driver at init time.
> Something like:

> #define module_platform_driver(__driver) \
> int __driver##_init(void) \
> { \
> 	return platform_driver_register(&(__driver)); \
> } \
> module_init(__driver##_init); \
> void ##__driver##_exit(void) \
> { \
> 	platform_driver_unregister(&(__driver)); \
> } \
> module_exit(##__driver##_exit);

> It's not a lot of code, but I dislike how much boilerplate every
> single driver has to use if it doesn't do anything special.

Yeah, this sort of stuff would be helpful - there's quite a bit of
boilerplate you end up having to write to get drivers going.

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

* Re: [PATCH v2 6/7] clk: Add initial WM831x clock driver
  2011-10-04 20:50           ` Mark Brown
@ 2011-10-04 23:22             ` Grant Likely
  -1 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-10-04 23:22 UTC (permalink / raw)
  To: Mark Brown
  Cc: Mike Turquette, linux-kernel, linux-arm-kernel, jeremy.kerr,
	tglx, linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev,
	paul, sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann,
	linux, eric.miao, richard.zhao

On Tue, Oct 04, 2011 at 09:50:02PM +0100, Mark Brown wrote:
> On Tue, Oct 04, 2011 at 12:18:18PM -0600, Grant Likely wrote:
> > #define module_platform_driver(__driver) \
> > int __driver##_init(void) \
> > { \
> > 	return platform_driver_register(&(__driver)); \
> > } \
> > module_init(__driver##_init); \
> > void ##__driver##_exit(void) \
> > { \
> > 	platform_driver_unregister(&(__driver)); \
> > } \
> > module_exit(##__driver##_exit);
> 
> > It's not a lot of code, but I dislike how much boilerplate every
> > single driver has to use if it doesn't do anything special.
> 
> Yeah, this sort of stuff would be helpful - there's quite a bit of
> boilerplate you end up having to write to get drivers going.

Draft patch written, and posting to the list soon...

g.


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

* [PATCH v2 6/7] clk: Add initial WM831x clock driver
@ 2011-10-04 23:22             ` Grant Likely
  0 siblings, 0 replies; 144+ messages in thread
From: Grant Likely @ 2011-10-04 23:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 04, 2011 at 09:50:02PM +0100, Mark Brown wrote:
> On Tue, Oct 04, 2011 at 12:18:18PM -0600, Grant Likely wrote:
> > #define module_platform_driver(__driver) \
> > int __driver##_init(void) \
> > { \
> > 	return platform_driver_register(&(__driver)); \
> > } \
> > module_init(__driver##_init); \
> > void ##__driver##_exit(void) \
> > { \
> > 	platform_driver_unregister(&(__driver)); \
> > } \
> > module_exit(##__driver##_exit);
> 
> > It's not a lot of code, but I dislike how much boilerplate every
> > single driver has to use if it doesn't do anything special.
> 
> Yeah, this sort of stuff would be helpful - there's quite a bit of
> boilerplate you end up having to write to get drivers going.

Draft patch written, and posting to the list soon...

g.

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-26 23:30               ` Rob Herring
@ 2011-10-05  1:41                 ` Saravana Kannan
  -1 siblings, 0 replies; 144+ messages in thread
From: Saravana Kannan @ 2011-10-05  1:41 UTC (permalink / raw)
  To: Rob Herring, Thomas Gleixner
  Cc: Turquette, Mike, Jeremy Kerr, paul, linaro-dev, linus.walleij,
	patches, broonie, magnus.damm, linux-kernel, eric.miao, linux,
	Jamie Iles, arnd.bergmann, Saravana Kannan, linux-arm-kernel,
	Stephen Boyd

On 09/26/2011 04:30 PM, Rob Herring wrote:
> On 09/26/2011 05:37 PM, Turquette, Mike wrote:
>> On Mon, Sep 26, 2011 at 12:37 PM, Jamie Iles<jamie@jamieiles.com>  wrote:
>>> On Mon, Sep 26, 2011 at 02:10:32PM -0500, Rob Herring wrote:
>>>> On 09/26/2011 01:40 PM, Jamie Iles wrote:
>>>>> On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
>>>>>>> +static void clk_gate_set_bit(struct clk_hw *clk)
>>>>>>> +{
>>>>>>> + struct clk_gate *gate = to_clk_gate(clk);
>>>>>>> + u32 reg;
>>>>>>> +
>>>>>>> + reg = __raw_readl(gate->reg);
>>>>>>> + reg |= BIT(gate->bit_idx);
>>>>>>> + __raw_writel(reg, gate->reg);
>>>>>>
>>>>>> Don't these read-mod-writes need a spinlock around it?
>>>>>>
>>>>>> It's possible to have an enable bits and dividers in the same register.
>>>>>> If you did a set_rate and while doing an enable/disable, there would be
>>>>>> a problem. Also, it may be 2 different clocks in the same register, so
>>>>>> the spinlock needs to be shared and not per clock.
>>>>>
>>>>> Well the prepare lock will be held here and I believe that would be
>>>>> sufficient.
>>>>
>>>> No, the enable spinlock is protecting enable/disable. But set_rate is
>>>> protected by the prepare mutex. So you clearly don't need locking if you
>>>> have a register of only 1 bit enables. If you have a register accessed
>>>> by both enable/disable and prepare/unprepare/set_rate, then you need
>>>> some protection.
>>>
>>> OK fair point, but I would guess that if you had a clock like this then
>>> you probably wouldn't use this simple gated clock would you?  (speaking
>>> from my world where we have quite simple clocks ;-))
>>
>> I think it is a safe assumption that if a register controls both
>> enable/disable and some programmable divider then,
>>
>> 1) those controls are probably for the same clock
>> 2) that clock won't be using the cookie-cutter gated-clock
>> implementation anyways
>
> By definition of simple gated clock, the other bits have to be for
> another clock. The restriction is that all the other bits can only be
> clock gate bits.
>
>>
>> Rob, do you feel these assumptions are OK and locking can remain the
>> same in this patch?
>
> Perhaps it is rare enough that it is not worth it use generic code in
> this case. If so, the documentation should be clear about this
> constraint. It is not something anyone will have hit before because
> everyone used a single global lock. Now with the api being split between
> 2 locks, this adds a new complexity.

I kinda agree with Rob on this. There are very few, if any, such simple 
clocks on MSM chips. It's very easy to a SoC clock developer to 
accidentally use these simple clocks without realizing the point that 
Rob brings up.

> I think the simple gated clock code should be usable for any clock
> controlled by a single bit in a 32-bit register independent of other
> things in that register.

To take care of the scenario Rob bring up, the prepare/unprepare and 
enable/disable code will have to grab a per-tree register-lock before 
accessing any registers. The prepare/unprepare code should obviously be 
written to hold this register-lock for as small of a duration as 
possible. For example, if the prepare code is doing voltage increase, 
the register-lock should be grabber _after_ the voltage is increased. At 
least, this is approximately how the MSM clock code can be mapped onto 
this generic framework.

I think we should just go ahead and implement the per-tree register lock 
so that the generic clock implementations are more useful. The lock will 
really be held only for a very short time and hence shouldn't matter 
that there is a single lock for all the clocks in a tree.

Thomas,

Did you get a chance to send out your patches with support for per-tree 
locking? I would really like to see that as part of the first patch 
series that gets pulled in.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-10-05  1:41                 ` Saravana Kannan
  0 siblings, 0 replies; 144+ messages in thread
From: Saravana Kannan @ 2011-10-05  1:41 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/26/2011 04:30 PM, Rob Herring wrote:
> On 09/26/2011 05:37 PM, Turquette, Mike wrote:
>> On Mon, Sep 26, 2011 at 12:37 PM, Jamie Iles<jamie@jamieiles.com>  wrote:
>>> On Mon, Sep 26, 2011 at 02:10:32PM -0500, Rob Herring wrote:
>>>> On 09/26/2011 01:40 PM, Jamie Iles wrote:
>>>>> On Mon, Sep 26, 2011 at 01:33:08PM -0500, Rob Herring wrote:
>>>>>>> +static void clk_gate_set_bit(struct clk_hw *clk)
>>>>>>> +{
>>>>>>> + struct clk_gate *gate = to_clk_gate(clk);
>>>>>>> + u32 reg;
>>>>>>> +
>>>>>>> + reg = __raw_readl(gate->reg);
>>>>>>> + reg |= BIT(gate->bit_idx);
>>>>>>> + __raw_writel(reg, gate->reg);
>>>>>>
>>>>>> Don't these read-mod-writes need a spinlock around it?
>>>>>>
>>>>>> It's possible to have an enable bits and dividers in the same register.
>>>>>> If you did a set_rate and while doing an enable/disable, there would be
>>>>>> a problem. Also, it may be 2 different clocks in the same register, so
>>>>>> the spinlock needs to be shared and not per clock.
>>>>>
>>>>> Well the prepare lock will be held here and I believe that would be
>>>>> sufficient.
>>>>
>>>> No, the enable spinlock is protecting enable/disable. But set_rate is
>>>> protected by the prepare mutex. So you clearly don't need locking if you
>>>> have a register of only 1 bit enables. If you have a register accessed
>>>> by both enable/disable and prepare/unprepare/set_rate, then you need
>>>> some protection.
>>>
>>> OK fair point, but I would guess that if you had a clock like this then
>>> you probably wouldn't use this simple gated clock would you?  (speaking
>>> from my world where we have quite simple clocks ;-))
>>
>> I think it is a safe assumption that if a register controls both
>> enable/disable and some programmable divider then,
>>
>> 1) those controls are probably for the same clock
>> 2) that clock won't be using the cookie-cutter gated-clock
>> implementation anyways
>
> By definition of simple gated clock, the other bits have to be for
> another clock. The restriction is that all the other bits can only be
> clock gate bits.
>
>>
>> Rob, do you feel these assumptions are OK and locking can remain the
>> same in this patch?
>
> Perhaps it is rare enough that it is not worth it use generic code in
> this case. If so, the documentation should be clear about this
> constraint. It is not something anyone will have hit before because
> everyone used a single global lock. Now with the api being split between
> 2 locks, this adds a new complexity.

I kinda agree with Rob on this. There are very few, if any, such simple 
clocks on MSM chips. It's very easy to a SoC clock developer to 
accidentally use these simple clocks without realizing the point that 
Rob brings up.

> I think the simple gated clock code should be usable for any clock
> controlled by a single bit in a 32-bit register independent of other
> things in that register.

To take care of the scenario Rob bring up, the prepare/unprepare and 
enable/disable code will have to grab a per-tree register-lock before 
accessing any registers. The prepare/unprepare code should obviously be 
written to hold this register-lock for as small of a duration as 
possible. For example, if the prepare code is doing voltage increase, 
the register-lock should be grabber _after_ the voltage is increased. At 
least, this is approximately how the MSM clock code can be mapped onto 
this generic framework.

I think we should just go ahead and implement the per-tree register lock 
so that the generic clock implementations are more useful. The lock will 
really be held only for a very short time and hence shouldn't matter 
that there is a single lock for all the clocks in a tree.

Thomas,

Did you get a chance to send out your patches with support for per-tree 
locking? I would really like to see that as part of the first patch 
series that gets pulled in.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-06  1:17     ` Saravana Kannan
  -1 siblings, 0 replies; 144+ messages in thread
From: Saravana Kannan @ 2011-10-06  1:17 UTC (permalink / raw)
  To: Mike Turquette, paul, grant.likely, arnd.bergmann, tglx,
	Russell King - ARM Linux
  Cc: linux-kernel, linaro-dev, linus.walleij, patches, eric.miao,
	broonie, magnus.damm, amit.kucheria, richard.zhao, dsaxena,
	shawn.guo, Saravana Kannan, linux, jeremy.kerr, linux-arm-kernel,
	Stephen Boyd

On 09/22/2011 03:26 PM, Mike Turquette wrote:
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..d6ae10b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> +#ifdef CONFIG_GENERIC_CLK
> +
> +struct clk_hw {
> +	struct clk *clk;
> +};
> +
> +/**
> + * struct clk_hw_ops -  Callback operations for hardware clocks; these are to
> + * be provided by the clock implementation, and will be called by drivers
> + * through the clk_* API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may sleep. Called with
> + *		prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with enable_lock held. This function must not
> + *		sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with enable_lock held.
> + *		This function must not sleep.
> + *
> + * @recalc_rate	Recalculate the rate of this clock, by quering hardware
> + *		and/or the clock's parent. Called with the global clock mutex
> + *		held. Optional, but recommended - if this op is not set,
> + *		clk_get_rate will return 0.
> + *
> + * @get_parent	Query the parent of this clock; for clocks with multiple
> + *		possible parents, query the hardware for the current
> + *		parent. Currently only called when the clock is first
> + *		registered.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
> + * should be done in clk_prepare. Switching that will not sleep should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
>    */
> +struct clk_hw_ops {
> +	int		(*prepare)(struct clk_hw *);
> +	void		(*unprepare)(struct clk_hw *);
> +	int		(*enable)(struct clk_hw *);
> +	void		(*disable)(struct clk_hw *);
> +	unsigned long	(*recalc_rate)(struct clk_hw *);
> +	long		(*round_rate)(struct clk_hw *, unsigned long);
> +	struct clk *	(*get_parent)(struct clk_hw *);
> +};

I would like to understand the need for recalc rate if that's something 
that we want to go into the common framework (even if it's optional). I 
have mostly heard only second hand explanations of the need for 
recalc_rate(), so I might not have the full picture. But for all the 
cases that I can think of, recalc_rate seems like a paradox.

If recalc_rate() is used to make sure the "current rate" of a "clock A" 
is always known even if it's parent "clock B"'s rate is changed, then it 
also means that the rate of "clock A" can change without 
clk_set_rate(clock A, new rate). That in turn means that the 
clk_get_rate() just gives the instantaneous snapshot of the rate. So, 
any use of clk_get_rate(clock A) for anything other than 
printing/logging the return value is broken code. In which case, do we 
really care for recalc_rate()? We could just return the rate that it was 
set to when clk_set_rate() was called and call it a day or return 0 for 
such clocks to indicate that the clock rate is "unknown".

The whole concept of trying to recalculate the rate for a clock makes me 
feel uneasy since it promotes misunderstanding the behavior of the clock 
and writing bad code based on that misunderstanding.

I would like to hear to real usecases before I propose some alternatives 
that I have in mind.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-06  1:17     ` Saravana Kannan
  0 siblings, 0 replies; 144+ messages in thread
From: Saravana Kannan @ 2011-10-06  1:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/22/2011 03:26 PM, Mike Turquette wrote:
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..d6ae10b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> +#ifdef CONFIG_GENERIC_CLK
> +
> +struct clk_hw {
> +	struct clk *clk;
> +};
> +
> +/**
> + * struct clk_hw_ops -  Callback operations for hardware clocks; these are to
> + * be provided by the clock implementation, and will be called by drivers
> + * through the clk_* API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may sleep. Called with
> + *		prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with enable_lock held. This function must not
> + *		sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with enable_lock held.
> + *		This function must not sleep.
> + *
> + * @recalc_rate	Recalculate the rate of this clock, by quering hardware
> + *		and/or the clock's parent. Called with the global clock mutex
> + *		held. Optional, but recommended - if this op is not set,
> + *		clk_get_rate will return 0.
> + *
> + * @get_parent	Query the parent of this clock; for clocks with multiple
> + *		possible parents, query the hardware for the current
> + *		parent. Currently only called when the clock is first
> + *		registered.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
> + * should be done in clk_prepare. Switching that will not sleep should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
>    */
> +struct clk_hw_ops {
> +	int		(*prepare)(struct clk_hw *);
> +	void		(*unprepare)(struct clk_hw *);
> +	int		(*enable)(struct clk_hw *);
> +	void		(*disable)(struct clk_hw *);
> +	unsigned long	(*recalc_rate)(struct clk_hw *);
> +	long		(*round_rate)(struct clk_hw *, unsigned long);
> +	struct clk *	(*get_parent)(struct clk_hw *);
> +};

I would like to understand the need for recalc rate if that's something 
that we want to go into the common framework (even if it's optional). I 
have mostly heard only second hand explanations of the need for 
recalc_rate(), so I might not have the full picture. But for all the 
cases that I can think of, recalc_rate seems like a paradox.

If recalc_rate() is used to make sure the "current rate" of a "clock A" 
is always known even if it's parent "clock B"'s rate is changed, then it 
also means that the rate of "clock A" can change without 
clk_set_rate(clock A, new rate). That in turn means that the 
clk_get_rate() just gives the instantaneous snapshot of the rate. So, 
any use of clk_get_rate(clock A) for anything other than 
printing/logging the return value is broken code. In which case, do we 
really care for recalc_rate()? We could just return the rate that it was 
set to when clk_set_rate() was called and call it a day or return 0 for 
such clocks to indicate that the clock rate is "unknown".

The whole concept of trying to recalculate the rate for a clock makes me 
feel uneasy since it promotes misunderstanding the behavior of the clock 
and writing bad code based on that misunderstanding.

I would like to hear to real usecases before I propose some alternatives 
that I have in mind.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-06  1:17     ` Saravana Kannan
@ 2011-10-06 16:11       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-06 16:11 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: paul, grant.likely, arnd.bergmann, tglx,
	Russell King - ARM Linux, linux-kernel, linaro-dev,
	linus.walleij, patches, eric.miao, broonie, magnus.damm,
	amit.kucheria, richard.zhao, dsaxena, shawn.guo, jeremy.kerr,
	linux-arm-kernel, Stephen Boyd

On Wed, Oct 5, 2011 at 6:17 PM, Saravana Kannan <skannan@codeaurora.org> wrote:
> On 09/22/2011 03:26 PM, Mike Turquette wrote:
>> +       unsigned long   (*recalc_rate)(struct clk_hw *);
>> +       long            (*round_rate)(struct clk_hw *, unsigned long);
>> +       struct clk *    (*get_parent)(struct clk_hw *);
>> +};
>
> I would like to understand the need for recalc rate if that's something that
> we want to go into the common framework (even if it's optional). I have
> mostly heard only second hand explanations of the need for recalc_rate(), so
> I might not have the full picture. But for all the cases that I can think
> of, recalc_rate seems like a paradox.

Recalc rate has four main uses that I can think of off the top of my head:
1) clk_set_rate is called on clock0, which is a non-leaf clock.  All
clocks "below" clock0 have had their rates changed, yet no one called
clk_set_rate on those child clocks.  We use recalc to walk the
sub-tree of children and recalculate their rates based on the new rate
of their parent, clock0.

2) exact same as #1, but using clk_set_parent instead of clk_set_rate.
 Again, changing the rate of a clock "high up" in the tree will affect
the rates of many child clocks below it.

3) at boot-time/init-time when we don't trust the bootloader and need
to determine the clock rates by parsing registers

4) modeling rates for clocks that we don't really control.  This is
not as common as the above three, but there are times when we're
interested in knowing a clock rate (perhaps for debug purposes), but
it's scaling logic is in firmware or somehow independent of the Linux
clock framework.

> If recalc_rate() is used to make sure the "current rate" of a "clock A" is
> always known even if it's parent "clock B"'s rate is changed, then it also
> means that the rate of "clock A" can change without clk_set_rate(clock A,
> new rate). That in turn means that the clk_get_rate() just gives the
> instantaneous snapshot of the rate. So, any use of clk_get_rate(clock A) for
> anything other than printing/logging the return value is broken code. In

For most clocks, the first three examples I give above will cover all
of the times that a clock's rate will change.  As long as a
recalc/tree-walk is present then clk->rate is not out of sync and thus
printing/reading that value is not broken.

> which case, do we really care for recalc_rate()? We could just return the
> rate that it was set to when clk_set_rate() was called and call it a day or
> return 0 for such clocks to indicate that the clock rate is "unknown".

What's the point of tracking a rate if it can't be trusted?  Also, it
is important to recalc rates whenever changes are made "high up" in
the clock tree once we start to work on rate-change-arbitration
issues, etc.

Regards,
Mike

> The whole concept of trying to recalculate the rate for a clock makes me
> feel uneasy since it promotes misunderstanding the behavior of the clock and
> writing bad code based on that misunderstanding.
>
> I would like to hear to real usecases before I propose some alternatives
> that I have in mind.
>
> Thanks,
> Saravana
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
>

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-06 16:11       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-06 16:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 5, 2011 at 6:17 PM, Saravana Kannan <skannan@codeaurora.org> wrote:
> On 09/22/2011 03:26 PM, Mike Turquette wrote:
>> + ? ? ? unsigned long ? (*recalc_rate)(struct clk_hw *);
>> + ? ? ? long ? ? ? ? ? ?(*round_rate)(struct clk_hw *, unsigned long);
>> + ? ? ? struct clk * ? ?(*get_parent)(struct clk_hw *);
>> +};
>
> I would like to understand the need for recalc rate if that's something that
> we want to go into the common framework (even if it's optional). I have
> mostly heard only second hand explanations of the need for recalc_rate(), so
> I might not have the full picture. But for all the cases that I can think
> of, recalc_rate seems like a paradox.

Recalc rate has four main uses that I can think of off the top of my head:
1) clk_set_rate is called on clock0, which is a non-leaf clock.  All
clocks "below" clock0 have had their rates changed, yet no one called
clk_set_rate on those child clocks.  We use recalc to walk the
sub-tree of children and recalculate their rates based on the new rate
of their parent, clock0.

2) exact same as #1, but using clk_set_parent instead of clk_set_rate.
 Again, changing the rate of a clock "high up" in the tree will affect
the rates of many child clocks below it.

3) at boot-time/init-time when we don't trust the bootloader and need
to determine the clock rates by parsing registers

4) modeling rates for clocks that we don't really control.  This is
not as common as the above three, but there are times when we're
interested in knowing a clock rate (perhaps for debug purposes), but
it's scaling logic is in firmware or somehow independent of the Linux
clock framework.

> If recalc_rate() is used to make sure the "current rate" of a "clock A" is
> always known even if it's parent "clock B"'s rate is changed, then it also
> means that the rate of "clock A" can change without clk_set_rate(clock A,
> new rate). That in turn means that the clk_get_rate() just gives the
> instantaneous snapshot of the rate. So, any use of clk_get_rate(clock A) for
> anything other than printing/logging the return value is broken code. In

For most clocks, the first three examples I give above will cover all
of the times that a clock's rate will change.  As long as a
recalc/tree-walk is present then clk->rate is not out of sync and thus
printing/reading that value is not broken.

> which case, do we really care for recalc_rate()? We could just return the
> rate that it was set to when clk_set_rate() was called and call it a day or
> return 0 for such clocks to indicate that the clock rate is "unknown".

What's the point of tracking a rate if it can't be trusted?  Also, it
is important to recalc rates whenever changes are made "high up" in
the clock tree once we start to work on rate-change-arbitration
issues, etc.

Regards,
Mike

> The whole concept of trying to recalculate the rate for a clock makes me
> feel uneasy since it promotes misunderstanding the behavior of the clock and
> writing bad code based on that misunderstanding.
>
> I would like to hear to real usecases before I propose some alternatives
> that I have in mind.
>
> Thanks,
> Saravana
>
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
>

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-11 11:25     ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-11 11:25 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, and a set of clock operations. Different clock
> implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> The interface is split into two halves:
> 
>  * struct clk, which is the generic-device-driver interface. This
>    provides a set of functions which drivers may use to request
>    enable/disable, query or manipulate in a hardware-independent manner.
> 
>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>    interface. Clock drivers implement the ops, which allow the core
>    clock code to implement the generic 'struct clk' API.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
> common, opaque struct clk, and a set of clock operations (defined per
> type of clock):
> 
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };
> 
>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
> 
>   static int clk_foo_enable(struct clk_hw *clk)
>   {
>   	struct clk_foo *foo = to_clk_foo(clk);
>   	raw_writeb(foo->enable_reg, 1);
>   	return 0;
>   }
> 
>   struct clk_hw_ops clk_foo_ops = {
>   	.enable = clk_foo_enable,
>   };
> 
> And in the platform initialisation code:
> 
>   struct clk_foo my_clk_foo;
> 
>   void init_clocks(void)
>   {
>   	my_clk_foo.enable_reg = ioremap(...);
> 
>   	clk_register(&clk_foo_ops, &my_clk_foo, NULL);
>   }
> 
> Changes from Thomas Gleixner <tglx@linutronix.de>.
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> TODO:
> 
>  * We don't keep any internal reference to the clock topology at present.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Create a dummy clk_unregister and prototype/document it and clk_register
> Constify struct clk_hw_ops
> Remove spinlock.h header, include kernel.h
> Use EOPNOTSUPP instead of ENOTSUPP
> Add might_sleep to clk_prepare/clk_unprepare stubs
> Properly init children hlist and child_node
> Whitespace and typo fixes
> 
>  drivers/clk/Kconfig  |    3 +
>  drivers/clk/Makefile |    1 +
>  drivers/clk/clk.c    |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    7 ++
>  include/linux/clk.h  |  140 +++++++++++++++++++++++++++---
>  5 files changed, 371 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/clk/clk.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3530927..c53ed59 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
>  
>  config HAVE_MACH_CLKDEV
>  	bool
> +
> +config GENERIC_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..570d5b9 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_GENERIC_CLK)	+= clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..1cd7315
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,232 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +struct clk {
> +	const char		*name;
> +	const struct clk_hw_ops	*ops;
> +	struct clk_hw		*hw;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	struct clk		*parent;
> +	unsigned long		rate;
> +};
> +
> +static DEFINE_SPINLOCK(enable_lock);
> +static DEFINE_MUTEX(prepare_lock);
> +
> +static void __clk_unprepare(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return;
> +
> +	if (--clk->prepare_count > 0)
> +		return;
> +
> +	WARN_ON(clk->enable_count > 0);
> +
> +	if (clk->ops->unprepare)
> +		clk->ops->unprepare(clk->hw);
> +
> +	__clk_unprepare(clk->parent);
> +}
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&prepare_lock);
> +	__clk_unprepare(clk);
> +	mutex_unlock(&prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +static int __clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (clk->prepare_count == 0) {
> +		ret = __clk_prepare(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->prepare) {
> +			ret = clk->ops->prepare(clk->hw);
> +			if (ret) {
> +				__clk_unprepare(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->prepare_count++;
> +
> +	return 0;
> +}
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret;
> +
> +	mutex_lock(&prepare_lock);
> +	ret = __clk_prepare(clk);
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +static void __clk_disable(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->enable_count == 0))
> +		return;
> +
> +	if (--clk->enable_count > 0)
> +		return;
> +
> +	if (clk->ops->disable)
> +		clk->ops->disable(clk->hw);
> +	__clk_disable(clk->parent);
> +}
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	__clk_disable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +static int __clk_enable(struct clk *clk)
> +{
> +	int ret;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return -ESHUTDOWN;
> +
> +
> +	if (clk->enable_count == 0) {
> +		ret = __clk_enable(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->enable) {
> +			ret = clk->ops->enable(clk->hw);
> +			if (ret) {
> +				__clk_disable(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->enable_count++;
> +	return 0;
> +}
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	ret = __clk_enable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (!clk)
> +		return 0;
> +	return clk->rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk && clk->ops->round_rate)
> +		return clk->ops->round_rate(clk->hw, rate);
> +	return rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (!clk)
> +		return NULL;
> +
> +	return clk->parent;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +		const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> +	if (!clk)
> +		return NULL;
> +
> +	INIT_HLIST_HEAD(&clk->children);
> +	INIT_HLIST_NODE(&clk->child_node);
> +
> +	clk->name = name;
> +	clk->ops = ops;
> +	clk->hw = hw;
> +	hw->clk = clk;
> +
> +	/* Query the hardware for parent and initial rate */
> +
> +	if (clk->ops->get_parent)
> +		/* We don't to lock against prepare/enable here, as
> +		 * the clock is not yet accessible from anywhere */
> +		clk->parent = clk->ops->get_parent(clk->hw);
> +
> +	if (clk->ops->recalc_rate)
> +		clk->rate = clk->ops->recalc_rate(clk->hw);
Why not set it to parent's rate if recalc_rate is NULL?
> +
> +
> +	return clk;
> +}
> +EXPORT_SYMBOL_GPL(clk_register);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 6db161f..e2a9719 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -23,6 +23,13 @@
>  static LIST_HEAD(clocks);
>  static DEFINE_MUTEX(clocks_mutex);
>  
> +/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
> + * through other headers; we don't want them used anywhere but here. */
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +extern int __clk_get(struct clk *clk);
> +extern void __clk_put(struct clk *clk);
> +#endif
> +
>  /*
>   * Find the correct struct clk for the device and connection ID.
>   * We do slightly fuzzy matching here:
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..d6ae10b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,17 +12,137 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +struct clk;
> +
> +#ifdef CONFIG_GENERIC_CLK
> +
> +struct clk_hw {
> +	struct clk *clk;
> +};
> +
> +/**
> + * struct clk_hw_ops -  Callback operations for hardware clocks; these are to
> + * be provided by the clock implementation, and will be called by drivers
> + * through the clk_* API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may sleep. Called with
> + *		prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with enable_lock held. This function must not
> + *		sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with enable_lock held.
> + *		This function must not sleep.
> + *
> + * @recalc_rate	Recalculate the rate of this clock, by quering hardware
> + *		and/or the clock's parent. Called with the global clock mutex
> + *		held. Optional, but recommended - if this op is not set,
> + *		clk_get_rate will return 0.
If a clock don't have any divider, recalc_rate may be NULL. In such case,
clk_get_rate should return parent's rate.

Thanks
Richard
> + *
> + * @get_parent	Query the parent of this clock; for clocks with multiple
> + *		possible parents, query the hardware for the current
> + *		parent. Currently only called when the clock is first
> + *		registered.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
> + * should be done in clk_prepare. Switching that will not sleep should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
>   */
> +struct clk_hw_ops {
> +	int		(*prepare)(struct clk_hw *);
> +	void		(*unprepare)(struct clk_hw *);
> +	int		(*enable)(struct clk_hw *);
> +	void		(*disable)(struct clk_hw *);
> +	unsigned long	(*recalc_rate)(struct clk_hw *);
> +	long		(*round_rate)(struct clk_hw *, unsigned long);
> +	struct clk *	(*get_parent)(struct clk_hw *);
> +};
>  
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any possibly sleeping initialisation on @clk, allowing the clock to be
> + * later enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possibly sleeping) cleanup on clk. This function may sleep.
> + */
> +void clk_unprepare(struct clk *clk);
> +
> +/**
> + * clk_register - register and initialize a new clock
> + *
> + * @ops: ops for the new clock
> + * @hw: struct clk_hw to be passed to the ops of the new clock
> + * @name: name to use for the new clock
> + *
> + * Register a new clock with the clk subsystem.  Returns either a
> + * struct clk for the new clock or a NULL pointer.
> + */
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +			 const char *name);
> +
> +/**
> + * clk_unregister - remove a clock
> + *
> + * @clk: clock to unregister
> + *
> + * Remove a clock from the clk subsystem.  This is currently not
> + * implemented but is provided to allow unregistration code to be
> + * written in drivers ready for use when an implementation is
> + * provided.
> + */
> +static inline int clk_unregister(struct clk *clk)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
> +#else /* !CONFIG_GENERIC_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * For !CONFIG_GENERIC_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
>   */
> -struct clk;
> +static inline int clk_prepare(struct clk *clk) {
> +	might_sleep();
> +	return 0;
> +}
> +
> +static inline void clk_unprepare(struct clk *clk) {
> +	might_sleep();
> +}
> +
> +#endif /* !CONFIG_GENERIC_CLK */
>  
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.
> @@ -67,6 +188,7 @@ void clk_disable(struct clk *clk);
>  /**
>   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
>   *		  This is only valid once the clock source has been enabled.
> + *		  Returns zero if the clock rate is unknown.
>   * @clk: clock source
>   */
>  unsigned long clk_get_rate(struct clk *clk);
> @@ -83,12 +205,6 @@ unsigned long clk_get_rate(struct clk *clk);
>   */
>  void clk_put(struct clk *clk);
>  
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>   * clk_round_rate - adjust a rate to the exact rate a clock can provide
>   * @clk: clock source
> @@ -97,7 +213,7 @@ void clk_put(struct clk *clk);
>   * Returns rounded clock rate in Hz, or negative errno.
>   */
>  long clk_round_rate(struct clk *clk, unsigned long rate);
> - 
> +
>  /**
>   * clk_set_rate - set the clock rate for a clock source
>   * @clk: clock source
> @@ -106,7 +222,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
>   * Returns success (0) or negative errno.
>   */
>  int clk_set_rate(struct clk *clk, unsigned long rate);
> - 
> +
>  /**
>   * clk_set_parent - set the parent clock source for this clock
>   * @clk: clock source
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-11 11:25     ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-11 11:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, and a set of clock operations. Different clock
> implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> The interface is split into two halves:
> 
>  * struct clk, which is the generic-device-driver interface. This
>    provides a set of functions which drivers may use to request
>    enable/disable, query or manipulate in a hardware-independent manner.
> 
>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>    interface. Clock drivers implement the ops, which allow the core
>    clock code to implement the generic 'struct clk' API.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
> common, opaque struct clk, and a set of clock operations (defined per
> type of clock):
> 
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };
> 
>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
> 
>   static int clk_foo_enable(struct clk_hw *clk)
>   {
>   	struct clk_foo *foo = to_clk_foo(clk);
>   	raw_writeb(foo->enable_reg, 1);
>   	return 0;
>   }
> 
>   struct clk_hw_ops clk_foo_ops = {
>   	.enable = clk_foo_enable,
>   };
> 
> And in the platform initialisation code:
> 
>   struct clk_foo my_clk_foo;
> 
>   void init_clocks(void)
>   {
>   	my_clk_foo.enable_reg = ioremap(...);
> 
>   	clk_register(&clk_foo_ops, &my_clk_foo, NULL);
>   }
> 
> Changes from Thomas Gleixner <tglx@linutronix.de>.
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> TODO:
> 
>  * We don't keep any internal reference to the clock topology at present.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Create a dummy clk_unregister and prototype/document it and clk_register
> Constify struct clk_hw_ops
> Remove spinlock.h header, include kernel.h
> Use EOPNOTSUPP instead of ENOTSUPP
> Add might_sleep to clk_prepare/clk_unprepare stubs
> Properly init children hlist and child_node
> Whitespace and typo fixes
> 
>  drivers/clk/Kconfig  |    3 +
>  drivers/clk/Makefile |    1 +
>  drivers/clk/clk.c    |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    7 ++
>  include/linux/clk.h  |  140 +++++++++++++++++++++++++++---
>  5 files changed, 371 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/clk/clk.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3530927..c53ed59 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
>  
>  config HAVE_MACH_CLKDEV
>  	bool
> +
> +config GENERIC_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..570d5b9 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_GENERIC_CLK)	+= clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..1cd7315
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,232 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/slab.h>
> +#include <linux/spinlock.h>
> +
> +struct clk {
> +	const char		*name;
> +	const struct clk_hw_ops	*ops;
> +	struct clk_hw		*hw;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	struct clk		*parent;
> +	unsigned long		rate;
> +};
> +
> +static DEFINE_SPINLOCK(enable_lock);
> +static DEFINE_MUTEX(prepare_lock);
> +
> +static void __clk_unprepare(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return;
> +
> +	if (--clk->prepare_count > 0)
> +		return;
> +
> +	WARN_ON(clk->enable_count > 0);
> +
> +	if (clk->ops->unprepare)
> +		clk->ops->unprepare(clk->hw);
> +
> +	__clk_unprepare(clk->parent);
> +}
> +
> +void clk_unprepare(struct clk *clk)
> +{
> +	mutex_lock(&prepare_lock);
> +	__clk_unprepare(clk);
> +	mutex_unlock(&prepare_lock);
> +}
> +EXPORT_SYMBOL_GPL(clk_unprepare);
> +
> +static int __clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (clk->prepare_count == 0) {
> +		ret = __clk_prepare(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->prepare) {
> +			ret = clk->ops->prepare(clk->hw);
> +			if (ret) {
> +				__clk_unprepare(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->prepare_count++;
> +
> +	return 0;
> +}
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret;
> +
> +	mutex_lock(&prepare_lock);
> +	ret = __clk_prepare(clk);
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_prepare);
> +
> +static void __clk_disable(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->enable_count == 0))
> +		return;
> +
> +	if (--clk->enable_count > 0)
> +		return;
> +
> +	if (clk->ops->disable)
> +		clk->ops->disable(clk->hw);
> +	__clk_disable(clk->parent);
> +}
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	__clk_disable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +static int __clk_enable(struct clk *clk)
> +{
> +	int ret;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return -ESHUTDOWN;
> +
> +
> +	if (clk->enable_count == 0) {
> +		ret = __clk_enable(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->enable) {
> +			ret = clk->ops->enable(clk->hw);
> +			if (ret) {
> +				__clk_disable(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->enable_count++;
> +	return 0;
> +}
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	ret = __clk_enable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	if (!clk)
> +		return 0;
> +	return clk->rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (clk && clk->ops->round_rate)
> +		return clk->ops->round_rate(clk->hw, rate);
> +	return rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	if (!clk)
> +		return NULL;
> +
> +	return clk->parent;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	/* not yet implemented */
> +	return -ENOSYS;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +		const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> +	if (!clk)
> +		return NULL;
> +
> +	INIT_HLIST_HEAD(&clk->children);
> +	INIT_HLIST_NODE(&clk->child_node);
> +
> +	clk->name = name;
> +	clk->ops = ops;
> +	clk->hw = hw;
> +	hw->clk = clk;
> +
> +	/* Query the hardware for parent and initial rate */
> +
> +	if (clk->ops->get_parent)
> +		/* We don't to lock against prepare/enable here, as
> +		 * the clock is not yet accessible from anywhere */
> +		clk->parent = clk->ops->get_parent(clk->hw);
> +
> +	if (clk->ops->recalc_rate)
> +		clk->rate = clk->ops->recalc_rate(clk->hw);
Why not set it to parent's rate if recalc_rate is NULL?
> +
> +
> +	return clk;
> +}
> +EXPORT_SYMBOL_GPL(clk_register);
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index 6db161f..e2a9719 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -23,6 +23,13 @@
>  static LIST_HEAD(clocks);
>  static DEFINE_MUTEX(clocks_mutex);
>  
> +/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
> + * through other headers; we don't want them used anywhere but here. */
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
> +extern int __clk_get(struct clk *clk);
> +extern void __clk_put(struct clk *clk);
> +#endif
> +
>  /*
>   * Find the correct struct clk for the device and connection ID.
>   * We do slightly fuzzy matching here:
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1d37f42..d6ae10b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -3,6 +3,7 @@
>   *
>   *  Copyright (C) 2004 ARM Limited.
>   *  Written by Deep Blue Solutions Limited.
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
>   *
>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License version 2 as
> @@ -11,17 +12,137 @@
>  #ifndef __LINUX_CLK_H
>  #define __LINUX_CLK_H
>  
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +
>  struct device;
>  
> -/*
> - * The base API.
> +struct clk;
> +
> +#ifdef CONFIG_GENERIC_CLK
> +
> +struct clk_hw {
> +	struct clk *clk;
> +};
> +
> +/**
> + * struct clk_hw_ops -  Callback operations for hardware clocks; these are to
> + * be provided by the clock implementation, and will be called by drivers
> + * through the clk_* API.
> + *
> + * @prepare:	Prepare the clock for enabling. This must not return until
> + *		the clock is fully prepared, and it's safe to call clk_enable.
> + *		This callback is intended to allow clock implementations to
> + *		do any initialisation that may sleep. Called with
> + *		prepare_lock held.
> + *
> + * @unprepare:	Release the clock from its prepared state. This will typically
> + *		undo any work done in the @prepare callback. Called with
> + *		prepare_lock held.
> + *
> + * @enable:	Enable the clock atomically. This must not return until the
> + *		clock is generating a valid clock signal, usable by consumer
> + *		devices. Called with enable_lock held. This function must not
> + *		sleep.
> + *
> + * @disable:	Disable the clock atomically. Called with enable_lock held.
> + *		This function must not sleep.
> + *
> + * @recalc_rate	Recalculate the rate of this clock, by quering hardware
> + *		and/or the clock's parent. Called with the global clock mutex
> + *		held. Optional, but recommended - if this op is not set,
> + *		clk_get_rate will return 0.
If a clock don't have any divider, recalc_rate may be NULL. In such case,
clk_get_rate should return parent's rate.

Thanks
Richard
> + *
> + * @get_parent	Query the parent of this clock; for clocks with multiple
> + *		possible parents, query the hardware for the current
> + *		parent. Currently only called when the clock is first
> + *		registered.
> + *
> + * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
> + * implementations to split any work between atomic (enable) and sleepable
> + * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
> + * should be done in clk_prepare. Switching that will not sleep should be done
> + * in clk_enable.
> + *
> + * Typically, drivers will call clk_prepare when a clock may be needed later
> + * (eg. when a device is opened), and clk_enable when the clock is actually
> + * required (eg. from an interrupt). Note that clk_prepare *must* have been
> + * called before clk_enable.
>   */
> +struct clk_hw_ops {
> +	int		(*prepare)(struct clk_hw *);
> +	void		(*unprepare)(struct clk_hw *);
> +	int		(*enable)(struct clk_hw *);
> +	void		(*disable)(struct clk_hw *);
> +	unsigned long	(*recalc_rate)(struct clk_hw *);
> +	long		(*round_rate)(struct clk_hw *, unsigned long);
> +	struct clk *	(*get_parent)(struct clk_hw *);
> +};
>  
> +/**
> + * clk_prepare - prepare clock for atomic enabling.
> + *
> + * @clk: The clock to prepare
> + *
> + * Do any possibly sleeping initialisation on @clk, allowing the clock to be
> + * later enabled atomically (via clk_enable). This function may sleep.
> + */
> +int clk_prepare(struct clk *clk);
> +
> +/**
> + * clk_unprepare - release clock from prepared state
> + *
> + * @clk: The clock to release
> + *
> + * Do any (possibly sleeping) cleanup on clk. This function may sleep.
> + */
> +void clk_unprepare(struct clk *clk);
> +
> +/**
> + * clk_register - register and initialize a new clock
> + *
> + * @ops: ops for the new clock
> + * @hw: struct clk_hw to be passed to the ops of the new clock
> + * @name: name to use for the new clock
> + *
> + * Register a new clock with the clk subsystem.  Returns either a
> + * struct clk for the new clock or a NULL pointer.
> + */
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +			 const char *name);
> +
> +/**
> + * clk_unregister - remove a clock
> + *
> + * @clk: clock to unregister
> + *
> + * Remove a clock from the clk subsystem.  This is currently not
> + * implemented but is provided to allow unregistration code to be
> + * written in drivers ready for use when an implementation is
> + * provided.
> + */
> +static inline int clk_unregister(struct clk *clk)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
> +#else /* !CONFIG_GENERIC_CLK */
>  
>  /*
> - * struct clk - an machine class defined object / cookie.
> + * For !CONFIG_GENERIC_CLK, we don't enforce any atomicity
> + * requirements for clk_enable/clk_disable, so the prepare and unprepare
> + * functions are no-ops
>   */
> -struct clk;
> +static inline int clk_prepare(struct clk *clk) {
> +	might_sleep();
> +	return 0;
> +}
> +
> +static inline void clk_unprepare(struct clk *clk) {
> +	might_sleep();
> +}
> +
> +#endif /* !CONFIG_GENERIC_CLK */
>  
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.
> @@ -67,6 +188,7 @@ void clk_disable(struct clk *clk);
>  /**
>   * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
>   *		  This is only valid once the clock source has been enabled.
> + *		  Returns zero if the clock rate is unknown.
>   * @clk: clock source
>   */
>  unsigned long clk_get_rate(struct clk *clk);
> @@ -83,12 +205,6 @@ unsigned long clk_get_rate(struct clk *clk);
>   */
>  void clk_put(struct clk *clk);
>  
> -
> -/*
> - * The remaining APIs are optional for machine class support.
> - */
> -
> -
>  /**
>   * clk_round_rate - adjust a rate to the exact rate a clock can provide
>   * @clk: clock source
> @@ -97,7 +213,7 @@ void clk_put(struct clk *clk);
>   * Returns rounded clock rate in Hz, or negative errno.
>   */
>  long clk_round_rate(struct clk *clk, unsigned long rate);
> - 
> +
>  /**
>   * clk_set_rate - set the clock rate for a clock source
>   * @clk: clock source
> @@ -106,7 +222,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
>   * Returns success (0) or negative errno.
>   */
>  int clk_set_rate(struct clk *clk, unsigned long rate);
> - 
> +
>  /**
>   * clk_set_parent - set the parent clock source for this clock
>   * @clk: clock source
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

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

* Re: [PATCH v2 2/7] clk: Implement clk_set_rate
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-11 11:49     ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-11 11:49 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, skannan, linux,
	jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Thu, Sep 22, 2011 at 03:26:57PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Implement clk_set_rate by adding a set_rate callback to clk_hw_ops.
> Rates are propagated down the clock tree and recalculated.  Also adds a
> flag for signaling that parents must change rates to achieve the desired
> frequency (upstream propagation).
> 
> TODO:
> Upstream propagation is not yet implemented.
> Device pre-change and post-change notifications are not implemented, but
> are marked up as FIXME comments.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Remove upstream propagation (for now)
> Rename CLK_SET_RATE_PROPAGATE to CLK_PARENT_RATE_CHANGE
> 
>  drivers/clk/clk.c   |   71 ++++++++++++++++++++++++++++++++++++++++++++++----
>  include/linux/clk.h |   12 ++++++++
>  2 files changed, 77 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 1cd7315..86636c2 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -21,6 +21,8 @@ struct clk {
>  	unsigned int		enable_count;
>  	unsigned int		prepare_count;
>  	struct clk		*parent;
> +	struct hlist_head	children;
> +	struct hlist_node	child_node;
>  	unsigned long		rate;
>  };
>  
> @@ -176,10 +178,57 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
>  }
>  EXPORT_SYMBOL_GPL(clk_round_rate);
>  
> +/*
> + * clk_recalc_rates - Given a clock (with a recently updated clk->rate),
> + *	notify its children that the rate may need to be recalculated, using
> + *	ops->recalc_rate().
> + */
> +static void clk_recalc_rates(struct clk *clk)
> +{
> +	struct hlist_node *tmp;
> +	struct clk *child;
> +
> +	if (clk->ops->recalc_rate)
> +		clk->rate = clk->ops->recalc_rate(clk->hw);
pass it parent rate if recalc_rate is NULL?
> +
> +	/* FIXME add post-rate change notification here */
> +
> +	hlist_for_each_entry(child, tmp, &clk->children, child_node)
> +		clk_recalc_rates(child);
> +}
> +
>  int clk_set_rate(struct clk *clk, unsigned long rate)
>  {
> -	/* not yet implemented */
> -	return -ENOSYS;
> +	unsigned long parent_rate, new_rate;
> +	int ret = 0;
> +
> +	if (!clk->ops->set_rate)
> +		return -ENOSYS;
> +
> +	new_rate = rate;
> +
> +	/* prevent racing with updates to the clock topology */
> +	mutex_lock(&prepare_lock);
> +
> +	/* FIXME add pre-rate change notification here */
> +
> +	ret = clk->ops->set_rate(clk->hw, new_rate, &parent_rate);
> +
> +	/* FIXME ignores CLK_PARENT_RATE_CHANGE */
why do we need upstream propagate? for cascaded dividers? It may effect
parent's other children.
Does rate have to be rate returned by round_rate? I guess we can
accept none exact rate.

Thanks
Richard
> +	if (ret < 0)
> +		/* FIXME add rate change abort notification here */
> +		goto out;
> +
> +	/*
> +	 * If successful recalculate the rates of the clock, including
> +	 * children.
> +	 */
> +	clk_recalc_rates(clk);
> +
> +out:
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(clk_set_rate);
>  
> @@ -216,16 +265,26 @@ struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
>  	clk->hw = hw;
>  	hw->clk = clk;
>  
> -	/* Query the hardware for parent and initial rate */
> +	/*
> +	 * Query the hardware for parent and initial rate. We may alter
> +	 * the clock topology, making this clock available from the parent's
> +	 * children list. So, we need to protect against concurrent
> +	 * accesses through set_rate
> +	 */
> +	mutex_lock(&prepare_lock);
>  
> -	if (clk->ops->get_parent)
> -		/* We don't to lock against prepare/enable here, as
> -		 * the clock is not yet accessible from anywhere */
> +	if (clk->ops->get_parent) {
>  		clk->parent = clk->ops->get_parent(clk->hw);
> +		if (clk->parent)
> +			hlist_add_head(&clk->child_node,
> +					&clk->parent->children);
> +	}
>  
>  	if (clk->ops->recalc_rate)
>  		clk->rate = clk->ops->recalc_rate(clk->hw);
>  
> +	mutex_unlock(&prepare_lock);
> +
>  
>  	return clk;
>  }
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index d6ae10b..0d2cd5e 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -58,6 +58,12 @@ struct clk_hw {
>   *		parent. Currently only called when the clock is first
>   *		registered.
>   *
> + * @set_rate	Change the rate of this clock. If this callback returns
> + *		CLK_SET_RATE_PROPAGATE, the rate change will be propagated to
> + *		the parent clock (which may propagate again). The requested
> + *		rate of the parent is passed back from the callback in the
> + *		second 'unsigned long *' argument.
> + *
>   * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
>   * implementations to split any work between atomic (enable) and sleepable
>   * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
> @@ -76,9 +82,15 @@ struct clk_hw_ops {
>  	void		(*disable)(struct clk_hw *);
>  	unsigned long	(*recalc_rate)(struct clk_hw *);
>  	long		(*round_rate)(struct clk_hw *, unsigned long);
> +	int		(*set_rate)(struct clk_hw *,
> +					unsigned long, unsigned long *);
>  	struct clk *	(*get_parent)(struct clk_hw *);
>  };
>  
> +enum {
> +	CLK_PARENT_RATE_CHANGE = 1,
> +};
> +
>  /**
>   * clk_prepare - prepare clock for atomic enabling.
>   *
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


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

* [PATCH v2 2/7] clk: Implement clk_set_rate
@ 2011-10-11 11:49     ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-11 11:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:57PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Implement clk_set_rate by adding a set_rate callback to clk_hw_ops.
> Rates are propagated down the clock tree and recalculated.  Also adds a
> flag for signaling that parents must change rates to achieve the desired
> frequency (upstream propagation).
> 
> TODO:
> Upstream propagation is not yet implemented.
> Device pre-change and post-change notifications are not implemented, but
> are marked up as FIXME comments.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Remove upstream propagation (for now)
> Rename CLK_SET_RATE_PROPAGATE to CLK_PARENT_RATE_CHANGE
> 
>  drivers/clk/clk.c   |   71 ++++++++++++++++++++++++++++++++++++++++++++++----
>  include/linux/clk.h |   12 ++++++++
>  2 files changed, 77 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 1cd7315..86636c2 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -21,6 +21,8 @@ struct clk {
>  	unsigned int		enable_count;
>  	unsigned int		prepare_count;
>  	struct clk		*parent;
> +	struct hlist_head	children;
> +	struct hlist_node	child_node;
>  	unsigned long		rate;
>  };
>  
> @@ -176,10 +178,57 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
>  }
>  EXPORT_SYMBOL_GPL(clk_round_rate);
>  
> +/*
> + * clk_recalc_rates - Given a clock (with a recently updated clk->rate),
> + *	notify its children that the rate may need to be recalculated, using
> + *	ops->recalc_rate().
> + */
> +static void clk_recalc_rates(struct clk *clk)
> +{
> +	struct hlist_node *tmp;
> +	struct clk *child;
> +
> +	if (clk->ops->recalc_rate)
> +		clk->rate = clk->ops->recalc_rate(clk->hw);
pass it parent rate if recalc_rate is NULL?
> +
> +	/* FIXME add post-rate change notification here */
> +
> +	hlist_for_each_entry(child, tmp, &clk->children, child_node)
> +		clk_recalc_rates(child);
> +}
> +
>  int clk_set_rate(struct clk *clk, unsigned long rate)
>  {
> -	/* not yet implemented */
> -	return -ENOSYS;
> +	unsigned long parent_rate, new_rate;
> +	int ret = 0;
> +
> +	if (!clk->ops->set_rate)
> +		return -ENOSYS;
> +
> +	new_rate = rate;
> +
> +	/* prevent racing with updates to the clock topology */
> +	mutex_lock(&prepare_lock);
> +
> +	/* FIXME add pre-rate change notification here */
> +
> +	ret = clk->ops->set_rate(clk->hw, new_rate, &parent_rate);
> +
> +	/* FIXME ignores CLK_PARENT_RATE_CHANGE */
why do we need upstream propagate? for cascaded dividers? It may effect
parent's other children.
Does rate have to be rate returned by round_rate? I guess we can
accept none exact rate.

Thanks
Richard
> +	if (ret < 0)
> +		/* FIXME add rate change abort notification here */
> +		goto out;
> +
> +	/*
> +	 * If successful recalculate the rates of the clock, including
> +	 * children.
> +	 */
> +	clk_recalc_rates(clk);
> +
> +out:
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(clk_set_rate);
>  
> @@ -216,16 +265,26 @@ struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
>  	clk->hw = hw;
>  	hw->clk = clk;
>  
> -	/* Query the hardware for parent and initial rate */
> +	/*
> +	 * Query the hardware for parent and initial rate. We may alter
> +	 * the clock topology, making this clock available from the parent's
> +	 * children list. So, we need to protect against concurrent
> +	 * accesses through set_rate
> +	 */
> +	mutex_lock(&prepare_lock);
>  
> -	if (clk->ops->get_parent)
> -		/* We don't to lock against prepare/enable here, as
> -		 * the clock is not yet accessible from anywhere */
> +	if (clk->ops->get_parent) {
>  		clk->parent = clk->ops->get_parent(clk->hw);
> +		if (clk->parent)
> +			hlist_add_head(&clk->child_node,
> +					&clk->parent->children);
> +	}
>  
>  	if (clk->ops->recalc_rate)
>  		clk->rate = clk->ops->recalc_rate(clk->hw);
>  
> +	mutex_unlock(&prepare_lock);
> +
>  
>  	return clk;
>  }
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index d6ae10b..0d2cd5e 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -58,6 +58,12 @@ struct clk_hw {
>   *		parent. Currently only called when the clock is first
>   *		registered.
>   *
> + * @set_rate	Change the rate of this clock. If this callback returns
> + *		CLK_SET_RATE_PROPAGATE, the rate change will be propagated to
> + *		the parent clock (which may propagate again). The requested
> + *		rate of the parent is passed back from the callback in the
> + *		second 'unsigned long *' argument.
> + *
>   * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
>   * implementations to split any work between atomic (enable) and sleepable
>   * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
> @@ -76,9 +82,15 @@ struct clk_hw_ops {
>  	void		(*disable)(struct clk_hw *);
>  	unsigned long	(*recalc_rate)(struct clk_hw *);
>  	long		(*round_rate)(struct clk_hw *, unsigned long);
> +	int		(*set_rate)(struct clk_hw *,
> +					unsigned long, unsigned long *);
>  	struct clk *	(*get_parent)(struct clk_hw *);
>  };
>  
> +enum {
> +	CLK_PARENT_RATE_CHANGE = 1,
> +};
> +
>  /**
>   * clk_prepare - prepare clock for atomic enabling.
>   *
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-12  6:46     ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-12  6:46 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, Jamie Iles,
	skannan, linux, jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Add copyright header
> Fold in Jamie's patch for set-to-disable clks
> Use BIT macro instead of shift
> 
>  drivers/clk/Kconfig    |    4 ++
>  drivers/clk/Makefile   |    1 +
>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h    |   13 ++++++++
>  4 files changed, 96 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-gate.c

I feel hard to tell the tree the clk parent, at register/init time. For the
simple gate clk, the only way is to set .get_parent. But normally, for clk
without any divider we set .get_parent to NULL. Maybe we can put .parent to
struct clk_hw?

Thanks
Richard
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d8313d7..a78967c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -12,3 +12,7 @@ config GENERIC_CLK
>  config GENERIC_CLK_FIXED
>  	bool
>  	depends on GENERIC_CLK
> +
> +config GENERIC_CLK_GATE
> +	bool
> +	depends on GENERIC_CLK
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 9a3325a..d186446 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -2,3 +2,4 @@
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
>  obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
> +obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> new file mode 100644
> index 0000000..a1d8e79
> --- /dev/null
> +++ b/drivers/clk/clk-gate.c
> @@ -0,0 +1,78 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Simple clk gate implementation
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <asm/io.h>
> +
> +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
> +
> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> +{
> +	return clk_get_rate(clk_get_parent(clk->clk));
> +}
> +
> +static void clk_gate_set_bit(struct clk_hw *clk)
> +{
> +	struct clk_gate *gate = to_clk_gate(clk);
> +	u32 reg;
> +
> +	reg = __raw_readl(gate->reg);
> +	reg |= BIT(gate->bit_idx);
> +	__raw_writel(reg, gate->reg);
> +}
> +
> +static void clk_gate_clear_bit(struct clk_hw *clk)
> +{
> +	struct clk_gate *gate = to_clk_gate(clk);
> +	u32 reg;
> +
> +	reg = __raw_readl(gate->reg);
> +	reg &= ~BIT(gate->bit_idx);
> +	__raw_writel(reg, gate->reg);
> +}
> +
> +static int clk_gate_enable_set(struct clk_hw *clk)
> +{
> +	clk_gate_set_bit(clk);
> +
> +	return 0;
> +}
> +
> +static void clk_gate_disable_clear(struct clk_hw *clk)
> +{
> +	clk_gate_clear_bit(clk);
> +}
> +
> +struct clk_hw_ops clk_gate_set_enable_ops = {
> +	.recalc_rate = clk_gate_get_rate,
> +	.enable = clk_gate_enable_set,
> +	.disable = clk_gate_disable_clear,
> +};
> +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
> +
> +static int clk_gate_enable_clear(struct clk_hw *clk)
> +{
> +	clk_gate_clear_bit(clk);
> +
> +	return 0;
> +}
> +
> +static void clk_gate_disable_set(struct clk_hw *clk)
> +{
> +	clk_gate_set_bit(clk);
> +}
> +
> +struct clk_hw_ops clk_gate_set_disable_ops = {
> +	.recalc_rate = clk_gate_get_rate,
> +	.enable = clk_gate_enable_clear,
> +	.disable = clk_gate_disable_set,
> +};
> +EXPORT_SYMBOL_GPL(clk_gate_set_disable_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1903dd8..626fd0d 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -124,6 +124,19 @@ extern struct clk_hw_ops clk_fixed_ops;
>  
>  #endif /* CONFIG_GENERIC_CLK_FIXED */
>  
> +#ifdef CONFIG_GENERIC_CLK_GATE
> +
> +struct clk_gate {
> +	struct clk_hw	hw;
> +	void __iomem	*reg;
> +	u8		bit_idx;
> +};
> +
> +extern struct clk_hw_ops clk_gate_set_enable_ops;
> +extern struct clk_hw_ops clk_gate_set_disable_ops;
> +
> +#endif /* CONFIG_GENERIC_CLK_GATE */
> +
>  /**
>   * clk_register - register and initialize a new clock
>   *
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-10-12  6:46     ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-12  6:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Add copyright header
> Fold in Jamie's patch for set-to-disable clks
> Use BIT macro instead of shift
> 
>  drivers/clk/Kconfig    |    4 ++
>  drivers/clk/Makefile   |    1 +
>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h    |   13 ++++++++
>  4 files changed, 96 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-gate.c

I feel hard to tell the tree the clk parent, at register/init time. For the
simple gate clk, the only way is to set .get_parent. But normally, for clk
without any divider we set .get_parent to NULL. Maybe we can put .parent to
struct clk_hw?

Thanks
Richard
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index d8313d7..a78967c 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -12,3 +12,7 @@ config GENERIC_CLK
>  config GENERIC_CLK_FIXED
>  	bool
>  	depends on GENERIC_CLK
> +
> +config GENERIC_CLK_GATE
> +	bool
> +	depends on GENERIC_CLK
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 9a3325a..d186446 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -2,3 +2,4 @@
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
>  obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
> +obj-$(CONFIG_GENERIC_CLK_GATE)	+= clk-gate.o
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> new file mode 100644
> index 0000000..a1d8e79
> --- /dev/null
> +++ b/drivers/clk/clk-gate.c
> @@ -0,0 +1,78 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Simple clk gate implementation
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <asm/io.h>
> +
> +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
> +
> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> +{
> +	return clk_get_rate(clk_get_parent(clk->clk));
> +}
> +
> +static void clk_gate_set_bit(struct clk_hw *clk)
> +{
> +	struct clk_gate *gate = to_clk_gate(clk);
> +	u32 reg;
> +
> +	reg = __raw_readl(gate->reg);
> +	reg |= BIT(gate->bit_idx);
> +	__raw_writel(reg, gate->reg);
> +}
> +
> +static void clk_gate_clear_bit(struct clk_hw *clk)
> +{
> +	struct clk_gate *gate = to_clk_gate(clk);
> +	u32 reg;
> +
> +	reg = __raw_readl(gate->reg);
> +	reg &= ~BIT(gate->bit_idx);
> +	__raw_writel(reg, gate->reg);
> +}
> +
> +static int clk_gate_enable_set(struct clk_hw *clk)
> +{
> +	clk_gate_set_bit(clk);
> +
> +	return 0;
> +}
> +
> +static void clk_gate_disable_clear(struct clk_hw *clk)
> +{
> +	clk_gate_clear_bit(clk);
> +}
> +
> +struct clk_hw_ops clk_gate_set_enable_ops = {
> +	.recalc_rate = clk_gate_get_rate,
> +	.enable = clk_gate_enable_set,
> +	.disable = clk_gate_disable_clear,
> +};
> +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
> +
> +static int clk_gate_enable_clear(struct clk_hw *clk)
> +{
> +	clk_gate_clear_bit(clk);
> +
> +	return 0;
> +}
> +
> +static void clk_gate_disable_set(struct clk_hw *clk)
> +{
> +	clk_gate_set_bit(clk);
> +}
> +
> +struct clk_hw_ops clk_gate_set_disable_ops = {
> +	.recalc_rate = clk_gate_get_rate,
> +	.enable = clk_gate_enable_clear,
> +	.disable = clk_gate_disable_set,
> +};
> +EXPORT_SYMBOL_GPL(clk_gate_set_disable_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 1903dd8..626fd0d 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -124,6 +124,19 @@ extern struct clk_hw_ops clk_fixed_ops;
>  
>  #endif /* CONFIG_GENERIC_CLK_FIXED */
>  
> +#ifdef CONFIG_GENERIC_CLK_GATE
> +
> +struct clk_gate {
> +	struct clk_hw	hw;
> +	void __iomem	*reg;
> +	u8		bit_idx;
> +};
> +
> +extern struct clk_hw_ops clk_gate_set_enable_ops;
> +extern struct clk_hw_ops clk_gate_set_disable_ops;
> +
> +#endif /* CONFIG_GENERIC_CLK_GATE */
> +
>  /**
>   * clk_register - register and initialize a new clock
>   *
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-10-12  6:46     ` Richard Zhao
@ 2011-10-12 14:59       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-12 14:59 UTC (permalink / raw)
  To: Richard Zhao
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, amit.kucheria, richard.zhao,
	grant.likely, dsaxena, arnd.bergmann, shawn.guo, Jamie Iles,
	skannan, linux, jeremy.kerr, tglx, linux-arm-kernel, sboyd

On Tue, Oct 11, 2011 at 11:46 PM, Richard Zhao
<richard.zhao@freescale.com> wrote:
> On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>>
>> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> ---
>> Changes since v1:
>> Add copyright header
>> Fold in Jamie's patch for set-to-disable clks
>> Use BIT macro instead of shift
>>
>>  drivers/clk/Kconfig    |    4 ++
>>  drivers/clk/Makefile   |    1 +
>>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/clk.h    |   13 ++++++++
>>  4 files changed, 96 insertions(+), 0 deletions(-)
>>  create mode 100644 drivers/clk/clk-gate.c
>
> I feel hard to tell the tree the clk parent, at register/init time. For the
> simple gate clk, the only way is to set .get_parent. But normally, for clk
> without any divider we set .get_parent to NULL. Maybe we can put .parent to
> struct clk_hw?

For non-mux clocks, whose parent is *always* going to be the same, you
should create a duplicate .parent in the clk_hw_* structure and then
have .get_parent return clk_hw_*->parent.

This is analogous to the way clk_hw_fixed returns clk_hw_fixed->rate
when .recalc is called on it.

Regards,
Mike

> Thanks
> Richard
>>
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index d8313d7..a78967c 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -12,3 +12,7 @@ config GENERIC_CLK
>>  config GENERIC_CLK_FIXED
>>       bool
>>       depends on GENERIC_CLK
>> +
>> +config GENERIC_CLK_GATE
>> +     bool
>> +     depends on GENERIC_CLK
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 9a3325a..d186446 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -2,3 +2,4 @@
>>  obj-$(CONFIG_CLKDEV_LOOKUP)  += clkdev.o
>>  obj-$(CONFIG_GENERIC_CLK)    += clk.o
>>  obj-$(CONFIG_GENERIC_CLK_FIXED)      += clk-fixed.o
>> +obj-$(CONFIG_GENERIC_CLK_GATE)       += clk-gate.o
>> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
>> new file mode 100644
>> index 0000000..a1d8e79
>> --- /dev/null
>> +++ b/drivers/clk/clk-gate.c
>> @@ -0,0 +1,78 @@
>> +/*
>> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * Simple clk gate implementation
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/module.h>
>> +#include <asm/io.h>
>> +
>> +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
>> +
>> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
>> +{
>> +     return clk_get_rate(clk_get_parent(clk->clk));
>> +}
>> +
>> +static void clk_gate_set_bit(struct clk_hw *clk)
>> +{
>> +     struct clk_gate *gate = to_clk_gate(clk);
>> +     u32 reg;
>> +
>> +     reg = __raw_readl(gate->reg);
>> +     reg |= BIT(gate->bit_idx);
>> +     __raw_writel(reg, gate->reg);
>> +}
>> +
>> +static void clk_gate_clear_bit(struct clk_hw *clk)
>> +{
>> +     struct clk_gate *gate = to_clk_gate(clk);
>> +     u32 reg;
>> +
>> +     reg = __raw_readl(gate->reg);
>> +     reg &= ~BIT(gate->bit_idx);
>> +     __raw_writel(reg, gate->reg);
>> +}
>> +
>> +static int clk_gate_enable_set(struct clk_hw *clk)
>> +{
>> +     clk_gate_set_bit(clk);
>> +
>> +     return 0;
>> +}
>> +
>> +static void clk_gate_disable_clear(struct clk_hw *clk)
>> +{
>> +     clk_gate_clear_bit(clk);
>> +}
>> +
>> +struct clk_hw_ops clk_gate_set_enable_ops = {
>> +     .recalc_rate = clk_gate_get_rate,
>> +     .enable = clk_gate_enable_set,
>> +     .disable = clk_gate_disable_clear,
>> +};
>> +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
>> +
>> +static int clk_gate_enable_clear(struct clk_hw *clk)
>> +{
>> +     clk_gate_clear_bit(clk);
>> +
>> +     return 0;
>> +}
>> +
>> +static void clk_gate_disable_set(struct clk_hw *clk)
>> +{
>> +     clk_gate_set_bit(clk);
>> +}
>> +
>> +struct clk_hw_ops clk_gate_set_disable_ops = {
>> +     .recalc_rate = clk_gate_get_rate,
>> +     .enable = clk_gate_enable_clear,
>> +     .disable = clk_gate_disable_set,
>> +};
>> +EXPORT_SYMBOL_GPL(clk_gate_set_disable_ops);
>> diff --git a/include/linux/clk.h b/include/linux/clk.h
>> index 1903dd8..626fd0d 100644
>> --- a/include/linux/clk.h
>> +++ b/include/linux/clk.h
>> @@ -124,6 +124,19 @@ extern struct clk_hw_ops clk_fixed_ops;
>>
>>  #endif /* CONFIG_GENERIC_CLK_FIXED */
>>
>> +#ifdef CONFIG_GENERIC_CLK_GATE
>> +
>> +struct clk_gate {
>> +     struct clk_hw   hw;
>> +     void __iomem    *reg;
>> +     u8              bit_idx;
>> +};
>> +
>> +extern struct clk_hw_ops clk_gate_set_enable_ops;
>> +extern struct clk_hw_ops clk_gate_set_disable_ops;
>> +
>> +#endif /* CONFIG_GENERIC_CLK_GATE */
>> +
>>  /**
>>   * clk_register - register and initialize a new clock
>>   *
>> --
>> 1.7.4.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-10-12 14:59       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-12 14:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Oct 11, 2011 at 11:46 PM, Richard Zhao
<richard.zhao@freescale.com> wrote:
> On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>>
>> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> ---
>> Changes since v1:
>> Add copyright header
>> Fold in Jamie's patch for set-to-disable clks
>> Use BIT macro instead of shift
>>
>> ?drivers/clk/Kconfig ? ?| ? ?4 ++
>> ?drivers/clk/Makefile ? | ? ?1 +
>> ?drivers/clk/clk-gate.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++++
>> ?include/linux/clk.h ? ?| ? 13 ++++++++
>> ?4 files changed, 96 insertions(+), 0 deletions(-)
>> ?create mode 100644 drivers/clk/clk-gate.c
>
> I feel hard to tell the tree the clk parent, at register/init time. For the
> simple gate clk, the only way is to set .get_parent. But normally, for clk
> without any divider we set .get_parent to NULL. Maybe we can put .parent to
> struct clk_hw?

For non-mux clocks, whose parent is *always* going to be the same, you
should create a duplicate .parent in the clk_hw_* structure and then
have .get_parent return clk_hw_*->parent.

This is analogous to the way clk_hw_fixed returns clk_hw_fixed->rate
when .recalc is called on it.

Regards,
Mike

> Thanks
> Richard
>>
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index d8313d7..a78967c 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -12,3 +12,7 @@ config GENERIC_CLK
>> ?config GENERIC_CLK_FIXED
>> ? ? ? bool
>> ? ? ? depends on GENERIC_CLK
>> +
>> +config GENERIC_CLK_GATE
>> + ? ? bool
>> + ? ? depends on GENERIC_CLK
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 9a3325a..d186446 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -2,3 +2,4 @@
>> ?obj-$(CONFIG_CLKDEV_LOOKUP) ?+= clkdev.o
>> ?obj-$(CONFIG_GENERIC_CLK) ? ?+= clk.o
>> ?obj-$(CONFIG_GENERIC_CLK_FIXED) ? ? ?+= clk-fixed.o
>> +obj-$(CONFIG_GENERIC_CLK_GATE) ? ? ? += clk-gate.o
>> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
>> new file mode 100644
>> index 0000000..a1d8e79
>> --- /dev/null
>> +++ b/drivers/clk/clk-gate.c
>> @@ -0,0 +1,78 @@
>> +/*
>> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * Simple clk gate implementation
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/module.h>
>> +#include <asm/io.h>
>> +
>> +#define to_clk_gate(clk) container_of(clk, struct clk_gate, hw)
>> +
>> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
>> +{
>> + ? ? return clk_get_rate(clk_get_parent(clk->clk));
>> +}
>> +
>> +static void clk_gate_set_bit(struct clk_hw *clk)
>> +{
>> + ? ? struct clk_gate *gate = to_clk_gate(clk);
>> + ? ? u32 reg;
>> +
>> + ? ? reg = __raw_readl(gate->reg);
>> + ? ? reg |= BIT(gate->bit_idx);
>> + ? ? __raw_writel(reg, gate->reg);
>> +}
>> +
>> +static void clk_gate_clear_bit(struct clk_hw *clk)
>> +{
>> + ? ? struct clk_gate *gate = to_clk_gate(clk);
>> + ? ? u32 reg;
>> +
>> + ? ? reg = __raw_readl(gate->reg);
>> + ? ? reg &= ~BIT(gate->bit_idx);
>> + ? ? __raw_writel(reg, gate->reg);
>> +}
>> +
>> +static int clk_gate_enable_set(struct clk_hw *clk)
>> +{
>> + ? ? clk_gate_set_bit(clk);
>> +
>> + ? ? return 0;
>> +}
>> +
>> +static void clk_gate_disable_clear(struct clk_hw *clk)
>> +{
>> + ? ? clk_gate_clear_bit(clk);
>> +}
>> +
>> +struct clk_hw_ops clk_gate_set_enable_ops = {
>> + ? ? .recalc_rate = clk_gate_get_rate,
>> + ? ? .enable = clk_gate_enable_set,
>> + ? ? .disable = clk_gate_disable_clear,
>> +};
>> +EXPORT_SYMBOL_GPL(clk_gate_set_enable_ops);
>> +
>> +static int clk_gate_enable_clear(struct clk_hw *clk)
>> +{
>> + ? ? clk_gate_clear_bit(clk);
>> +
>> + ? ? return 0;
>> +}
>> +
>> +static void clk_gate_disable_set(struct clk_hw *clk)
>> +{
>> + ? ? clk_gate_set_bit(clk);
>> +}
>> +
>> +struct clk_hw_ops clk_gate_set_disable_ops = {
>> + ? ? .recalc_rate = clk_gate_get_rate,
>> + ? ? .enable = clk_gate_enable_clear,
>> + ? ? .disable = clk_gate_disable_set,
>> +};
>> +EXPORT_SYMBOL_GPL(clk_gate_set_disable_ops);
>> diff --git a/include/linux/clk.h b/include/linux/clk.h
>> index 1903dd8..626fd0d 100644
>> --- a/include/linux/clk.h
>> +++ b/include/linux/clk.h
>> @@ -124,6 +124,19 @@ extern struct clk_hw_ops clk_fixed_ops;
>>
>> ?#endif /* CONFIG_GENERIC_CLK_FIXED */
>>
>> +#ifdef CONFIG_GENERIC_CLK_GATE
>> +
>> +struct clk_gate {
>> + ? ? struct clk_hw ? hw;
>> + ? ? void __iomem ? ?*reg;
>> + ? ? u8 ? ? ? ? ? ? ?bit_idx;
>> +};
>> +
>> +extern struct clk_hw_ops clk_gate_set_enable_ops;
>> +extern struct clk_hw_ops clk_gate_set_disable_ops;
>> +
>> +#endif /* CONFIG_GENERIC_CLK_GATE */
>> +
>> ?/**
>> ? * clk_register - register and initialize a new clock
>> ? *
>> --
>> 1.7.4.1
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-13 14:44     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 144+ messages in thread
From: Russell King - ARM Linux @ 2011-10-13 14:44 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, shawn.guo, skannan, magnus.damm,
	arnd.bergmann, eric.miao, richard.zhao

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };

Eww, no, this really isn't going to scale for platforms like OMAP - to
have all the operations indirected through a set of function pointers
for every clock just because the enable register (or enable bit) is
in a different position is completely absurd.

I'm not soo concerned about the increase in memory usage (for 100 to 200
clock definitions its only 4 to 8k) but what worries me the most is
initializing these damned things.  It's an awful lot of initializers,
which means the potential for an awful lot of conflicts should something
change in this structure.

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-13 14:44     ` Russell King - ARM Linux
  0 siblings, 0 replies; 144+ messages in thread
From: Russell King - ARM Linux @ 2011-10-13 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };

Eww, no, this really isn't going to scale for platforms like OMAP - to
have all the operations indirected through a set of function pointers
for every clock just because the enable register (or enable bit) is
in a different position is completely absurd.

I'm not soo concerned about the increase in memory usage (for 100 to 200
clock definitions its only 4 to 8k) but what worries me the most is
initializing these damned things.  It's an awful lot of initializers,
which means the potential for an awful lot of conflicts should something
change in this structure.

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-13 14:45     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 144+ messages in thread
From: Russell King - ARM Linux @ 2011-10-13 14:45 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, shawn.guo, skannan, magnus.damm,
	arnd.bergmann, eric.miao, richard.zhao, Jamie Iles

On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> new file mode 100644
> index 0000000..a1d8e79
> --- /dev/null
> +++ b/drivers/clk/clk-gate.c
> @@ -0,0 +1,78 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Simple clk gate implementation
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <asm/io.h>

linux/io.h please.

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-10-13 14:45     ` Russell King - ARM Linux
  0 siblings, 0 replies; 144+ messages in thread
From: Russell King - ARM Linux @ 2011-10-13 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> new file mode 100644
> index 0000000..a1d8e79
> --- /dev/null
> +++ b/drivers/clk/clk-gate.c
> @@ -0,0 +1,78 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Simple clk gate implementation
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <asm/io.h>

linux/io.h please.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-13 14:44     ` Russell King - ARM Linux
@ 2011-10-13 17:16       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-13 17:16 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, shawn.guo, skannan, magnus.damm,
	arnd.bergmann, eric.miao, richard.zhao

On Thu, Oct 13, 2011 at 7:44 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
>>   struct clk_hw_ops {
>>       int             (*prepare)(struct clk_hw *);
>>       void            (*unprepare)(struct clk_hw *);
>>       int             (*enable)(struct clk_hw *);
>>       void            (*disable)(struct clk_hw *);
>>       unsigned long   (*recalc_rate)(struct clk_hw *);
>>       int             (*set_rate)(struct clk_hw *,
>>                                       unsigned long, unsigned long *);
>>       long            (*round_rate)(struct clk_hw *, unsigned long);
>>       int             (*set_parent)(struct clk_hw *, struct clk *);
>>       struct clk *    (*get_parent)(struct clk_hw *);
>>   };
>>
>> Platform clock code can register a clock through clk_register, passing a
>> set of operations, and a pointer to hardware-specific data:
>>
>>   struct clk_hw_foo {
>>       struct clk_hw clk;
>>       void __iomem *enable_reg;
>>   };
>
> Eww, no, this really isn't going to scale for platforms like OMAP - to
> have all the operations indirected through a set of function pointers
> for every clock just because the enable register (or enable bit) is
> in a different position is completely absurd.

Russel,

I'm porting the OMAP clock framework to common clock right now and it
is going well.

For many clocks near the root of the tree I've been able to re-use
struct clk_hw_fixed & clk_fixed_ops (see patch 3 or 4 in this series),
which actually represents a decrease in memory consumption over the
old OMAP struct clk (which populated many of the operations func
pointers directly, causing duplication).

So far I don't see scalability as an issue.  In fact the design solves
some problems neatly for us.  For now I am creating one "uber clock",
struct clk_hw_omap, which dumps all of the clksel, pll, gate control &
mux crap directly from OMAP's old struct clk.  This is not optimal for
the long-term, but is a reasonable stepping stone which handles 90% of
OMAP clocks.  The new common struct clk makes it much easier for us to
treat PLLs differently from typical dividers, which can be treated
differently from dividers in modules, which can be treated differently
from pure mux clocks, etc.

> I'm not soo concerned about the increase in memory usage (for 100 to 200
> clock definitions its only 4 to 8k) but what worries me the most is
> initializing these damned things.  It's an awful lot of initializers,
> which means the potential for an awful lot of conflicts should something
> change in this structure.

As I stated above, so far memory usage has actually *decreased* due to
removing so many duplicated function pointers for OMAP's old struct
clk.  I wouldn't be surprised if other SoCs experienced the same lift.

Also, in my own tree I've broken out clk_register into clk_init also.
clk_register is still the thing to call if you have dynamically
created clocks, as it handles the malloc, and it then calls clk_init.
clk_init can be used by for static clock data and just handles
initializing the mutex/list/whatever.  Does this allay some of your
concerns?  Are you just trying to avoid allocating all of that memory
dynamically?

Regards,
Mike

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-13 17:16       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-13 17:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Oct 13, 2011 at 7:44 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
>> ? struct clk_hw_ops {
>> ? ? ? int ? ? ? ? ? ? (*prepare)(struct clk_hw *);
>> ? ? ? void ? ? ? ? ? ?(*unprepare)(struct clk_hw *);
>> ? ? ? int ? ? ? ? ? ? (*enable)(struct clk_hw *);
>> ? ? ? void ? ? ? ? ? ?(*disable)(struct clk_hw *);
>> ? ? ? unsigned long ? (*recalc_rate)(struct clk_hw *);
>> ? ? ? int ? ? ? ? ? ? (*set_rate)(struct clk_hw *,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long, unsigned long *);
>> ? ? ? long ? ? ? ? ? ?(*round_rate)(struct clk_hw *, unsigned long);
>> ? ? ? int ? ? ? ? ? ? (*set_parent)(struct clk_hw *, struct clk *);
>> ? ? ? struct clk * ? ?(*get_parent)(struct clk_hw *);
>> ? };
>>
>> Platform clock code can register a clock through clk_register, passing a
>> set of operations, and a pointer to hardware-specific data:
>>
>> ? struct clk_hw_foo {
>> ? ? ? struct clk_hw clk;
>> ? ? ? void __iomem *enable_reg;
>> ? };
>
> Eww, no, this really isn't going to scale for platforms like OMAP - to
> have all the operations indirected through a set of function pointers
> for every clock just because the enable register (or enable bit) is
> in a different position is completely absurd.

Russel,

I'm porting the OMAP clock framework to common clock right now and it
is going well.

For many clocks near the root of the tree I've been able to re-use
struct clk_hw_fixed & clk_fixed_ops (see patch 3 or 4 in this series),
which actually represents a decrease in memory consumption over the
old OMAP struct clk (which populated many of the operations func
pointers directly, causing duplication).

So far I don't see scalability as an issue.  In fact the design solves
some problems neatly for us.  For now I am creating one "uber clock",
struct clk_hw_omap, which dumps all of the clksel, pll, gate control &
mux crap directly from OMAP's old struct clk.  This is not optimal for
the long-term, but is a reasonable stepping stone which handles 90% of
OMAP clocks.  The new common struct clk makes it much easier for us to
treat PLLs differently from typical dividers, which can be treated
differently from dividers in modules, which can be treated differently
from pure mux clocks, etc.

> I'm not soo concerned about the increase in memory usage (for 100 to 200
> clock definitions its only 4 to 8k) but what worries me the most is
> initializing these damned things. ?It's an awful lot of initializers,
> which means the potential for an awful lot of conflicts should something
> change in this structure.

As I stated above, so far memory usage has actually *decreased* due to
removing so many duplicated function pointers for OMAP's old struct
clk.  I wouldn't be surprised if other SoCs experienced the same lift.

Also, in my own tree I've broken out clk_register into clk_init also.
clk_register is still the thing to call if you have dynamically
created clocks, as it handles the malloc, and it then calls clk_init.
clk_init can be used by for static clock data and just handles
initializing the mutex/list/whatever.  Does this allay some of your
concerns?  Are you just trying to avoid allocating all of that memory
dynamically?

Regards,
Mike

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-10-13 14:45     ` Russell King - ARM Linux
@ 2011-10-13 17:18       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-13 17:18 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, shawn.guo, skannan, magnus.damm,
	arnd.bergmann, eric.miao, richard.zhao, Jamie Iles

On Thu, Oct 13, 2011 at 7:45 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
>> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
>> new file mode 100644
>> index 0000000..a1d8e79
>> --- /dev/null
>> +++ b/drivers/clk/clk-gate.c
>> @@ -0,0 +1,78 @@
>> +/*
>> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * Simple clk gate implementation
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/module.h>
>> +#include <asm/io.h>
>
> linux/io.h please.
>

Will roll into v3.

Thanks for reviewing,
Mike

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-10-13 17:18       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-13 17:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Oct 13, 2011 at 7:45 AM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
>> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
>> new file mode 100644
>> index 0000000..a1d8e79
>> --- /dev/null
>> +++ b/drivers/clk/clk-gate.c
>> @@ -0,0 +1,78 @@
>> +/*
>> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * Simple clk gate implementation
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/module.h>
>> +#include <asm/io.h>
>
> linux/io.h please.
>

Will roll into v3.

Thanks for reviewing,
Mike

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-14  8:10     ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-14  8:10 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, amit.kucheria, grant.likely,
	dsaxena, arnd.bergmann, shawn.guo, skannan, linux, jeremy.kerr,
	tglx, linux-arm-kernel, sboyd

Hi Mike,

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, and a set of clock operations. Different clock
> implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> The interface is split into two halves:
> 
>  * struct clk, which is the generic-device-driver interface. This
>    provides a set of functions which drivers may use to request
>    enable/disable, query or manipulate in a hardware-independent manner.
> 
>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>    interface. Clock drivers implement the ops, which allow the core
>    clock code to implement the generic 'struct clk' API.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
> common, opaque struct clk, and a set of clock operations (defined per
> type of clock):
> 
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };
> 
>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
> 
>   static int clk_foo_enable(struct clk_hw *clk)
>   {
>   	struct clk_foo *foo = to_clk_foo(clk);
>   	raw_writeb(foo->enable_reg, 1);
>   	return 0;
>   }
> 
>   struct clk_hw_ops clk_foo_ops = {
>   	.enable = clk_foo_enable,
>   };
> 
> And in the platform initialisation code:
> 
>   struct clk_foo my_clk_foo;
> 
>   void init_clocks(void)
>   {
>   	my_clk_foo.enable_reg = ioremap(...);
> 
>   	clk_register(&clk_foo_ops, &my_clk_foo, NULL);
>   }
> 
> Changes from Thomas Gleixner <tglx@linutronix.de>.
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> TODO:
> 
>  * We don't keep any internal reference to the clock topology at present.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Create a dummy clk_unregister and prototype/document it and clk_register
> Constify struct clk_hw_ops
> Remove spinlock.h header, include kernel.h
> Use EOPNOTSUPP instead of ENOTSUPP
> Add might_sleep to clk_prepare/clk_unprepare stubs
> Properly init children hlist and child_node
> Whitespace and typo fixes
> 
>  drivers/clk/Kconfig  |    3 +
>  drivers/clk/Makefile |    1 +
>  drivers/clk/clk.c    |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    7 ++
>  include/linux/clk.h  |  140 +++++++++++++++++++++++++++---
>  5 files changed, 371 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/clk/clk.c
> 
[...]
> +static void __clk_disable(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->enable_count == 0))
> +		return;
> +
> +	if (--clk->enable_count > 0)
> +		return;
> +
> +	if (clk->ops->disable)
> +		clk->ops->disable(clk->hw);
> +	__clk_disable(clk->parent);
> +}
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	__clk_disable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +static int __clk_enable(struct clk *clk)
> +{
> +	int ret;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return -ESHUTDOWN;
> +
> +
> +	if (clk->enable_count == 0) {
> +		ret = __clk_enable(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->enable) {
> +			ret = clk->ops->enable(clk->hw);
> +			if (ret) {
> +				__clk_disable(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->enable_count++;
> +	return 0;
> +}
Could you expose __clk_enable/__clk_disable? I find it hard to implement
clk group. clk group means, when a major clk enable/disable, it want a set
of other clks enable/disable accordingly.
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	ret = __clk_enable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
[...]

Thanks
Richard 


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-14  8:10     ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-14  8:10 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mike,

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
> 
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, and a set of clock operations. Different clock
> implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
> 
> The interface is split into two halves:
> 
>  * struct clk, which is the generic-device-driver interface. This
>    provides a set of functions which drivers may use to request
>    enable/disable, query or manipulate in a hardware-independent manner.
> 
>  * struct clk_hw and struct clk_hw_ops, which is the hardware-specific
>    interface. Clock drivers implement the ops, which allow the core
>    clock code to implement the generic 'struct clk' API.
> 
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
> 
> Platforms can enable the generic struct clock through
> CONFIG_GENERIC_CLK. In this case, the clock infrastructure consists of a
> common, opaque struct clk, and a set of clock operations (defined per
> type of clock):
> 
>   struct clk_hw_ops {
>   	int		(*prepare)(struct clk_hw *);
>   	void		(*unprepare)(struct clk_hw *);
>   	int		(*enable)(struct clk_hw *);
>   	void		(*disable)(struct clk_hw *);
>   	unsigned long	(*recalc_rate)(struct clk_hw *);
>   	int		(*set_rate)(struct clk_hw *,
>   					unsigned long, unsigned long *);
>   	long		(*round_rate)(struct clk_hw *, unsigned long);
>   	int		(*set_parent)(struct clk_hw *, struct clk *);
>   	struct clk *	(*get_parent)(struct clk_hw *);
>   };
> 
> Platform clock code can register a clock through clk_register, passing a
> set of operations, and a pointer to hardware-specific data:
> 
>   struct clk_hw_foo {
>   	struct clk_hw clk;
>   	void __iomem *enable_reg;
>   };
> 
>   #define to_clk_foo(c) offsetof(c, clk_hw_foo, clk)
> 
>   static int clk_foo_enable(struct clk_hw *clk)
>   {
>   	struct clk_foo *foo = to_clk_foo(clk);
>   	raw_writeb(foo->enable_reg, 1);
>   	return 0;
>   }
> 
>   struct clk_hw_ops clk_foo_ops = {
>   	.enable = clk_foo_enable,
>   };
> 
> And in the platform initialisation code:
> 
>   struct clk_foo my_clk_foo;
> 
>   void init_clocks(void)
>   {
>   	my_clk_foo.enable_reg = ioremap(...);
> 
>   	clk_register(&clk_foo_ops, &my_clk_foo, NULL);
>   }
> 
> Changes from Thomas Gleixner <tglx@linutronix.de>.
> 
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt <benh@kernel.crashing.org>.
> 
> TODO:
> 
>  * We don't keep any internal reference to the clock topology at present.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Create a dummy clk_unregister and prototype/document it and clk_register
> Constify struct clk_hw_ops
> Remove spinlock.h header, include kernel.h
> Use EOPNOTSUPP instead of ENOTSUPP
> Add might_sleep to clk_prepare/clk_unprepare stubs
> Properly init children hlist and child_node
> Whitespace and typo fixes
> 
>  drivers/clk/Kconfig  |    3 +
>  drivers/clk/Makefile |    1 +
>  drivers/clk/clk.c    |  232 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/clk/clkdev.c |    7 ++
>  include/linux/clk.h  |  140 +++++++++++++++++++++++++++---
>  5 files changed, 371 insertions(+), 12 deletions(-)
>  create mode 100644 drivers/clk/clk.c
> 
[...]
> +static void __clk_disable(struct clk *clk)
> +{
> +	if (!clk)
> +		return;
> +
> +	if (WARN_ON(clk->enable_count == 0))
> +		return;
> +
> +	if (--clk->enable_count > 0)
> +		return;
> +
> +	if (clk->ops->disable)
> +		clk->ops->disable(clk->hw);
> +	__clk_disable(clk->parent);
> +}
> +
> +void clk_disable(struct clk *clk)
> +{
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	__clk_disable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);
> +
> +static int __clk_enable(struct clk *clk)
> +{
> +	int ret;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return -ESHUTDOWN;
> +
> +
> +	if (clk->enable_count == 0) {
> +		ret = __clk_enable(clk->parent);
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->enable) {
> +			ret = clk->ops->enable(clk->hw);
> +			if (ret) {
> +				__clk_disable(clk->parent);
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->enable_count++;
> +	return 0;
> +}
Could you expose __clk_enable/__clk_disable? I find it hard to implement
clk group. clk group means, when a major clk enable/disable, it want a set
of other clks enable/disable accordingly.
> +
> +int clk_enable(struct clk *clk)
> +{
> +	unsigned long flags;
> +	int ret;
> +
> +	spin_lock_irqsave(&enable_lock, flags);
> +	ret = __clk_enable(clk);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
[...]

Thanks
Richard 

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-14  8:10     ` Richard Zhao
@ 2011-10-14 10:05       ` Mark Brown
  -1 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-14 10:05 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Mike Turquette, linux-kernel, paul, linaro-dev, linus.walleij,
	patches, eric.miao, magnus.damm, amit.kucheria, grant.likely,
	dsaxena, arnd.bergmann, shawn.guo, skannan, linux, jeremy.kerr,
	tglx, linux-arm-kernel, sboyd

On Fri, Oct 14, 2011 at 04:10:26PM +0800, Richard Zhao wrote:
> On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:

snip essentially Mike's entire mail - *please* delete irrelevant quotes
from your replies, it makes it very much easier to find the new text in
your mail and is much more friendly to people reading mail on mobile
devices.

> > +static int __clk_enable(struct clk *clk)
> > +{

> Could you expose __clk_enable/__clk_disable? I find it hard to implement
> clk group. clk group means, when a major clk enable/disable, it want a set
> of other clks enable/disable accordingly.

Shouldn't this be something the core is implementing?  I'd strongly
expect that the clock drivers are relatively dumb and delegate all the
decision making to the core API.  Otherwise it's going to be hard for
the core to implement any logic that involves working with more than one
clock like rate change notification, or guarantee that driver requests
made through the API are satisfied, as the state of the clocks will be
changing underneath it.

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-14 10:05       ` Mark Brown
  0 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-14 10:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 14, 2011 at 04:10:26PM +0800, Richard Zhao wrote:
> On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:

snip essentially Mike's entire mail - *please* delete irrelevant quotes
from your replies, it makes it very much easier to find the new text in
your mail and is much more friendly to people reading mail on mobile
devices.

> > +static int __clk_enable(struct clk *clk)
> > +{

> Could you expose __clk_enable/__clk_disable? I find it hard to implement
> clk group. clk group means, when a major clk enable/disable, it want a set
> of other clks enable/disable accordingly.

Shouldn't this be something the core is implementing?  I'd strongly
expect that the clock drivers are relatively dumb and delegate all the
decision making to the core API.  Otherwise it's going to be hard for
the core to implement any logic that involves working with more than one
clock like rate change notification, or guarantee that driver requests
made through the API are satisfied, as the state of the clocks will be
changing underneath it.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-14 10:05       ` Mark Brown
@ 2011-10-14 10:32         ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-14 10:32 UTC (permalink / raw)
  To: Mark Brown
  Cc: jeremy.kerr, paul, linaro-dev, linus.walleij, linux-arm-kernel,
	patches, magnus.damm, linux-kernel, eric.miao, grant.likely,
	dsaxena, tglx, amit.kucheria, linux, arnd.bergmann, sboyd,
	skannan, shawn.guo, Mike Turquette

On Fri, Oct 14, 2011 at 11:05:04AM +0100, Mark Brown wrote:
> On Fri, Oct 14, 2011 at 04:10:26PM +0800, Richard Zhao wrote:
> > On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> 
> snip essentially Mike's entire mail - *please* delete irrelevant quotes
> from your replies, it makes it very much easier to find the new text in
> your mail and is much more friendly to people reading mail on mobile
> devices.
I snip not enough? sorry for that. I'll be carefull.
> 
> > > +static int __clk_enable(struct clk *clk)
> > > +{
> 
> > Could you expose __clk_enable/__clk_disable? I find it hard to implement
> > clk group. clk group means, when a major clk enable/disable, it want a set
> > of other clks enable/disable accordingly.
> 
> Shouldn't this be something the core is implementing?  I'd strongly
> expect that the clock drivers are relatively dumb and delegate all the
> decision making to the core API.  Otherwise it's going to be hard for
> the core to implement any logic that involves working with more than one
> clock like rate change notification, or guarantee that driver requests
> made through the API are satisfied, as the state of the clocks will be
> changing underneath it.
>From my point of view, the first step of generic clk can be, easy to adopt
features of clocks in current mainline git.
Back to the clk group, I have a patch based on Sascha's work. 
http://git.linaro.org/gitweb?p=people/riczhao/linux-2.6.git;a=shortlog;h=refs/heads/imx-clk

Thanks
Richard
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-14 10:32         ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-14 10:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 14, 2011 at 11:05:04AM +0100, Mark Brown wrote:
> On Fri, Oct 14, 2011 at 04:10:26PM +0800, Richard Zhao wrote:
> > On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> 
> snip essentially Mike's entire mail - *please* delete irrelevant quotes
> from your replies, it makes it very much easier to find the new text in
> your mail and is much more friendly to people reading mail on mobile
> devices.
I snip not enough? sorry for that. I'll be carefull.
> 
> > > +static int __clk_enable(struct clk *clk)
> > > +{
> 
> > Could you expose __clk_enable/__clk_disable? I find it hard to implement
> > clk group. clk group means, when a major clk enable/disable, it want a set
> > of other clks enable/disable accordingly.
> 
> Shouldn't this be something the core is implementing?  I'd strongly
> expect that the clock drivers are relatively dumb and delegate all the
> decision making to the core API.  Otherwise it's going to be hard for
> the core to implement any logic that involves working with more than one
> clock like rate change notification, or guarantee that driver requests
> made through the API are satisfied, as the state of the clocks will be
> changing underneath it.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-14 18:14     ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-14 18:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-arm-kernel, jeremy.kerr, broonie, tglx, linus.walleij,
	amit.kucheria, dsaxena, patches, linaro-dev, paul, grant.likely,
	sboyd, shawn.guo, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao, Mike Turquette

On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>  struct clk_hw_ops {
>        int             (*prepare)(struct clk_hw *);
>        void            (*unprepare)(struct clk_hw *);
>        int             (*enable)(struct clk_hw *);
>        void            (*disable)(struct clk_hw *);
>        unsigned long   (*recalc_rate)(struct clk_hw *);

In implementing recalc for divider clocks, I started to wonder, "why
not just pass struct clk *clk into the clk_hw_ops func ptrs?".

recalc is an obvious example whereby we need access to parent->rate.
The code usually ends up looking something like:

unsigned long omap_recalc_rate(struct clk_hw *hw)
{
        struct clk *parent;
        struct clk_hw_omap *oclk;

        parent = hw->clk->parent;
        oclk = to_clk_omap(hw);
        ...
}

That's a bit of a song and dance to have to do in almost every op, and
often these ops will need access to stuff like clk->rate also.   Is
there any opposition to just passing in struct clk?  e.g:

unsigned long omap_recalc_rate(struct clk *clk)
{
        struct clk *parent;
        struct clk_hw_omap *oclk;

        parent = clk->parent;
        oclk = to_clk_omap(clk->hw);
        ...
}

It is a small nitpick, but it affects the API for everybody so best to
get it right now before folks start migrating over to it.

Thanks,
Mike

>        int             (*set_rate)(struct clk_hw *,
>                                        unsigned long, unsigned long *);
>        long            (*round_rate)(struct clk_hw *, unsigned long);
>        int             (*set_parent)(struct clk_hw *, struct clk *);
>        struct clk *    (*get_parent)(struct clk_hw *);
>  };

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-14 18:14     ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-14 18:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> ?struct clk_hw_ops {
> ? ? ? ?int ? ? ? ? ? ? (*prepare)(struct clk_hw *);
> ? ? ? ?void ? ? ? ? ? ?(*unprepare)(struct clk_hw *);
> ? ? ? ?int ? ? ? ? ? ? (*enable)(struct clk_hw *);
> ? ? ? ?void ? ? ? ? ? ?(*disable)(struct clk_hw *);
> ? ? ? ?unsigned long ? (*recalc_rate)(struct clk_hw *);

In implementing recalc for divider clocks, I started to wonder, "why
not just pass struct clk *clk into the clk_hw_ops func ptrs?".

recalc is an obvious example whereby we need access to parent->rate.
The code usually ends up looking something like:

unsigned long omap_recalc_rate(struct clk_hw *hw)
{
        struct clk *parent;
        struct clk_hw_omap *oclk;

        parent = hw->clk->parent;
        oclk = to_clk_omap(hw);
        ...
}

That's a bit of a song and dance to have to do in almost every op, and
often these ops will need access to stuff like clk->rate also.   Is
there any opposition to just passing in struct clk?  e.g:

unsigned long omap_recalc_rate(struct clk *clk)
{
        struct clk *parent;
        struct clk_hw_omap *oclk;

        parent = clk->parent;
        oclk = to_clk_omap(clk->hw);
        ...
}

It is a small nitpick, but it affects the API for everybody so best to
get it right now before folks start migrating over to it.

Thanks,
Mike

> ? ? ? ?int ? ? ? ? ? ? (*set_rate)(struct clk_hw *,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long, unsigned long *);
> ? ? ? ?long ? ? ? ? ? ?(*round_rate)(struct clk_hw *, unsigned long);
> ? ? ? ?int ? ? ? ? ? ? (*set_parent)(struct clk_hw *, struct clk *);
> ? ? ? ?struct clk * ? ?(*get_parent)(struct clk_hw *);
> ?};

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-14 18:14     ` Turquette, Mike
@ 2011-10-15  2:24       ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-15  2:24 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches, broonie,
	magnus.damm, amit.kucheria, linux, grant.likely, dsaxena,
	eric.miao, shawn.guo, skannan, sboyd, jeremy.kerr, tglx,
	linux-arm-kernel, arnd.bergmann

On Fri, Oct 14, 2011 at 11:14:19AM -0700, Turquette, Mike wrote:
> On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
> > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> >  struct clk_hw_ops {
> >        int             (*prepare)(struct clk_hw *);
> >        void            (*unprepare)(struct clk_hw *);
> >        int             (*enable)(struct clk_hw *);
> >        void            (*disable)(struct clk_hw *);
> >        unsigned long   (*recalc_rate)(struct clk_hw *);
> 
> In implementing recalc for divider clocks, I started to wonder, "why
> not just pass struct clk *clk into the clk_hw_ops func ptrs?".
> 
> recalc is an obvious example whereby we need access to parent->rate.
> The code usually ends up looking something like:
> 
> unsigned long omap_recalc_rate(struct clk_hw *hw)
> {
>         struct clk *parent;
>         struct clk_hw_omap *oclk;
> 
>         parent = hw->clk->parent;
clk drivers can not see struct clk details. I use clk_get_parent.
>         oclk = to_clk_omap(hw);
>         ...
> }
> 
> That's a bit of a song and dance to have to do in almost every op, and
> often these ops will need access to stuff like clk->rate also.   Is
> there any opposition to just passing in struct clk?  e.g:
> 
> unsigned long omap_recalc_rate(struct clk *clk)
> {
>         struct clk *parent;
>         struct clk_hw_omap *oclk;
> 
>         parent = clk->parent;
>         oclk = to_clk_omap(clk->hw);
>         ...
> }
In my understanding, struct clk stores things specific to clk core,
struct clk_hw stores common things needed by clk drivers. For static clk driver
there' some problems:
 - For clocks without mux, I need duplicate a  .parent and set .get_parent.
   Even when we adopt DT and dynamicly create clk, it's still a problem.
   Moving .parent to clk_hw can fix it.
 - When I define a clk array, I don't need to find another place to store .ops.
   It's not problem for dynamic creating clock.
 - As I mentioned in another mail, clk group need no lock version prepare/unprepare
   and enable/disable functions
   Another way is, add a "{struct clk_hw *clks; int count}" in clk_hw, let clk
   core handle it.
   I prefer the second way, but I'm not sure whether it's common enough. It's
   still a problem for dynamic creating clock.

Thanks
Richard
> 
> It is a small nitpick, but it affects the API for everybody so best to
> get it right now before folks start migrating over to it.
> 
> Thanks,
> Mike
> 
> >        int             (*set_rate)(struct clk_hw *,
> >                                        unsigned long, unsigned long *);
> >        long            (*round_rate)(struct clk_hw *, unsigned long);
> >        int             (*set_parent)(struct clk_hw *, struct clk *);
> >        struct clk *    (*get_parent)(struct clk_hw *);
> >  };
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-15  2:24       ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-15  2:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 14, 2011 at 11:14:19AM -0700, Turquette, Mike wrote:
> On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
> > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > ?struct clk_hw_ops {
> > ? ? ? ?int ? ? ? ? ? ? (*prepare)(struct clk_hw *);
> > ? ? ? ?void ? ? ? ? ? ?(*unprepare)(struct clk_hw *);
> > ? ? ? ?int ? ? ? ? ? ? (*enable)(struct clk_hw *);
> > ? ? ? ?void ? ? ? ? ? ?(*disable)(struct clk_hw *);
> > ? ? ? ?unsigned long ? (*recalc_rate)(struct clk_hw *);
> 
> In implementing recalc for divider clocks, I started to wonder, "why
> not just pass struct clk *clk into the clk_hw_ops func ptrs?".
> 
> recalc is an obvious example whereby we need access to parent->rate.
> The code usually ends up looking something like:
> 
> unsigned long omap_recalc_rate(struct clk_hw *hw)
> {
>         struct clk *parent;
>         struct clk_hw_omap *oclk;
> 
>         parent = hw->clk->parent;
clk drivers can not see struct clk details. I use clk_get_parent.
>         oclk = to_clk_omap(hw);
>         ...
> }
> 
> That's a bit of a song and dance to have to do in almost every op, and
> often these ops will need access to stuff like clk->rate also.   Is
> there any opposition to just passing in struct clk?  e.g:
> 
> unsigned long omap_recalc_rate(struct clk *clk)
> {
>         struct clk *parent;
>         struct clk_hw_omap *oclk;
> 
>         parent = clk->parent;
>         oclk = to_clk_omap(clk->hw);
>         ...
> }
In my understanding, struct clk stores things specific to clk core,
struct clk_hw stores common things needed by clk drivers. For static clk driver
there' some problems:
 - For clocks without mux, I need duplicate a  .parent and set .get_parent.
   Even when we adopt DT and dynamicly create clk, it's still a problem.
   Moving .parent to clk_hw can fix it.
 - When I define a clk array, I don't need to find another place to store .ops.
   It's not problem for dynamic creating clock.
 - As I mentioned in another mail, clk group need no lock version prepare/unprepare
   and enable/disable functions
   Another way is, add a "{struct clk_hw *clks; int count}" in clk_hw, let clk
   core handle it.
   I prefer the second way, but I'm not sure whether it's common enough. It's
   still a problem for dynamic creating clock.

Thanks
Richard
> 
> It is a small nitpick, but it affects the API for everybody so best to
> get it right now before folks start migrating over to it.
> 
> Thanks,
> Mike
> 
> > ? ? ? ?int ? ? ? ? ? ? (*set_rate)(struct clk_hw *,
> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long, unsigned long *);
> > ? ? ? ?long ? ? ? ? ? ?(*round_rate)(struct clk_hw *, unsigned long);
> > ? ? ? ?int ? ? ? ? ? ? (*set_parent)(struct clk_hw *, struct clk *);
> > ? ? ? ?struct clk * ? ?(*get_parent)(struct clk_hw *);
> > ?};
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-15  2:24       ` Richard Zhao
@ 2011-10-15  2:34         ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-15  2:34 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: linux-arm-kernel, paul, linaro-dev, linus.walleij, patches,
	sboyd, broonie, magnus.damm, linux-kernel, amit.kucheria,
	grant.likely, dsaxena, tglx, eric.miao, linux, skannan,
	jeremy.kerr, shawn.guo, arnd.bergmann

>  - When I define a clk array, I don't need to find another place to store .ops.
                                  ^^^^^
remove "don't". sorry for that.
 


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-15  2:34         ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-15  2:34 UTC (permalink / raw)
  To: linux-arm-kernel

>  - When I define a clk array, I don't need to find another place to store .ops.
                                  ^^^^^
remove "don't". sorry for that.
 

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-14 10:32         ` Richard Zhao
@ 2011-10-16 17:55           ` Sascha Hauer
  -1 siblings, 0 replies; 144+ messages in thread
From: Sascha Hauer @ 2011-10-16 17:55 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Mark Brown, paul, linaro-dev, linus.walleij, patches, shawn.guo,
	magnus.damm, linux-kernel, eric.miao, grant.likely, dsaxena,
	amit.kucheria, skannan, linux, jeremy.kerr, sboyd,
	Mike Turquette, tglx, linux-arm-kernel, arnd.bergmann

On Fri, Oct 14, 2011 at 06:32:33PM +0800, Richard Zhao wrote:
> On Fri, Oct 14, 2011 at 11:05:04AM +0100, Mark Brown wrote:
> > On Fri, Oct 14, 2011 at 04:10:26PM +0800, Richard Zhao wrote:
> > > On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> > 
> > snip essentially Mike's entire mail - *please* delete irrelevant quotes
> > from your replies, it makes it very much easier to find the new text in
> > your mail and is much more friendly to people reading mail on mobile
> > devices.
> I snip not enough? sorry for that. I'll be carefull.
> > 
> > > > +static int __clk_enable(struct clk *clk)
> > > > +{
> > 
> > > Could you expose __clk_enable/__clk_disable? I find it hard to implement
> > > clk group. clk group means, when a major clk enable/disable, it want a set
> > > of other clks enable/disable accordingly.
> > 
> > Shouldn't this be something the core is implementing?  I'd strongly
> > expect that the clock drivers are relatively dumb and delegate all the
> > decision making to the core API.  Otherwise it's going to be hard for
> > the core to implement any logic that involves working with more than one
> > clock like rate change notification, or guarantee that driver requests
> > made through the API are satisfied, as the state of the clocks will be
> > changing underneath it.
> From my point of view, the first step of generic clk can be, easy to adopt
> features of clocks in current mainline git.
> Back to the clk group, I have a patch based on Sascha's work. 
> http://git.linaro.org/gitweb?p=people/riczhao/linux-2.6.git;a=shortlog;h=refs/heads/imx-clk

I thought further about this and a clock group is not something we want
to have at all. Clocks are supposed to be arranged in a tree and
grouping clocks together violates this which leads to problems.
This grouping should be done at driver level, so when a driver needs
more than one clock it should request them all, maybe with a clk_get_all
helper function.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-16 17:55           ` Sascha Hauer
  0 siblings, 0 replies; 144+ messages in thread
From: Sascha Hauer @ 2011-10-16 17:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 14, 2011 at 06:32:33PM +0800, Richard Zhao wrote:
> On Fri, Oct 14, 2011 at 11:05:04AM +0100, Mark Brown wrote:
> > On Fri, Oct 14, 2011 at 04:10:26PM +0800, Richard Zhao wrote:
> > > On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> > 
> > snip essentially Mike's entire mail - *please* delete irrelevant quotes
> > from your replies, it makes it very much easier to find the new text in
> > your mail and is much more friendly to people reading mail on mobile
> > devices.
> I snip not enough? sorry for that. I'll be carefull.
> > 
> > > > +static int __clk_enable(struct clk *clk)
> > > > +{
> > 
> > > Could you expose __clk_enable/__clk_disable? I find it hard to implement
> > > clk group. clk group means, when a major clk enable/disable, it want a set
> > > of other clks enable/disable accordingly.
> > 
> > Shouldn't this be something the core is implementing?  I'd strongly
> > expect that the clock drivers are relatively dumb and delegate all the
> > decision making to the core API.  Otherwise it's going to be hard for
> > the core to implement any logic that involves working with more than one
> > clock like rate change notification, or guarantee that driver requests
> > made through the API are satisfied, as the state of the clocks will be
> > changing underneath it.
> From my point of view, the first step of generic clk can be, easy to adopt
> features of clocks in current mainline git.
> Back to the clk group, I have a patch based on Sascha's work. 
> http://git.linaro.org/gitweb?p=people/riczhao/linux-2.6.git;a=shortlog;h=refs/heads/imx-clk

I thought further about this and a clock group is not something we want
to have at all. Clocks are supposed to be arranged in a tree and
grouping clocks together violates this which leads to problems.
This grouping should be done at driver level, so when a driver needs
more than one clock it should request them all, maybe with a clk_get_all
helper function.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-10-12 14:59       ` Turquette, Mike
@ 2011-10-16 18:26         ` Sascha Hauer
  -1 siblings, 0 replies; 144+ messages in thread
From: Sascha Hauer @ 2011-10-16 18:26 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Richard Zhao, jeremy.kerr, paul, linaro-dev, linus.walleij,
	patches, broonie, magnus.damm, linux-kernel, eric.miao, linux,
	grant.likely, dsaxena, tglx, amit.kucheria, skannan, Jamie Iles,
	arnd.bergmann, sboyd, richard.zhao, shawn.guo, linux-arm-kernel

On Wed, Oct 12, 2011 at 07:59:19AM -0700, Turquette, Mike wrote:
> On Tue, Oct 11, 2011 at 11:46 PM, Richard Zhao
> <richard.zhao@freescale.com> wrote:
> > On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> >> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> >>
> >> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> >> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> >> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> >> Signed-off-by: Mike Turquette <mturquette@ti.com>
> >> ---
> >> Changes since v1:
> >> Add copyright header
> >> Fold in Jamie's patch for set-to-disable clks
> >> Use BIT macro instead of shift
> >>
> >>  drivers/clk/Kconfig    |    4 ++
> >>  drivers/clk/Makefile   |    1 +
> >>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
> >>  include/linux/clk.h    |   13 ++++++++
> >>  4 files changed, 96 insertions(+), 0 deletions(-)
> >>  create mode 100644 drivers/clk/clk-gate.c
> >
> > I feel hard to tell the tree the clk parent, at register/init time. For the
> > simple gate clk, the only way is to set .get_parent. But normally, for clk
> > without any divider we set .get_parent to NULL. Maybe we can put .parent to
> > struct clk_hw?
> 
> For non-mux clocks, whose parent is *always* going to be the same, you
> should create a duplicate .parent in the clk_hw_* structure and then
> have .get_parent return clk_hw_*->parent.

Maybe I do not understand what you mean here, but I think there is
something missing in the gate.

> 
> This is analogous to the way clk_hw_fixed returns clk_hw_fixed->rate
> when .recalc is called on it.
> 
> >> +
> >> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> >> +{
> >> +     return clk_get_rate(clk_get_parent(clk->clk));
> >> +}

clk_get_parent goes down to clk_gate_set_enable_ops.get_parent below...

> >> +
> >> +
> >> +struct clk_hw_ops clk_gate_set_enable_ops = {
> >> +     .recalc_rate = clk_gate_get_rate,
> >> +     .enable = clk_gate_enable_set,
> >> +     .disable = clk_gate_disable_clear,
> >> +};

...but this does not have a get_parent pointer, so clk_get_parent()
for a gate always returns NULL which means that a gate never has
a valid rate.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-10-16 18:26         ` Sascha Hauer
  0 siblings, 0 replies; 144+ messages in thread
From: Sascha Hauer @ 2011-10-16 18:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 12, 2011 at 07:59:19AM -0700, Turquette, Mike wrote:
> On Tue, Oct 11, 2011 at 11:46 PM, Richard Zhao
> <richard.zhao@freescale.com> wrote:
> > On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> >> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> >>
> >> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> >> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> >> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> >> Signed-off-by: Mike Turquette <mturquette@ti.com>
> >> ---
> >> Changes since v1:
> >> Add copyright header
> >> Fold in Jamie's patch for set-to-disable clks
> >> Use BIT macro instead of shift
> >>
> >> ?drivers/clk/Kconfig ? ?| ? ?4 ++
> >> ?drivers/clk/Makefile ? | ? ?1 +
> >> ?drivers/clk/clk-gate.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++++
> >> ?include/linux/clk.h ? ?| ? 13 ++++++++
> >> ?4 files changed, 96 insertions(+), 0 deletions(-)
> >> ?create mode 100644 drivers/clk/clk-gate.c
> >
> > I feel hard to tell the tree the clk parent, at register/init time. For the
> > simple gate clk, the only way is to set .get_parent. But normally, for clk
> > without any divider we set .get_parent to NULL. Maybe we can put .parent to
> > struct clk_hw?
> 
> For non-mux clocks, whose parent is *always* going to be the same, you
> should create a duplicate .parent in the clk_hw_* structure and then
> have .get_parent return clk_hw_*->parent.

Maybe I do not understand what you mean here, but I think there is
something missing in the gate.

> 
> This is analogous to the way clk_hw_fixed returns clk_hw_fixed->rate
> when .recalc is called on it.
> 
> >> +
> >> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> >> +{
> >> + ? ? return clk_get_rate(clk_get_parent(clk->clk));
> >> +}

clk_get_parent goes down to clk_gate_set_enable_ops.get_parent below...

> >> +
> >> +
> >> +struct clk_hw_ops clk_gate_set_enable_ops = {
> >> + ? ? .recalc_rate = clk_gate_get_rate,
> >> + ? ? .enable = clk_gate_enable_set,
> >> + ? ? .disable = clk_gate_disable_clear,
> >> +};

...but this does not have a get_parent pointer, so clk_get_parent()
for a gate always returns NULL which means that a gate never has
a valid rate.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-15  2:24       ` Richard Zhao
@ 2011-10-16 21:17         ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-16 21:17 UTC (permalink / raw)
  To: Richard Zhao
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches, broonie,
	magnus.damm, amit.kucheria, linux, grant.likely, dsaxena,
	eric.miao, shawn.guo, skannan, sboyd, jeremy.kerr, tglx,
	linux-arm-kernel, arnd.bergmann

On Fri, Oct 14, 2011 at 7:24 PM, Richard Zhao <richard.zhao@linaro.org> wrote:
> On Fri, Oct 14, 2011 at 11:14:19AM -0700, Turquette, Mike wrote:
>> On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
>> unsigned long omap_recalc_rate(struct clk_hw *hw)
>> {
>>         struct clk *parent;
>>         struct clk_hw_omap *oclk;
>>
>>         parent = hw->clk->parent;
> clk drivers can not see struct clk details. I use clk_get_parent.

clk_get_parent should query the hardware to see what the parent is.
This can have undesireable overhead.  It is quite acceptable to
reference a clock's parent through clk->parent, just as it is
acceptable to get a clock rate through clk->rate.

An analogous situation is a clk_get_rate call which uses a clk's
.recalc.  There is undesirable overhead involved in .recalc for clocks
whose rates won't change behind our backs, so best to just treat the
data in struct clk as cache and reference it directly.

>>         oclk = to_clk_omap(hw);
>>         ...
>> }
>>
...
>>
>> unsigned long omap_recalc_rate(struct clk *clk)
>> {
>>         struct clk *parent;
>>         struct clk_hw_omap *oclk;
>>
>>         parent = clk->parent;
>>         oclk = to_clk_omap(clk->hw);
>>         ...
>> }
> In my understanding, struct clk stores things specific to clk core,
> struct clk_hw stores common things needed by clk drivers. For static clk driver
> there' some problems:
>  - For clocks without mux, I need duplicate a  .parent and set .get_parent.
>   Even when we adopt DT and dynamicly create clk, it's still a problem.
>   Moving .parent to clk_hw can fix it.

For clocks with a fixed parent we should just pass it in at
register-time.  We should definitely not move .parent out of struct
clk, since struct clk should be the platform agnostic bit that lets us
do tree walks, build topology, etc etc.

If you really want a .parent outside of struct clk then duplicate it
in your struct clk_hw_imx and teach your .ops about it (analogous to
struct clk_hw_fixed->rate).

>  - When I define a clk array, I don't need to find another place to store .ops.
>   It's not problem for dynamic creating clock.

Something like the following?

static struct clk aess_fclk;

static const clk_hw_ops aess_fclk_ops = {
        .recalc = &omap2_clksel_recalc,
        .round_rate = &omap2_clksel_round_rate,
        .set_rate = &omap2_clksel_set_rate,
};

static struct clk_hw_omap aess_fclk_hw = {
        .hw = {
                .clk = &aess_fclk,
        },
        .clksel = &aess_fclk_div,
        .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
        .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
};

static struct clk aess_fclk = {
        .name = "aess_fclk",
        .ops = &aess_fclk_ops,
        .hw = &aess_fclk_hw.hw,
        .parent = &abe_clk,
};

>  - As I mentioned in another mail, clk group need no lock version prepare/unprepare
>   and enable/disable functions

Clock groups are out of scope for this first series.  We should
discuss more what the needs are for your clock groups.  If it boils
down to just enabling all of the clocks for a given device then you
might want to abstract that away with pm_runtime_* calls, and maybe a
supplementary layer like OMAP's hwmod.  But I might be way off base, I
really don't understand your use case for clock groups.

>   Another way is, add a "{struct clk_hw *clks; int count}" in clk_hw, let clk
>   core handle it.
>   I prefer the second way, but I'm not sure whether it's common enough. It's
>   still a problem for dynamic creating clock.

struct clk_hw is just a pointer for navigating from struct clk ->
struct your_custom_clk and vice versa.  Again can you elaborate on
your needs for managing multiple clocks with a single struct clk_hw?

Thanks,
Mike

>
> Thanks
> Richard
>>
>> It is a small nitpick, but it affects the API for everybody so best to
>> get it right now before folks start migrating over to it.
>>
>> Thanks,
>> Mike
>>
>> >        int             (*set_rate)(struct clk_hw *,
>> >                                        unsigned long, unsigned long *);
>> >        long            (*round_rate)(struct clk_hw *, unsigned long);
>> >        int             (*set_parent)(struct clk_hw *, struct clk *);
>> >        struct clk *    (*get_parent)(struct clk_hw *);
>> >  };
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-16 21:17         ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-16 21:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 14, 2011 at 7:24 PM, Richard Zhao <richard.zhao@linaro.org> wrote:
> On Fri, Oct 14, 2011 at 11:14:19AM -0700, Turquette, Mike wrote:
>> On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
>> unsigned long omap_recalc_rate(struct clk_hw *hw)
>> {
>> ? ? ? ? struct clk *parent;
>> ? ? ? ? struct clk_hw_omap *oclk;
>>
>> ? ? ? ? parent = hw->clk->parent;
> clk drivers can not see struct clk details. I use clk_get_parent.

clk_get_parent should query the hardware to see what the parent is.
This can have undesireable overhead.  It is quite acceptable to
reference a clock's parent through clk->parent, just as it is
acceptable to get a clock rate through clk->rate.

An analogous situation is a clk_get_rate call which uses a clk's
.recalc.  There is undesirable overhead involved in .recalc for clocks
whose rates won't change behind our backs, so best to just treat the
data in struct clk as cache and reference it directly.

>> ? ? ? ? oclk = to_clk_omap(hw);
>> ? ? ? ? ...
>> }
>>
...
>>
>> unsigned long omap_recalc_rate(struct clk *clk)
>> {
>> ? ? ? ? struct clk *parent;
>> ? ? ? ? struct clk_hw_omap *oclk;
>>
>> ? ? ? ? parent = clk->parent;
>> ? ? ? ? oclk = to_clk_omap(clk->hw);
>> ? ? ? ? ...
>> }
> In my understanding, struct clk stores things specific to clk core,
> struct clk_hw stores common things needed by clk drivers. For static clk driver
> there' some problems:
> ?- For clocks without mux, I need duplicate a ?.parent and set .get_parent.
> ? Even when we adopt DT and dynamicly create clk, it's still a problem.
> ? Moving .parent to clk_hw can fix it.

For clocks with a fixed parent we should just pass it in at
register-time.  We should definitely not move .parent out of struct
clk, since struct clk should be the platform agnostic bit that lets us
do tree walks, build topology, etc etc.

If you really want a .parent outside of struct clk then duplicate it
in your struct clk_hw_imx and teach your .ops about it (analogous to
struct clk_hw_fixed->rate).

> ?- When I define a clk array, I don't need to find another place to store .ops.
> ? It's not problem for dynamic creating clock.

Something like the following?

static struct clk aess_fclk;

static const clk_hw_ops aess_fclk_ops = {
        .recalc = &omap2_clksel_recalc,
        .round_rate = &omap2_clksel_round_rate,
        .set_rate = &omap2_clksel_set_rate,
};

static struct clk_hw_omap aess_fclk_hw = {
        .hw = {
                .clk = &aess_fclk,
        },
        .clksel = &aess_fclk_div,
        .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
        .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
};

static struct clk aess_fclk = {
        .name = "aess_fclk",
        .ops = &aess_fclk_ops,
        .hw = &aess_fclk_hw.hw,
        .parent = &abe_clk,
};

> ?- As I mentioned in another mail, clk group need no lock version prepare/unprepare
> ? and enable/disable functions

Clock groups are out of scope for this first series.  We should
discuss more what the needs are for your clock groups.  If it boils
down to just enabling all of the clocks for a given device then you
might want to abstract that away with pm_runtime_* calls, and maybe a
supplementary layer like OMAP's hwmod.  But I might be way off base, I
really don't understand your use case for clock groups.

> ? Another way is, add a "{struct clk_hw *clks; int count}" in clk_hw, let clk
> ? core handle it.
> ? I prefer the second way, but I'm not sure whether it's common enough. It's
> ? still a problem for dynamic creating clock.

struct clk_hw is just a pointer for navigating from struct clk ->
struct your_custom_clk and vice versa.  Again can you elaborate on
your needs for managing multiple clocks with a single struct clk_hw?

Thanks,
Mike

>
> Thanks
> Richard
>>
>> It is a small nitpick, but it affects the API for everybody so best to
>> get it right now before folks start migrating over to it.
>>
>> Thanks,
>> Mike
>>
>> > ? ? ? ?int ? ? ? ? ? ? (*set_rate)(struct clk_hw *,
>> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long, unsigned long *);
>> > ? ? ? ?long ? ? ? ? ? ?(*round_rate)(struct clk_hw *, unsigned long);
>> > ? ? ? ?int ? ? ? ? ? ? (*set_parent)(struct clk_hw *, struct clk *);
>> > ? ? ? ?struct clk * ? ?(*get_parent)(struct clk_hw *);
>> > ?};
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-10-16 18:26         ` Sascha Hauer
@ 2011-10-17  6:42           ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-17  6:42 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Turquette, Mike, linaro-dev, eric.miao, grant.likely, Jamie Iles,
	jeremy.kerr, sboyd, linux, magnus.damm, dsaxena, shawn.guo,
	arnd.bergmann, patches, tglx, linux-arm-kernel, paul,
	linus.walleij, broonie, linux-kernel, amit.kucheria,
	Richard Zhao, skannan

On Sun, Oct 16, 2011 at 08:26:49PM +0200, Sascha Hauer wrote:
> On Wed, Oct 12, 2011 at 07:59:19AM -0700, Turquette, Mike wrote:
> > On Tue, Oct 11, 2011 at 11:46 PM, Richard Zhao
> > <richard.zhao@freescale.com> wrote:
> > > On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> > >> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > >>
> > >> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> > >> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > >> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> > >> Signed-off-by: Mike Turquette <mturquette@ti.com>
> > >> ---
> > >> Changes since v1:
> > >> Add copyright header
> > >> Fold in Jamie's patch for set-to-disable clks
> > >> Use BIT macro instead of shift
> > >>
> > >>  drivers/clk/Kconfig    |    4 ++
> > >>  drivers/clk/Makefile   |    1 +
> > >>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
> > >>  include/linux/clk.h    |   13 ++++++++
> > >>  4 files changed, 96 insertions(+), 0 deletions(-)
> > >>  create mode 100644 drivers/clk/clk-gate.c
> > >
> > > I feel hard to tell the tree the clk parent, at register/init time. For the
> > > simple gate clk, the only way is to set .get_parent. But normally, for clk
> > > without any divider we set .get_parent to NULL. Maybe we can put .parent to
> > > struct clk_hw?
> > 
> > For non-mux clocks, whose parent is *always* going to be the same, you
> > should create a duplicate .parent in the clk_hw_* structure and then
> > have .get_parent return clk_hw_*->parent.
> 
> Maybe I do not understand what you mean here, but I think there is
> something missing in the gate.
yes, clk_gate can not set fixed parent in v2 patch. Mike means add .parent int clk_gate
and set .get_parent in the ops.
> 
> > 
> > This is analogous to the way clk_hw_fixed returns clk_hw_fixed->rate
> > when .recalc is called on it.
> > 
> > >> +
> > >> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> > >> +{
> > >> +     return clk_get_rate(clk_get_parent(clk->clk));
> > >> +}
> 
> clk_get_parent goes down to clk_gate_set_enable_ops.get_parent below...
> 
> > >> +
> > >> +
> > >> +struct clk_hw_ops clk_gate_set_enable_ops = {
> > >> +     .recalc_rate = clk_gate_get_rate,
> > >> +     .enable = clk_gate_enable_set,
> > >> +     .disable = clk_gate_disable_clear,
> > >> +};
> 
> ...but this does not have a get_parent pointer, so clk_get_parent()
> for a gate always returns NULL which means that a gate never has
> a valid rate.
> 
> Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-10-17  6:42           ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-17  6:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 16, 2011 at 08:26:49PM +0200, Sascha Hauer wrote:
> On Wed, Oct 12, 2011 at 07:59:19AM -0700, Turquette, Mike wrote:
> > On Tue, Oct 11, 2011 at 11:46 PM, Richard Zhao
> > <richard.zhao@freescale.com> wrote:
> > > On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
> > >> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > >>
> > >> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> > >> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> > >> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
> > >> Signed-off-by: Mike Turquette <mturquette@ti.com>
> > >> ---
> > >> Changes since v1:
> > >> Add copyright header
> > >> Fold in Jamie's patch for set-to-disable clks
> > >> Use BIT macro instead of shift
> > >>
> > >> ?drivers/clk/Kconfig ? ?| ? ?4 ++
> > >> ?drivers/clk/Makefile ? | ? ?1 +
> > >> ?drivers/clk/clk-gate.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++++
> > >> ?include/linux/clk.h ? ?| ? 13 ++++++++
> > >> ?4 files changed, 96 insertions(+), 0 deletions(-)
> > >> ?create mode 100644 drivers/clk/clk-gate.c
> > >
> > > I feel hard to tell the tree the clk parent, at register/init time. For the
> > > simple gate clk, the only way is to set .get_parent. But normally, for clk
> > > without any divider we set .get_parent to NULL. Maybe we can put .parent to
> > > struct clk_hw?
> > 
> > For non-mux clocks, whose parent is *always* going to be the same, you
> > should create a duplicate .parent in the clk_hw_* structure and then
> > have .get_parent return clk_hw_*->parent.
> 
> Maybe I do not understand what you mean here, but I think there is
> something missing in the gate.
yes, clk_gate can not set fixed parent in v2 patch. Mike means add .parent int clk_gate
and set .get_parent in the ops.
> 
> > 
> > This is analogous to the way clk_hw_fixed returns clk_hw_fixed->rate
> > when .recalc is called on it.
> > 
> > >> +
> > >> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
> > >> +{
> > >> + ? ? return clk_get_rate(clk_get_parent(clk->clk));
> > >> +}
> 
> clk_get_parent goes down to clk_gate_set_enable_ops.get_parent below...
> 
> > >> +
> > >> +
> > >> +struct clk_hw_ops clk_gate_set_enable_ops = {
> > >> + ? ? .recalc_rate = clk_gate_get_rate,
> > >> + ? ? .enable = clk_gate_enable_set,
> > >> + ? ? .disable = clk_gate_disable_clear,
> > >> +};
> 
> ...but this does not have a get_parent pointer, so clk_get_parent()
> for a gate always returns NULL which means that a gate never has
> a valid rate.
> 
> Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-16 17:55           ` Sascha Hauer
@ 2011-10-17  8:48             ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-17  8:48 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: linux-arm-kernel, paul, linaro-dev, linus.walleij, patches,
	Mark Brown, magnus.damm, linux-kernel, eric.miao, grant.likely,
	arnd.bergmann, dsaxena, tglx, amit.kucheria, linux, skannan,
	Mike Turquette, jeremy.kerr, shawn.guo, sboyd

On Sun, Oct 16, 2011 at 07:55:21PM +0200, Sascha Hauer wrote:
> On Fri, Oct 14, 2011 at 06:32:33PM +0800, Richard Zhao wrote:
> > On Fri, Oct 14, 2011 at 11:05:04AM +0100, Mark Brown wrote:
> > > On Fri, Oct 14, 2011 at 04:10:26PM +0800, Richard Zhao wrote:
> > > > On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> > > 
> > > snip essentially Mike's entire mail - *please* delete irrelevant quotes
> > > from your replies, it makes it very much easier to find the new text in
> > > your mail and is much more friendly to people reading mail on mobile
> > > devices.
> > I snip not enough? sorry for that. I'll be carefull.
> > > 
> > > > > +static int __clk_enable(struct clk *clk)
> > > > > +{
> > > 
> > > > Could you expose __clk_enable/__clk_disable? I find it hard to implement
> > > > clk group. clk group means, when a major clk enable/disable, it want a set
> > > > of other clks enable/disable accordingly.
> > > 
> > > Shouldn't this be something the core is implementing?  I'd strongly
> > > expect that the clock drivers are relatively dumb and delegate all the
> > > decision making to the core API.  Otherwise it's going to be hard for
> > > the core to implement any logic that involves working with more than one
> > > clock like rate change notification, or guarantee that driver requests
> > > made through the API are satisfied, as the state of the clocks will be
> > > changing underneath it.
> > From my point of view, the first step of generic clk can be, easy to adopt
> > features of clocks in current mainline git.
> > Back to the clk group, I have a patch based on Sascha's work. 
> > http://git.linaro.org/gitweb?p=people/riczhao/linux-2.6.git;a=shortlog;h=refs/heads/imx-clk
> 
> I thought further about this and a clock group is not something we want
> to have at all. Clocks are supposed to be arranged in a tree and
> grouping clocks together violates this which leads to problems.
> This grouping should be done at driver level, so when a driver needs
> more than one clock it should request them all, maybe with a clk_get_all
> helper function.
clock group is not limited to help driver get clock. It refects clock dependency.
For example, devices that possible access to on-chip RAM, depend on OCRAM clock. 
On imx53, VPU depends on OCRAM clock, even when VPU does not use OCRAM.

Thanks
Richard
> 
> Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-17  8:48             ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-17  8:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 16, 2011 at 07:55:21PM +0200, Sascha Hauer wrote:
> On Fri, Oct 14, 2011 at 06:32:33PM +0800, Richard Zhao wrote:
> > On Fri, Oct 14, 2011 at 11:05:04AM +0100, Mark Brown wrote:
> > > On Fri, Oct 14, 2011 at 04:10:26PM +0800, Richard Zhao wrote:
> > > > On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> > > 
> > > snip essentially Mike's entire mail - *please* delete irrelevant quotes
> > > from your replies, it makes it very much easier to find the new text in
> > > your mail and is much more friendly to people reading mail on mobile
> > > devices.
> > I snip not enough? sorry for that. I'll be carefull.
> > > 
> > > > > +static int __clk_enable(struct clk *clk)
> > > > > +{
> > > 
> > > > Could you expose __clk_enable/__clk_disable? I find it hard to implement
> > > > clk group. clk group means, when a major clk enable/disable, it want a set
> > > > of other clks enable/disable accordingly.
> > > 
> > > Shouldn't this be something the core is implementing?  I'd strongly
> > > expect that the clock drivers are relatively dumb and delegate all the
> > > decision making to the core API.  Otherwise it's going to be hard for
> > > the core to implement any logic that involves working with more than one
> > > clock like rate change notification, or guarantee that driver requests
> > > made through the API are satisfied, as the state of the clocks will be
> > > changing underneath it.
> > From my point of view, the first step of generic clk can be, easy to adopt
> > features of clocks in current mainline git.
> > Back to the clk group, I have a patch based on Sascha's work. 
> > http://git.linaro.org/gitweb?p=people/riczhao/linux-2.6.git;a=shortlog;h=refs/heads/imx-clk
> 
> I thought further about this and a clock group is not something we want
> to have at all. Clocks are supposed to be arranged in a tree and
> grouping clocks together violates this which leads to problems.
> This grouping should be done at driver level, so when a driver needs
> more than one clock it should request them all, maybe with a clk_get_all
> helper function.
clock group is not limited to help driver get clock. It refects clock dependency.
For example, devices that possible access to on-chip RAM, depend on OCRAM clock. 
On imx53, VPU depends on OCRAM clock, even when VPU does not use OCRAM.

Thanks
Richard
> 
> Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-17  8:48             ` Richard Zhao
@ 2011-10-17  9:20               ` Mark Brown
  -1 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-17  9:20 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Sascha Hauer, linux-arm-kernel, paul, linaro-dev, linus.walleij,
	patches, magnus.damm, linux-kernel, eric.miao, grant.likely,
	arnd.bergmann, dsaxena, tglx, amit.kucheria, linux, skannan,
	Mike Turquette, jeremy.kerr, shawn.guo, sboyd

On Mon, Oct 17, 2011 at 04:48:52PM +0800, Richard Zhao wrote:

> For example, devices that possible access to on-chip RAM, depend on OCRAM clock. 
> On imx53, VPU depends on OCRAM clock, even when VPU does not use OCRAM.

So if the VPU depends on OCRAM the VPU should be enabling the OCRAM
clock.  The function of a given clock isn't terribly relevant, and
certainly grouping clocks together doesn't seem to be the obvious
solution from what you've said - if the driver doesn't know about the
clock it seems like the core ought to be enabling it transparently
rather than gluing it together with some other random clock.

Either way the point here is that individual drivers shouldn't be hand
coding this stuff, it should be being handled by core code.

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-17  9:20               ` Mark Brown
  0 siblings, 0 replies; 144+ messages in thread
From: Mark Brown @ 2011-10-17  9:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 17, 2011 at 04:48:52PM +0800, Richard Zhao wrote:

> For example, devices that possible access to on-chip RAM, depend on OCRAM clock. 
> On imx53, VPU depends on OCRAM clock, even when VPU does not use OCRAM.

So if the VPU depends on OCRAM the VPU should be enabling the OCRAM
clock.  The function of a given clock isn't terribly relevant, and
certainly grouping clocks together doesn't seem to be the obvious
solution from what you've said - if the driver doesn't know about the
clock it seems like the core ought to be enabling it transparently
rather than gluing it together with some other random clock.

Either way the point here is that individual drivers shouldn't be hand
coding this stuff, it should be being handled by core code.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-17  9:20               ` Mark Brown
@ 2011-10-17 10:53                 ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-17 10:53 UTC (permalink / raw)
  To: Mark Brown
  Cc: jeremy.kerr, paul, linaro-dev, linus.walleij, patches, shawn.guo,
	Sascha Hauer, magnus.damm, linux-kernel, eric.miao, grant.likely,
	dsaxena, amit.kucheria, skannan, linux, arnd.bergmann, sboyd,
	tglx, linux-arm-kernel, Mike Turquette

On Mon, Oct 17, 2011 at 10:20:28AM +0100, Mark Brown wrote:
> On Mon, Oct 17, 2011 at 04:48:52PM +0800, Richard Zhao wrote:
> 
> > For example, devices that possible access to on-chip RAM, depend on OCRAM clock. 
> > On imx53, VPU depends on OCRAM clock, even when VPU does not use OCRAM.
> 
> So if the VPU depends on OCRAM the VPU should be enabling the OCRAM
> clock.  The function of a given clock isn't terribly relevant, and
> certainly grouping clocks together doesn't seem to be the obvious
> solution from what you've said
VPU don't know OCRAM clk, it's SoC specific. I know it's clock function
replationship. But it's the only better place to refect the dependency 
in clock tree. Another dependency example, from SoC bus topology, some bus
clk always depends on bus switch/hub.
> - if the driver doesn't know about the
> clock it seems like the core ought to be enabling it transparently
> rather than gluing it together with some other random clock.
If you mean clk core here, then we need things like below:
struct clk_hw {
	struct clk *clk;
	struct dependency {
		struct clk_hw *clks;
		int count;
	};
};
Though Mike does not like to add things in clk_hw, but it's the only place
to put common things of clk drivers.

Thanks
Richard
> 
> Either way the point here is that individual drivers shouldn't be hand
> coding this stuff, it should be being handled by core code.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-17 10:53                 ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-17 10:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 17, 2011 at 10:20:28AM +0100, Mark Brown wrote:
> On Mon, Oct 17, 2011 at 04:48:52PM +0800, Richard Zhao wrote:
> 
> > For example, devices that possible access to on-chip RAM, depend on OCRAM clock. 
> > On imx53, VPU depends on OCRAM clock, even when VPU does not use OCRAM.
> 
> So if the VPU depends on OCRAM the VPU should be enabling the OCRAM
> clock.  The function of a given clock isn't terribly relevant, and
> certainly grouping clocks together doesn't seem to be the obvious
> solution from what you've said
VPU don't know OCRAM clk, it's SoC specific. I know it's clock function
replationship. But it's the only better place to refect the dependency 
in clock tree. Another dependency example, from SoC bus topology, some bus
clk always depends on bus switch/hub.
> - if the driver doesn't know about the
> clock it seems like the core ought to be enabling it transparently
> rather than gluing it together with some other random clock.
If you mean clk core here, then we need things like below:
struct clk_hw {
	struct clk *clk;
	struct dependency {
		struct clk_hw *clks;
		int count;
	};
};
Though Mike does not like to add things in clk_hw, but it's the only place
to put common things of clk drivers.

Thanks
Richard
> 
> Either way the point here is that individual drivers shouldn't be hand
> coding this stuff, it should be being handled by core code.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-17 10:53                 ` Richard Zhao
@ 2011-10-17 11:05                   ` Sascha Hauer
  -1 siblings, 0 replies; 144+ messages in thread
From: Sascha Hauer @ 2011-10-17 11:05 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Mark Brown, jeremy.kerr, paul, linaro-dev, linus.walleij,
	patches, shawn.guo, magnus.damm, linux-kernel, eric.miao,
	grant.likely, dsaxena, amit.kucheria, skannan, linux,
	arnd.bergmann, sboyd, tglx, linux-arm-kernel, Mike Turquette

On Mon, Oct 17, 2011 at 06:53:03PM +0800, Richard Zhao wrote:
> On Mon, Oct 17, 2011 at 10:20:28AM +0100, Mark Brown wrote:
> > On Mon, Oct 17, 2011 at 04:48:52PM +0800, Richard Zhao wrote:
> > 
> > > For example, devices that possible access to on-chip RAM, depend on OCRAM clock. 
> > > On imx53, VPU depends on OCRAM clock, even when VPU does not use OCRAM.
> > 
> > So if the VPU depends on OCRAM the VPU should be enabling the OCRAM
> > clock.  The function of a given clock isn't terribly relevant, and
> > certainly grouping clocks together doesn't seem to be the obvious
> > solution from what you've said
> VPU don't know OCRAM clk, it's SoC specific. I know it's clock function
> replationship. But it's the only better place to refect the dependency 
> in clock tree. Another dependency example, from SoC bus topology, some bus
> clk always depends on bus switch/hub.
> > - if the driver doesn't know about the
> > clock it seems like the core ought to be enabling it transparently
> > rather than gluing it together with some other random clock.
> If you mean clk core here, then we need things like below:
> struct clk_hw {
> 	struct clk *clk;
> 	struct dependency {
> 		struct clk_hw *clks;
> 		int count;
> 	};
> };
> Though Mike does not like to add things in clk_hw, but it's the only place
> to put common things of clk drivers.

It's not a problem to associate multiple clocks to a device, we can do
this now already. What a driver can't do now is give-me-all-clocks-I-need(dev),
but this problem should not be solved at clock core level but at the
clkdev level.
The fact is that the different clocks for a device are really different
clocks. A dumb driver may want to request/enable all relevant clocks at
once while a more sophisticated driver may want to enable the clock for
accessing registers in the probe function and a baud clock on device
open time.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-17 11:05                   ` Sascha Hauer
  0 siblings, 0 replies; 144+ messages in thread
From: Sascha Hauer @ 2011-10-17 11:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 17, 2011 at 06:53:03PM +0800, Richard Zhao wrote:
> On Mon, Oct 17, 2011 at 10:20:28AM +0100, Mark Brown wrote:
> > On Mon, Oct 17, 2011 at 04:48:52PM +0800, Richard Zhao wrote:
> > 
> > > For example, devices that possible access to on-chip RAM, depend on OCRAM clock. 
> > > On imx53, VPU depends on OCRAM clock, even when VPU does not use OCRAM.
> > 
> > So if the VPU depends on OCRAM the VPU should be enabling the OCRAM
> > clock.  The function of a given clock isn't terribly relevant, and
> > certainly grouping clocks together doesn't seem to be the obvious
> > solution from what you've said
> VPU don't know OCRAM clk, it's SoC specific. I know it's clock function
> replationship. But it's the only better place to refect the dependency 
> in clock tree. Another dependency example, from SoC bus topology, some bus
> clk always depends on bus switch/hub.
> > - if the driver doesn't know about the
> > clock it seems like the core ought to be enabling it transparently
> > rather than gluing it together with some other random clock.
> If you mean clk core here, then we need things like below:
> struct clk_hw {
> 	struct clk *clk;
> 	struct dependency {
> 		struct clk_hw *clks;
> 		int count;
> 	};
> };
> Though Mike does not like to add things in clk_hw, but it's the only place
> to put common things of clk drivers.

It's not a problem to associate multiple clocks to a device, we can do
this now already. What a driver can't do now is give-me-all-clocks-I-need(dev),
but this problem should not be solved at clock core level but at the
clkdev level.
The fact is that the different clocks for a device are really different
clocks. A dumb driver may want to request/enable all relevant clocks at
once while a more sophisticated driver may want to enable the clock for
accessing registers in the probe function and a baud clock on device
open time.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-17 11:05                   ` Sascha Hauer
@ 2011-10-17 11:30                     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 144+ messages in thread
From: Russell King - ARM Linux @ 2011-10-17 11:30 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Richard Zhao, Mark Brown, jeremy.kerr, paul, linaro-dev,
	linus.walleij, patches, shawn.guo, magnus.damm, linux-kernel,
	eric.miao, grant.likely, dsaxena, amit.kucheria, skannan,
	arnd.bergmann, sboyd, tglx, linux-arm-kernel, Mike Turquette

On Mon, Oct 17, 2011 at 01:05:39PM +0200, Sascha Hauer wrote:
> It's not a problem to associate multiple clocks to a device, we can do
> this now already. What a driver can't do now is give-me-all-clocks-I-need(dev),
> but this problem should not be solved at clock core level but at the
> clkdev level.

I don't think it even needs solving at the clkdev level.

In order to get all clocks for a specific device, we'd need variable
length arrays to store the individual struct clk pointers, which isn't
going to be all that nice.  We'd need clk_get_alldev() and
clk_put_alldev() to deal with these variable length arrays - and as
far as the driver is concerned that's an opaque object - it can't know
anything about any particular individual struct clk in the array.

Then we'd need operations to operate on the array itself, which means
much more API baggage.

Also, if it did need to know about one particular struct clk, then
there's problems with avoiding that struct clk in the alldev() versions
(or we'll see drivers doing clk_get() followed by clk_disable() to
work-around any enabling done via the array versions.)

> The fact is that the different clocks for a device are really different
> clocks. A dumb driver may want to request/enable all relevant clocks at
> once while a more sophisticated driver may want to enable the clock for
> accessing registers in the probe function and a baud clock on device
> open time.

I don't think you can get away from drivers having to know about their
individual clocks in some form or other - and I don't think a dumb
driver should be a justification for creating an API.  If a dumb driver
wants to get the clocks for a device it has to behave as if it were
a smart driver and request each one (maybe having an array itself)
such as this:

static const char *con_ids[NR_CLKS] = {
	"foo",
	"bar",
};

struct driver_priv {
	struct clk *clk[NR_CLKS];
};

	
	for (err = i = 0; i < NR_CLKS; i++) {
		priv->clk[i] = clk_get(dev, con_ids[i];
		if (IS_ERR(priv->clk[i])) {
			err = PTR_ERR(priv->clk[i]);
			break;
		}
	}

	if (err) {
		for (i = 0; i < NR_CLKS && !IS_ERR(priv->clk[i]); i++)
			clk_put(priv->clk[i]);
		return err;
	}

This approach also has the advantage that we know what order the clocks
will be in the array, and so we can sensibly index the array to obtain
a particular clock.

However, going back to the bus fabric case, a driver probably doesn't
have the knowledge - it's a platform topology thing - one which can't
be represented by a clock tree.

It might help if we represented our busses closer to reality - like PCI
does - rather than a flattened set of platform devices.  Couple that with
runtime PM and a driver for the bus fabric, and it should fall out
fairly naturally from the infrastructure we already have.

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-17 11:30                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 144+ messages in thread
From: Russell King - ARM Linux @ 2011-10-17 11:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 17, 2011 at 01:05:39PM +0200, Sascha Hauer wrote:
> It's not a problem to associate multiple clocks to a device, we can do
> this now already. What a driver can't do now is give-me-all-clocks-I-need(dev),
> but this problem should not be solved at clock core level but at the
> clkdev level.

I don't think it even needs solving at the clkdev level.

In order to get all clocks for a specific device, we'd need variable
length arrays to store the individual struct clk pointers, which isn't
going to be all that nice.  We'd need clk_get_alldev() and
clk_put_alldev() to deal with these variable length arrays - and as
far as the driver is concerned that's an opaque object - it can't know
anything about any particular individual struct clk in the array.

Then we'd need operations to operate on the array itself, which means
much more API baggage.

Also, if it did need to know about one particular struct clk, then
there's problems with avoiding that struct clk in the alldev() versions
(or we'll see drivers doing clk_get() followed by clk_disable() to
work-around any enabling done via the array versions.)

> The fact is that the different clocks for a device are really different
> clocks. A dumb driver may want to request/enable all relevant clocks at
> once while a more sophisticated driver may want to enable the clock for
> accessing registers in the probe function and a baud clock on device
> open time.

I don't think you can get away from drivers having to know about their
individual clocks in some form or other - and I don't think a dumb
driver should be a justification for creating an API.  If a dumb driver
wants to get the clocks for a device it has to behave as if it were
a smart driver and request each one (maybe having an array itself)
such as this:

static const char *con_ids[NR_CLKS] = {
	"foo",
	"bar",
};

struct driver_priv {
	struct clk *clk[NR_CLKS];
};

	
	for (err = i = 0; i < NR_CLKS; i++) {
		priv->clk[i] = clk_get(dev, con_ids[i];
		if (IS_ERR(priv->clk[i])) {
			err = PTR_ERR(priv->clk[i]);
			break;
		}
	}

	if (err) {
		for (i = 0; i < NR_CLKS && !IS_ERR(priv->clk[i]); i++)
			clk_put(priv->clk[i]);
		return err;
	}

This approach also has the advantage that we know what order the clocks
will be in the array, and so we can sensibly index the array to obtain
a particular clock.

However, going back to the bus fabric case, a driver probably doesn't
have the knowledge - it's a platform topology thing - one which can't
be represented by a clock tree.

It might help if we represented our busses closer to reality - like PCI
does - rather than a flattened set of platform devices.  Couple that with
runtime PM and a driver for the bus fabric, and it should fall out
fairly naturally from the infrastructure we already have.

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-16 21:17         ` Turquette, Mike
@ 2011-10-17 11:31           ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-17 11:31 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: linux-arm-kernel, paul, linaro-dev, linus.walleij, patches,
	sboyd, broonie, magnus.damm, linux-kernel, amit.kucheria,
	grant.likely, dsaxena, tglx, eric.miao, linux, skannan,
	jeremy.kerr, shawn.guo, arnd.bergmann

On Sun, Oct 16, 2011 at 02:17:29PM -0700, Turquette, Mike wrote:
> On Fri, Oct 14, 2011 at 7:24 PM, Richard Zhao <richard.zhao@linaro.org> wrote:
> > On Fri, Oct 14, 2011 at 11:14:19AM -0700, Turquette, Mike wrote:
> >> On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
> >> unsigned long omap_recalc_rate(struct clk_hw *hw)
> >> {
> >>         struct clk *parent;
> >>         struct clk_hw_omap *oclk;
> >>
> >>         parent = hw->clk->parent;
> > clk drivers can not see struct clk details. I use clk_get_parent.
> 
> clk_get_parent should query the hardware to see what the parent is.
> This can have undesireable overhead.  It is quite acceptable to
> reference a clock's parent through clk->parent, just as it is
> acceptable to get a clock rate through clk->rate.
IMHO, we only need to get parent from hw at register/init time.
clk_get_parent can get it from cache, like current code.
> 
> An analogous situation is a clk_get_rate call which uses a clk's
> .recalc.  There is undesirable overhead involved in .recalc for clocks
> whose rates won't change behind our backs, so best to just treat the
> data in struct clk as cache and reference it directly.
> 
> >>         oclk = to_clk_omap(hw);
> >>         ...
> >> }
> >>
> ...
> >>
> >> unsigned long omap_recalc_rate(struct clk *clk)
> >> {
> >>         struct clk *parent;
> >>         struct clk_hw_omap *oclk;
> >>
> >>         parent = clk->parent;
> >>         oclk = to_clk_omap(clk->hw);
> >>         ...
> >> }
> > In my understanding, struct clk stores things specific to clk core,
> > struct clk_hw stores common things needed by clk drivers. For static clk driver
> > there' some problems:
> >  - For clocks without mux, I need duplicate a  .parent and set .get_parent.
> >   Even when we adopt DT and dynamicly create clk, it's still a problem.
> >   Moving .parent to clk_hw can fix it.
> 
> For clocks with a fixed parent we should just pass it in at
> register-time.  We should definitely not move .parent out of struct
> clk, since struct clk should be the platform agnostic bit that lets us
> do tree walks, build topology, etc etc.
> 
> If you really want a .parent outside of struct clk then duplicate it
> in your struct clk_hw_imx
I don't have clk_hw_imx. I just use generic clks like clk_hw_gate, clk_hw_divider,
clk_hw_mux, and some specific clks.
>  and teach your .ops about it (analogous to
> struct clk_hw_fixed->rate).
I have to define things like below:
stuct pair {
	struct clk_hw *clk = clk_hw_gate.hw;
	struct clk_hw_ops *ops;
};
and use for (.. ) to register the clk array.
> 
> >  - When I define a clk array, I don't need to find another place to store .ops.
> >   It's not problem for dynamic creating clock.
> 
> Something like the following?
> 
> static struct clk aess_fclk;
> 
> static const clk_hw_ops aess_fclk_ops = {
>         .recalc = &omap2_clksel_recalc,
>         .round_rate = &omap2_clksel_round_rate,
>         .set_rate = &omap2_clksel_set_rate,
> };
> 
> static struct clk_hw_omap aess_fclk_hw = {
>         .hw = {
>                 .clk = &aess_fclk,
>         },
>         .clksel = &aess_fclk_div,
>         .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
>         .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
> };
> 
> static struct clk aess_fclk = {
>         .name = "aess_fclk",
>         .ops = &aess_fclk_ops,
>         .hw = &aess_fclk_hw.hw,
>         .parent = &abe_clk,
> };
If we don't protect struct clk members, how about the below:
struct clk_hw_omap aess_fclk = {
	.clk = {
		.name = "aess_fclk",
		.ops = &aess_fclk_ops,
		.parent = &abe_clk,
		};
         .clksel = &aess_fclk_div,
         .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
         .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
};

> 
> >  - As I mentioned in another mail, clk group need no lock version prepare/unprepare
> >   and enable/disable functions
> 
> Clock groups are out of scope for this first series.  We should
> discuss more what the needs are for your clock groups.  If it boils
> down to just enabling all of the clocks for a given device then you
> might want to abstract that away with pm_runtime_* calls, and maybe a
> supplementary layer like OMAP's hwmod.  But I might be way off base, I
> really don't understand your use case for clock groups.
clk group is clk function dependency. I talked about it in another email in this thread.
That's ok to leave it to other framework.
> 
> >   Another way is, add a "{struct clk_hw *clks; int count}" in clk_hw, let clk
> >   core handle it.
> >   I prefer the second way, but I'm not sure whether it's common enough. It's
> >   still a problem for dynamic creating clock.
> 
> struct clk_hw is just a pointer for navigating from struct clk ->
> struct your_custom_clk and vice versa.  Again can you elaborate on
> your needs for managing multiple clocks with a single struct clk_hw?

> 
> Thanks,
> Mike
> 
> >
> > Thanks
> > Richard
> >>
> >> It is a small nitpick, but it affects the API for everybody so best to
> >> get it right now before folks start migrating over to it.
> >>
> >> Thanks,
> >> Mike
> >>
> >> >        int             (*set_rate)(struct clk_hw *,
> >> >                                        unsigned long, unsigned long *);
> >> >        long            (*round_rate)(struct clk_hw *, unsigned long);
> >> >        int             (*set_parent)(struct clk_hw *, struct clk *);
> >> >        struct clk *    (*get_parent)(struct clk_hw *);
> >> >  };
> >>
> >> _______________________________________________
> >> linux-arm-kernel mailing list
> >> linux-arm-kernel@lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >>
> >
> >
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-17 11:31           ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-17 11:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 16, 2011 at 02:17:29PM -0700, Turquette, Mike wrote:
> On Fri, Oct 14, 2011 at 7:24 PM, Richard Zhao <richard.zhao@linaro.org> wrote:
> > On Fri, Oct 14, 2011 at 11:14:19AM -0700, Turquette, Mike wrote:
> >> On Thu, Sep 22, 2011 at 3:26 PM, Mike Turquette <mturquette@ti.com> wrote:
> >> unsigned long omap_recalc_rate(struct clk_hw *hw)
> >> {
> >> ? ? ? ? struct clk *parent;
> >> ? ? ? ? struct clk_hw_omap *oclk;
> >>
> >> ? ? ? ? parent = hw->clk->parent;
> > clk drivers can not see struct clk details. I use clk_get_parent.
> 
> clk_get_parent should query the hardware to see what the parent is.
> This can have undesireable overhead.  It is quite acceptable to
> reference a clock's parent through clk->parent, just as it is
> acceptable to get a clock rate through clk->rate.
IMHO, we only need to get parent from hw at register/init time.
clk_get_parent can get it from cache, like current code.
> 
> An analogous situation is a clk_get_rate call which uses a clk's
> .recalc.  There is undesirable overhead involved in .recalc for clocks
> whose rates won't change behind our backs, so best to just treat the
> data in struct clk as cache and reference it directly.
> 
> >> ? ? ? ? oclk = to_clk_omap(hw);
> >> ? ? ? ? ...
> >> }
> >>
> ...
> >>
> >> unsigned long omap_recalc_rate(struct clk *clk)
> >> {
> >> ? ? ? ? struct clk *parent;
> >> ? ? ? ? struct clk_hw_omap *oclk;
> >>
> >> ? ? ? ? parent = clk->parent;
> >> ? ? ? ? oclk = to_clk_omap(clk->hw);
> >> ? ? ? ? ...
> >> }
> > In my understanding, struct clk stores things specific to clk core,
> > struct clk_hw stores common things needed by clk drivers. For static clk driver
> > there' some problems:
> > ?- For clocks without mux, I need duplicate a ?.parent and set .get_parent.
> > ? Even when we adopt DT and dynamicly create clk, it's still a problem.
> > ? Moving .parent to clk_hw can fix it.
> 
> For clocks with a fixed parent we should just pass it in at
> register-time.  We should definitely not move .parent out of struct
> clk, since struct clk should be the platform agnostic bit that lets us
> do tree walks, build topology, etc etc.
> 
> If you really want a .parent outside of struct clk then duplicate it
> in your struct clk_hw_imx
I don't have clk_hw_imx. I just use generic clks like clk_hw_gate, clk_hw_divider,
clk_hw_mux, and some specific clks.
>  and teach your .ops about it (analogous to
> struct clk_hw_fixed->rate).
I have to define things like below:
stuct pair {
	struct clk_hw *clk = clk_hw_gate.hw;
	struct clk_hw_ops *ops;
};
and use for (.. ) to register the clk array.
> 
> > ?- When I define a clk array, I don't need to find another place to store .ops.
> > ? It's not problem for dynamic creating clock.
> 
> Something like the following?
> 
> static struct clk aess_fclk;
> 
> static const clk_hw_ops aess_fclk_ops = {
>         .recalc = &omap2_clksel_recalc,
>         .round_rate = &omap2_clksel_round_rate,
>         .set_rate = &omap2_clksel_set_rate,
> };
> 
> static struct clk_hw_omap aess_fclk_hw = {
>         .hw = {
>                 .clk = &aess_fclk,
>         },
>         .clksel = &aess_fclk_div,
>         .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
>         .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
> };
> 
> static struct clk aess_fclk = {
>         .name = "aess_fclk",
>         .ops = &aess_fclk_ops,
>         .hw = &aess_fclk_hw.hw,
>         .parent = &abe_clk,
> };
If we don't protect struct clk members, how about the below:
struct clk_hw_omap aess_fclk = {
	.clk = {
		.name = "aess_fclk",
		.ops = &aess_fclk_ops,
		.parent = &abe_clk,
		};
         .clksel = &aess_fclk_div,
         .clksel_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
         .clksel_mask = OMAP4430_CLKSEL_AESS_FCLK_MASK,
};

> 
> > ?- As I mentioned in another mail, clk group need no lock version prepare/unprepare
> > ? and enable/disable functions
> 
> Clock groups are out of scope for this first series.  We should
> discuss more what the needs are for your clock groups.  If it boils
> down to just enabling all of the clocks for a given device then you
> might want to abstract that away with pm_runtime_* calls, and maybe a
> supplementary layer like OMAP's hwmod.  But I might be way off base, I
> really don't understand your use case for clock groups.
clk group is clk function dependency. I talked about it in another email in this thread.
That's ok to leave it to other framework.
> 
> > ? Another way is, add a "{struct clk_hw *clks; int count}" in clk_hw, let clk
> > ? core handle it.
> > ? I prefer the second way, but I'm not sure whether it's common enough. It's
> > ? still a problem for dynamic creating clock.
> 
> struct clk_hw is just a pointer for navigating from struct clk ->
> struct your_custom_clk and vice versa.  Again can you elaborate on
> your needs for managing multiple clocks with a single struct clk_hw?

> 
> Thanks,
> Mike
> 
> >
> > Thanks
> > Richard
> >>
> >> It is a small nitpick, but it affects the API for everybody so best to
> >> get it right now before folks start migrating over to it.
> >>
> >> Thanks,
> >> Mike
> >>
> >> > ? ? ? ?int ? ? ? ? ? ? (*set_rate)(struct clk_hw *,
> >> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned long, unsigned long *);
> >> > ? ? ? ?long ? ? ? ? ? ?(*round_rate)(struct clk_hw *, unsigned long);
> >> > ? ? ? ?int ? ? ? ? ? ? (*set_parent)(struct clk_hw *, struct clk *);
> >> > ? ? ? ?struct clk * ? ?(*get_parent)(struct clk_hw *);
> >> > ?};
> >>
> >> _______________________________________________
> >> linux-arm-kernel mailing list
> >> linux-arm-kernel at lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >>
> >
> >
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

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

* Re: [PATCH v2 4/7] clk: Add simple gated clock
  2011-10-17  6:42           ` Richard Zhao
@ 2011-10-17 17:46             ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-17 17:46 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Sascha Hauer, linaro-dev, eric.miao, grant.likely, Jamie Iles,
	jeremy.kerr, sboyd, linux, magnus.damm, dsaxena, shawn.guo,
	arnd.bergmann, patches, tglx, linux-arm-kernel, paul,
	linus.walleij, broonie, linux-kernel, amit.kucheria,
	Richard Zhao, skannan

On Sun, Oct 16, 2011 at 11:42 PM, Richard Zhao <richard.zhao@linaro.org> wrote:
> On Sun, Oct 16, 2011 at 08:26:49PM +0200, Sascha Hauer wrote:
>> On Wed, Oct 12, 2011 at 07:59:19AM -0700, Turquette, Mike wrote:
>> > On Tue, Oct 11, 2011 at 11:46 PM, Richard Zhao
>> > <richard.zhao@freescale.com> wrote:
>> > > On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
>> > >> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>> > >>
>> > >> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>> > >> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> > >> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
>> > >> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> > >> ---
>> > >> Changes since v1:
>> > >> Add copyright header
>> > >> Fold in Jamie's patch for set-to-disable clks
>> > >> Use BIT macro instead of shift
>> > >>
>> > >>  drivers/clk/Kconfig    |    4 ++
>> > >>  drivers/clk/Makefile   |    1 +
>> > >>  drivers/clk/clk-gate.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++++
>> > >>  include/linux/clk.h    |   13 ++++++++
>> > >>  4 files changed, 96 insertions(+), 0 deletions(-)
>> > >>  create mode 100644 drivers/clk/clk-gate.c
>> > >
>> > > I feel hard to tell the tree the clk parent, at register/init time. For the
>> > > simple gate clk, the only way is to set .get_parent. But normally, for clk
>> > > without any divider we set .get_parent to NULL. Maybe we can put .parent to
>> > > struct clk_hw?
>> >
>> > For non-mux clocks, whose parent is *always* going to be the same, you
>> > should create a duplicate .parent in the clk_hw_* structure and then
>> > have .get_parent return clk_hw_*->parent.
>>
>> Maybe I do not understand what you mean here, but I think there is
>> something missing in the gate.
> yes, clk_gate can not set fixed parent in v2 patch. Mike means add .parent int clk_gate
> and set .get_parent in the ops.

Yes, it seems I was unclear.  I mean to say that a .parent can be
added to any clk hw implementation (clk_hw_imx or whatever) and the
paired .ops (in this case, .get_parent) will know about it's
existence.

Regards,
Mike

>>
>> >
>> > This is analogous to the way clk_hw_fixed returns clk_hw_fixed->rate
>> > when .recalc is called on it.
>> >
>> > >> +
>> > >> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
>> > >> +{
>> > >> +     return clk_get_rate(clk_get_parent(clk->clk));
>> > >> +}
>>
>> clk_get_parent goes down to clk_gate_set_enable_ops.get_parent below...
>>
>> > >> +
>> > >> +
>> > >> +struct clk_hw_ops clk_gate_set_enable_ops = {
>> > >> +     .recalc_rate = clk_gate_get_rate,
>> > >> +     .enable = clk_gate_enable_set,
>> > >> +     .disable = clk_gate_disable_clear,
>> > >> +};
>>
>> ...but this does not have a get_parent pointer, so clk_get_parent()
>> for a gate always returns NULL which means that a gate never has
>> a valid rate.
>>
>> Sascha
>>
>> --
>> Pengutronix e.K.                           |                             |
>> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
>> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
>> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>

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

* [PATCH v2 4/7] clk: Add simple gated clock
@ 2011-10-17 17:46             ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-17 17:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 16, 2011 at 11:42 PM, Richard Zhao <richard.zhao@linaro.org> wrote:
> On Sun, Oct 16, 2011 at 08:26:49PM +0200, Sascha Hauer wrote:
>> On Wed, Oct 12, 2011 at 07:59:19AM -0700, Turquette, Mike wrote:
>> > On Tue, Oct 11, 2011 at 11:46 PM, Richard Zhao
>> > <richard.zhao@freescale.com> wrote:
>> > > On Thu, Sep 22, 2011 at 03:26:59PM -0700, Mike Turquette wrote:
>> > >> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>> > >>
>> > >> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
>> > >> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> > >> Signed-off-by: Jamie Iles <jamie@jamieiles.com>
>> > >> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> > >> ---
>> > >> Changes since v1:
>> > >> Add copyright header
>> > >> Fold in Jamie's patch for set-to-disable clks
>> > >> Use BIT macro instead of shift
>> > >>
>> > >> ?drivers/clk/Kconfig ? ?| ? ?4 ++
>> > >> ?drivers/clk/Makefile ? | ? ?1 +
>> > >> ?drivers/clk/clk-gate.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++++
>> > >> ?include/linux/clk.h ? ?| ? 13 ++++++++
>> > >> ?4 files changed, 96 insertions(+), 0 deletions(-)
>> > >> ?create mode 100644 drivers/clk/clk-gate.c
>> > >
>> > > I feel hard to tell the tree the clk parent, at register/init time. For the
>> > > simple gate clk, the only way is to set .get_parent. But normally, for clk
>> > > without any divider we set .get_parent to NULL. Maybe we can put .parent to
>> > > struct clk_hw?
>> >
>> > For non-mux clocks, whose parent is *always* going to be the same, you
>> > should create a duplicate .parent in the clk_hw_* structure and then
>> > have .get_parent return clk_hw_*->parent.
>>
>> Maybe I do not understand what you mean here, but I think there is
>> something missing in the gate.
> yes, clk_gate can not set fixed parent in v2 patch. Mike means add .parent int clk_gate
> and set .get_parent in the ops.

Yes, it seems I was unclear.  I mean to say that a .parent can be
added to any clk hw implementation (clk_hw_imx or whatever) and the
paired .ops (in this case, .get_parent) will know about it's
existence.

Regards,
Mike

>>
>> >
>> > This is analogous to the way clk_hw_fixed returns clk_hw_fixed->rate
>> > when .recalc is called on it.
>> >
>> > >> +
>> > >> +static unsigned long clk_gate_get_rate(struct clk_hw *clk)
>> > >> +{
>> > >> + ? ? return clk_get_rate(clk_get_parent(clk->clk));
>> > >> +}
>>
>> clk_get_parent goes down to clk_gate_set_enable_ops.get_parent below...
>>
>> > >> +
>> > >> +
>> > >> +struct clk_hw_ops clk_gate_set_enable_ops = {
>> > >> + ? ? .recalc_rate = clk_gate_get_rate,
>> > >> + ? ? .enable = clk_gate_enable_set,
>> > >> + ? ? .disable = clk_gate_disable_clear,
>> > >> +};
>>
>> ...but this does not have a get_parent pointer, so clk_get_parent()
>> for a gate always returns NULL which means that a gate never has
>> a valid rate.
>>
>> Sascha
>>
>> --
>> Pengutronix e.K. ? ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
>> Industrial Linux Solutions ? ? ? ? ? ? ? ? | http://www.pengutronix.de/ ?|
>> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 ? ?|
>> Amtsgericht Hildesheim, HRA 2686 ? ? ? ? ? | Fax: ? +49-5121-206917-5555 |
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
>

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-21  9:00     ` Richard Zhao
  -1 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-21  9:00 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, paul, linaro-dev, linus.walleij, patches,
	eric.miao, broonie, magnus.damm, amit.kucheria, grant.likely,
	dsaxena, arnd.bergmann, shawn.guo, skannan, linux, jeremy.kerr,
	tglx, linux-arm-kernel, sboyd

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> +/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
> + * through other headers; we don't want them used anywhere but here. */
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
change to CONFIG_GENERIC_CLK?
> +extern int __clk_get(struct clk *clk);
> +extern void __clk_put(struct clk *clk);
clk.c does not define it.
> +#endif

Thanks
Richard 


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-21  9:00     ` Richard Zhao
  0 siblings, 0 replies; 144+ messages in thread
From: Richard Zhao @ 2011-10-21  9:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> +/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
> + * through other headers; we don't want them used anywhere but here. */
> +#ifdef CONFIG_USE_COMMON_STRUCT_CLK
change to CONFIG_GENERIC_CLK?
> +extern int __clk_get(struct clk *clk);
> +extern void __clk_put(struct clk *clk);
clk.c does not define it.
> +#endif

Thanks
Richard 

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-23 12:55     ` Shawn Guo
  -1 siblings, 0 replies; 144+ messages in thread
From: Shawn Guo @ 2011-10-23 12:55 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

Hi Mike,

Some random comments/nits ...

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +		const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> +	if (!clk)
> +		return NULL;
> +
> +	INIT_HLIST_HEAD(&clk->children);
> +	INIT_HLIST_NODE(&clk->child_node);
> +
The children and child_node are introduced in patch #2, and should not
be used in patch #1.

> +	clk->name = name;
> +	clk->ops = ops;
> +	clk->hw = hw;
> +	hw->clk = clk;
> +
> +	/* Query the hardware for parent and initial rate */
> +
> +	if (clk->ops->get_parent)
> +		/* We don't to lock against prepare/enable here, as
> +		 * the clock is not yet accessible from anywhere */
/*
 * Multiple line comments
 */

> +		clk->parent = clk->ops->get_parent(clk->hw);
> +
> +	if (clk->ops->recalc_rate)
> +		clk->rate = clk->ops->recalc_rate(clk->hw);
> +
> +
One blank line is good enough.

> +	return clk;
> +}

-- 
Regards,
Shawn


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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-23 12:55     ` Shawn Guo
  0 siblings, 0 replies; 144+ messages in thread
From: Shawn Guo @ 2011-10-23 12:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mike,

Some random comments/nits ...

On Thu, Sep 22, 2011 at 03:26:56PM -0700, Mike Turquette wrote:
> +struct clk *clk_register(const struct clk_hw_ops *ops, struct clk_hw *hw,
> +		const char *name)
> +{
> +	struct clk *clk;
> +
> +	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> +	if (!clk)
> +		return NULL;
> +
> +	INIT_HLIST_HEAD(&clk->children);
> +	INIT_HLIST_NODE(&clk->child_node);
> +
The children and child_node are introduced in patch #2, and should not
be used in patch #1.

> +	clk->name = name;
> +	clk->ops = ops;
> +	clk->hw = hw;
> +	hw->clk = clk;
> +
> +	/* Query the hardware for parent and initial rate */
> +
> +	if (clk->ops->get_parent)
> +		/* We don't to lock against prepare/enable here, as
> +		 * the clock is not yet accessible from anywhere */
/*
 * Multiple line comments
 */

> +		clk->parent = clk->ops->get_parent(clk->hw);
> +
> +	if (clk->ops->recalc_rate)
> +		clk->rate = clk->ops->recalc_rate(clk->hw);
> +
> +
One blank line is good enough.

> +	return clk;
> +}

-- 
Regards,
Shawn

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

* Re: [PATCH v2 2/7] clk: Implement clk_set_rate
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-23 14:24     ` Shawn Guo
  -1 siblings, 0 replies; 144+ messages in thread
From: Shawn Guo @ 2011-10-23 14:24 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Thu, Sep 22, 2011 at 03:26:57PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Implement clk_set_rate by adding a set_rate callback to clk_hw_ops.
> Rates are propagated down the clock tree and recalculated.  Also adds a
> flag for signaling that parents must change rates to achieve the desired
> frequency (upstream propagation).
> 
> TODO:
> Upstream propagation is not yet implemented.
> Device pre-change and post-change notifications are not implemented, but
> are marked up as FIXME comments.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Remove upstream propagation (for now)
> Rename CLK_SET_RATE_PROPAGATE to CLK_PARENT_RATE_CHANGE

[...]

> + * @set_rate	Change the rate of this clock. If this callback returns
> + *		CLK_SET_RATE_PROPAGATE, the rate change will be propagated to

s/CLK_SET_RATE_PROPAGATE/CLK_PARENT_RATE_CHANGE, as suggested by your
change log above?

> + *		the parent clock (which may propagate again). The requested
> + *		rate of the parent is passed back from the callback in the
> + *		second 'unsigned long *' argument.
> + *

-- 
Regards,
Shawn


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

* [PATCH v2 2/7] clk: Implement clk_set_rate
@ 2011-10-23 14:24     ` Shawn Guo
  0 siblings, 0 replies; 144+ messages in thread
From: Shawn Guo @ 2011-10-23 14:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:57PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Implement clk_set_rate by adding a set_rate callback to clk_hw_ops.
> Rates are propagated down the clock tree and recalculated.  Also adds a
> flag for signaling that parents must change rates to achieve the desired
> frequency (upstream propagation).
> 
> TODO:
> Upstream propagation is not yet implemented.
> Device pre-change and post-change notifications are not implemented, but
> are marked up as FIXME comments.
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Remove upstream propagation (for now)
> Rename CLK_SET_RATE_PROPAGATE to CLK_PARENT_RATE_CHANGE

[...]

> + * @set_rate	Change the rate of this clock. If this callback returns
> + *		CLK_SET_RATE_PROPAGATE, the rate change will be propagated to

s/CLK_SET_RATE_PROPAGATE/CLK_PARENT_RATE_CHANGE, as suggested by your
change log above?

> + *		the parent clock (which may propagate again). The requested
> + *		rate of the parent is passed back from the callback in the
> + *		second 'unsigned long *' argument.
> + *

-- 
Regards,
Shawn

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

* Re: [PATCH v2 3/7] clk: Add fixed-rate clock
  2011-09-22 22:26   ` Mike Turquette
@ 2011-10-23 14:30     ` Shawn Guo
  -1 siblings, 0 replies; 144+ messages in thread
From: Shawn Guo @ 2011-10-23 14:30 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Thu, Sep 22, 2011 at 03:26:58PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Add copyright header
> 
>  drivers/clk/Kconfig     |    4 ++++
>  drivers/clk/Makefile    |    1 +
>  drivers/clk/clk-fixed.c |   24 ++++++++++++++++++++++++
>  include/linux/clk.h     |   14 ++++++++++++++
>  4 files changed, 43 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-fixed.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index c53ed59..d8313d7 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -8,3 +8,7 @@ config HAVE_MACH_CLKDEV
>  
>  config GENERIC_CLK
>  	bool
> +
> +config GENERIC_CLK_FIXED
> +	bool
> +	depends on GENERIC_CLK
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 570d5b9..9a3325a 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,3 +1,4 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
> +obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
> diff --git a/drivers/clk/clk-fixed.c b/drivers/clk/clk-fixed.c
> new file mode 100644
> index 0000000..956fb9a
> --- /dev/null
> +++ b/drivers/clk/clk-fixed.c
> @@ -0,0 +1,24 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Simple fixed-rate clock implementation
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +#define to_clk_fixed(c) container_of(c, struct clk_hw_fixed, hw)
> +
> +static unsigned long clk_fixed_recalc_rate(struct clk_hw *hw)
> +{
> +	return to_clk_fixed(hw)->rate;
> +}
> +
> +struct clk_hw_ops clk_fixed_ops = {
> +	.recalc_rate = clk_fixed_recalc_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 0d2cd5e..1903dd8 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -110,6 +110,20 @@ int clk_prepare(struct clk *clk);
>   */
>  void clk_unprepare(struct clk *clk);
>  
> +/* Base clock implementations. Platform clock implementations can use these
> + * directly, or 'subclass' as approprate */
> +
/*
 * Multiple lines comments
 */

Regards,
Shawn

> +#ifdef CONFIG_GENERIC_CLK_FIXED
> +
> +struct clk_hw_fixed {
> +	struct clk_hw	hw;
> +	unsigned long	rate;
> +};
> +
> +extern struct clk_hw_ops clk_fixed_ops;
> +
> +#endif /* CONFIG_GENERIC_CLK_FIXED */
> +
>  /**
>   * clk_register - register and initialize a new clock
>   *
> -- 
> 1.7.4.1
> 
> 


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

* [PATCH v2 3/7] clk: Add fixed-rate clock
@ 2011-10-23 14:30     ` Shawn Guo
  0 siblings, 0 replies; 144+ messages in thread
From: Shawn Guo @ 2011-10-23 14:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Sep 22, 2011 at 03:26:58PM -0700, Mike Turquette wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> ---
> Changes since v1:
> Add copyright header
> 
>  drivers/clk/Kconfig     |    4 ++++
>  drivers/clk/Makefile    |    1 +
>  drivers/clk/clk-fixed.c |   24 ++++++++++++++++++++++++
>  include/linux/clk.h     |   14 ++++++++++++++
>  4 files changed, 43 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-fixed.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index c53ed59..d8313d7 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -8,3 +8,7 @@ config HAVE_MACH_CLKDEV
>  
>  config GENERIC_CLK
>  	bool
> +
> +config GENERIC_CLK_FIXED
> +	bool
> +	depends on GENERIC_CLK
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 570d5b9..9a3325a 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,3 +1,4 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>  obj-$(CONFIG_GENERIC_CLK)	+= clk.o
> +obj-$(CONFIG_GENERIC_CLK_FIXED)	+= clk-fixed.o
> diff --git a/drivers/clk/clk-fixed.c b/drivers/clk/clk-fixed.c
> new file mode 100644
> index 0000000..956fb9a
> --- /dev/null
> +++ b/drivers/clk/clk-fixed.c
> @@ -0,0 +1,24 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Simple fixed-rate clock implementation
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +
> +#define to_clk_fixed(c) container_of(c, struct clk_hw_fixed, hw)
> +
> +static unsigned long clk_fixed_recalc_rate(struct clk_hw *hw)
> +{
> +	return to_clk_fixed(hw)->rate;
> +}
> +
> +struct clk_hw_ops clk_fixed_ops = {
> +	.recalc_rate = clk_fixed_recalc_rate,
> +};
> +EXPORT_SYMBOL_GPL(clk_fixed_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 0d2cd5e..1903dd8 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -110,6 +110,20 @@ int clk_prepare(struct clk *clk);
>   */
>  void clk_unprepare(struct clk *clk);
>  
> +/* Base clock implementations. Platform clock implementations can use these
> + * directly, or 'subclass' as approprate */
> +
/*
 * Multiple lines comments
 */

Regards,
Shawn

> +#ifdef CONFIG_GENERIC_CLK_FIXED
> +
> +struct clk_hw_fixed {
> +	struct clk_hw	hw;
> +	unsigned long	rate;
> +};
> +
> +extern struct clk_hw_ops clk_fixed_ops;
> +
> +#endif /* CONFIG_GENERIC_CLK_FIXED */
> +
>  /**
>   * clk_register - register and initialize a new clock
>   *
> -- 
> 1.7.4.1
> 
> 

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-23 12:55     ` Shawn Guo
@ 2011-10-23 16:49       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-23 16:49 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Sun, Oct 23, 2011 at 5:55 AM, Shawn Guo <shawn.guo@freescale.com> wrote:
> Hi Mike,
>
> Some random comments/nits ...

Thanks for reviewing Shawn.  Will roll changes into V3.

Regards,
Mike

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-23 16:49       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-23 16:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 23, 2011 at 5:55 AM, Shawn Guo <shawn.guo@freescale.com> wrote:
> Hi Mike,
>
> Some random comments/nits ...

Thanks for reviewing Shawn.  Will roll changes into V3.

Regards,
Mike

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

* Re: [PATCH v2 2/7] clk: Implement clk_set_rate
  2011-10-23 14:24     ` Shawn Guo
@ 2011-10-23 16:50       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-23 16:50 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Sun, Oct 23, 2011 at 7:24 AM, Shawn Guo <shawn.guo@freescale.com> wrote:
> On Thu, Sep 22, 2011 at 03:26:57PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> [...]
>
>> + * @set_rate Change the rate of this clock. If this callback returns
>> + *           CLK_SET_RATE_PROPAGATE, the rate change will be propagated to
>
> s/CLK_SET_RATE_PROPAGATE/CLK_PARENT_RATE_CHANGE, as suggested by your
> change log above?

Thanks for reviewing.  Will roll into V3 patchset.

Regards,
Mike

>
>> + *           the parent clock (which may propagate again). The requested
>> + *           rate of the parent is passed back from the callback in the
>> + *           second 'unsigned long *' argument.
>> + *
>
> --
> Regards,
> Shawn
>
>

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

* [PATCH v2 2/7] clk: Implement clk_set_rate
@ 2011-10-23 16:50       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-23 16:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 23, 2011 at 7:24 AM, Shawn Guo <shawn.guo@freescale.com> wrote:
> On Thu, Sep 22, 2011 at 03:26:57PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> [...]
>
>> + * @set_rate Change the rate of this clock. If this callback returns
>> + * ? ? ? ? ? CLK_SET_RATE_PROPAGATE, the rate change will be propagated to
>
> s/CLK_SET_RATE_PROPAGATE/CLK_PARENT_RATE_CHANGE, as suggested by your
> change log above?

Thanks for reviewing.  Will roll into V3 patchset.

Regards,
Mike

>
>> + * ? ? ? ? ? the parent clock (which may propagate again). The requested
>> + * ? ? ? ? ? rate of the parent is passed back from the callback in the
>> + * ? ? ? ? ? second 'unsigned long *' argument.
>> + *
>
> --
> Regards,
> Shawn
>
>

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

* Re: [PATCH v2 3/7] clk: Add fixed-rate clock
  2011-10-23 14:30     ` Shawn Guo
@ 2011-10-23 16:51       ` Turquette, Mike
  -1 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-23 16:51 UTC (permalink / raw)
  To: Shawn Guo
  Cc: linux-kernel, linux-arm-kernel, jeremy.kerr, broonie, tglx,
	linus.walleij, amit.kucheria, dsaxena, patches, linaro-dev, paul,
	grant.likely, sboyd, skannan, magnus.damm, arnd.bergmann, linux,
	eric.miao, richard.zhao

On Sun, Oct 23, 2011 at 7:30 AM, Shawn Guo <shawn.guo@freescale.com> wrote:
> On Thu, Sep 22, 2011 at 03:26:58PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>> +/* Base clock implementations. Platform clock implementations can use these
>> + * directly, or 'subclass' as approprate */
>> +
> /*
>  * Multiple lines comments
>  */

Thanks for the review Shawn.  Will roll into V3 patchset.

Regards,
Mike

> Regards,
> Shawn

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

* [PATCH v2 3/7] clk: Add fixed-rate clock
@ 2011-10-23 16:51       ` Turquette, Mike
  0 siblings, 0 replies; 144+ messages in thread
From: Turquette, Mike @ 2011-10-23 16:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Oct 23, 2011 at 7:30 AM, Shawn Guo <shawn.guo@freescale.com> wrote:
> On Thu, Sep 22, 2011 at 03:26:58PM -0700, Mike Turquette wrote:
>> From: Jeremy Kerr <jeremy.kerr@canonical.com>
>> +/* Base clock implementations. Platform clock implementations can use these
>> + * directly, or 'subclass' as approprate */
>> +
> /*
> ?* Multiple lines comments
> ?*/

Thanks for the review Shawn.  Will roll into V3 patchset.

Regards,
Mike

> Regards,
> Shawn

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

* Re: [PATCH v2 1/7] clk: Add a generic clock infrastructure
  2011-10-03 14:17     ` Rob Herring
@ 2011-10-27 11:54       ` Domenico Andreoli
  -1 siblings, 0 replies; 144+ messages in thread
From: Domenico Andreoli @ 2011-10-27 11:54 UTC (permalink / raw)
  To: Mike Turquette
  Cc: jeremy.kerr, paul, linaro-dev, linus.walleij, patches, broonie,
	magnus.damm, linux-kernel, eric.miao, grant.likely, dsaxena,
	tglx, amit.kucheria, skannan, linux, arnd.bergmann, sboyd,
	richard.zhao, shawn.guo, linux-arm-kernel, Rob Herring

Hi,

On 09/22/2011 05:26 PM, Mike Turquette wrote:
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3530927..c53ed59 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
>  
>  config HAVE_MACH_CLKDEV
>  	bool
> +
> +config GENERIC_CLK
> +	bool

Now that Russel's prepare/unprepare patch is mainlined, I think you
want to select HAVE_CLK_PREPARE here (and remove your prepare/unprepare
function declarations in clk.h).

Regards,
Domenico

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

* [PATCH v2 1/7] clk: Add a generic clock infrastructure
@ 2011-10-27 11:54       ` Domenico Andreoli
  0 siblings, 0 replies; 144+ messages in thread
From: Domenico Andreoli @ 2011-10-27 11:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 09/22/2011 05:26 PM, Mike Turquette wrote:
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3530927..c53ed59 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
>  
>  config HAVE_MACH_CLKDEV
>  	bool
> +
> +config GENERIC_CLK
> +	bool

Now that Russel's prepare/unprepare patch is mainlined, I think you
want to select HAVE_CLK_PREPARE here (and remove your prepare/unprepare
function declarations in clk.h).

Regards,
Domenico

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

end of thread, other threads:[~2011-10-27 11:54 UTC | newest]

Thread overview: 144+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-22 22:26 [PATCH v2 0/7] Add a generic struct clk Mike Turquette
2011-09-22 22:26 ` Mike Turquette
2011-09-22 22:26 ` [PATCH v2 1/7] clk: Add a generic clock infrastructure Mike Turquette
2011-09-22 22:26   ` Mike Turquette
2011-09-25  3:55   ` Grant Likely
2011-09-25  3:55     ` Grant Likely
2011-09-25  5:26     ` Turquette, Mike
2011-09-25  5:26       ` Turquette, Mike
2011-10-03 14:17   ` Rob Herring
2011-10-03 14:17     ` Rob Herring
2011-10-03 14:25     ` Mark Brown
2011-10-03 14:25       ` Mark Brown
2011-10-03 15:24       ` Rob Herring
2011-10-03 15:24         ` Rob Herring
2011-10-03 16:31         ` Mark Brown
2011-10-03 16:31           ` Mark Brown
2011-10-03 16:43           ` Russell King - ARM Linux
2011-10-03 16:43             ` Russell King - ARM Linux
2011-10-03 17:05             ` Mark Brown
2011-10-03 17:05               ` Mark Brown
2011-10-04 18:09     ` Grant Likely
2011-10-04 18:09       ` Grant Likely
2011-10-27 11:54     ` Domenico Andreoli
2011-10-27 11:54       ` Domenico Andreoli
2011-10-03 22:02   ` Rob Herring
2011-10-03 22:02     ` Rob Herring
2011-10-03 22:15     ` Turquette, Mike
2011-10-03 22:15       ` Turquette, Mike
2011-10-06  1:17   ` Saravana Kannan
2011-10-06  1:17     ` Saravana Kannan
2011-10-06 16:11     ` Turquette, Mike
2011-10-06 16:11       ` Turquette, Mike
2011-10-11 11:25   ` Richard Zhao
2011-10-11 11:25     ` Richard Zhao
2011-10-13 14:44   ` Russell King - ARM Linux
2011-10-13 14:44     ` Russell King - ARM Linux
2011-10-13 17:16     ` Turquette, Mike
2011-10-13 17:16       ` Turquette, Mike
2011-10-14  8:10   ` Richard Zhao
2011-10-14  8:10     ` Richard Zhao
2011-10-14 10:05     ` Mark Brown
2011-10-14 10:05       ` Mark Brown
2011-10-14 10:32       ` Richard Zhao
2011-10-14 10:32         ` Richard Zhao
2011-10-16 17:55         ` Sascha Hauer
2011-10-16 17:55           ` Sascha Hauer
2011-10-17  8:48           ` Richard Zhao
2011-10-17  8:48             ` Richard Zhao
2011-10-17  9:20             ` Mark Brown
2011-10-17  9:20               ` Mark Brown
2011-10-17 10:53               ` Richard Zhao
2011-10-17 10:53                 ` Richard Zhao
2011-10-17 11:05                 ` Sascha Hauer
2011-10-17 11:05                   ` Sascha Hauer
2011-10-17 11:30                   ` Russell King - ARM Linux
2011-10-17 11:30                     ` Russell King - ARM Linux
2011-10-14 18:14   ` Turquette, Mike
2011-10-14 18:14     ` Turquette, Mike
2011-10-15  2:24     ` Richard Zhao
2011-10-15  2:24       ` Richard Zhao
2011-10-15  2:34       ` Richard Zhao
2011-10-15  2:34         ` Richard Zhao
2011-10-16 21:17       ` Turquette, Mike
2011-10-16 21:17         ` Turquette, Mike
2011-10-17 11:31         ` Richard Zhao
2011-10-17 11:31           ` Richard Zhao
2011-10-21  9:00   ` Richard Zhao
2011-10-21  9:00     ` Richard Zhao
2011-10-23 12:55   ` Shawn Guo
2011-10-23 12:55     ` Shawn Guo
2011-10-23 16:49     ` Turquette, Mike
2011-10-23 16:49       ` Turquette, Mike
2011-09-22 22:26 ` [PATCH v2 2/7] clk: Implement clk_set_rate Mike Turquette
2011-09-22 22:26   ` Mike Turquette
2011-10-11 11:49   ` Richard Zhao
2011-10-11 11:49     ` Richard Zhao
2011-10-23 14:24   ` Shawn Guo
2011-10-23 14:24     ` Shawn Guo
2011-10-23 16:50     ` Turquette, Mike
2011-10-23 16:50       ` Turquette, Mike
2011-09-22 22:26 ` [PATCH v2 3/7] clk: Add fixed-rate clock Mike Turquette
2011-09-22 22:26   ` Mike Turquette
2011-10-23 14:30   ` Shawn Guo
2011-10-23 14:30     ` Shawn Guo
2011-10-23 16:51     ` Turquette, Mike
2011-10-23 16:51       ` Turquette, Mike
2011-09-22 22:26 ` [PATCH v2 4/7] clk: Add simple gated clock Mike Turquette
2011-09-22 22:26   ` Mike Turquette
2011-09-25  4:02   ` Grant Likely
2011-09-25  4:02     ` Grant Likely
2011-09-25  5:27     ` Turquette, Mike
2011-09-25  5:27       ` Turquette, Mike
2011-09-26 18:33   ` Rob Herring
2011-09-26 18:33     ` Rob Herring
2011-09-26 18:40     ` Jamie Iles
2011-09-26 18:40       ` Jamie Iles
2011-09-26 19:10       ` Rob Herring
2011-09-26 19:10         ` Rob Herring
2011-09-26 19:37         ` Jamie Iles
2011-09-26 19:37           ` Jamie Iles
2011-09-26 22:37           ` Turquette, Mike
2011-09-26 22:37             ` Turquette, Mike
2011-09-26 23:30             ` Rob Herring
2011-09-26 23:30               ` Rob Herring
2011-10-05  1:41               ` Saravana Kannan
2011-10-05  1:41                 ` Saravana Kannan
2011-10-12  6:46   ` Richard Zhao
2011-10-12  6:46     ` Richard Zhao
2011-10-12 14:59     ` Turquette, Mike
2011-10-12 14:59       ` Turquette, Mike
2011-10-16 18:26       ` Sascha Hauer
2011-10-16 18:26         ` Sascha Hauer
2011-10-17  6:42         ` Richard Zhao
2011-10-17  6:42           ` Richard Zhao
2011-10-17 17:46           ` Turquette, Mike
2011-10-17 17:46             ` Turquette, Mike
2011-10-13 14:45   ` Russell King - ARM Linux
2011-10-13 14:45     ` Russell King - ARM Linux
2011-10-13 17:18     ` Turquette, Mike
2011-10-13 17:18       ` Turquette, Mike
2011-09-22 22:27 ` [PATCH v2 5/7] clk: Add Kconfig option to build all generic clk drivers Mike Turquette
2011-09-22 22:27   ` Mike Turquette
2011-09-22 22:27 ` [PATCH v2 6/7] clk: Add initial WM831x clock driver Mike Turquette
2011-09-22 22:27   ` Mike Turquette
2011-09-25  4:08   ` Grant Likely
2011-09-25  4:08     ` Grant Likely
2011-09-25  5:29     ` Turquette, Mike
2011-09-25  5:29       ` Turquette, Mike
2011-09-26  9:38     ` Mark Brown
2011-09-26  9:38       ` Mark Brown
2011-10-04 18:18       ` Grant Likely
2011-10-04 18:18         ` Grant Likely
2011-10-04 20:50         ` Mark Brown
2011-10-04 20:50           ` Mark Brown
2011-10-04 23:22           ` Grant Likely
2011-10-04 23:22             ` Grant Likely
2011-09-22 22:27 ` [PATCH v2 7/7] x86: Enable generic clk API on x86 Mike Turquette
2011-09-22 22:27   ` Mike Turquette
2011-09-22 23:17 ` [PATCH v2 0/7] Add a generic struct clk Turquette, Mike
2011-09-22 23:17   ` Turquette, Mike
2011-09-25  4:10 ` Grant Likely
2011-09-25  4:10   ` Grant Likely
2011-09-29 18:54 ` Mark Brown
2011-09-29 18:54   ` Mark Brown

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.