linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/4] common clk framework
@ 2012-03-03  8:28 Mike Turquette
  2012-03-03  8:28 ` [PATCH v5 1/4] Documentation: common clk API Mike Turquette
                   ` (4 more replies)
  0 siblings, 5 replies; 51+ messages in thread
From: Mike Turquette @ 2012-03-03  8:28 UTC (permalink / raw)
  To: Russell King
  Cc: patches, linaro-dev, linux-kernel, linux-arm-kernel,
	Mike Turquette, Jeremy Kerr, Thomas Gleixner, Arnd Bergman,
	Paul Walmsley, Shawn Guo, Richard Zhao, Saravana Kannan,
	Magnus Damm, Rob Herring, Mark Brown, Linus Walleij,
	Stephen Boyd, Amit Kucheria, Deepak Saxena, Grant Likely,
	Andrew Lunn

From: Mike Turquette <mturquette@ti.com>

The common clock framework defines a common struct clk as well as an
implementation of the clk api that unifies clock operations on various
platforms and devices.

The net result is consolidation of many different struct clk definitions
and platform-specific clock framework implementations.

I consider this version merge-worthy pending ACKs from the relevant
maintainers; namely Russell, Thomas and the platform folks interested in
porting to this framework.

I would like to thank everyone who participated in the common clk
sessions at Linaro Connect and ELC; the feedback was invaluable.

Also I would like to thank Shawn Guo, Richard Zhao, Saravana Kannan and
Magnus Damm for tirelessly updating their platforms for the last few
revisions of this patch series and providng excellent feedback each
time.

Major changes since v4:
 * rolled in TGLX's comments on overall design.  We now have,
   * proper handling of root clocks and orphan clocks
   * multi-parent clocks are handled in the core
   * struct clk is shielded from struct clk_foo and vice versa
     * this is a return to the previous struct clk_hw design
 * split basic clock types out into separate files
 * split headers up by purpose
   * clk.h remains the driver-level interface
     * declarations for rate change notifiers are the only additions
   * clk-provider.h is primary header for implementing clock operations
   * clk-private.h allows for static initialization of clock data
 * validation and bug fixes
 * rebased onto Linus' v3.3-rc5 tag

Patches can be pulled from:
git://git.linaro.org/people/mturquette/linux.git v3.3-rc5-clkv5

v4 can be found at,
http://article.gmane.org/gmane.linux.linaro.devel/8896/

v3 can be found at,
http://article.gmane.org/gmane.linux.kernel/1218622

Mike Turquette (4):
  Documentation: common clk API
  clk: Kconfig: add entry for HAVE_CLK_PREPARE
  clk: introduce the common clock framework
  clk: basic clock hardware types

 Documentation/clk.txt        |  201 +++++++
 drivers/clk/Kconfig          |   31 +
 drivers/clk/Makefile         |    2 +
 drivers/clk/clk-divider.c    |  199 +++++++
 drivers/clk/clk-fixed-rate.c |   81 +++
 drivers/clk/clk-gate.c       |  121 ++++
 drivers/clk/clk-mux.c        |  114 ++++
 drivers/clk/clk.c            | 1323 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-private.h  |  192 ++++++
 include/linux/clk-provider.h |  294 ++++++++++
 include/linux/clk.h          |   68 ++-
 11 files changed, 2621 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/clk.txt
 create mode 100644 drivers/clk/clk-divider.c
 create mode 100644 drivers/clk/clk-fixed-rate.c
 create mode 100644 drivers/clk/clk-gate.c
 create mode 100644 drivers/clk/clk-mux.c
 create mode 100644 drivers/clk/clk.c
 create mode 100644 include/linux/clk-private.h
 create mode 100644 include/linux/clk-provider.h

Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnd Bergman <arnd.bergmann@linaro.org>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Shawn Guo <shawn.guo@freescale.com>
Cc: Richard Zhao <richard.zhao@linaro.org>
Cc: Saravana Kannan <skannan@codeaurora.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Amit Kucheria <amit.kucheria@linaro.org>
Cc: Deepak Saxena <dsaxena@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Andrew Lunn <andrew@lunn.ch>

-- 
1.7.5.4


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

* [PATCH v5 1/4] Documentation: common clk API
  2012-03-03  8:28 [PATCH v5 0/4] common clk framework Mike Turquette
@ 2012-03-03  8:28 ` Mike Turquette
  2012-03-03  8:28 ` [PATCH v5 2/4] clk: Kconfig: add entry for HAVE_CLK_PREPARE Mike Turquette
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 51+ messages in thread
From: Mike Turquette @ 2012-03-03  8:28 UTC (permalink / raw)
  To: Russell King
  Cc: patches, linaro-dev, linux-kernel, linux-arm-kernel,
	Mike Turquette, Mike Turquette, Jeremy Kerr, Thomas Gleixner,
	Arnd Bergman, Paul Walmsley, Shawn Guo, Richard Zhao,
	Saravana Kannan, Magnus Damm, Rob Herring, Mark Brown,
	Linus Walleij, Stephen Boyd, Amit Kucheria, Deepak Saxena,
	Grant Likely, Andrew Lunn

Provide documentation for the common clk structures and APIs.  This code
can be found in drivers/clk/ and include/linux/clk*.h.

Signed-off-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Mike Turquette <mturquette@ti.com>
Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnd Bergman <arnd.bergmann@linaro.org>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Shawn Guo <shawn.guo@freescale.com>
Cc: Richard Zhao <richard.zhao@linaro.org>
Cc: Saravana Kannan <skannan@codeaurora.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Amit Kucheria <amit.kucheria@linaro.org>
Cc: Deepak Saxena <dsaxena@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Andrew Lunn <andrew@lunn.ch>
---
 Documentation/clk.txt |  201 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 201 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/clk.txt

diff --git a/Documentation/clk.txt b/Documentation/clk.txt
new file mode 100644
index 0000000..d4db278
--- /dev/null
+++ b/Documentation/clk.txt
@@ -0,0 +1,201 @@
+		The Common Clk Framework
+		Mike Turquette <mturquette@ti.com>
+
+This document endeavours to explain the common clk framework details,
+and how to port a platform over to this framework.  It is not yet a
+detailed explanation of the clock api in include/linux/clk.h, but
+perhaps someday it will include that information.
+
+	Part 1 - introduction and interface split
+
+The common clk framework is an interface to control the clock nodes
+available on various devices today.  This may come in the form of clock
+gating, rate adjustment, muxing or other operations.  This framework is
+enabled with the CONFIG_COMMON_CLK option.
+
+The interface itself is divided into two halves, each shielded from the
+details of its counterpart.  First is the common definition of struct
+clk which attempts to unify the framework-level accounting and
+infrastructure that has traditionally been replicated across a variety of
+platforms.  This includes a top-level implementation of the clk.h api,
+defined in drivers/clk/clk.c.  The definition of struct clk_ops, whose
+operations are invoked by the clk api implementation, rounds out the
+first half the interface.
+
+The second half of the interface is comprised of the hardware-specific callbacks
+registered with struct clk_ops and the corresponding hardware-specific
+structures needed to model a particular clock.  For the remainder of this
+document any reference to a callback in struct clk_ops, such as .enable
+or .set_rate, implies the hardware-specific implementation of that code.
+Likewise references to struct clk_foo are a convenient shorthand for the
+hypothetical implementation of the clocks in the wildly popular "foo"
+hardware.
+
+Tying the two halves of this interface together is struct clk_hw, which is
+defined in struct clk_foo and pointed to within struct clk.  This allows easy
+navigaton between the two.
+
+	Part 2 - common data structures and api
+
+Below is the common struct clk definition from include/linux/clk.h, modified for brevity:
+
+	struct clk {
+		const char		*name;
+		const struct clk_ops	*ops;
+		struct clk_hw		*hw;
+		char			**parent_names;
+		struct clk		**parents;
+		struct clk		*parent;
+		struct hlist_head	children;
+		struct hlist_node	child_node;
+		...
+	};
+
+The members above make up the core of the clk tree topology.  The clk
+api itself defines several driver-facing functions which operate on
+struct clk.  That api is documented in include/linux/clk.h.
+
+Platforms and devices utilizing the common struct clk use the struct
+clk_ops pointer in struct clk to perform the hardware-specific parts of
+the operations defined in clk.h:
+
+	struct clk_ops {
+		int		(*prepare)(struct clk_hw *hw);
+		void		(*unprepare)(struct clk_hw *hw);
+		int		(*enable)(struct clk_hw *hw);
+		void		(*disable)(struct clk_hw *hw);
+		unsigned long	(*recalc_rate)(struct clk_hw *hw,
+						unsigned long parent_rate);
+		long		(*round_rate)(struct clk_hw *hw, unsigned long,
+						unsigned long *);
+		int		(*set_parent)(struct clk_hw *hw, u8 index);
+		u8		(*get_parent)(struct clk_hw *hw);
+		int		(*set_rate)(struct clk_hw *hw, unsigned long);
+		void		(*init)(struct clk_hw *hw);
+	};
+
+	Part 3 - hardware clk implementations
+
+The strength of the common struct clk comes from its .ops and .hw pointers
+which abstract the details of struct clk from the hardware-specific bits, and
+vice versa.  To illustrate consider the simple gateable clk implementation in
+drivers/clk/clk-basic.c:
+
+struct clk_gate {
+	struct clk_hw	hw;
+	void __iomem    *reg;
+	u8              bit_idx;
+	...
+};
+
+struct clk_gate contains clk_hw as well as hardware-specific knowledge about
+which register and bit controls this clk's gating.  Nothing about clock
+topology or accounting, such as enable_count or notifier_count, is needed here.
+That is all handled by the common framework code and struct clk.
+
+Let's walk through enabling this clk from driver code:
+
+	struct clk *clk;
+	clk = clk_get(NULL, "my_gateable_clk");
+
+	clk_prepare(clk);
+	clk_enable(clk);
+
+The call graph for clk_enable is very simple:
+
+clk_enable(clk);
+	clk->ops->enable(clk->hw);
+	[which resolves to...]
+		clk_gate_enable(hw);
+		[which resolves struct clk gate with to_clk_gate(hw)]
+			clk_gate_set_bit(gate);
+
+And the definition of clk_gate_set_bit:
+
+static void clk_gate_set_bit(struct clk_gate *gate)
+{
+	u32 reg;
+
+	reg = __raw_readl(gate->reg);
+	reg |= BIT(gate->bit_idx);
+	writel(reg, gate->reg);
+}
+
+Note to_clk_gate is defined as:
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, clk)
+
+This pattern of abstraction is used for every clock hardware
+representation.
+
+	Part 4 - supporting your own clk hardware
+
+When implementing support for a new type of clock it only necessary to
+include the following header:
+
+#include <linux/clk-provider.h>
+
+include/linux/clk.h is included within that header and clk-private.h
+must never be included from the code which implements the operations for
+a clock.  More on that below in Part 5.
+
+To construct a clk hardware structure for your platform you must define
+the following:
+
+struct clk_foo {
+	struct clk_hw hw;
+	... hardware specific data goes here ...
+};
+
+To take advantage of your data you'll need to support valid operations
+for your clk:
+
+struct clk_ops clk_foo_ops {
+	.enable		= &clk_foo_enable;
+	.disable	= &clk_foo_disable;
+};
+
+Implement the above functions using container_of:
+
+#define to_clk_foo(_hw) container_of(_hw, struct clk_foo, hw)
+
+int clk_foo_enable(struct clk_hw *hw)
+{
+	struct clk_foo *foo;
+
+	foo = to_clk_foo(hw);
+
+	... perform magic on foo ...
+
+	return 0;
+};
+
+Finally, register your clock at run-time with a hardware-specific
+registration function.  This function simply populates struct clk_foo's
+data and then calls:
+
+clk_register(...)
+
+With the appropriate parameters.  See the basic clock types in
+drivers/clk/clk-*.c for examples.
+
+	Part 5 - static initialization of clock data
+
+For platforms with many clocks (often numbering into the hundreds) it
+may be desirable to statically initialize some clock data.  This
+presents a problem since the definition of struct clk should be hidden
+from everyone except for the clock core in drivers/clk/clk.c.
+
+To get around this problem struct clk's definition is exposed in
+include/linux/clk-private.h along with some macros for more easily
+initializing instances of the basic clock types.
+
+clk-private.h must NEVER be included by code which implements struct
+clk_ops callbacks, nor must it be included by any logic which pokes
+around inside of struct clk at run-time.  To do so is a layering
+violation.
+
+To better enforce this policy, always follow this simple rule: any
+statically initialized clock data MUST be defined in a separate file
+from the logic that implements its ops.  Basically separate the logic
+from the data and all is well.
-- 
1.7.5.4


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

* [PATCH v5 2/4] clk: Kconfig: add entry for HAVE_CLK_PREPARE
  2012-03-03  8:28 [PATCH v5 0/4] common clk framework Mike Turquette
  2012-03-03  8:28 ` [PATCH v5 1/4] Documentation: common clk API Mike Turquette
@ 2012-03-03  8:28 ` Mike Turquette
  2012-03-05  2:04   ` Richard Zhao
  2012-03-03  8:29 ` [PATCH v5 3/4] clk: introduce the common clock framework Mike Turquette
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 51+ messages in thread
From: Mike Turquette @ 2012-03-03  8:28 UTC (permalink / raw)
  To: Russell King
  Cc: patches, linaro-dev, linux-kernel, linux-arm-kernel,
	Mike Turquette, Mike Turquette, Jeremy Kerr, Thomas Gleixner,
	Arnd Bergman, Paul Walmsley, Richard Zhao, Saravana Kannan,
	Magnus Damm, Rob Herring, Mark Brown, Linus Walleij,
	Stephen Boyd, Amit Kucheria, Deepak Saxena, Grant Likely,
	Andrew Lunn

The common clk framework provides clk_prepare and clk_unprepare
implementations.  Create an entry for HAVE_CLK_PREPARE so that
COMMON_CLK can select it.

Signed-off-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Mike Turquette <mturquette@ti.com>
Acked-by: Shawn Guo <shawn.guo@linaro.org>
Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnd Bergman <arnd.bergmann@linaro.org>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Richard Zhao <richard.zhao@linaro.org>
Cc: Saravana Kannan <skannan@codeaurora.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Amit Kucheria <amit.kucheria@linaro.org>
Cc: Deepak Saxena <dsaxena@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Andrew Lunn <andrew@lunn.ch>
---
 drivers/clk/Kconfig |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 9b3cd08..3912576 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -8,3 +8,6 @@ config HAVE_CLK_PREPARE
 
 config HAVE_MACH_CLKDEV
 	bool
+
+config HAVE_CLK_PREPARE
+	bool
-- 
1.7.5.4


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

* [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-03  8:28 [PATCH v5 0/4] common clk framework Mike Turquette
  2012-03-03  8:28 ` [PATCH v5 1/4] Documentation: common clk API Mike Turquette
  2012-03-03  8:28 ` [PATCH v5 2/4] clk: Kconfig: add entry for HAVE_CLK_PREPARE Mike Turquette
@ 2012-03-03  8:29 ` Mike Turquette
  2012-03-03 13:31   ` Sascha Hauer
                     ` (2 more replies)
  2012-03-03  8:29 ` [PATCH v5 4/4] clk: basic clock hardware types Mike Turquette
  2012-03-09  2:34 ` [PATCH v5 0/4] common clk framework Richard Zhao
  4 siblings, 3 replies; 51+ messages in thread
From: Mike Turquette @ 2012-03-03  8:29 UTC (permalink / raw)
  To: Russell King
  Cc: patches, linaro-dev, linux-kernel, linux-arm-kernel,
	Mike Turquette, Mike Turquette, Jeremy Kerr, Thomas Gleixner,
	Arnd Bergman, Paul Walmsley, Shawn Guo, Richard Zhao,
	Saravana Kannan, Magnus Damm, Rob Herring, Mark Brown,
	Linus Walleij, Stephen Boyd, Amit Kucheria, Deepak Saxena,
	Grant Likely, Andrew Lunn

The common clock framework defines a common struct clk useful across
most platforms as well as an implementation of the clk api that drivers
can use safely for managing clocks.

The net result is consolidation of many different struct clk definitions
and platform-specific clock framework implementations.

This patch introduces the common struct clk, struct clk_ops and an
implementation of the well-known clock api in include/clk/clk.h.
Platforms may define their own hardware-specific clock structure and
their own clock operation callbacks, so long as it wraps an instance of
struct clk_hw.

See Documentation/clk.txt for more details.

This patch is based on the work of Jeremy Kerr, which in turn was based
on the work of Ben Herrenschmidt.

Signed-off-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Mike Turquette <mturquette@ti.com>
Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnd Bergman <arnd.bergmann@linaro.org>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Shawn Guo <shawn.guo@freescale.com>
Cc: Richard Zhao <richard.zhao@linaro.org>
Cc: Saravana Kannan <skannan@codeaurora.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Amit Kucheria <amit.kucheria@linaro.org>
Cc: Deepak Saxena <dsaxena@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Andrew Lunn <andrew@lunn.ch>
---
 drivers/clk/Kconfig          |   28 +
 drivers/clk/Makefile         |    1 +
 drivers/clk/clk.c            | 1323 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-private.h  |   68 +++
 include/linux/clk-provider.h |  169 ++++++
 include/linux/clk.h          |   68 ++-
 6 files changed, 1652 insertions(+), 5 deletions(-)
 create mode 100644 drivers/clk/clk.c
 create mode 100644 include/linux/clk-private.h
 create mode 100644 include/linux/clk-provider.h

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 3912576..18eb8c2 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -11,3 +11,31 @@ config HAVE_MACH_CLKDEV
 
 config HAVE_CLK_PREPARE
 	bool
+
+menuconfig COMMON_CLK
+	bool "Common Clock Framework"
+	select HAVE_CLK_PREPARE
+	---help---
+	  The common clock framework is a single definition of struct
+	  clk, useful across many platforms, as well as an
+	  implementation of the clock API in include/linux/clk.h.
+	  Architectures utilizing the common struct clk should select
+	  this automatically, but it may be necessary to manually select
+	  this option for loadable modules requiring the common clock
+	  framework.
+
+	  If in doubt, say "N".
+
+if COMMON_CLK
+
+config COMMON_CLK_DEBUG
+	bool "DebugFS representation of clock tree"
+	depends on COMMON_CLK
+	---help---
+	  Creates a directory hierchy in debugfs for visualizing the clk
+	  tree structure.  Each directory contains read-only members
+	  that export information specific to that clk node: clk_rate,
+	  clk_flags, clk_prepare_count, clk_enable_count &
+	  clk_notifier_count.
+
+endif
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..ff362c4 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_COMMON_CLK)	+= clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..b979d74
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,1323 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
+ *
+ * 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.  See Documentation/clk.txt
+ */
+
+#include <linux/clk-private.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+static DEFINE_SPINLOCK(enable_lock);
+static DEFINE_MUTEX(prepare_lock);
+
+static HLIST_HEAD(clk_root_list);
+static HLIST_HEAD(clk_orphan_list);
+static LIST_HEAD(clk_notifier_list);
+
+/***        debugfs support        ***/
+
+#ifdef CONFIG_COMMON_CLK_DEBUG
+#include <linux/debugfs.h>
+
+static struct dentry *rootdir;
+static struct dentry *orphandir;
+static int inited = 0;
+
+/* caller must hold prepare_lock */
+static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
+{
+	struct dentry *d;
+	int ret = -ENOMEM;
+
+	if (!clk || !pdentry) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	d = debugfs_create_dir(clk->name, pdentry);
+	if (!d)
+		goto out;
+
+	clk->dentry = d;
+
+	d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry,
+			(u32 *)&clk->rate);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
+			(u32 *)&clk->flags);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry,
+			(u32 *)&clk->prepare_count);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry,
+			(u32 *)&clk->enable_count);
+	if (!d)
+		goto err_out;
+
+	d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry,
+			(u32 *)&clk->notifier_count);
+	if (!d)
+		goto err_out;
+
+	ret = 0;
+	goto out;
+
+err_out:
+	debugfs_remove(clk->dentry);
+out:
+	return ret;
+}
+
+/* caller must hold prepare_lock */
+static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
+{
+	struct clk *child;
+	struct hlist_node *tmp;
+	int ret = -EINVAL;;
+
+	if (!clk || !pdentry)
+		goto out;
+
+	ret = clk_debug_create_one(clk, pdentry);
+
+	if (ret)
+		goto out;
+
+	hlist_for_each_entry(child, tmp, &clk->children, child_node)
+		clk_debug_create_subtree(child, clk->dentry);
+
+	ret = 0;
+out:
+	return ret;
+}
+
+/**
+ * clk_debug_register - add a clk node to the debugfs clk tree
+ * @clk: the clk being added to the debugfs clk tree
+ *
+ * Dynamically adds a clk to the debugfs clk tree if debugfs has been
+ * initialized.  Otherwise it bails out early since the debugfs clk tree
+ * will be created lazily by clk_debug_init as part of a late_initcall.
+ *
+ * Caller must hold prepare_lock.  Only clk_init calls this function (so
+ * far) so this is taken care.
+ */
+static int clk_debug_register(struct clk *clk)
+{
+	struct clk *parent;
+	struct dentry *pdentry;
+	int ret = 0;
+
+	if (!inited)
+		goto out;
+
+	parent = clk->parent;
+
+	/*
+	 * Check to see if a clk is a root clk.  Also check that it is
+	 * safe to add this clk to debugfs
+	 */
+	if (!parent)
+		if (clk->flags & CLK_IS_ROOT)
+			pdentry = rootdir;
+		else
+			pdentry = orphandir;
+	else
+		if (parent->dentry)
+			pdentry = parent->dentry;
+		else
+			goto out;
+
+	ret = clk_debug_create_subtree(clk, pdentry);
+
+out:
+	return ret;
+}
+
+/**
+ * clk_debug_init - lazily create the debugfs clk tree visualization
+ *
+ * clks are often initialized very early during boot before memory can
+ * be dynamically allocated and well before debugfs is setup.
+ * clk_debug_init walks the clk tree hierarchy while holding
+ * prepare_lock and creates the topology as part of a late_initcall,
+ * thus insuring that clks initialized very early will still be
+ * represented in the debugfs clk tree.  This function should only be
+ * called once at boot-time, and all other clks added dynamically will
+ * be done so with clk_debug_register.
+ */
+static int __init clk_debug_init(void)
+{
+	struct clk *clk;
+	struct hlist_node *tmp;
+
+	rootdir = debugfs_create_dir("clk", NULL);
+
+	if (!rootdir)
+		return -ENOMEM;
+
+	orphandir = debugfs_create_dir("orphans", rootdir);
+
+	if (!orphandir)
+		return -ENOMEM;
+
+	mutex_lock(&prepare_lock);
+
+	hlist_for_each_entry(clk, tmp, &clk_root_list, child_node)
+		clk_debug_create_subtree(clk, rootdir);
+
+	hlist_for_each_entry(clk, tmp, &clk_orphan_list, child_node)
+		clk_debug_create_subtree(clk, orphandir);
+
+	inited = 1;
+
+	mutex_unlock(&prepare_lock);
+
+	return 0;
+}
+late_initcall(clk_debug_init);
+#else
+static inline int clk_debug_register(struct clk *clk) { return 0; }
+#endif /* CONFIG_COMMON_CLK_DEBUG */
+
+/***    helper functions   ***/
+
+inline const char *__clk_get_name(struct clk *clk)
+{
+	return !clk ? NULL : clk->name;
+}
+
+inline struct clk_hw *__clk_get_hw(struct clk *clk)
+{
+	return !clk ? NULL : clk->hw;
+}
+
+inline u8 __clk_get_num_parents(struct clk *clk)
+{
+	return !clk ? -EINVAL : clk->num_parents;
+}
+
+inline struct clk *__clk_get_parent(struct clk *clk)
+{
+	return !clk ? NULL : clk->parent;
+}
+
+inline unsigned long __clk_get_rate(struct clk *clk)
+{
+	return !clk ? -EINVAL : clk->rate;
+}
+
+inline unsigned long __clk_get_flags(struct clk *clk)
+{
+	return !clk ? -EINVAL : clk->flags;
+}
+
+static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
+{
+	struct clk *child;
+	struct clk *ret;
+	struct hlist_node *tmp;
+
+	if (!strcmp(clk->name, name))
+		return clk;
+
+	hlist_for_each_entry(child, tmp, &clk->children, child_node) {
+		ret = __clk_lookup_subtree(name, child);
+		if (ret)
+			return ret;
+	}
+
+	return NULL;
+}
+
+struct clk *__clk_lookup(const char *name)
+{
+	struct clk *root_clk;
+	struct clk *ret;
+	struct hlist_node *tmp;
+
+	/* search the 'proper' clk tree first */
+	hlist_for_each_entry(root_clk, tmp, &clk_root_list, child_node) {
+		ret = __clk_lookup_subtree(name, root_clk);
+		if (ret)
+			return ret;
+	}
+
+	/* if not found, then search the orphan tree */
+	hlist_for_each_entry(root_clk, tmp, &clk_orphan_list, child_node) {
+		ret = __clk_lookup_subtree(name, root_clk);
+		if (ret)
+			return ret;
+	}
+
+	return NULL;
+}
+
+/***        clk api        ***/
+
+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);
+}
+
+/**
+ * clk_unprepare - undo preparation of a clock source
+ * @clk: the clk being unprepare
+ *
+ * clk_unprepare may sleep, which differentiates it from clk_disable.  In a
+ * simple case, clk_unprepare can be used instead of clk_disable to gate a clk
+ * if the operation may sleep.  One example is a clk which is accessed over
+ * I2c.  In the complex case a clk gate operation may require a fast and a slow
+ * part.  It is this reason that clk_unprepare and clk_disable are not mutually
+ * exclusive.  In fact clk_disable must be called before clk_unprepare.
+ */
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&prepare_lock);
+	__clk_unprepare(clk);
+	mutex_unlock(&prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+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;
+}
+
+/**
+ * clk_prepare - prepare a clock source
+ * @clk: the clk being prepared
+ *
+ * clk_prepare may sleep, which differentiates it from clk_enable.  In a simple
+ * case, clk_prepare can be used instead of clk_enable to ungate a clk if the
+ * operation may sleep.  One example is a clk which is accessed over I2c.  In
+ * the complex case a clk ungate operation may require a fast and a slow part.
+ * It is this reason that clk_prepare and clk_enable are not mutually
+ * exclusive.  In fact clk_prepare must be called before clk_enable.
+ * Returns 0 on success, -EERROR otherwise.
+ */
+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);
+
+	if (clk->parent)
+		__clk_disable(clk->parent);
+}
+
+/**
+ * clk_disable - gate a clock
+ * @clk: the clk being gated
+ *
+ * clk_disable must not sleep, which differentiates it from clk_unprepare.  In
+ * a simple case, clk_disable can be used instead of clk_unprepare to gate a
+ * clk if the operation is fast and will never sleep.  One example is a
+ * SoC-internal clk which is controlled via simple register writes.  In the
+ * complex case a clk gate operation may require a fast and a slow part.  It is
+ * this reason that clk_unprepare and clk_disable are not mutually exclusive.
+ * In fact clk_disable must be called before clk_unprepare.
+ */
+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 = 0;
+
+	if (!clk)
+		return 0;
+
+	if (WARN_ON(clk->prepare_count == 0))
+		return -ESHUTDOWN;
+
+	if (clk->enable_count == 0) {
+		if (clk->parent)
+			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;
+}
+
+/**
+ * clk_enable - ungate a clock
+ * @clk: the clk being ungated
+ *
+ * clk_enable must not sleep, which differentiates it from clk_prepare.  In a
+ * simple case, clk_enable can be used instead of clk_prepare to ungate a clk
+ * if the operation will never sleep.  One example is a SoC-internal clk which
+ * is controlled via simple register writes.  In the complex case a clk ungate
+ * operation may require a fast and a slow part.  It is this reason that
+ * clk_enable and clk_prepare are not mutually exclusive.  In fact clk_prepare
+ * must be called before clk_enable.  Returns 0 on success, -EERROR
+ * otherwise.
+ */
+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);
+
+/**
+ * clk_get_rate - return the rate of clk
+ * @clk: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk.  Does not query the hardware.  If
+ * clk is NULL then returns -EINVAL.
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+	unsigned long rate;
+
+	mutex_lock(&prepare_lock);
+	rate = __clk_get_rate(clk);
+	mutex_unlock(&prepare_lock);
+
+	return rate;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+/**
+ * __clk_round_rate - round the given rate for a clk
+ * @clk: round the rate of this clock
+ *
+ * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
+ */
+unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (!clk && !clk->ops->round_rate)
+		return -EINVAL;
+
+	return clk->ops->round_rate(clk->hw, rate, NULL);
+}
+
+/**
+ * clk_round_rate - round the given rate for a clk
+ * @clk: the clk for which we are rounding a rate
+ * @rate: the rate which is to be rounded
+ *
+ * Takes in a rate as input and rounds it to a rate that the clk can actually
+ * use which is then returned.  If clk doesn't support round_rate operation
+ * then the rate passed in is returned.
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long ret = rate;
+
+	mutex_lock(&prepare_lock);
+	if (clk && clk->ops->round_rate)
+		ret = __clk_round_rate(clk, rate);
+	mutex_unlock(&prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+/**
+ * __clk_notify - call clk notifier chain
+ * @clk: struct clk * that is changing rate
+ * @msg: clk notifier type (see include/linux/clk.h)
+ * @old_rate: old clk rate
+ * @new_rate: new clk rate
+ *
+ * Triggers a notifier call chain on the clk rate-change notification
+ * for 'clk'.  Passes a pointer to the struct clk and the previous
+ * and current rates to the notifier callback.  Intended to be called by
+ * internal clock code only.  Returns NOTIFY_DONE from the last driver
+ * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
+ * a driver returns that.
+ */
+static int __clk_notify(struct clk *clk, unsigned long msg,
+		unsigned long old_rate, unsigned long new_rate)
+{
+	struct clk_notifier *cn;
+	struct clk_notifier_data cnd;
+	int ret = NOTIFY_DONE;
+
+	cnd.clk = clk;
+	cnd.old_rate = old_rate;
+	cnd.new_rate = new_rate;
+
+	list_for_each_entry(cn, &clk_notifier_list, node) {
+		if (cn->clk == clk) {
+			ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
+					&cnd);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * __clk_recalc_rates
+ * @clk: first clk in the subtree
+ * @msg: notification type (see include/linux/clk.h)
+ *
+ * Walks the subtree of clks starting with clk and recalculates rates as it
+ * goes.  Note that if a clk does not implement the recalc_rate operation then
+ * propagation of that subtree stops and all of that clks children will not
+ * have their rates updated.
+ *
+ * clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
+ * if necessary.
+ *
+ * Caller must hold prepare_lock.
+ */
+static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
+{
+	unsigned long old_rate;
+	unsigned long parent_rate = 0;
+	struct hlist_node *tmp;
+	struct clk *child;
+
+	old_rate = clk->rate;
+
+	if (clk->parent)
+		parent_rate = clk->parent->rate;
+
+	if (clk->ops->recalc_rate)
+		clk->rate = clk->ops->recalc_rate(clk->hw, parent_rate);
+	else
+		clk->rate = parent_rate;
+
+	/*
+	 * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE
+	 * & ABORT_RATE_CHANGE notifiers
+	 */
+	if (clk->notifier_count && msg)
+		__clk_notify(clk, msg, old_rate, clk->rate);
+
+	hlist_for_each_entry(child, tmp, &clk->children, child_node)
+		__clk_recalc_rates(child, msg);
+}
+
+/**
+ * __clk_speculate_rates
+ * @clk: first clk in the subtree
+ * @parent_rate: the "future" rate of clk's parent
+ *
+ * Walks the subtree of clks starting with clk, speculating rates as it
+ * goes and firing off PRE_RATE_CHANGE notifications as necessary.
+ *
+ * Unlike clk_recalc_rates, clk_speculate_rates exists only for sending
+ * pre-rate change notifications and returns early if no clks in the
+ * subtree have subscribed to the notifications.
+ *
+ * Caller must hold prepare_lock.
+ */
+static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
+{
+	struct hlist_node *tmp;
+	struct clk *child;
+	unsigned long new_rate;
+	int ret = NOTIFY_DONE;
+
+	if (!clk->ops->recalc_rate)
+		goto out;
+
+	new_rate = clk->ops->recalc_rate(clk->hw, parent_rate);
+
+	/* abort the rate change if a driver returns NOTIFY_BAD */
+	if (clk->notifier_count)
+		ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
+
+	if (ret == NOTIFY_BAD)
+		goto out;
+
+	hlist_for_each_entry(child, tmp, &clk->children, child_node) {
+		ret = __clk_speculate_rates(child, new_rate);
+		if (ret == NOTIFY_BAD)
+			break;
+	}
+
+out:
+	return ret;
+}
+
+/**
+ * DOC: Using the CLK_SET_RATE_PARENT flag
+ *
+ * __clk_set_rate changes the child's rate before the parent's to more
+ * easily handle failure conditions.
+ *
+ * This means clk might run out of spec for a short time if its rate is
+ * increased before the parent's rate is updated.
+ *
+ * To prevent this consider setting the CLK_SET_RATE_GATE flag on any
+ * clk where you also set the CLK_SET_RATE_PARENT flag
+ *
+ * PRE_RATE_CHANGE notifications are supposed to stack as a rate change
+ * request propagates up the clk tree.  This reflects the different
+ * rates that a downstream clk might experience if left enabled while
+ * upstream parents change their rates.
+ */
+static struct clk *__clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk *fail_clk = NULL;
+	int ret = NOTIFY_DONE;
+	unsigned long old_rate = clk->rate;
+	unsigned long new_rate;
+	unsigned long parent_old_rate;
+	unsigned long parent_new_rate = 0;
+	struct clk *child;
+	struct hlist_node *tmp;
+
+	/* bail early if we can't change rate while clk is enabled */
+	if ((clk->flags & CLK_SET_RATE_GATE) && clk->enable_count)
+		return clk;
+
+	/* find the new rate and see if parent rate should change too */
+	WARN_ON(!clk->ops->round_rate);
+
+	new_rate = clk->ops->round_rate(clk->hw, rate, &parent_new_rate);
+
+	/* NOTE: pre-rate change notifications will stack */
+	if (clk->notifier_count)
+		ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
+
+	if (ret == NOTIFY_BAD)
+		return clk;
+
+	/* speculate rate changes down the tree */
+	hlist_for_each_entry(child, tmp, &clk->children, child_node) {
+		ret = __clk_speculate_rates(child, new_rate);
+		if (ret == NOTIFY_BAD)
+			return clk;
+	}
+
+	/* change the rate of this clk */
+	if (clk->ops->set_rate)
+		ret = clk->ops->set_rate(clk->hw, new_rate);
+
+	if (ret == NOTIFY_BAD)
+		return clk;
+
+	/*
+	 * change the rate of the parent clk if necessary
+	 *
+	 * hitting the nested 'if' path implies we have hit a .set_rate
+	 * failure somewhere upstream while propagating __clk_set_rate
+	 * up the clk tree.  roll back the clk rates one by one and
+	 * return the pointer to the clk that failed.  clk_set_rate will
+	 * use the pointer to propagate a rate-change abort notifier
+	 * from the "highest" point.
+	 */
+	if ((clk->flags & CLK_SET_RATE_PARENT) && parent_new_rate) {
+		parent_old_rate = clk->parent->rate;
+		fail_clk = __clk_set_rate(clk->parent, parent_new_rate);
+
+		/* roll back changes if parent rate change failed */
+		if (fail_clk) {
+			pr_warn("%s: failed to set parent %s rate to %lu\n",
+					__func__, fail_clk->name,
+					parent_new_rate);
+
+			/*
+			 * Send PRE_RATE_CHANGE notifiers down the tree
+			 * again, since we're rolling back the rate
+			 * changes due to the abort.
+			 *
+			 * Ignore any NOTIFY_BAD's since this *is* the
+			 * exception handler.
+			 *
+			 * NOTE: pre-rate change notifications will stack
+			 */
+			__clk_speculate_rates(clk, clk->parent->rate);
+
+			clk->ops->set_rate(clk->hw, old_rate);
+		}
+		return fail_clk;
+	}
+
+	/*
+	 * set clk's rate & recalculate the rates of clk's children
+	 *
+	 * hitting this path implies we have successfully finished
+	 * propagating recursive calls to __clk_set_rate up the clk tree
+	 * (if necessary) and it is safe to propagate __clk_recalc_rates
+	 * and post-rate change notifiers down the clk tree from this
+	 * point.
+	 */
+	__clk_recalc_rates(clk, POST_RATE_CHANGE);
+
+	return NULL;
+}
+
+/**
+ * clk_set_rate - specify a new rate for clk
+ * @clk: the clk whose rate is being changed
+ * @rate: the new rate for clk
+ *
+ * In the simplest case clk_set_rate will only change the rate of clk.
+ *
+ * If clk has the CLK_SET_RATE_GATE flag set and it is enabled this call
+ * will fail; only when the clk is disabled will it be able to change
+ * its rate.
+ *
+ * Setting the CLK_SET_RATE_PARENT flag allows clk_set_rate to
+ * recursively propagate up to clk's parent; whether or not this happens
+ * depends on the outcome of clk's .round_rate implementation.  If
+ * *parent_rate is 0 after calling .round_rate then upstream parent
+ * propagation is ignored.  If *parent_rate comes back with a new rate
+ * for clk's parent then we propagate up to clk's parent and set it's
+ * rate.  Upward propagation will continue until either a clk does not
+ * support the CLK_SET_RATE_PARENT flag or .round_rate stops requesting
+ * changes to clk's parent_rate.  If there is a failure during upstream
+ * propagation then clk_set_rate will unwind and restore each clk's rate
+ * that had been successfully changed.  Afterwards a rate change abort
+ * notification will be propagated downstream, starting from the clk
+ * that failed.
+ *
+ * At the end of all of the rate setting, clk_set_rate internally calls
+ * __clk_recalc_rates and propagates the rate changes downstream,
+ * starting from the highest clk whose rate was changed.  This has the
+ * added benefit of propagating post-rate change notifiers.
+ *
+ * Note that while post-rate change and rate change abort notifications
+ * are guaranteed to be sent to a clk only once per call to
+ * clk_set_rate, pre-change notifications will be sent for every clk
+ * whose rate is changed.  Stacking pre-change notifications is noisy
+ * for the drivers subscribed to them, but this allows drivers to react
+ * to intermediate clk rate changes up until the point where the final
+ * rate is achieved at the end of upstream propagation.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk *fail_clk;
+	int ret = 0;
+
+	/* prevent racing with updates to the clock topology */
+	mutex_lock(&prepare_lock);
+
+	/* bail early if nothing to do */
+	if (rate == clk->rate)
+		goto out;
+
+	fail_clk = __clk_set_rate(clk, rate);
+	if (fail_clk) {
+		pr_warn("%s: failed to set %s rate\n", __func__,
+				fail_clk->name);
+		__clk_recalc_rates(clk, ABORT_RATE_CHANGE);
+		ret = -EIO;
+	}
+
+out:
+	mutex_unlock(&prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+/**
+ * clk_get_parent - return the parent of a clk
+ * @clk: the clk whose parent gets returned
+ *
+ * Simply returns clk->parent.  Returns NULL if clk is NULL.
+ */
+struct clk *clk_get_parent(struct clk *clk)
+{
+	struct clk *parent;
+
+	mutex_lock(&prepare_lock);
+	parent = __clk_get_parent(clk);
+	mutex_unlock(&prepare_lock);
+
+	return parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+/*
+ * .get_parent is mandatory for clocks with multiple possible parents.  It is
+ * optional for single-parent clocks.  Always call .get_parent if it is
+ * available and WARN if it is missing for multi-parent clocks.
+ *
+ * For single-parent clocks without .get_parent, first check to see if the
+ * .parents array exists, and if so use it to avoid an expensive tree
+ * traversal.  If .parents does not exist then walk the tree with __clk_lookup.
+ */
+static struct clk *__clk_init_parent(struct clk *clk)
+{
+	struct clk *ret = NULL;
+	u8 index;
+
+	/* handle the trivial cases */
+
+	if (!clk->num_parents)
+		goto out;
+
+	if (clk->num_parents == 1) {
+		if (IS_ERR_OR_NULL(clk->parent))
+			ret = clk->parent = __clk_lookup(clk->parent_names[0]);
+		ret = clk->parent;
+		goto out;
+	}
+
+	if (!clk->ops->get_parent) {
+		WARN(!clk->ops->get_parent,
+			"%s: multi-parent clocks must implement .get_parent\n",
+			__func__);
+		goto out;
+	};
+
+	/*
+	 * Do our best to cache parent clocks in clk->parents.  This prevents
+	 * unnecessary and expensive calls to __clk_lookup.  We don't set
+	 * clk->parent here; that is done by the calling function
+	 */
+
+	index = clk->ops->get_parent(clk->hw);
+
+	if (!clk->parents)
+		clk->parents =
+			kmalloc((sizeof(struct clk*) * clk->num_parents),
+					GFP_KERNEL);
+
+	if (!clk->parents)
+		ret = __clk_lookup(clk->parent_names[index]);
+	else if (!clk->parents[index])
+		ret = clk->parents[index] =
+			__clk_lookup(clk->parent_names[index]);
+	else
+		ret = clk->parents[index];
+
+out:
+	return ret;
+}
+
+void __clk_reparent(struct clk *clk, struct clk *new_parent)
+{
+#ifdef CONFIG_COMMON_CLK_DEBUG
+	struct dentry *d;
+	struct dentry *new_parent_d;
+#endif
+
+	if (!clk || !new_parent)
+		return;
+
+	hlist_del(&clk->child_node);
+
+	if (new_parent)
+		hlist_add_head(&clk->child_node, &new_parent->children);
+	else
+		hlist_add_head(&clk->child_node, &clk_orphan_list);
+
+#ifdef CONFIG_COMMON_CLK_DEBUG
+	if (!inited)
+		goto out;
+
+	if (new_parent)
+		new_parent_d = new_parent->dentry;
+	else
+		new_parent_d = orphandir;
+
+	d = debugfs_rename(clk->dentry->d_parent, clk->dentry,
+			new_parent_d, clk->name);
+	if (d)
+		clk->dentry = d;
+	else
+		pr_debug("%s: failed to rename debugfs entry for %s\n",
+				__func__, clk->name);
+out:
+#endif
+
+	clk->parent = new_parent;
+
+	__clk_recalc_rates(clk, POST_RATE_CHANGE);
+}
+
+static int __clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk *old_parent;
+	unsigned long flags;
+	int ret = -EINVAL;
+	u8 i;
+
+	old_parent = clk->parent;
+
+	/* find index of new parent clock using cached parent ptrs */
+	for (i = 0; i < clk->num_parents; i++)
+		if (clk->parents[i] == parent)
+			break;
+
+	/*
+	 * find index of new parent clock using string name comparison
+	 * also try to cache the parent to avoid future calls to __clk_lookup
+	 */
+	if (i == clk->num_parents)
+		for (i = 0; i < clk->num_parents; i++)
+			if (!strcmp(clk->parent_names[i], parent->name)) {
+				clk->parents[i] = __clk_lookup(parent->name);
+				break;
+			}
+
+	if (i == clk->num_parents) {
+		pr_debug("%s: clock %s is not a possible parent of clock %s\n",
+				__func__, parent->name, clk->name);
+		goto out;
+	}
+
+	/* migrate prepare and enable */
+	if (clk->prepare_count)
+		__clk_prepare(parent);
+
+	/* FIXME replace with clk_is_enabled(clk) someday */
+	spin_lock_irqsave(&enable_lock, flags);
+	if (clk->enable_count)
+		__clk_enable(parent);
+	spin_unlock_irqrestore(&enable_lock, flags);
+
+	/* change clock input source */
+	ret = clk->ops->set_parent(clk->hw, i);
+
+	/* clean up old prepare and enable */
+	spin_lock_irqsave(&enable_lock, flags);
+	if (clk->enable_count)
+		__clk_disable(old_parent);
+	spin_unlock_irqrestore(&enable_lock, flags);
+
+	if (clk->prepare_count)
+		__clk_unprepare(old_parent);
+
+out:
+	return ret;
+}
+
+/**
+ * clk_set_parent - switch the parent of a mux clk
+ * @clk: the mux clk whose input we are switching
+ * @parent: the new input to clk
+ *
+ * Re-parent clk to use parent as it's new input source.  If clk has the
+ * CLK_SET_PARENT_GATE flag set then clk must be gated for this
+ * operation to succeed.  After successfully changing clk's parent
+ * clk_set_parent will update the clk topology, sysfs topology and
+ * propagate rate recalculation via __clk_recalc_rates.  Returns 0 on
+ * success, -EERROR otherwise.
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	int ret = 0;
+
+	if (!clk || !clk->ops)
+		return -EINVAL;
+
+	if (!clk->ops->set_parent)
+		return -ENOSYS;
+
+	/* prevent racing with updates to the clock topology */
+	mutex_lock(&prepare_lock);
+
+	if (clk->parent == parent)
+		goto out;
+
+	/* propagate PRE_RATE_CHANGE notifications */
+	if (clk->notifier_count)
+		ret = __clk_speculate_rates(clk, parent->rate);
+
+	/* abort if a driver objects */
+	if (ret == NOTIFY_STOP)
+		goto out;
+
+	/* only re-parent if the clock is not in use */
+	if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count)
+		ret = -EBUSY;
+	else
+		ret = __clk_set_parent(clk, parent);
+
+	/* propagate ABORT_RATE_CHANGE if .set_parent failed */
+	if (ret) {
+		__clk_recalc_rates(clk, ABORT_RATE_CHANGE);
+		goto out;
+	}
+
+	/* propagate rate recalculation downstream */
+	__clk_reparent(clk, parent);
+
+out:
+	mutex_unlock(&prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+/**
+ * __clk_init - initialize the data structures in a struct clk
+ * @dev:	device initializing this clk, placeholder for now
+ * @clk:	clk being initialized
+ *
+ * Initializes the lists in struct clk, queries the hardware for the
+ * parent and rate and sets them both.
+ *
+ * Any struct clk passed into __clk_init must have the following members
+ * populated:
+ * 	.name
+ * 	.ops
+ * 	.hw
+ * 	.parent_names
+ * 	.num_parents
+ * 	.flags
+ *
+ * Essentially, everything that would normally be passed into clk_register is
+ * assumed to be initialized already in __clk_init.  The other members may be
+ * populated, but are optional.
+ *
+ * __clk_init is only exposed via clk-private.h and is intended for use with
+ * very large numbers of clocks that need to be statically initialized.  It is
+ * a layering violation to include clk-private.h from any code which implements
+ * a clock's .ops; as such any statically initialized clock data MUST be in a
+ * separate C file from the logic that implements it's operations.
+ */
+void __clk_init(struct device *dev, struct clk *clk)
+{
+	int i;
+	struct clk *orphan;
+	struct hlist_node *tmp;
+
+	if (!clk)
+		return;
+
+	mutex_lock(&prepare_lock);
+
+	/* check to see if a clock with this name is already registered */
+	if (__clk_lookup(clk->name))
+		goto out;
+
+	/*
+	 * Allocate an array of struct clk *'s to avoid unnecessary string
+	 * look-ups of clk's possible parents.  This can fail for clocks passed
+	 * in to clk_init during early boot; thus any access to clk->parents[]
+	 * must always check for a NULL pointer and try to populate it if
+	 * necessary.
+	 *
+	 * If clk->parents is not NULL we skip this entire block.  This allows
+	 * for clock drivers to statically initialize clk->parents.
+	 */
+	if (clk->num_parents && !clk->parents) {
+		clk->parents = kmalloc((sizeof(struct clk*) * clk->num_parents),
+				GFP_KERNEL);
+		/*
+		 * __clk_lookup returns NULL for parents that have not been
+		 * clk_init'd; thus any access to clk->parents[] must check
+		 * for a NULL pointer.  We can always perform lazy lookups for
+		 * missing parents later on.
+		 */
+		if (clk->parents)
+			for (i = 0; i < clk->num_parents; i++)
+				clk->parents[i] =
+					__clk_lookup(clk->parent_names[i]);
+	}
+
+	clk->parent = __clk_init_parent(clk);
+
+	/*
+	 * Populate clk->parent if parent has already been __clk_init'd.  If
+	 * parent has not yet been __clk_init'd then place clk in the orphan
+	 * list.  If clk has set the CLK_IS_ROOT flag then place it in the root
+	 * clk list.
+	 *
+	 * Every time a new clk is clk_init'd then we walk the list of orphan
+	 * clocks and re-parent any that are children of the clock currently
+	 * being clk_init'd.
+	 */
+	if (clk->parent)
+		hlist_add_head(&clk->child_node,
+				&clk->parent->children);
+	else if (clk->flags & CLK_IS_ROOT)
+		hlist_add_head(&clk->child_node, &clk_root_list);
+	else
+		hlist_add_head(&clk->child_node, &clk_orphan_list);
+
+	/*
+	 * Set clk's rate.  The preferred method is to use .recalc_rate.  For
+	 * simple clocks and lazy developers the default fallback is to use the
+	 * parent's rate.  If a clock doesn't have a parent (or is orphaned)
+	 * then rate is set to zero.
+	 */
+	if (clk->ops->recalc_rate)
+		clk->rate = clk->ops->recalc_rate(clk->hw,
+				__clk_get_rate(clk->parent));
+	else if (clk->parent)
+		clk->rate = clk->parent->rate;
+	else
+		clk->rate = 0;
+
+	/*
+	 * walk the list of orphan clocks and reparent any that are children of
+	 * this clock
+	 */
+	hlist_for_each_entry(orphan, tmp, &clk_orphan_list, child_node)
+		__clk_reparent(orphan, __clk_init_parent(orphan));
+
+	/*
+	 * optional platform-specific magic
+	 *
+	 * The .init callback is not used by any of the basic clock types, but
+	 * exists for weird hardware that must perform initialization magic.
+	 * Please consider other ways of solving initialization problems before
+	 * using this callback, as it's use is discouraged.
+	 */
+	if (clk->ops->init)
+		clk->ops->init(clk->hw);
+
+	clk_debug_register(clk);
+
+out:
+	mutex_unlock(&prepare_lock);
+
+	return;
+}
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @name: clock name
+ * @ops: operations this clock supports
+ * @hw: link to hardware-specific clock data
+ * @parent_names: array of string names for all possible parents
+ * @num_parents: number of possible parents
+ * @flags: framework-level hints and quirks
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API.
+ */
+struct clk *clk_register(struct device *dev, const char *name,
+		const struct clk_ops *ops, struct clk_hw *hw,
+		char **parent_names, u8 num_parents, unsigned long flags)
+{
+	struct clk *clk;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return NULL;
+
+	clk->name = name;
+	clk->ops = ops;
+	clk->hw = hw;
+	clk->flags = flags;
+	clk->parent_names = parent_names;
+	clk->num_parents = num_parents;
+	hw->clk = clk;
+
+	__clk_init(dev, clk);
+
+	return clk;
+}
+EXPORT_SYMBOL_GPL(clk_register);
+
+/***        clk rate change notifiers        ***/
+
+/**
+ * clk_notifier_register - add a clk rate change notifier
+ * @clk: struct clk * to watch
+ * @nb: struct notifier_block * with callback info
+ *
+ * Request notification when clk's rate changes.  This uses an SRCU
+ * notifier because we want it to block and notifier unregistrations are
+ * uncommon.  The callbacks associated with the notifier must not
+ * re-enter into the clk framework by calling any top-level clk APIs;
+ * this will cause a nested prepare_lock mutex.
+ *
+ * Pre-change notifier callbacks will be passed the current, pre-change
+ * rate of the clk via struct clk_notifier_data.old_rate.  The new,
+ * post-change rate of the clk is passed via struct
+ * clk_notifier.new_rate.
+ *
+ * Post-change notifiers will pass the now-current, post-change rate of
+ * the clk in both struct clk_notifier_data.old_rate and struct
+ * clk_notifier_data.new_rate.
+ *
+ * Abort-change notifiers are effectively the opposite of pre-change
+ * notifiers: the original pre-change clk rate is passed in via struct
+ * clk_notifier_data.new_rate and the failed post-change rate is passed
+ * in via struct clk_notifier_data.old_rate.
+ *
+ * clk_notifier_register() must be called from non-atomic context.
+ * Returns -EINVAL if called with null arguments, -ENOMEM upon
+ * allocation failure; otherwise, passes along the return value of
+ * srcu_notifier_chain_register().
+ */
+int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
+{
+	struct clk_notifier *cn;
+	int ret = -ENOMEM;
+
+	if (!clk || !nb)
+		return -EINVAL;
+
+	mutex_lock(&prepare_lock);
+
+	/* search the list of notifiers for this clk */
+	list_for_each_entry(cn, &clk_notifier_list, node)
+		if (cn->clk == clk)
+			break;
+
+	/* if clk wasn't in the notifier list, allocate new clk_notifier */
+	if (cn->clk != clk) {
+		cn = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
+		if (!cn)
+			goto out;
+
+		cn->clk = clk;
+		srcu_init_notifier_head(&cn->notifier_head);
+
+		list_add(&cn->node, &clk_notifier_list);
+	}
+
+	ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
+
+	clk->notifier_count++;
+
+out:
+	mutex_unlock(&prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_notifier_register);
+
+/**
+ * clk_notifier_unregister - remove a clk rate change notifier
+ * @clk: struct clk *
+ * @nb: struct notifier_block * with callback info
+ *
+ * Request no further notification for changes to 'clk' and frees memory
+ * allocated in clk_notifier_register.
+ *
+ * Returns -EINVAL if called with null arguments; otherwise, passes
+ * along the return value of srcu_notifier_chain_unregister().
+ */
+int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
+{
+	struct clk_notifier *cn = NULL;
+	int ret = -EINVAL;
+
+	if (!clk || !nb)
+		return -EINVAL;
+
+	mutex_lock(&prepare_lock);
+
+	list_for_each_entry(cn, &clk_notifier_list, node)
+		if (cn->clk == clk)
+			break;
+
+	if (cn->clk == clk) {
+		ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
+
+		clk->notifier_count--;
+
+		/* XXX the notifier code should handle this better */
+		if (!cn->notifier_head.head) {
+			srcu_cleanup_notifier_head(&cn->notifier_head);
+			kfree(cn);
+		}
+
+	} else {
+		ret = -ENOENT;
+	}
+
+	mutex_unlock(&prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_notifier_unregister);
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
new file mode 100644
index 0000000..33bf6a7
--- /dev/null
+++ b/include/linux/clk-private.h
@@ -0,0 +1,68 @@
+/*
+ *  linux/include/linux/clk-private.h
+ *
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
+ *  Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __LINUX_CLK_PRIVATE_H
+#define __LINUX_CLK_PRIVATE_H
+
+#include <linux/clk-provider.h>
+#include <linux/list.h>
+
+/*
+ * WARNING: Do not include clk-private.h from any file that implements struct
+ * clk_ops.  Doing so is a layering violation!
+ *
+ * This header exists only to allow for statically initialized clock data.  Any
+ * static clock data must be defined in a separate file from the logic that
+ * implements the clock operations for that same data.
+ */
+
+#ifdef CONFIG_COMMON_CLK
+
+struct clk {
+	const char		*name;
+	const struct clk_ops	*ops;
+	struct clk_hw		*hw;
+	struct clk		*parent;
+	char			**parent_names;
+	struct clk		**parents;
+	u8			num_parents;
+	unsigned long		rate;
+	unsigned long		flags;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	struct hlist_head	children;
+	struct hlist_node	child_node;
+	unsigned int		notifier_count;
+#ifdef CONFIG_COMMON_CLK_DEBUG
+	struct dentry		*dentry;
+#endif
+};
+
+/**
+ * __clk_init - initialize the data structures in a struct clk
+ * @dev:	device initializing this clk, placeholder for now
+ * @clk:	clk being initialized
+ *
+ * Initializes the lists in struct clk, queries the hardware for the
+ * parent and rate and sets them both.
+ *
+ * Any struct clk passed into __clk_init must have the following members
+ * populated:
+ * 	.name
+ * 	.ops
+ * 	.hw
+ * 	.parent_names
+ * 	.num_parents
+ * 	.flags
+ */
+void __clk_init(struct device *dev, struct clk *clk);
+
+#endif /* CONFIG_COMMON_CLK */
+#endif /* CLK_PRIVATE_H */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
new file mode 100644
index 0000000..c9ed582
--- /dev/null
+++ b/include/linux/clk-provider.h
@@ -0,0 +1,169 @@
+/*
+ *  linux/include/linux/clk-provider.h
+ *
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
+ *  Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
+ *
+ * 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.
+ */
+#ifndef __LINUX_CLK_PROVIDER_H
+#define __LINUX_CLK_PROVIDER_H
+
+#include <linux/clk.h>
+
+#ifdef CONFIG_COMMON_CLK
+
+/**
+ * struct clk_hw - handle for traversing from a struct clk to its corresponding
+ * hardware-specific structure.  struct clk_hw should be declared within struct
+ * clk_foo and then referenced by the struct clk instance that uses struct
+ * clk_foo's clk_ops
+ *
+ * clk: pointer to the struct clk instance that points back to this struct
+ * clk_hw instance
+ */
+struct clk_hw {
+	struct clk *clk;
+};
+
+/*
+ * flags used across common struct clk.  these flags should only affect the
+ * top-level framework.  custom flags for dealing with hardware specifics
+ * belong in struct clk_foo
+ */
+#define CLK_SET_RATE_GATE	BIT(0) /* must be gated across rate change */
+#define CLK_SET_PARENT_GATE	BIT(1) /* must be gated across re-parent */
+#define CLK_SET_RATE_PARENT	BIT(2) /* propagate rate change up one level */
+#define CLK_IGNORE_UNUSED	BIT(3) /* do not gate even if unused */
+#define CLK_IS_ROOT		BIT(4) /* root clk, has no parent */
+
+/**
+ * struct clk_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.  The
+ * 		parent rate is an input parameter.  It is up to the caller to
+ * 		insure that the prepare_mutex is held across this call.
+ * 		Returns the calculated rate.  Optional, but recommended - if
+ * 		this op is not set then clock rate will be initialized to 0.
+ *
+ * @round_rate:	Given a target rate as input, returns the closest rate actually
+ * 		supported by the clock.
+ *
+ * @get_parent:	Queries the hardware to determine the parent of a clock.  The
+ * 		return value is a u8 which specifies the index corresponding to
+ * 		the parent clock.  This index can be applied to either the
+ * 		.parent_names or .parents arrays.  In short, this function
+ * 		translates the parent value read from hardware into an array
+ * 		index.  Currently only called when the clock is initialized by
+ * 		__clk_init.  This callback is mandatory for clocks with
+ * 		multiple parents.  It is optional (and unnecessary) for clocks
+ * 		with 0 or 1 parents.
+ *
+ * @set_parent:	Change the input source of this clock; for clocks with multiple
+ * 		possible parents specify a new parent by passing in the index
+ * 		as a u8 corresponding to the parent in either the .parent_names
+ * 		or .parents arrays.  This function in affect translates an
+ * 		array index into the value programmed into the hardware.
+ * 		Returns 0 on success, -EERROR otherwise.
+ *
+ * @set_rate:	Change the rate of this clock. If this callback returns
+ * 		CLK_SET_RATE_PARENT, the rate change will be propagated to the
+ * 		parent clock (which may propagate again if the parent clock
+ * 		also sets this flag). The requested rate of the parent is
+ * 		passed back from the callback in the second 'unsigned long *'
+ * 		argument.  Note that it is up to the hardware clock's set_rate
+ * 		implementation to insure that clocks do not run out of spec
+ * 		when propgating the call to set_rate up to the parent.  One way
+ * 		to do this is to gate the clock (via clk_disable and/or
+ * 		clk_unprepare) before calling clk_set_rate, then ungating it
+ * 		afterward.  If your clock also has the CLK_GATE_SET_RATE flag
+ * 		set then this will insure safety.  Returns 0 on success,
+ * 		-EERROR otherwise.
+ *
+ * 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 enabling a clock requires code that might sleep,
+ * this must be done in clk_prepare.  Clock enable code that will never be
+ * called in a sleepable context may be implement 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_ops {
+	int		(*prepare)(struct clk_hw *hw);
+	void		(*unprepare)(struct clk_hw *hw);
+	int		(*enable)(struct clk_hw *hw);
+	void		(*disable)(struct clk_hw *hw);
+	unsigned long	(*recalc_rate)(struct clk_hw *hw,
+					unsigned long parent_rate);
+	long		(*round_rate)(struct clk_hw *hw, unsigned long,
+					unsigned long *);
+	int		(*set_parent)(struct clk_hw *hw, u8 index);
+	u8		(*get_parent)(struct clk_hw *hw);
+	int		(*set_rate)(struct clk_hw *hw, unsigned long);
+	void		(*init)(struct clk_hw *hw);
+};
+
+
+/**
+ * clk_register - allocate a new clock, register it and return an opaque cookie
+ * @dev: device that is registering this clock
+ * @name: clock name
+ * @ops: operations this clock supports
+ * @hw: link to hardware-specific clock data
+ * @parent_names: array of string names for all possible parents
+ * @num_parents: number of possible parents
+ * @flags: framework-level hints and quirks
+ *
+ * clk_register is the primary interface for populating the clock tree with new
+ * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * cannot be dereferenced by driver code but may be used in conjuction with the
+ * rest of the clock API.
+ */
+struct clk *clk_register(struct device *dev, const char *name,
+		const struct clk_ops *ops, struct clk_hw *hw,
+		char **parent_names, u8 num_parents, unsigned long flags);
+
+/* helper functions */
+const char *__clk_get_name(struct clk *clk);
+struct clk_hw *__clk_get_hw(struct clk *clk);
+u8 __clk_get_num_parents(struct clk *clk);
+struct clk *__clk_get_parent(struct clk *clk);
+unsigned long __clk_get_rate(struct clk *clk);
+unsigned long __clk_get_flags(struct clk *clk);
+struct clk *__clk_lookup(const char *name);
+
+/*
+ * FIXME clock api without lock protection
+ */
+int __clk_prepare(struct clk *clk);
+void __clk_unprepare(struct clk *clk);
+void __clk_reparent(struct clk *clk, struct clk *new_parent);
+unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
+
+#endif /* CONFIG_COMMON_CLK */
+#endif /* CLK_PROVIDER_H */
diff --git a/include/linux/clk.h b/include/linux/clk.h
index b9d46fa..b025272 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) 2011-2012 Linaro Ltd <mturquette@linaro.org>
  *
  * 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
@@ -12,18 +13,75 @@
 #define __LINUX_CLK_H
 
 #include <linux/kernel.h>
+#include <linux/notifier.h>
 
 struct device;
 
-/*
- * The base API.
+struct clk;
+
+#ifdef CONFIG_COMMON_CLK
+
+/**
+ * DOC: clk notifier callback types
+ *
+ * PRE_RATE_CHANGE - called immediately before the clk rate is changed,
+ *     to indicate that the rate change will proceed.  Drivers must
+ *     immediately terminate any operations that will be affected by the
+ *     rate change.  Callbacks may either return NOTIFY_DONE or
+ *     NOTIFY_STOP.
+ *
+ * ABORT_RATE_CHANGE: called if the rate change failed for some reason
+ *     after PRE_RATE_CHANGE.  In this case, all registered notifiers on
+ *     the clk will be called with ABORT_RATE_CHANGE. Callbacks must
+ *     always return NOTIFY_DONE.
+ *
+ * POST_RATE_CHANGE - called after the clk rate change has successfully
+ *     completed.  Callbacks must always return NOTIFY_DONE.
+ *
  */
+#define PRE_RATE_CHANGE			BIT(0)
+#define POST_RATE_CHANGE		BIT(1)
+#define ABORT_RATE_CHANGE		BIT(2)
 
+/**
+ * struct clk_notifier - associate a clk with a notifier
+ * @clk: struct clk * to associate the notifier with
+ * @notifier_head: a blocking_notifier_head for this clk
+ * @node: linked list pointers
+ *
+ * A list of struct clk_notifier is maintained by the notifier code.
+ * An entry is created whenever code registers the first notifier on a
+ * particular @clk.  Future notifiers on that @clk are added to the
+ * @notifier_head.
+ */
+struct clk_notifier {
+	struct clk			*clk;
+	struct srcu_notifier_head	notifier_head;
+	struct list_head		node;
+};
 
-/*
- * struct clk - an machine class defined object / cookie.
+/**
+ * struct clk_notifier_data - rate data to pass to the notifier callback
+ * @clk: struct clk * being changed
+ * @old_rate: previous rate of this clk
+ * @new_rate: new rate of this clk
+ *
+ * For a pre-notifier, old_rate is the clk's rate before this rate
+ * change, and new_rate is what the rate will be in the future.  For a
+ * post-notifier, old_rate and new_rate are both set to the clk's
+ * current rate (this was done to optimize the implementation).
  */
-struct clk;
+struct clk_notifier_data {
+	struct clk		*clk;
+	unsigned long		old_rate;
+	unsigned long		new_rate;
+};
+
+int clk_notifier_register(struct clk *clk, struct notifier_block *nb);
+
+int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
+
+#endif /* !CONFIG_COMMON_CLK */
 
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
-- 
1.7.5.4


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

* [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-03  8:28 [PATCH v5 0/4] common clk framework Mike Turquette
                   ` (2 preceding siblings ...)
  2012-03-03  8:29 ` [PATCH v5 3/4] clk: introduce the common clock framework Mike Turquette
@ 2012-03-03  8:29 ` Mike Turquette
  2012-03-04 14:26   ` Andrew Lunn
                     ` (4 more replies)
  2012-03-09  2:34 ` [PATCH v5 0/4] common clk framework Richard Zhao
  4 siblings, 5 replies; 51+ messages in thread
From: Mike Turquette @ 2012-03-03  8:29 UTC (permalink / raw)
  To: Russell King
  Cc: patches, linaro-dev, linux-kernel, linux-arm-kernel,
	Mike Turquette, Mike Turquette, Jeremy Kerr, Thomas Gleixner,
	Arnd Bergman, Paul Walmsley, Shawn Guo, Sascha Hauer, Jamie Iles,
	Richard Zhao, Saravana Kannan, Magnus Damm, Rob Herring,
	Mark Brown, Linus Walleij, Stephen Boyd, Amit Kucheria,
	Deepak Saxena, Grant Likely, Andrew Lunn

Many platforms support simple gateable clocks, fixed-rate clocks,
adjustable divider clocks and multi-parent multiplexer clocks.

This patch introduces basic clock types for the above-mentioned hardware
which share some common characteristics.

Based on original work by Jeremy Kerr and contribution by Jamie Iles.
Dividers and multiplexor clocks originally contributed by Richard Zhao &
Sascha Hauer.

Signed-off-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Mike Turquette <mturquette@ti.com>
Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnd Bergman <arnd.bergmann@linaro.org>
Cc: Paul Walmsley <paul@pwsan.com>
Cc: Shawn Guo <shawn.guo@freescale.com>
Cc: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Jamie Iles <jamie@jamieiles.com>
Cc: Richard Zhao <richard.zhao@linaro.org>
Cc: Saravana Kannan <skannan@codeaurora.org>
Cc: Magnus Damm <magnus.damm@gmail.com>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
Cc: Linus Walleij <linus.walleij@stericsson.com>
Cc: Stephen Boyd <sboyd@codeaurora.org>
Cc: Amit Kucheria <amit.kucheria@linaro.org>
Cc: Deepak Saxena <dsaxena@linaro.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Andrew Lunn <andrew@lunn.ch>
---
 drivers/clk/Makefile         |    3 +-
 drivers/clk/clk-divider.c    |  198 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clk-fixed-rate.c |   81 +++++++++++++++++
 drivers/clk/clk-gate.c       |  121 +++++++++++++++++++++++++
 drivers/clk/clk-mux.c        |  114 ++++++++++++++++++++++++
 include/linux/clk-private.h  |  124 ++++++++++++++++++++++++++
 include/linux/clk-provider.h |  125 ++++++++++++++++++++++++++
 7 files changed, 765 insertions(+), 1 deletions(-)
 create mode 100644 drivers/clk/clk-divider.c
 create mode 100644 drivers/clk/clk-fixed-rate.c
 create mode 100644 drivers/clk/clk-gate.c
 create mode 100644 drivers/clk/clk-mux.c

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index ff362c4..1f736bc 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,3 +1,4 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
-obj-$(CONFIG_COMMON_CLK)	+= clk.o
+obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed-rate.o clk-gate.o \
+				   clk-mux.o clk-divider.o
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
new file mode 100644
index 0000000..8f02930
--- /dev/null
+++ b/drivers/clk/clk-divider.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * 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.
+ *
+ * Adjustable divider clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+
+/*
+ * DOC: basic adjustable divider clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.  clk->rate = parent->rate / divisor
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
+static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_divider *divider = to_clk_divider(hw);
+	unsigned int div;
+
+	div = readl(divider->reg) >> divider->shift;
+	div &= (1 << divider->width) - 1;
+
+	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
+		div++;
+
+	return parent_rate / div;
+}
+
+static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
+		unsigned long *best_parent_rate)
+{
+	struct clk_divider *divider = to_clk_divider(hw);
+	int i, bestdiv = 0;
+	unsigned long parent_rate, best = 0, now, maxdiv;
+
+	maxdiv = (1 << divider->width);
+
+	if (divider->flags & CLK_DIVIDER_ONE_BASED)
+		maxdiv--;
+
+	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
+		parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
+		bestdiv = parent_rate / rate;
+		bestdiv = bestdiv == 0 ? 1 : bestdiv;
+		bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+		goto out;
+	}
+
+	/*
+	 * The maximum divider we can use without overflowing
+	 * unsigned long in rate * i below
+	 */
+	maxdiv = min(ULONG_MAX / rate, maxdiv);
+
+	for (i = 1; i <= maxdiv; i++) {
+		int div;
+		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
+				rate * i);
+		div = parent_rate / rate;
+		div = div > maxdiv ? maxdiv : div;
+		div = div < 1 ? 1 : div;
+		now = parent_rate / div;
+
+		if (now <= rate && now >= best) {
+			bestdiv = div;
+			best = now;
+			*best_parent_rate = parent_rate;
+		}
+	}
+
+	if (!bestdiv) {
+		bestdiv = (1 << divider->width);
+		parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1);
+	} else {
+		parent_rate = best * bestdiv;
+	}
+
+out:
+	if (best_parent_rate)
+		*best_parent_rate = parent_rate;
+
+	return bestdiv;
+}
+
+static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	unsigned long best_parent_rate;
+	int div = clk_divider_bestdiv(hw, rate, &best_parent_rate);
+	if (prate) {
+		if (best_parent_rate == __clk_get_rate(
+					__clk_get_parent(hw->clk)))
+			*prate = 0;
+		else
+			*prate = best_parent_rate;
+	}
+
+	return best_parent_rate / div;
+}
+
+static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate)
+{
+	unsigned long best_parent_rate;
+	struct clk_divider *divider = to_clk_divider(hw);
+	unsigned int div;
+	unsigned long flags = 0;
+	u32 val;
+
+	div = clk_divider_bestdiv(hw, rate, &best_parent_rate);
+
+	if (divider->lock)
+		spin_lock_irqsave(divider->lock, flags);
+
+	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
+		div--;
+
+	val = readl(divider->reg);
+	val &= ~(((1 << divider->width) - 1) << divider->shift);
+	val |= div << divider->shift;
+	writel(val, divider->reg);
+
+	if (divider->lock)
+		spin_unlock_irqrestore(divider->lock, flags);
+
+	return 0;
+}
+
+struct clk_ops clk_divider_ops = {
+	.recalc_rate = clk_divider_recalc_rate,
+	.round_rate = clk_divider_round_rate,
+	.set_rate = clk_divider_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_divider_ops);
+
+struct clk *clk_register_divider(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_divider_flags, spinlock_t *lock)
+{
+	struct clk_divider *div;
+	char **parent_names = NULL;
+	u8 len;
+
+	div = kmalloc(sizeof(struct clk_divider), GFP_KERNEL);
+
+	if (!div) {
+		pr_err("%s: could not allocate divider clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_divider assignments */
+	div->reg = reg;
+	div->shift = shift;
+	div->width = width;
+	div->flags = clk_divider_flags;
+	div->lock = lock;
+
+	if (parent_name) {
+		parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
+
+		if (! parent_names)
+			goto out;
+
+		len = sizeof(char) * strlen(parent_name);
+
+		parent_names[0] = kmalloc(len, GFP_KERNEL);
+
+		if (!parent_names[0])
+			goto out;
+
+		strncpy(parent_names[0], parent_name, len);
+	}
+
+out:
+	return clk_register(dev, name,
+			&clk_divider_ops, &div->hw,
+			parent_names,
+			(parent_name ? 1 : 0),
+			flags);
+}
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
new file mode 100644
index 0000000..651b06f
--- /dev/null
+++ b/drivers/clk/clk-fixed-rate.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * 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.
+ *
+ * Fixed rate clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+/*
+ * DOC: basic fixed-rate clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parents are prepared
+ * enable - clk_enable only ensures parents are enabled
+ * rate - rate is always a fixed value.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw)
+
+static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	return to_clk_fixed_rate(hw)->fixed_rate;
+}
+
+struct clk_ops clk_fixed_rate_ops = {
+	.recalc_rate = clk_fixed_rate_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
+
+struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		unsigned long fixed_rate)
+{
+	struct clk_fixed_rate *fixed;
+	char **parent_names = NULL;
+	u8 len;
+
+	fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
+
+	if (!fixed) {
+		pr_err("%s: could not allocate fixed clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_fixed_rate assignments */
+	fixed->fixed_rate = fixed_rate;
+
+	if (parent_name) {
+		parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
+
+		if (! parent_names)
+			goto out;
+
+		len = sizeof(char) * strlen(parent_name);
+
+		parent_names[0] = kmalloc(len, GFP_KERNEL);
+
+		if (!parent_names[0])
+			goto out;
+
+		strncpy(parent_names[0], parent_name, len);
+	}
+
+out:
+	return clk_register(dev, name,
+			&clk_fixed_rate_ops, &fixed->hw,
+			parent_names,
+			(parent_name ? 1 : 0),
+			flags);
+}
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
new file mode 100644
index 0000000..e831f7b
--- /dev/null
+++ b/drivers/clk/clk-gate.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * 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.
+ *
+ * Gated clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+
+/**
+ * DOC: basic gatable clock which can gate and ungate it's ouput
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent are prepared
+ * enable - clk_enable and clk_disable are functional & control gating
+ * rate - inherits rate from parent.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
+
+static void clk_gate_set_bit(struct clk_gate *gate)
+{
+	u32 reg;
+
+	reg = readl(gate->reg);
+	reg |= BIT(gate->bit_idx);
+	writel(reg, gate->reg);
+}
+
+static void clk_gate_clear_bit(struct clk_gate *gate)
+{
+	u32 reg;
+
+	reg = readl(gate->reg);
+	reg &= ~BIT(gate->bit_idx);
+	writel(reg, gate->reg);
+}
+
+static int clk_gate_enable(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+		clk_gate_clear_bit(gate);
+	else
+		clk_gate_set_bit(gate);
+
+	return 0;
+}
+
+static void clk_gate_disable(struct clk_hw *hw)
+{
+	struct clk_gate *gate = to_clk_gate(hw);
+
+	if (gate->flags & CLK_GATE_SET_TO_DISABLE)
+		clk_gate_set_bit(gate);
+	else
+		clk_gate_clear_bit(gate);
+}
+
+struct clk_ops clk_gate_ops = {
+	.enable = clk_gate_enable,
+	.disable = clk_gate_disable,
+};
+EXPORT_SYMBOL_GPL(clk_gate_ops);
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock)
+{
+	struct clk_gate *gate;
+	char **parent_names = NULL;
+	u8 len;
+
+	gate = kmalloc(sizeof(struct clk_gate), GFP_KERNEL);
+
+	if (!gate) {
+		pr_err("%s: could not allocate gated clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_gate assignments */
+	gate->reg = reg;
+	gate->bit_idx = bit_idx;
+	gate->flags = clk_gate_flags;
+	gate->lock = lock;
+
+	if (parent_name) {
+		parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
+
+		if (! parent_names)
+			goto out;
+
+		len = sizeof(char) * strlen(parent_name);
+
+		parent_names[0] = kmalloc(len, GFP_KERNEL);
+
+		if (!parent_names[0])
+			goto out;
+
+		strncpy(parent_names[0], parent_name, len);
+	}
+
+out:
+	return clk_register(dev, name,
+			&clk_gate_ops, &gate->hw,
+			parent_names,
+			(parent_name ? 1 : 0),
+			flags);
+}
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
new file mode 100644
index 0000000..bb66f26
--- /dev/null
+++ b/drivers/clk/clk-mux.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
+ *
+ * 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 multiplexer clock implementation
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+
+/*
+ * DOC: basic adjustable multiplexer clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is only affected by parent switching.  No clk_set_rate support
+ * parent - parent is adjustable through clk_set_parent
+ */
+
+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
+
+static u8 clk_mux_get_parent(struct clk_hw *hw)
+{
+	struct clk_mux *mux = to_clk_mux(hw);
+	u32 val;
+
+	/*
+	 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
+	 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
+	 * to 0x7 (index starts at one)
+	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
+	 * val = 0x4 really means "bit 2, index starts at bit 0"
+	 */
+	val = readl(mux->reg) >> mux->shift;
+	val &= (1 << mux->width) - 1;
+
+	if (val && (mux->flags & CLK_MUX_INDEX_BIT))
+		val = ffs(val) - 1;
+
+	if (val && (mux->flags & CLK_MUX_INDEX_ONE))
+		val--;
+
+	if (val >= __clk_get_num_parents(hw->clk))
+		return -EINVAL;
+
+	return val;
+}
+
+static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_mux *mux = to_clk_mux(hw);
+	u32 val;
+	unsigned long flags = 0;
+
+	if (mux->flags & CLK_MUX_INDEX_BIT)
+		index = (1 << ffs(index));
+
+	if (mux->flags & CLK_MUX_INDEX_ONE)
+		index++;
+
+	if (mux->lock)
+		spin_lock_irqsave(mux->lock, flags);
+
+	val = readl(mux->reg);
+	val &= ~(((1 << mux->width) - 1) << mux->shift);
+	val |= index << mux->shift;
+	writel(val, mux->reg);
+
+	if (mux->lock)
+		spin_unlock_irqrestore(mux->lock, flags);
+
+	return 0;
+}
+
+struct clk_ops clk_mux_ops = {
+	.get_parent = clk_mux_get_parent,
+	.set_parent = clk_mux_set_parent,
+};
+EXPORT_SYMBOL_GPL(clk_mux_ops);
+
+struct clk *clk_register_mux(struct device *dev, const char *name,
+		char **parent_names, u8 num_parents, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_mux_flags, spinlock_t *lock)
+{
+	struct clk_mux *mux;
+
+	mux = kmalloc(sizeof(struct clk_mux), GFP_KERNEL);
+
+	if (!mux) {
+		pr_err("%s: could not allocate mux clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_mux assignments */
+	mux->reg = reg;
+	mux->shift = shift;
+	mux->width = width;
+	mux->flags = clk_mux_flags;
+	mux->lock = lock;
+
+	return clk_register(dev, name, &clk_mux_ops, &mux->hw,
+			parent_names, num_parents, flags);
+}
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 33bf6a7..d06e6fb 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -45,6 +45,130 @@ struct clk {
 #endif
 };
 
+/*
+ * DOC: Basic clock implementations common to many platforms
+ *
+ * Each basic clock hardware type is comprised of a structure describing the
+ * clock hardware, implementations of the relevant callbacks in struct clk_ops,
+ * unique flags for that hardware type, a registration function and an
+ * alternative macro for static initialization
+ */
+
+extern struct clk_ops clk_fixed_rate_ops;
+
+#define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate,		\
+				_fixed_rate_flags)		\
+	static struct clk _name;				\
+	static char *_name##_parent_names[] = {};		\
+	static struct clk_fixed_rate _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.fixed_rate = _rate,				\
+		.flags = _fixed_rate_flags,			\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_fixed_rate_ops,			\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _name##_parent_names,		\
+		.num_parents =					\
+			ARRAY_SIZE(_name##_parent_names),	\
+		.flags = _flags,				\
+	};
+
+extern struct clk_ops clk_gate_ops;
+
+#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,	\
+				_flags, _reg, _bit_idx,		\
+				_gate_flags, _lock)		\
+	static struct clk _name;				\
+	static char *_name##_parent_names[] = {			\
+		_parent_name,					\
+	};							\
+	static struct clk *_name##_parents[] = {		\
+		_parent_ptr,					\
+	};							\
+	static struct clk_gate _name##_hw = {			\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.reg = _reg,					\
+		.bit_idx = _bit_idx,				\
+		.flags = _gate_flags				\
+		.lock = _lock,					\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_gate_ops,				\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _name##_parent_names,		\
+		.num_parents =					\
+			ARRAY_SIZE(_name##parent_names),	\
+		.parents = _name##_parents,			\
+		.flags = _flags,				\
+	};
+
+extern struct clk_ops clk_divider_ops;
+
+#define DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
+				_flags, _reg, _shift, _width,	\
+				_divider_flags, _lock)		\
+	static struct clk _name;				\
+	static char *_name##_parent_names[] = {			\
+		_parent_name,					\
+	};							\
+	static struct clk *_name##_parents[] = {		\
+		_parent_ptr,					\
+	};							\
+	static struct clk_divider _name##_hw = {		\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.reg = _reg,					\
+		.shift = _shift,				\
+		.width = _width,				\
+		.flags = _divider_flags,			\
+		.lock = _lock,					\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_divider_ops,			\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _name##_parent_names,		\
+		.num_parents =					\
+			ARRAY_SIZE(_name##_parent_names),	\
+		.parents = _name##_parents,			\
+		.flags = _flags,				\
+	};
+
+extern struct clk_ops clk_mux_ops;
+
+#define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags,	\
+				_reg, _shift, _width,		\
+				_mux_flags, _lock)		\
+	static struct clk _name;				\
+	static struct clk_mux _name##_hw = {			\
+		.hw = {						\
+			.clk = &_name,				\
+		},						\
+		.reg = _reg,					\
+		.shift = _shift,				\
+		.width = _width,				\
+		.flags = _mux_flags,				\
+		.lock = _lock,					\
+	};							\
+	static struct clk _name = {				\
+		.name = #_name,					\
+		.ops = &clk_mux_ops,				\
+		.hw = &_name##_hw.hw,				\
+		.parent_names = _parent_names,			\
+		.num_parents =					\
+			ARRAY_SIZE(_parent_names),		\
+		.parents = _parents,				\
+		.flags = _flags,				\
+	};
+
 /**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index c9ed582..9b7dd5e 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -128,6 +128,131 @@ struct clk_ops {
 	void		(*init)(struct clk_hw *hw);
 };
 
+/*
+ * DOC: Basic clock implementations common to many platforms
+ *
+ * Each basic clock hardware type is comprised of a structure describing the
+ * clock hardware, implementations of the relevant callbacks in struct clk_ops,
+ * unique flags for that hardware type, a registration function and an
+ * alternative macro for static initialization
+ */
+
+/**
+ * struct clk_fixed_rate - fixed-rate clock
+ * @hw:		handle between common and hardware-specific interfaces
+ * @fixed_rate:	constant frequency of clock
+ */
+struct clk_fixed_rate {
+	struct		clk_hw hw;
+	unsigned long	fixed_rate;
+	u8		flags;
+};
+
+struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		unsigned long fixed_rate);
+
+/**
+ * struct clk_gate - gating clock
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register controlling gate
+ * @bit_idx:	single bit controlling gate
+ * @flags:	hardware-specific flags
+ * @lock:	register lock
+ *
+ * Clock which can gate its output.  Implements .enable & .disable
+ *
+ * Flags:
+ * CLK_GATE_SET_DISABLE - by default this clock sets the bit at bit_idx to
+ * 	enable the clock.  Setting this flag does the opposite: setting the bit
+ * 	disable the clock and clearing it enables the clock
+ */
+struct clk_gate {
+	struct clk_hw hw;
+	void __iomem	*reg;
+	u8		bit_idx;
+	u8		flags;
+	spinlock_t	*lock;
+};
+
+#define CLK_GATE_SET_TO_DISABLE		BIT(0)
+
+struct clk *clk_register_gate(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 bit_idx,
+		u8 clk_gate_flags, spinlock_t *lock);
+
+/**
+ * struct clk_divider - adjustable divider clock
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register containing the divider
+ * @shift:	shift to the divider bit field
+ * @width:	width of the divider bit field
+ * @lock:	register lock
+ *
+ * Clock with an adjustable divider affecting its output frequency.  Implements
+ * .recalc_rate, .set_rate and .round_rate
+ *
+ * Flags:
+ * CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the
+ * 	register plus one.  If CLK_DIVIDER_ONE_BASED is set then the divider is
+ * 	the raw value read from the register, with the value of zero considered
+ * 	invalid
+ * CLK_DIVIDER_POWER_OF_TWO - clock divisor is 2 raised to the value read from
+ * 	the hardware register
+ */
+struct clk_divider {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		shift;
+	u8		width;
+	u8		flags;
+	spinlock_t	*lock;
+};
+
+#define CLK_DIVIDER_ONE_BASED		BIT(0)
+#define CLK_DIVIDER_POWER_OF_TWO	BIT(1)
+
+struct clk *clk_register_divider(struct device *dev, const char *name,
+		const char *parent_name, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_divider_flags, spinlock_t *lock);
+
+/**
+ * struct clk_mux - multiplexer clock
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register controlling multiplexer
+ * @shift:	shift to multiplexer bit field
+ * @width:	width of mutliplexer bit field
+ * @num_clks:	number of parent clocks
+ * @lock:	register lock
+ *
+ * Clock with multiple selectable parents.  Implements .get_parent, .set_parent
+ * and .recalc_rate
+ *
+ * Flags:
+ * CLK_MUX_INDEX_ONE - register index starts at 1, not 0
+ * CLK_MUX_INDEX_BITWISE - register index is a single bit (power of two)
+ */
+struct clk_mux {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		shift;
+	u8		width;
+	u8		flags;
+	spinlock_t	*lock;
+};
+
+#define CLK_MUX_INDEX_ONE		BIT(0)
+#define CLK_MUX_INDEX_BIT		BIT(1)
+
+struct clk *clk_register_mux(struct device *dev, const char *name,
+		char **parent_names, u8 num_parents, unsigned long flags,
+		void __iomem *reg, u8 shift, u8 width,
+		u8 clk_mux_flags, spinlock_t *lock);
 
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
-- 
1.7.5.4


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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-03  8:29 ` [PATCH v5 3/4] clk: introduce the common clock framework Mike Turquette
@ 2012-03-03 13:31   ` Sascha Hauer
  2012-03-03 17:14     ` Turquette, Mike
  2012-03-05  9:22   ` Richard Zhao
  2012-03-13 11:24   ` Sascha Hauer
  2 siblings, 1 reply; 51+ messages in thread
From: Sascha Hauer @ 2012-03-03 13:31 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jeremy Kerr, Mike Turquette, Magnus Damm,
	Deepak Saxena, linux-arm-kernel, Arnd Bergman, patches,
	Rob Herring, Thomas Gleixner, Richard Zhao, Shawn Guo,
	Paul Walmsley, Linus Walleij, Mark Brown, Stephen Boyd,
	linux-kernel, Amit Kucheria

On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:
> The common clock framework defines a common struct clk useful across
> most platforms as well as an implementation of the clk api that drivers
> can use safely for managing clocks.
> 
> The net result is consolidation of many different struct clk definitions
> and platform-specific clock framework implementations.
> 
> This patch introduces the common struct clk, struct clk_ops and an
> implementation of the well-known clock api in include/clk/clk.h.
> Platforms may define their own hardware-specific clock structure and
> their own clock operation callbacks, so long as it wraps an instance of
> struct clk_hw.
> 
> See Documentation/clk.txt for more details.
> 
> This patch is based on the work of Jeremy Kerr, which in turn was based
> on the work of Ben Herrenschmidt.
> 
> +
> +/**
> + * struct clk_hw - handle for traversing from a struct clk to its corresponding
> + * hardware-specific structure.  struct clk_hw should be declared within struct
> + * clk_foo and then referenced by the struct clk instance that uses struct
> + * clk_foo's clk_ops
> + *
> + * clk: pointer to the struct clk instance that points back to this struct
> + * clk_hw instance
> + */
> +struct clk_hw {
> +	struct clk *clk;
> +};

The reason for doing this is that struct clk should be an opaque cookie
for both drivers and implementers of clocks. I recently had the idea whether
the roles of these two structs could be swapped. So instead of the above we
could do:

struct clk {
	struct clk_hw *hw;
}

The effect would be the same, but this version would make the struct clk
pointer known at compile time thus making it possible for static
initializers to specify their parent clock.

I just saw that clk_register now takes a parent name array, that may
make this change unnecessary anyway.

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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-03 13:31   ` Sascha Hauer
@ 2012-03-03 17:14     ` Turquette, Mike
  2012-03-04 11:52       ` Sascha Hauer
  0 siblings, 1 reply; 51+ messages in thread
From: Turquette, Mike @ 2012-03-03 17:14 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jeremy Kerr, Magnus Damm, Deepak Saxena,
	linux-arm-kernel, Arnd Bergman, patches, Rob Herring,
	Thomas Gleixner, Richard Zhao, Shawn Guo, Paul Walmsley,
	Linus Walleij, Mark Brown, Stephen Boyd, linux-kernel,
	Amit Kucheria

On Sat, Mar 3, 2012 at 5:31 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:
>> The common clock framework defines a common struct clk useful across
>> most platforms as well as an implementation of the clk api that drivers
>> can use safely for managing clocks.
>>
>> The net result is consolidation of many different struct clk definitions
>> and platform-specific clock framework implementations.
>>
>> This patch introduces the common struct clk, struct clk_ops and an
>> implementation of the well-known clock api in include/clk/clk.h.
>> Platforms may define their own hardware-specific clock structure and
>> their own clock operation callbacks, so long as it wraps an instance of
>> struct clk_hw.
>>
>> See Documentation/clk.txt for more details.
>>
>> This patch is based on the work of Jeremy Kerr, which in turn was based
>> on the work of Ben Herrenschmidt.
>>
>> +
>> +/**
>> + * struct clk_hw - handle for traversing from a struct clk to its corresponding
>> + * hardware-specific structure.  struct clk_hw should be declared within struct
>> + * clk_foo and then referenced by the struct clk instance that uses struct
>> + * clk_foo's clk_ops
>> + *
>> + * clk: pointer to the struct clk instance that points back to this struct
>> + * clk_hw instance
>> + */
>> +struct clk_hw {
>> +     struct clk *clk;
>> +};
>
> The reason for doing this is that struct clk should be an opaque cookie
> for both drivers and implementers of clocks. I recently had the idea whether
> the roles of these two structs could be swapped. So instead of the above we
> could do:
>
> struct clk {
>        struct clk_hw *hw;
> }

Firstly, struct clk is an opaque cookie for both drivers and
implementers of clocks with this patchset.

Secondly, struct clk does indeed have a pointer to struct clk_hw.
Refer to include/linux/clk-private.h in this patch.

The reference is cyclical.  A reference to struct clk can navigate to
struct clk_foo via container_of (usually something like "#define
to_clk_foo(_hw) container_of(_hw, struct clk_foo, hw)" where struct
clk's pointer to it's .hw member is passed into one of the struct
clk_ops callbacks.

Likewise if struct clk_foo needs the struct clk ptr for any reason
then it can get it from foo->hw->clk.

I believe this patch already does what you suggest, but I might be
missing your point.

>
> The effect would be the same, but this version would make the struct clk
> pointer known at compile time thus making it possible for static
> initializers to specify their parent clock.

This series achieves this goal also.  include/linux/clk-private.h
defines struct clk as well as macros for statically initializing the
basic clock types.  Pointers to the struct clk of a parent clock can
and are pre-populated in these macros, along with the mandatory array
of parent string names.  (note that parent pointer initialization is
optional and you can always pass in NULL into that specific field of
the macro)

>
> I just saw that clk_register now takes a parent name array, that may
> make this change unnecessary anyway.

clk_register exists for dynamic allocation and solves a different
problem from what you describe above.  For statically initialized
clocks the following is sufficient:

#include <linux/clk-private.h>

static char *abe_dpll_refclk_mux_ck_parent_names[] = {
        "sys_clkin_ck",
        "sys_32k_ck",
};

static struct clk *abe_dpll_refclk_mux_ck_parents[] = {
        &sys_clkin_ck,
        &sys_32k_ck,
};

DEFINE_CLK_MUX(abe_dpll_refclk_mux_ck,
        abe_dpll_refclk_mux_ck_parent_names,
        abe_dpll_refclk_mux_ck_parents,
        0x0,
        OMAP4430_CM_ABE_PLL_REF_CLKSEL,
        OMAP4430_CLKSEL_0_0_SHIFT,
        OMAP4430_CLKSEL_0_0_WIDTH,
        0x0,
        NULL);

__clk_init(NULL, &abe_dpll_refclk_mux_ck);

You might find it helpful to see how I've handled statically
initialized clocks for OMAP4.  These patches are a work in progress
but I'll send an RFC to the list very soon since others might find it
useful.  For now the above example can be seen in more detail at:
http://git.linaro.org/gitweb?p=people/mturquette/linux.git;a=blob;f=arch/arm/mach-omap2/clock44xx_data.c;h=7f833a7b2dca84a52c2bd1e7c8d9cfe560771258;hb=v3.3-rc5-clkv5-omap#l205

Let me know if I've missed your point somehow.

Thanks for the review,
Mike

>
> 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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-03 17:14     ` Turquette, Mike
@ 2012-03-04 11:52       ` Sascha Hauer
  2012-03-05  0:12         ` Turquette, Mike
  0 siblings, 1 reply; 51+ messages in thread
From: Sascha Hauer @ 2012-03-04 11:52 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Andrew Lunn, Paul Walmsley, linaro-dev, Linus Walleij, patches,
	Stephen Boyd, Mark Brown, Magnus Damm, linux-kernel, Rob Herring,
	Richard Zhao, Grant Likely, Deepak Saxena, Saravana Kannan,
	Thomas Gleixner, Shawn Guo, Amit Kucheria, Russell King,
	Jeremy Kerr, Arnd Bergman, linux-arm-kernel

On Sat, Mar 03, 2012 at 09:14:43AM -0800, Turquette, Mike wrote:
> On Sat, Mar 3, 2012 at 5:31 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:
> >> The common clock framework defines a common struct clk useful across
> >> most platforms as well as an implementation of the clk api that drivers
> >> can use safely for managing clocks.
> >>
> >> The net result is consolidation of many different struct clk definitions
> >> and platform-specific clock framework implementations.
> >>
> >> This patch introduces the common struct clk, struct clk_ops and an
> >> implementation of the well-known clock api in include/clk/clk.h.
> >> Platforms may define their own hardware-specific clock structure and
> >> their own clock operation callbacks, so long as it wraps an instance of
> >> struct clk_hw.
> >>
> >> See Documentation/clk.txt for more details.
> >>
> >> This patch is based on the work of Jeremy Kerr, which in turn was based
> >> on the work of Ben Herrenschmidt.
> >>
> >> +
> >> +/**
> >> + * struct clk_hw - handle for traversing from a struct clk to its corresponding
> >> + * hardware-specific structure.  struct clk_hw should be declared within struct
> >> + * clk_foo and then referenced by the struct clk instance that uses struct
> >> + * clk_foo's clk_ops
> >> + *
> >> + * clk: pointer to the struct clk instance that points back to this struct
> >> + * clk_hw instance
> >> + */
> >> +struct clk_hw {
> >> +     struct clk *clk;
> >> +};
> >
> > The reason for doing this is that struct clk should be an opaque cookie
> > for both drivers and implementers of clocks. I recently had the idea whether
> > the roles of these two structs could be swapped. So instead of the above we
> > could do:
> >
> > struct clk {
> >        struct clk_hw *hw;
> > }
> 
> Firstly, struct clk is an opaque cookie for both drivers and
> implementers of clocks with this patchset.
> 
> Secondly, struct clk does indeed have a pointer to struct clk_hw.
> Refer to include/linux/clk-private.h in this patch.
> 
> The reference is cyclical.  A reference to struct clk can navigate to
> struct clk_foo via container_of (usually something like "#define
> to_clk_foo(_hw) container_of(_hw, struct clk_foo, hw)" where struct
> clk's pointer to it's .hw member is passed into one of the struct
> clk_ops callbacks.
> 
> Likewise if struct clk_foo needs the struct clk ptr for any reason
> then it can get it from foo->hw->clk.
> 
> I believe this patch already does what you suggest, but I might be
> missing your point.

In include/linux/clk-private.h you expose struct clk outside the core.
This has to be done to make static initializers possible. There is a big
warning in this file that it must not be included from files implementing
struct clk_ops. You can simply avoid this warning by declaring struct clk
with only a single member:

include/linux/clk.h:

struct clk {
	struct clk_internal *internal;
};

This way everybody knows struct clk (thus can embed it in their static
initializers), but doesn't know anything about the internal members. Now
in drivers/clk/clk.c you declare struct clk_internal exactly like struct
clk was declared before:

struct clk_internal {
	const char		*name;
	const struct clk_ops	*ops;
	struct clk_hw		*hw;
	struct clk		*parent;
	char			**parent_names;
	struct clk		**parents;
	u8			num_parents;
	unsigned long		rate;
	unsigned long		flags;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	struct hlist_head	children;
	struct hlist_node	child_node;
	unsigned int		notifier_count;
#ifdef CONFIG_COMMON_CLK_DEBUG
	struct dentry		*dentry;
#endif
};

An instance of struct clk_internal will be allocated in
__clk_init/clk_register. Now the private data stays completely inside
the core and noone can abuse it.

With this __clk_init could be something like:

struct clk_initializer {
	const char		*name;
	const struct clk_ops	*ops;
	char			**parent_names;
	u8			num_parents;
	unsigned long		flags;
	struct clk		*clk;
};

void __clk_init(struct device *dev, struct clk_initializer *init);

I hope I made my intention a bit clearer.

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] 51+ messages in thread

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-03  8:29 ` [PATCH v5 4/4] clk: basic clock hardware types Mike Turquette
@ 2012-03-04 14:26   ` Andrew Lunn
  2012-03-04 14:35   ` Andrew Lunn
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 51+ messages in thread
From: Andrew Lunn @ 2012-03-04 14:26 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Mike Turquette, Jeremy Kerr, Thomas Gleixner,
	Arnd Bergman, Paul Walmsley, Shawn Guo, Sascha Hauer, Jamie Iles,
	Richard Zhao, Saravana Kannan, Magnus Damm, Rob Herring,
	Mark Brown, Linus Walleij, Stephen Boyd, Amit Kucheria,
	Deepak Saxena, Grant Likely, Andrew Lunn

> +#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,	\
> +				_flags, _reg, _bit_idx,		\
> +				_gate_flags, _lock)		\
> +	static struct clk _name;				\
> +	static char *_name##_parent_names[] = {			\
> +		_parent_name,					\
> +	};							\
> +	static struct clk *_name##_parents[] = {		\
> +		_parent_ptr,					\
> +	};							\
> +	static struct clk_gate _name##_hw = {			\
> +		.hw = {						\
> +			.clk = &_name,				\
> +		},						\
> +		.reg = _reg,					\
> +		.bit_idx = _bit_idx,				\
> +		.flags = _gate_flags				\

Hi Mike

Looks like a , is missing here after _gate_flags.

      Andrew

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

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-03  8:29 ` [PATCH v5 4/4] clk: basic clock hardware types Mike Turquette
  2012-03-04 14:26   ` Andrew Lunn
@ 2012-03-04 14:35   ` Andrew Lunn
  2012-03-05  0:15     ` Turquette, Mike
  2012-03-04 17:42   ` Andrew Lunn
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 51+ messages in thread
From: Andrew Lunn @ 2012-03-04 14:35 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Mike Turquette, Jeremy Kerr, Thomas Gleixner,
	Arnd Bergman, Paul Walmsley, Shawn Guo, Sascha Hauer, Jamie Iles,
	Richard Zhao, Saravana Kannan, Magnus Damm, Rob Herring,
	Mark Brown, Linus Walleij, Stephen Boyd, Amit Kucheria,
	Deepak Saxena, Grant Likely, Andrew Lunn

> +#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,	\
> +				_flags, _reg, _bit_idx,		\
> +				_gate_flags, _lock)		\
> +	static struct clk _name;				\
> +	static char *_name##_parent_names[] = {			\
> +		_parent_name,					\
> +	};							\
> +	static struct clk *_name##_parents[] = {		\
> +		_parent_ptr,					\
> +	};							\
> +	static struct clk_gate _name##_hw = {			\
> +		.hw = {						\
> +			.clk = &_name,				\
> +		},						\
> +		.reg = _reg,					\
> +		.bit_idx = _bit_idx,				\
> +		.flags = _gate_flags				\
> +		.lock = _lock,					\
> +	};							\
> +	static struct clk _name = {				\
> +		.name = #_name,					\
> +		.ops = &clk_gate_ops,				\
> +		.hw = &_name##_hw.hw,				\
> +		.parent_names = _name##_parent_names,		\
> +		.num_parents =					\
> +			ARRAY_SIZE(_name##parent_names),	\

Hi Mike

This should be _name##_parent_names, i.e. you are missing a _.

With this and the previous change, i get something which at least
compiles...

	Andrew

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

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-03  8:29 ` [PATCH v5 4/4] clk: basic clock hardware types Mike Turquette
  2012-03-04 14:26   ` Andrew Lunn
  2012-03-04 14:35   ` Andrew Lunn
@ 2012-03-04 17:42   ` Andrew Lunn
  2012-03-05  0:30     ` Turquette, Mike
  2012-03-04 20:33   ` [PATCH] clk: Fix compile errors in DEFINE_CLK_GATE Andrew Lunn
  2012-03-07 21:20   ` [PATCH v5 4/4] clk: basic clock hardware types Sascha Hauer
  4 siblings, 1 reply; 51+ messages in thread
From: Andrew Lunn @ 2012-03-04 17:42 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Mike Turquette, Jeremy Kerr, Thomas Gleixner,
	Arnd Bergman, Paul Walmsley, Shawn Guo, Sascha Hauer, Jamie Iles,
	Richard Zhao, Saravana Kannan, Magnus Damm, Rob Herring,
	Mark Brown, Linus Walleij, Stephen Boyd, Amit Kucheria,
	Deepak Saxena, Grant Likely, Andrew Lunn

On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
> Many platforms support simple gateable clocks, fixed-rate clocks,
> adjustable divider clocks and multi-parent multiplexer clocks.
> 
> This patch introduces basic clock types for the above-mentioned hardware
> which share some common characteristics.

Hi Mike

These basic clocks don't allow the use of prepare/unprepare, from the
side of the clock provider. I think i need this.

The Orion Kirkwood SoC has clock gating for most of its on chip
peripherals, which the other older Orion devices don't have. The SATA
and PCIe also allows the PHY to be shut down, again which older Orion
devices don't have. The current code links the clock and the PHY
together, shutting both down are the same time. So i would like to
perform the PHY shutdown in the unprepare() function of the clk
driver.

Is allowing to pass prepare/unprepare functions to basic clocks
something you want to support? If i prepare a patch would you consider
it?

	Thanks
		Andrew

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

* [PATCH] clk: Fix compile errors in DEFINE_CLK_GATE
  2012-03-03  8:29 ` [PATCH v5 4/4] clk: basic clock hardware types Mike Turquette
                     ` (2 preceding siblings ...)
  2012-03-04 17:42   ` Andrew Lunn
@ 2012-03-04 20:33   ` Andrew Lunn
  2012-03-05  0:31     ` Turquette, Mike
  2012-03-07 21:20   ` [PATCH v5 4/4] clk: basic clock hardware types Sascha Hauer
  4 siblings, 1 reply; 51+ messages in thread
From: Andrew Lunn @ 2012-03-04 20:33 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Mike Turquette, Jeremy Kerr, Thomas Gleixner,
	Arnd Bergman, Paul Walmsley, Shawn Guo, Sascha Hauer, Jamie Iles,
	Richard Zhao, Saravana Kannan, Magnus Damm, Rob Herring,
	Mark Brown, Linus Walleij, Stephen Boyd, Amit Kucheria,
	Deepak Saxena, Grant Likely, Andrew Lunn

>From 71e9a676b2b2f0dc2bb0cc395e8325cf38f4808b Mon Sep 17 00:00:00 2001
From: Andrew Lunn <andrew@lunn.ch>
Date: Sun, 4 Mar 2012 16:31:14 +0100
Subject: [PATCH] [clk] Fix compile errors in DEFINE_CLK_GATE()

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 include/linux/clk-private.h |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index d06e6fb..9d5c4b1 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -95,7 +95,7 @@ extern struct clk_ops clk_gate_ops;
 		},						\
 		.reg = _reg,					\
 		.bit_idx = _bit_idx,				\
-		.flags = _gate_flags				\
+		.flags = _gate_flags,				\
 		.lock = _lock,					\
 	};							\
 	static struct clk _name = {				\
@@ -104,7 +104,7 @@ extern struct clk_ops clk_gate_ops;
 		.hw = &_name##_hw.hw,				\
 		.parent_names = _name##_parent_names,		\
 		.num_parents =					\
-			ARRAY_SIZE(_name##parent_names),	\
+			ARRAY_SIZE(_name##_parent_names),	\
 		.parents = _name##_parents,			\
 		.flags = _flags,				\
 	};
-- 
1.7.2.5


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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-04 11:52       ` Sascha Hauer
@ 2012-03-05  0:12         ` Turquette, Mike
  2012-03-05  7:38           ` Sascha Hauer
  0 siblings, 1 reply; 51+ messages in thread
From: Turquette, Mike @ 2012-03-05  0:12 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Andrew Lunn, Paul Walmsley, linaro-dev, Linus Walleij, patches,
	Stephen Boyd, Mark Brown, Magnus Damm, linux-kernel, Rob Herring,
	Richard Zhao, Grant Likely, Deepak Saxena, Saravana Kannan,
	Thomas Gleixner, Shawn Guo, Amit Kucheria, Russell King,
	Jeremy Kerr, Arnd Bergman, linux-arm-kernel

On Sun, Mar 4, 2012 at 3:52 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Sat, Mar 03, 2012 at 09:14:43AM -0800, Turquette, Mike wrote:
>> On Sat, Mar 3, 2012 at 5:31 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
>> > On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:
>> >> The common clock framework defines a common struct clk useful across
>> >> most platforms as well as an implementation of the clk api that drivers
>> >> can use safely for managing clocks.
>> >>
>> >> The net result is consolidation of many different struct clk definitions
>> >> and platform-specific clock framework implementations.
>> >>
>> >> This patch introduces the common struct clk, struct clk_ops and an
>> >> implementation of the well-known clock api in include/clk/clk.h.
>> >> Platforms may define their own hardware-specific clock structure and
>> >> their own clock operation callbacks, so long as it wraps an instance of
>> >> struct clk_hw.
>> >>
>> >> See Documentation/clk.txt for more details.
>> >>
>> >> This patch is based on the work of Jeremy Kerr, which in turn was based
>> >> on the work of Ben Herrenschmidt.
>> >>
>> >> +
>> >> +/**
>> >> + * struct clk_hw - handle for traversing from a struct clk to its corresponding
>> >> + * hardware-specific structure.  struct clk_hw should be declared within struct
>> >> + * clk_foo and then referenced by the struct clk instance that uses struct
>> >> + * clk_foo's clk_ops
>> >> + *
>> >> + * clk: pointer to the struct clk instance that points back to this struct
>> >> + * clk_hw instance
>> >> + */
>> >> +struct clk_hw {
>> >> +     struct clk *clk;
>> >> +};
>> >
>> > The reason for doing this is that struct clk should be an opaque cookie
>> > for both drivers and implementers of clocks. I recently had the idea whether
>> > the roles of these two structs could be swapped. So instead of the above we
>> > could do:
>> >
>> > struct clk {
>> >        struct clk_hw *hw;
>> > }
>>
>> Firstly, struct clk is an opaque cookie for both drivers and
>> implementers of clocks with this patchset.
>>
>> Secondly, struct clk does indeed have a pointer to struct clk_hw.
>> Refer to include/linux/clk-private.h in this patch.
>>
>> The reference is cyclical.  A reference to struct clk can navigate to
>> struct clk_foo via container_of (usually something like "#define
>> to_clk_foo(_hw) container_of(_hw, struct clk_foo, hw)" where struct
>> clk's pointer to it's .hw member is passed into one of the struct
>> clk_ops callbacks.
>>
>> Likewise if struct clk_foo needs the struct clk ptr for any reason
>> then it can get it from foo->hw->clk.
>>
>> I believe this patch already does what you suggest, but I might be
>> missing your point.
>
> In include/linux/clk-private.h you expose struct clk outside the core.
> This has to be done to make static initializers possible. There is a big
> warning in this file that it must not be included from files implementing
> struct clk_ops. You can simply avoid this warning by declaring struct clk
> with only a single member:
>
> include/linux/clk.h:
>
> struct clk {
>        struct clk_internal *internal;
> };
>
> This way everybody knows struct clk (thus can embed it in their static
> initializers), but doesn't know anything about the internal members. Now
> in drivers/clk/clk.c you declare struct clk_internal exactly like struct
> clk was declared before:
>
> struct clk_internal {
>        const char              *name;
>        const struct clk_ops    *ops;
>        struct clk_hw           *hw;
>        struct clk              *parent;
>        char                    **parent_names;
>        struct clk              **parents;
>        u8                      num_parents;
>        unsigned long           rate;
>        unsigned long           flags;
>        unsigned int            enable_count;
>        unsigned int            prepare_count;
>        struct hlist_head       children;
>        struct hlist_node       child_node;
>        unsigned int            notifier_count;
> #ifdef CONFIG_COMMON_CLK_DEBUG
>        struct dentry           *dentry;
> #endif
> };
>
> An instance of struct clk_internal will be allocated in
> __clk_init/clk_register. Now the private data stays completely inside
> the core and noone can abuse it.

Hi Sascha,

I see the disconnect here.  For OMAP (and possibly other platforms) at
least some clock data is necessary during early boot, before the
regular allocation methods are available (timers for instance).  Due
to this my idea of static initialization was to take care of
everything that would normally require an allocator, which includes
the internals of struct clk; thus exposing struct clk is useful here
as you can still use the clock framework during very early boot.  Your
method above doesn't satisfy this requirement.  I'm not sure what the
purpose would be of statically allocating your version of struct clk,
which will ultimately need to allocate memory for the clock internals
anyways.  Can you elaborate the benefit of this approach over just
using the clk_foo_register functions?

Note that struct clk is still declared in clk.h (and clk-provider.h),
so platforms that have struct clk *clk declarations won't have a
problem.

Thanks much,
Mike

>
> With this __clk_init could be something like:
>
> struct clk_initializer {
>        const char              *name;
>        const struct clk_ops    *ops;
>        char                    **parent_names;
>        u8                      num_parents;
>        unsigned long           flags;
>        struct clk              *clk;
> };
>
> void __clk_init(struct device *dev, struct clk_initializer *init);
>
> I hope I made my intention a bit clearer.
>
> 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] 51+ messages in thread

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-04 14:35   ` Andrew Lunn
@ 2012-03-05  0:15     ` Turquette, Mike
  0 siblings, 0 replies; 51+ messages in thread
From: Turquette, Mike @ 2012-03-05  0:15 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Jeremy Kerr, Thomas Gleixner, Arnd Bergman,
	Paul Walmsley, Shawn Guo, Sascha Hauer, Jamie Iles, Richard Zhao,
	Saravana Kannan, Magnus Damm, Rob Herring, Mark Brown,
	Linus Walleij, Stephen Boyd, Amit Kucheria, Deepak Saxena,
	Grant Likely

On Sun, Mar 4, 2012 at 6:35 AM, Andrew Lunn <andrew@lunn.ch> wrote:
>> +#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,    \
>> +                             _flags, _reg, _bit_idx,         \
>> +                             _gate_flags, _lock)             \
>> +     static struct clk _name;                                \
>> +     static char *_name##_parent_names[] = {                 \
>> +             _parent_name,                                   \
>> +     };                                                      \
>> +     static struct clk *_name##_parents[] = {                \
>> +             _parent_ptr,                                    \
>> +     };                                                      \
>> +     static struct clk_gate _name##_hw = {                   \
>> +             .hw = {                                         \
>> +                     .clk = &_name,                          \
>> +             },                                              \
>> +             .reg = _reg,                                    \
>> +             .bit_idx = _bit_idx,                            \
>> +             .flags = _gate_flags                            \
>> +             .lock = _lock,                                  \
>> +     };                                                      \
>> +     static struct clk _name = {                             \
>> +             .name = #_name,                                 \
>> +             .ops = &clk_gate_ops,                           \
>> +             .hw = &_name##_hw.hw,                           \
>> +             .parent_names = _name##_parent_names,           \
>> +             .num_parents =                                  \
>> +                     ARRAY_SIZE(_name##parent_names),        \
>
> Hi Mike
>
> This should be _name##_parent_names, i.e. you are missing a _.
>
> With this and the previous change, i get something which at least
> compiles...

The gate clock is the only type of the basic clocks that I do not
(currently) use in my OMAP port and it's test coverage has suffered as
a result.  My bad.

Thanks for the review and the patch in the separate thread.  I'll take
the changes in.

Regards,
Mike

>
>        Andrew
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

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

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-04 17:42   ` Andrew Lunn
@ 2012-03-05  0:30     ` Turquette, Mike
  2012-03-05  8:48       ` Andrew Lunn
  0 siblings, 1 reply; 51+ messages in thread
From: Turquette, Mike @ 2012-03-05  0:30 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Jeremy Kerr, Thomas Gleixner, Arnd Bergman,
	Paul Walmsley, Shawn Guo, Sascha Hauer, Jamie Iles, Richard Zhao,
	Saravana Kannan, Magnus Damm, Rob Herring, Mark Brown,
	Linus Walleij, Stephen Boyd, Amit Kucheria, Deepak Saxena,
	Grant Likely, Rafael J. Wysocki

On Sun, Mar 4, 2012 at 9:42 AM, Andrew Lunn <andrew@lunn.ch> wrote:
> On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
>> Many platforms support simple gateable clocks, fixed-rate clocks,
>> adjustable divider clocks and multi-parent multiplexer clocks.
>>
>> This patch introduces basic clock types for the above-mentioned hardware
>> which share some common characteristics.
>
> Hi Mike
>
> These basic clocks don't allow the use of prepare/unprepare, from the
> side of the clock provider. I think i need this.

This is an interesting point and might help us nail down exactly what
we expect from clk_prepare/clk_unprepare.

>
> The Orion Kirkwood SoC has clock gating for most of its on chip
> peripherals, which the other older Orion devices don't have. The SATA
> and PCIe also allows the PHY to be shut down, again which older Orion
> devices don't have. The current code links the clock and the PHY
> together, shutting both down are the same time. So i would like to
> perform the PHY shutdown in the unprepare() function of the clk
> driver.

Do you feel it is The Right Thing to enable/disable the phy from
clk_prepare/clk_unprepare?  I had always imagined that clk_prepare's
purpose was always specific to clock-related activities; for example
maybe turn on a parent PLL that takes a long time to lock, as well as
for the sleepable cases such as clocks over i2c, etc.

However, I know that some others have already started performing
voltage scaling from clk_prepare, so clearly the api is not strict in
it's purpose.

Have you investigated powering up/down the phy from a different layer
such pm_runtime?  That might create a better layer of separation
between other resources needed by an IP block and the clock framework.
 For instance on OMAP we use pm_runtime_get(_sync) to call clk_prepare
& clk_enable and handle other power management-related resources.
Perhaps using the clock framework to power up/down your IP block is
not the right tool for the job.

>
> Is allowing to pass prepare/unprepare functions to basic clocks
> something you want to support? If i prepare a patch would you consider
> it?

My original instinct was "no".  The simple gate clock was always
supposed to be "simple" and if you need more than it provides then it
might be best for your platform to implement a specific clock type.
Especially since the purpose of clk_prepare is still up in the air.

But I'll keep an open mind and hopefully others can chime in.  Please
let me know what you think about my pm_runtime suggestion.  I've Cc'd
Rafael just in case he has something to add here from a design
perspective.

Regards,
Mike

>
>        Thanks
>                Andrew

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

* Re: [PATCH] clk: Fix compile errors in DEFINE_CLK_GATE
  2012-03-04 20:33   ` [PATCH] clk: Fix compile errors in DEFINE_CLK_GATE Andrew Lunn
@ 2012-03-05  0:31     ` Turquette, Mike
  0 siblings, 0 replies; 51+ messages in thread
From: Turquette, Mike @ 2012-03-05  0:31 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Jeremy Kerr, Thomas Gleixner, Arnd Bergman,
	Paul Walmsley, Shawn Guo, Sascha Hauer, Jamie Iles, Richard Zhao,
	Saravana Kannan, Magnus Damm, Rob Herring, Mark Brown,
	Linus Walleij, Stephen Boyd, Amit Kucheria, Deepak Saxena,
	Grant Likely

On Sun, Mar 4, 2012 at 12:33 PM, Andrew Lunn <andrew@lunn.ch> wrote:
> From 71e9a676b2b2f0dc2bb0cc395e8325cf38f4808b Mon Sep 17 00:00:00 2001
> From: Andrew Lunn <andrew@lunn.ch>
> Date: Sun, 4 Mar 2012 16:31:14 +0100
> Subject: [PATCH] [clk] Fix compile errors in DEFINE_CLK_GATE()
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>

Thanks Andrew.  Will roll this fix in.

Regards,
Mike

> ---
>  include/linux/clk-private.h |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
> index d06e6fb..9d5c4b1 100644
> --- a/include/linux/clk-private.h
> +++ b/include/linux/clk-private.h
> @@ -95,7 +95,7 @@ extern struct clk_ops clk_gate_ops;
>                },                                              \
>                .reg = _reg,                                    \
>                .bit_idx = _bit_idx,                            \
> -               .flags = _gate_flags                            \
> +               .flags = _gate_flags,                           \
>                .lock = _lock,                                  \
>        };                                                      \
>        static struct clk _name = {                             \
> @@ -104,7 +104,7 @@ extern struct clk_ops clk_gate_ops;
>                .hw = &_name##_hw.hw,                           \
>                .parent_names = _name##_parent_names,           \
>                .num_parents =                                  \
> -                       ARRAY_SIZE(_name##parent_names),        \
> +                       ARRAY_SIZE(_name##_parent_names),       \
>                .parents = _name##_parents,                     \
>                .flags = _flags,                                \
>        };
> --
> 1.7.2.5
>
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

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

* Re: [PATCH v5 2/4] clk: Kconfig: add entry for HAVE_CLK_PREPARE
  2012-03-03  8:28 ` [PATCH v5 2/4] clk: Kconfig: add entry for HAVE_CLK_PREPARE Mike Turquette
@ 2012-03-05  2:04   ` Richard Zhao
  2012-03-05 19:46     ` Turquette, Mike
  0 siblings, 1 reply; 51+ messages in thread
From: Richard Zhao @ 2012-03-05  2:04 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, Grant Likely, Paul Walmsley, Linus Walleij,
	patches, Stephen Boyd, Mark Brown, Magnus Damm, linux-kernel,
	Rob Herring, Richard Zhao, Arnd Bergman, Deepak Saxena,
	Saravana Kannan, Andrew Lunn, Amit Kucheria, linaro-dev,
	Jeremy Kerr, Thomas Gleixner, linux-arm-kernel, Mike Turquette

On Sat, Mar 03, 2012 at 12:28:59AM -0800, Mike Turquette wrote:
> The common clk framework provides clk_prepare and clk_unprepare
> implementations.  Create an entry for HAVE_CLK_PREPARE so that
> COMMON_CLK can select it.
> 
> Signed-off-by: Mike Turquette <mturquette@linaro.org>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> Acked-by: Shawn Guo <shawn.guo@linaro.org>
> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Arnd Bergman <arnd.bergmann@linaro.org>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Richard Zhao <richard.zhao@linaro.org>
> Cc: Saravana Kannan <skannan@codeaurora.org>
> Cc: Magnus Damm <magnus.damm@gmail.com>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc: Amit Kucheria <amit.kucheria@linaro.org>
> Cc: Deepak Saxena <dsaxena@linaro.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Andrew Lunn <andrew@lunn.ch>
> ---
>  drivers/clk/Kconfig |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 9b3cd08..3912576 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -8,3 +8,6 @@ config HAVE_CLK_PREPARE
>  
>  config HAVE_MACH_CLKDEV
>  	bool
> +
> +config HAVE_CLK_PREPARE
> +	bool
We've already had it. redundant?

Thanks
Richard
> -- 
> 1.7.5.4
> 
> 
> _______________________________________________
> 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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-05  0:12         ` Turquette, Mike
@ 2012-03-05  7:38           ` Sascha Hauer
  2012-03-05 20:03             ` Turquette, Mike
  0 siblings, 1 reply; 51+ messages in thread
From: Sascha Hauer @ 2012-03-05  7:38 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Andrew Lunn, Paul Walmsley, linaro-dev, Linus Walleij, patches,
	Stephen Boyd, Mark Brown, Magnus Damm, linux-kernel, Rob Herring,
	Richard Zhao, Grant Likely, Deepak Saxena, Saravana Kannan,
	Thomas Gleixner, Shawn Guo, Amit Kucheria, Russell King,
	Jeremy Kerr, Arnd Bergman, linux-arm-kernel

On Sun, Mar 04, 2012 at 04:12:21PM -0800, Turquette, Mike wrote:
> >>
> >> I believe this patch already does what you suggest, but I might be
> >> missing your point.
> >
> > In include/linux/clk-private.h you expose struct clk outside the core.
> > This has to be done to make static initializers possible. There is a big
> > warning in this file that it must not be included from files implementing
> > struct clk_ops. You can simply avoid this warning by declaring struct clk
> > with only a single member:
> >
> > include/linux/clk.h:
> >
> > struct clk {
> >        struct clk_internal *internal;
> > };
> >
> > This way everybody knows struct clk (thus can embed it in their static
> > initializers), but doesn't know anything about the internal members. Now
> > in drivers/clk/clk.c you declare struct clk_internal exactly like struct
> > clk was declared before:
> >
> > struct clk_internal {
> >        const char              *name;
> >        const struct clk_ops    *ops;
> >        struct clk_hw           *hw;
> >        struct clk              *parent;
> >        char                    **parent_names;
> >        struct clk              **parents;
> >        u8                      num_parents;
> >        unsigned long           rate;
> >        unsigned long           flags;
> >        unsigned int            enable_count;
> >        unsigned int            prepare_count;
> >        struct hlist_head       children;
> >        struct hlist_node       child_node;
> >        unsigned int            notifier_count;
> > #ifdef CONFIG_COMMON_CLK_DEBUG
> >        struct dentry           *dentry;
> > #endif
> > };
> >
> > An instance of struct clk_internal will be allocated in
> > __clk_init/clk_register. Now the private data stays completely inside
> > the core and noone can abuse it.
> 
> Hi Sascha,
> 
> I see the disconnect here.  For OMAP (and possibly other platforms) at
> least some clock data is necessary during early boot, before the
> regular allocation methods are available (timers for instance).

We had this problem on i.MX aswell. It turned out that the timer clock
is the only clock that is needed so early. We solved this by moving the
clock init to the system timer init function.

> Due
> to this my idea of static initialization was to take care of
> everything that would normally require an allocator, which includes
> the internals of struct clk; thus exposing struct clk is useful here
> as you can still use the clock framework during very early boot.  Your
> method above doesn't satisfy this requirement.  I'm not sure what the
> purpose would be of statically allocating your version of struct clk,
> which will ultimately need to allocate memory for the clock internals
> anyways.  Can you elaborate the benefit of this approach over just
> using the clk_foo_register functions?

As said the benefit is that you do not have to expose the internal
layout of struct clk outside the clock framework. Note that in the
file you referenced here:

http://git.linaro.org/gitweb?p=people/mturquette/linux.git;a=blob;f=arch/arm/mach-omap2/clock44xx_data.c;h=7f833a7b2dca84a52c2bd1e7c8d9cfe560771258;hb=v3.3-rc5-clkv5-omap#l205

You violate what you have in a comment above clk-private.h:

/* __clk_init is only exposed via clk-private.h and is intended for use with
 * very large numbers of clocks that need to be statically initialized. It is
 * a layering violation to include clk-private.h from any code which implements
 * a clock's .ops; as such any statically initialized clock data MUST be in
 * separate C file from the logic that implements it's operations.
 */

Well, the file is work in progress, you probably fix this before sending
it out, but I bet people will include clk-private.h and nobody else
notices it.

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] 51+ messages in thread

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-05  0:30     ` Turquette, Mike
@ 2012-03-05  8:48       ` Andrew Lunn
  2012-03-05  9:29         ` Sascha Hauer
  0 siblings, 1 reply; 51+ messages in thread
From: Andrew Lunn @ 2012-03-05  8:48 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Andrew Lunn, Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Jeremy Kerr, Thomas Gleixner, Arnd Bergman,
	Paul Walmsley, Shawn Guo, Sascha Hauer, Jamie Iles, Richard Zhao,
	Saravana Kannan, Magnus Damm, Rob Herring, Mark Brown,
	Linus Walleij, Stephen Boyd, Amit Kucheria, Deepak Saxena,
	Grant Likely, Rafael J. Wysocki

On Sun, Mar 04, 2012 at 04:30:08PM -0800, Turquette, Mike wrote:
> On Sun, Mar 4, 2012 at 9:42 AM, Andrew Lunn <andrew@lunn.ch> wrote:
> > On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
> >> Many platforms support simple gateable clocks, fixed-rate clocks,
> >> adjustable divider clocks and multi-parent multiplexer clocks.
> >>
> >> This patch introduces basic clock types for the above-mentioned hardware
> >> which share some common characteristics.
> >
> > Hi Mike
> >
> > These basic clocks don't allow the use of prepare/unprepare, from the
> > side of the clock provider. I think i need this.
> 
> This is an interesting point and might help us nail down exactly what
> we expect from clk_prepare/clk_unprepare.
> 
> >
> > The Orion Kirkwood SoC has clock gating for most of its on chip
> > peripherals, which the other older Orion devices don't have. The SATA
> > and PCIe also allows the PHY to be shut down, again which older Orion
> > devices don't have. The current code links the clock and the PHY
> > together, shutting both down are the same time. So i would like to
> > perform the PHY shutdown in the unprepare() function of the clk
> > driver.
> 
> Do you feel it is The Right Thing to enable/disable the phy from
> clk_prepare/clk_unprepare?  

Humm, not sure yet. I don't know all the different possibilities,
which is why i tried to describe my use case, rather than just assume
i need prepare/unprepare.

I also realized i did not explain my use case properly. 

At boot, uboot is turning on various clocks and SATA/PCIe PHYs etc, in
order to get the device booted. Linux takes over, and the
Orion/kirkwood board files, ask the kirkwood or generic Orion code to
create platform_data structures for the different devices that the
board uses. The kirkwood code keeps a bitmap of devices for which it
creates platform data for which there is a gated clock. Then in a
lateinit call, it turns on clocks which are needed, and also turns off
clocks which are no longer needed, because the board did not ask for a
driver binding for that device. If it turns off a SATA or PCIe clock,
it also turns off the PHY associated with it.

So we are talking about turning off hardware for which there is no
driver. This seems to exclude pm_runtime_get(_sync), which is about
hardware with drivers.

We touched on this subject a couple of months ago, at least with
respect to clocks. You said that is what the flag CLK_IGNORE_UNUSED
will be used for. In a lateinit call, you plan to iterate over all
clocks and turn off any which don't have CLK_IGNORE_UNUSED and have
not been enabled. I assume you will call both disable() and
unprepare(), and if i've can put code into the unprepare to turn the
PHY off, all is good.

> > Is allowing to pass prepare/unprepare functions to basic clocks
> > something you want to support? If i prepare a patch would you consider
> > it?
> 
> My original instinct was "no".  The simple gate clock was always
> supposed to be "simple" and if you need more than it provides then it
> might be best for your platform to implement a specific clock type.
> Especially since the purpose of clk_prepare is still up in the air.

I think i can wrap your simple gate clock, to make my "complex" gate
clock. What would help is if you would EXPORT_SYMBOL_GPL
clk_gate_enable() and clk_gate_disable(), since they do exactly what i
want. I can then build my own clk_ops structure, with my own
unprepare() function. I would probably use DEFINE_CLK_GATE as is, and
then at run time, before calling __clk_init() overwrite the .ops with
my own version.

However, if others have the need for {un}prepare(), it would be good
to have a generic solution.

   Andrew

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-03  8:29 ` [PATCH v5 3/4] clk: introduce the common clock framework Mike Turquette
  2012-03-03 13:31   ` Sascha Hauer
@ 2012-03-05  9:22   ` Richard Zhao
  2012-03-14  2:03     ` Turquette, Mike
  2012-03-13 11:24   ` Sascha Hauer
  2 siblings, 1 reply; 51+ messages in thread
From: Richard Zhao @ 2012-03-05  9:22 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jeremy Kerr, Mike Turquette, Magnus Damm,
	Deepak Saxena, linux-arm-kernel, Arnd Bergman, patches,
	Rob Herring, Thomas Gleixner, Richard Zhao, Shawn Guo,
	Paul Walmsley, Linus Walleij, Mark Brown, Stephen Boyd,
	linux-kernel, Amit Kucheria

Hi Mike,

On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:

[snip]

> +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);
> +
> +	if (clk->parent)
> +		__clk_disable(clk->parent);
if __clk_xxx handle NULL clk, we might not need to check parent here?
There're also many places that checks parent below.
> +}
> +
> +/**
> + * clk_disable - gate a clock
> + * @clk: the clk being gated
> + *
> + * clk_disable must not sleep, which differentiates it from clk_unprepare.  In
> + * a simple case, clk_disable can be used instead of clk_unprepare to gate a
> + * clk if the operation is fast and will never sleep.  One example is a
> + * SoC-internal clk which is controlled via simple register writes.  In the
> + * complex case a clk gate operation may require a fast and a slow part.  It is
> + * this reason that clk_unprepare and clk_disable are not mutually exclusive.
> + * In fact clk_disable must be called before clk_unprepare.
> + */
> +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 = 0;
> +
> +	if (!clk)
> +		return 0;
> +
> +	if (WARN_ON(clk->prepare_count == 0))
> +		return -ESHUTDOWN;
> +
> +	if (clk->enable_count == 0) {
> +		if (clk->parent)
> +			ret = __clk_enable(clk->parent);
ditto
> +
> +		if (ret)
> +			return ret;
> +
> +		if (clk->ops->enable) {
> +			ret = clk->ops->enable(clk->hw);
> +			if (ret) {
> +				__clk_disable(clk->parent);
it's good case that don't check parent is NULL.
> +				return ret;
> +			}
> +		}
> +	}
> +
> +	clk->enable_count++;
> +	return 0;
> +}
> +
> +/**
> + * clk_enable - ungate a clock
> + * @clk: the clk being ungated
> + *
> + * clk_enable must not sleep, which differentiates it from clk_prepare.  In a
> + * simple case, clk_enable can be used instead of clk_prepare to ungate a clk
> + * if the operation will never sleep.  One example is a SoC-internal clk which
> + * is controlled via simple register writes.  In the complex case a clk ungate
> + * operation may require a fast and a slow part.  It is this reason that
> + * clk_enable and clk_prepare are not mutually exclusive.  In fact clk_prepare
> + * must be called before clk_enable.  Returns 0 on success, -EERROR
> + * otherwise.
> + */
> +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);
> +
> +/**
> + * clk_get_rate - return the rate of clk
> + * @clk: the clk whose rate is being returned
> + *
> + * Simply returns the cached rate of the clk.  Does not query the hardware.  If
> + * clk is NULL then returns -EINVAL.
> + */
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	unsigned long rate;
> +
> +	mutex_lock(&prepare_lock);
> +	rate = __clk_get_rate(clk);
> +	mutex_unlock(&prepare_lock);
> +
> +	return rate;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_rate);
> +
> +/**
> + * __clk_round_rate - round the given rate for a clk
> + * @clk: round the rate of this clock
> + *
> + * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
> + */
> +unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (!clk && !clk->ops->round_rate)
be	         || ?
> +		return -EINVAL;
> +
> +	return clk->ops->round_rate(clk->hw, rate, NULL);
> +}
> +
> +/**
> + * clk_round_rate - round the given rate for a clk
> + * @clk: the clk for which we are rounding a rate
> + * @rate: the rate which is to be rounded
> + *
> + * Takes in a rate as input and rounds it to a rate that the clk can actually
> + * use which is then returned.  If clk doesn't support round_rate operation
> + * then the rate passed in is returned.
> + */
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	unsigned long ret = rate;
> +
> +	mutex_lock(&prepare_lock);
> +	if (clk && clk->ops->round_rate)
> +		ret = __clk_round_rate(clk, rate);
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
If clk is NULL, clk_round_rate and __clk_round_rate return different
values. Do you mean it?
> +}
> +EXPORT_SYMBOL_GPL(clk_round_rate);
> +
> +/**
> + * __clk_notify - call clk notifier chain
> + * @clk: struct clk * that is changing rate
> + * @msg: clk notifier type (see include/linux/clk.h)
> + * @old_rate: old clk rate
> + * @new_rate: new clk rate
> + *
> + * Triggers a notifier call chain on the clk rate-change notification
> + * for 'clk'.  Passes a pointer to the struct clk and the previous
> + * and current rates to the notifier callback.  Intended to be called by
> + * internal clock code only.  Returns NOTIFY_DONE from the last driver
> + * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
> + * a driver returns that.
> + */
> +static int __clk_notify(struct clk *clk, unsigned long msg,
> +		unsigned long old_rate, unsigned long new_rate)
> +{
> +	struct clk_notifier *cn;
> +	struct clk_notifier_data cnd;
> +	int ret = NOTIFY_DONE;
> +
> +	cnd.clk = clk;
> +	cnd.old_rate = old_rate;
> +	cnd.new_rate = new_rate;
> +
> +	list_for_each_entry(cn, &clk_notifier_list, node) {
> +		if (cn->clk == clk) {
> +			ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
> +					&cnd);
> +			break;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * __clk_recalc_rates
> + * @clk: first clk in the subtree
> + * @msg: notification type (see include/linux/clk.h)
> + *
> + * Walks the subtree of clks starting with clk and recalculates rates as it
> + * goes.  Note that if a clk does not implement the recalc_rate operation then
> + * propagation of that subtree stops and all of that clks children will not
> + * have their rates updated.
> + *
> + * clk_recalc_rates also propagates the POST_RATE_CHANGE notification,
> + * if necessary.
> + *
> + * Caller must hold prepare_lock.
> + */
> +static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
> +{
> +	unsigned long old_rate;
> +	unsigned long parent_rate = 0;
> +	struct hlist_node *tmp;
> +	struct clk *child;
> +
> +	old_rate = clk->rate;
> +
> +	if (clk->parent)
> +		parent_rate = clk->parent->rate;
> +
> +	if (clk->ops->recalc_rate)
> +		clk->rate = clk->ops->recalc_rate(clk->hw, parent_rate);
> +	else
> +		clk->rate = parent_rate;
> +
> +	/*
> +	 * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE
> +	 * & ABORT_RATE_CHANGE notifiers
> +	 */
> +	if (clk->notifier_count && msg)
> +		__clk_notify(clk, msg, old_rate, clk->rate);
> +
> +	hlist_for_each_entry(child, tmp, &clk->children, child_node)
> +		__clk_recalc_rates(child, msg);
> +}
> +
> +/**
> + * __clk_speculate_rates
> + * @clk: first clk in the subtree
> + * @parent_rate: the "future" rate of clk's parent
> + *
> + * Walks the subtree of clks starting with clk, speculating rates as it
> + * goes and firing off PRE_RATE_CHANGE notifications as necessary.
> + *
> + * Unlike clk_recalc_rates, clk_speculate_rates exists only for sending
> + * pre-rate change notifications and returns early if no clks in the
> + * subtree have subscribed to the notifications.
> + *
> + * Caller must hold prepare_lock.
> + */
> +static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
> +{
> +	struct hlist_node *tmp;
> +	struct clk *child;
> +	unsigned long new_rate;
> +	int ret = NOTIFY_DONE;
> +
> +	if (!clk->ops->recalc_rate)
> +		goto out;
When recalc_rate is NULL, it's possible for it and its children to have
notifier too.
> +
> +	new_rate = clk->ops->recalc_rate(clk->hw, parent_rate);
> +
> +	/* abort the rate change if a driver returns NOTIFY_BAD */
> +	if (clk->notifier_count)
> +		ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
> +
> +	if (ret == NOTIFY_BAD)
> +		goto out;
> +
> +	hlist_for_each_entry(child, tmp, &clk->children, child_node) {
> +		ret = __clk_speculate_rates(child, new_rate);
> +		if (ret == NOTIFY_BAD)
> +			break;
> +	}
Tell the notifier that already receive PRE_RATE_CHANGE abort?
> +
> +out:
> +	return ret;
> +}
> +
> +/**
> + * DOC: Using the CLK_SET_RATE_PARENT flag
> + *
> + * __clk_set_rate changes the child's rate before the parent's to more
> + * easily handle failure conditions.
> + *
> + * This means clk might run out of spec for a short time if its rate is
> + * increased before the parent's rate is updated.
> + *
> + * To prevent this consider setting the CLK_SET_RATE_GATE flag on any
> + * clk where you also set the CLK_SET_RATE_PARENT flag
> + *
> + * PRE_RATE_CHANGE notifications are supposed to stack as a rate change
> + * request propagates up the clk tree.  This reflects the different
> + * rates that a downstream clk might experience if left enabled while
> + * upstream parents change their rates.
> + */
> +static struct clk *__clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	struct clk *fail_clk = NULL;
> +	int ret = NOTIFY_DONE;
> +	unsigned long old_rate = clk->rate;
> +	unsigned long new_rate;
> +	unsigned long parent_old_rate;
> +	unsigned long parent_new_rate = 0;
> +	struct clk *child;
> +	struct hlist_node *tmp;
> +
> +	/* bail early if we can't change rate while clk is enabled */
> +	if ((clk->flags & CLK_SET_RATE_GATE) && clk->enable_count)
> +		return clk;
> +
> +	/* find the new rate and see if parent rate should change too */
> +	WARN_ON(!clk->ops->round_rate);
> +
> +	new_rate = clk->ops->round_rate(clk->hw, rate, &parent_new_rate);
> +
> +	/* NOTE: pre-rate change notifications will stack */
> +	if (clk->notifier_count)
> +		ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);

if ((clk->flags & CLK_SET_RATE_PARENT) && parent_new_rate)
	dowstream notify from parent clk?
> +
> +	if (ret == NOTIFY_BAD)
> +		return clk;
> +
> +	/* speculate rate changes down the tree */
> +	hlist_for_each_entry(child, tmp, &clk->children, child_node) {
> +		ret = __clk_speculate_rates(child, new_rate);
> +		if (ret == NOTIFY_BAD)
roll back?
> +			return clk;
> +	}
> +
> +	/* change the rate of this clk */
> +	if (clk->ops->set_rate)
If set_rate is NULL, it can fail at the beginning of this function.
> +		ret = clk->ops->set_rate(clk->hw, new_rate);
> +
> +	if (ret == NOTIFY_BAD)
you mean to check set_rate fail? Notify ABORT_RATE_CHANGE?
> +		return clk;
> +
> +	/*
> +	 * change the rate of the parent clk if necessary
> +	 *
> +	 * hitting the nested 'if' path implies we have hit a .set_rate
> +	 * failure somewhere upstream while propagating __clk_set_rate
> +	 * up the clk tree.  roll back the clk rates one by one and
> +	 * return the pointer to the clk that failed.  clk_set_rate will
> +	 * use the pointer to propagate a rate-change abort notifier
> +	 * from the "highest" point.
> +	 */
> +	if ((clk->flags & CLK_SET_RATE_PARENT) && parent_new_rate) {
> +		parent_old_rate = clk->parent->rate;
> +		fail_clk = __clk_set_rate(clk->parent, parent_new_rate);
> +
> +		/* roll back changes if parent rate change failed */
> +		if (fail_clk) {
> +			pr_warn("%s: failed to set parent %s rate to %lu\n",
> +					__func__, fail_clk->name,
> +					parent_new_rate);
> +
> +			/*
> +			 * Send PRE_RATE_CHANGE notifiers down the tree
> +			 * again, since we're rolling back the rate
> +			 * changes due to the abort.
> +			 *
> +			 * Ignore any NOTIFY_BAD's since this *is* the
> +			 * exception handler.
> +			 *
> +			 * NOTE: pre-rate change notifications will stack
> +			 */
> +			__clk_speculate_rates(clk, clk->parent->rate);
IMHO, driver can not be happy to receive multiple PRE_RATE_CHANGE.
Notify ABORT_RATE_CHANGE?

> +
> +			clk->ops->set_rate(clk->hw, old_rate);
> +		}
> +		return fail_clk;
> +	}
> +
> +	/*
> +	 * set clk's rate & recalculate the rates of clk's children
> +	 *
> +	 * hitting this path implies we have successfully finished
> +	 * propagating recursive calls to __clk_set_rate up the clk tree
> +	 * (if necessary) and it is safe to propagate __clk_recalc_rates
> +	 * and post-rate change notifiers down the clk tree from this
> +	 * point.
> +	 */
> +	__clk_recalc_rates(clk, POST_RATE_CHANGE);
> +
> +	return NULL;
> +}
> +
> +/**
> + * clk_set_rate - specify a new rate for clk
> + * @clk: the clk whose rate is being changed
> + * @rate: the new rate for clk
> + *
> + * In the simplest case clk_set_rate will only change the rate of clk.
> + *
> + * If clk has the CLK_SET_RATE_GATE flag set and it is enabled this call
> + * will fail; only when the clk is disabled will it be able to change
> + * its rate.
> + *
> + * Setting the CLK_SET_RATE_PARENT flag allows clk_set_rate to
> + * recursively propagate up to clk's parent; whether or not this happens
> + * depends on the outcome of clk's .round_rate implementation.  If
> + * *parent_rate is 0 after calling .round_rate then upstream parent
> + * propagation is ignored.  If *parent_rate comes back with a new rate
> + * for clk's parent then we propagate up to clk's parent and set it's
> + * rate.  Upward propagation will continue until either a clk does not
> + * support the CLK_SET_RATE_PARENT flag or .round_rate stops requesting
> + * changes to clk's parent_rate.  If there is a failure during upstream
> + * propagation then clk_set_rate will unwind and restore each clk's rate
> + * that had been successfully changed.  Afterwards a rate change abort
> + * notification will be propagated downstream, starting from the clk
> + * that failed.
> + *
> + * At the end of all of the rate setting, clk_set_rate internally calls
> + * __clk_recalc_rates and propagates the rate changes downstream,
> + * starting from the highest clk whose rate was changed.  This has the
> + * added benefit of propagating post-rate change notifiers.
> + *
> + * Note that while post-rate change and rate change abort notifications
> + * are guaranteed to be sent to a clk only once per call to
> + * clk_set_rate, pre-change notifications will be sent for every clk
> + * whose rate is changed.  Stacking pre-change notifications is noisy
> + * for the drivers subscribed to them, but this allows drivers to react
> + * to intermediate clk rate changes up until the point where the final
> + * rate is achieved at the end of upstream propagation.
> + *
> + * Returns 0 on success, -EERROR otherwise.
> + */
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	struct clk *fail_clk;
> +	int ret = 0;
> +
> +	/* prevent racing with updates to the clock topology */
> +	mutex_lock(&prepare_lock);
> +
> +	/* bail early if nothing to do */
> +	if (rate == clk->rate)
> +		goto out;
> +
> +	fail_clk = __clk_set_rate(clk, rate);
> +	if (fail_clk) {
> +		pr_warn("%s: failed to set %s rate\n", __func__,
> +				fail_clk->name);
> +		__clk_recalc_rates(clk, ABORT_RATE_CHANGE);
It might need to begin from parent clk. move it to __clk_set_rate?
> +		ret = -EIO;
> +	}
> +
> +out:
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_rate);
> +
> +/**
> + * clk_get_parent - return the parent of a clk
> + * @clk: the clk whose parent gets returned
> + *
> + * Simply returns clk->parent.  Returns NULL if clk is NULL.
> + */
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	struct clk *parent;
> +
> +	mutex_lock(&prepare_lock);
> +	parent = __clk_get_parent(clk);
> +	mutex_unlock(&prepare_lock);
> +
> +	return parent;
> +}
> +EXPORT_SYMBOL_GPL(clk_get_parent);
> +
> +/*
> + * .get_parent is mandatory for clocks with multiple possible parents.  It is
> + * optional for single-parent clocks.  Always call .get_parent if it is
> + * available and WARN if it is missing for multi-parent clocks.
> + *
> + * For single-parent clocks without .get_parent, first check to see if the
> + * .parents array exists, and if so use it to avoid an expensive tree
> + * traversal.  If .parents does not exist then walk the tree with __clk_lookup.
> + */
> +static struct clk *__clk_init_parent(struct clk *clk)
> +{
> +	struct clk *ret = NULL;
> +	u8 index;
> +
> +	/* handle the trivial cases */
> +
> +	if (!clk->num_parents)
> +		goto out;
> +
> +	if (clk->num_parents == 1) {
> +		if (IS_ERR_OR_NULL(clk->parent))
> +			ret = clk->parent = __clk_lookup(clk->parent_names[0]);
> +		ret = clk->parent;
> +		goto out;
> +	}
> +
> +	if (!clk->ops->get_parent) {
> +		WARN(!clk->ops->get_parent,
> +			"%s: multi-parent clocks must implement .get_parent\n",
> +			__func__);
> +		goto out;
> +	};
> +
> +	/*
> +	 * Do our best to cache parent clocks in clk->parents.  This prevents
> +	 * unnecessary and expensive calls to __clk_lookup.  We don't set
> +	 * clk->parent here; that is done by the calling function
> +	 */
> +
> +	index = clk->ops->get_parent(clk->hw);
> +
> +	if (!clk->parents)
> +		clk->parents =
> +			kmalloc((sizeof(struct clk*) * clk->num_parents),
> +					GFP_KERNEL);
> +
> +	if (!clk->parents)
> +		ret = __clk_lookup(clk->parent_names[index]);
> +	else if (!clk->parents[index])
> +		ret = clk->parents[index] =
> +			__clk_lookup(clk->parent_names[index]);
> +	else
> +		ret = clk->parents[index];
> +
> +out:
> +	return ret;
> +}
> +
> +void __clk_reparent(struct clk *clk, struct clk *new_parent)
> +{
> +#ifdef CONFIG_COMMON_CLK_DEBUG
> +	struct dentry *d;
> +	struct dentry *new_parent_d;
> +#endif
> +
> +	if (!clk || !new_parent)
> +		return;
> +
> +	hlist_del(&clk->child_node);
> +
> +	if (new_parent)
> +		hlist_add_head(&clk->child_node, &new_parent->children);
> +	else
> +		hlist_add_head(&clk->child_node, &clk_orphan_list);
> +
> +#ifdef CONFIG_COMMON_CLK_DEBUG
> +	if (!inited)
> +		goto out;
> +
> +	if (new_parent)
> +		new_parent_d = new_parent->dentry;
> +	else
> +		new_parent_d = orphandir;
> +
> +	d = debugfs_rename(clk->dentry->d_parent, clk->dentry,
> +			new_parent_d, clk->name);
> +	if (d)
> +		clk->dentry = d;
> +	else
> +		pr_debug("%s: failed to rename debugfs entry for %s\n",
> +				__func__, clk->name);
> +out:
> +#endif
> +
> +	clk->parent = new_parent;
> +
> +	__clk_recalc_rates(clk, POST_RATE_CHANGE);
> +}
> +
> +static int __clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	struct clk *old_parent;
> +	unsigned long flags;
> +	int ret = -EINVAL;
> +	u8 i;
> +
> +	old_parent = clk->parent;
> +
> +	/* find index of new parent clock using cached parent ptrs */
> +	for (i = 0; i < clk->num_parents; i++)
> +		if (clk->parents[i] == parent)
> +			break;
> +
> +	/*
> +	 * find index of new parent clock using string name comparison
> +	 * also try to cache the parent to avoid future calls to __clk_lookup
> +	 */
> +	if (i == clk->num_parents)
> +		for (i = 0; i < clk->num_parents; i++)
> +			if (!strcmp(clk->parent_names[i], parent->name)) {
> +				clk->parents[i] = __clk_lookup(parent->name);
> +				break;
> +			}
> +
> +	if (i == clk->num_parents) {
> +		pr_debug("%s: clock %s is not a possible parent of clock %s\n",
> +				__func__, parent->name, clk->name);
> +		goto out;
> +	}
> +
> +	/* migrate prepare and enable */
> +	if (clk->prepare_count)
> +		__clk_prepare(parent);
> +
> +	/* FIXME replace with clk_is_enabled(clk) someday */
> +	spin_lock_irqsave(&enable_lock, flags);
> +	if (clk->enable_count)
> +		__clk_enable(parent);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +
> +	/* change clock input source */
> +	ret = clk->ops->set_parent(clk->hw, i);
> +
> +	/* clean up old prepare and enable */
> +	spin_lock_irqsave(&enable_lock, flags);
> +	if (clk->enable_count)
> +		__clk_disable(old_parent);
> +	spin_unlock_irqrestore(&enable_lock, flags);
> +
> +	if (clk->prepare_count)
> +		__clk_unprepare(old_parent);
> +
> +out:
> +	return ret;
> +}
> +
> +/**
> + * clk_set_parent - switch the parent of a mux clk
> + * @clk: the mux clk whose input we are switching
> + * @parent: the new input to clk
> + *
> + * Re-parent clk to use parent as it's new input source.  If clk has the
> + * CLK_SET_PARENT_GATE flag set then clk must be gated for this
> + * operation to succeed.  After successfully changing clk's parent
> + * clk_set_parent will update the clk topology, sysfs topology and
> + * propagate rate recalculation via __clk_recalc_rates.  Returns 0 on
> + * success, -EERROR otherwise.
> + */
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	int ret = 0;
> +
> +	if (!clk || !clk->ops)
> +		return -EINVAL;
> +
> +	if (!clk->ops->set_parent)
> +		return -ENOSYS;
> +
> +	/* prevent racing with updates to the clock topology */
> +	mutex_lock(&prepare_lock);
> +
> +	if (clk->parent == parent)
> +		goto out;
> +
> +	/* propagate PRE_RATE_CHANGE notifications */
> +	if (clk->notifier_count)
> +		ret = __clk_speculate_rates(clk, parent->rate);
> +
> +	/* abort if a driver objects */
> +	if (ret == NOTIFY_STOP)
> +		goto out;
> +
> +	/* only re-parent if the clock is not in use */
> +	if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count)
> +		ret = -EBUSY;
> +	else
> +		ret = __clk_set_parent(clk, parent);
> +
> +	/* propagate ABORT_RATE_CHANGE if .set_parent failed */
> +	if (ret) {
> +		__clk_recalc_rates(clk, ABORT_RATE_CHANGE);
> +		goto out;
> +	}
> +
> +	/* propagate rate recalculation downstream */
> +	__clk_reparent(clk, parent);
> +
> +out:
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_set_parent);
> +
> +/**
> + * __clk_init - initialize the data structures in a struct clk
> + * @dev:	device initializing this clk, placeholder for now
> + * @clk:	clk being initialized
> + *
> + * Initializes the lists in struct clk, queries the hardware for the
> + * parent and rate and sets them both.
> + *
> + * Any struct clk passed into __clk_init must have the following members
> + * populated:
> + * 	.name
> + * 	.ops
> + * 	.hw
> + * 	.parent_names
> + * 	.num_parents
> + * 	.flags
> + *
> + * Essentially, everything that would normally be passed into clk_register is
> + * assumed to be initialized already in __clk_init.  The other members may be
> + * populated, but are optional.
> + *
> + * __clk_init is only exposed via clk-private.h and is intended for use with
> + * very large numbers of clocks that need to be statically initialized.  It is
> + * a layering violation to include clk-private.h from any code which implements
> + * a clock's .ops; as such any statically initialized clock data MUST be in a
> + * separate C file from the logic that implements it's operations.
> + */
> +void __clk_init(struct device *dev, struct clk *clk)
> +{
> +	int i;
> +	struct clk *orphan;
> +	struct hlist_node *tmp;
> +
> +	if (!clk)
> +		return;
> +
> +	mutex_lock(&prepare_lock);
> +
> +	/* check to see if a clock with this name is already registered */
> +	if (__clk_lookup(clk->name))
> +		goto out;
> +
> +	/*
> +	 * Allocate an array of struct clk *'s to avoid unnecessary string
> +	 * look-ups of clk's possible parents.  This can fail for clocks passed
> +	 * in to clk_init during early boot; thus any access to clk->parents[]
> +	 * must always check for a NULL pointer and try to populate it if
> +	 * necessary.
> +	 *
> +	 * If clk->parents is not NULL we skip this entire block.  This allows
> +	 * for clock drivers to statically initialize clk->parents.
> +	 */
> +	if (clk->num_parents && !clk->parents) {
> +		clk->parents = kmalloc((sizeof(struct clk*) * clk->num_parents),
> +				GFP_KERNEL);
> +		/*
> +		 * __clk_lookup returns NULL for parents that have not been
> +		 * clk_init'd; thus any access to clk->parents[] must check
> +		 * for a NULL pointer.  We can always perform lazy lookups for
> +		 * missing parents later on.
> +		 */
> +		if (clk->parents)
> +			for (i = 0; i < clk->num_parents; i++)
> +				clk->parents[i] =
> +					__clk_lookup(clk->parent_names[i]);
> +	}
> +
> +	clk->parent = __clk_init_parent(clk);
> +
> +	/*
> +	 * Populate clk->parent if parent has already been __clk_init'd.  If
> +	 * parent has not yet been __clk_init'd then place clk in the orphan
> +	 * list.  If clk has set the CLK_IS_ROOT flag then place it in the root
> +	 * clk list.
> +	 *
> +	 * Every time a new clk is clk_init'd then we walk the list of orphan
> +	 * clocks and re-parent any that are children of the clock currently
> +	 * being clk_init'd.
> +	 */
> +	if (clk->parent)
> +		hlist_add_head(&clk->child_node,
> +				&clk->parent->children);
> +	else if (clk->flags & CLK_IS_ROOT)
> +		hlist_add_head(&clk->child_node, &clk_root_list);
> +	else
> +		hlist_add_head(&clk->child_node, &clk_orphan_list);
> +
> +	/*
> +	 * Set clk's rate.  The preferred method is to use .recalc_rate.  For
> +	 * simple clocks and lazy developers the default fallback is to use the
> +	 * parent's rate.  If a clock doesn't have a parent (or is orphaned)
> +	 * then rate is set to zero.
> +	 */
> +	if (clk->ops->recalc_rate)
> +		clk->rate = clk->ops->recalc_rate(clk->hw,
> +				__clk_get_rate(clk->parent));
> +	else if (clk->parent)
> +		clk->rate = clk->parent->rate;
> +	else
> +		clk->rate = 0;
> +
> +	/*
> +	 * walk the list of orphan clocks and reparent any that are children of
> +	 * this clock
> +	 */
> +	hlist_for_each_entry(orphan, tmp, &clk_orphan_list, child_node)
> +		__clk_reparent(orphan, __clk_init_parent(orphan));
check whether orphan->parent is the value of  __clk_init_parent(orphan)
before reparent?
> +
> +	/*
> +	 * optional platform-specific magic
> +	 *
> +	 * The .init callback is not used by any of the basic clock types, but
> +	 * exists for weird hardware that must perform initialization magic.
> +	 * Please consider other ways of solving initialization problems before
> +	 * using this callback, as it's use is discouraged.
> +	 */
> +	if (clk->ops->init)
> +		clk->ops->init(clk->hw);
> +
> +	clk_debug_register(clk);
> +
> +out:
> +	mutex_unlock(&prepare_lock);
> +
> +	return;
> +}
> +
> +/**
> + * clk_register - allocate a new clock, register it and return an opaque cookie
> + * @dev: device that is registering this clock
> + * @name: clock name
> + * @ops: operations this clock supports
> + * @hw: link to hardware-specific clock data
> + * @parent_names: array of string names for all possible parents
> + * @num_parents: number of possible parents
> + * @flags: framework-level hints and quirks
> + *
> + * clk_register is the primary interface for populating the clock tree with new
> + * clock nodes.  It returns a pointer to the newly allocated struct clk which
> + * cannot be dereferenced by driver code but may be used in conjuction with the
> + * rest of the clock API.
> + */
> +struct clk *clk_register(struct device *dev, const char *name,
> +		const struct clk_ops *ops, struct clk_hw *hw,
> +		char **parent_names, u8 num_parents, unsigned long flags)
> +{
> +	struct clk *clk;
> +
> +	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> +	if (!clk)
> +		return NULL;
> +
> +	clk->name = name;
> +	clk->ops = ops;
> +	clk->hw = hw;
> +	clk->flags = flags;
> +	clk->parent_names = parent_names;
> +	clk->num_parents = num_parents;
> +	hw->clk = clk;
> +
> +	__clk_init(dev, clk);
> +
> +	return clk;
> +}
> +EXPORT_SYMBOL_GPL(clk_register);
> +
> +/***        clk rate change notifiers        ***/
> +
> +/**
> + * clk_notifier_register - add a clk rate change notifier
> + * @clk: struct clk * to watch
> + * @nb: struct notifier_block * with callback info
> + *
> + * Request notification when clk's rate changes.  This uses an SRCU
> + * notifier because we want it to block and notifier unregistrations are
> + * uncommon.  The callbacks associated with the notifier must not
> + * re-enter into the clk framework by calling any top-level clk APIs;
> + * this will cause a nested prepare_lock mutex.
> + *
> + * Pre-change notifier callbacks will be passed the current, pre-change
> + * rate of the clk via struct clk_notifier_data.old_rate.  The new,
> + * post-change rate of the clk is passed via struct
> + * clk_notifier.new_rate.
clk_notifier_data ?
> + *
> + * Post-change notifiers will pass the now-current, post-change rate of
> + * the clk in both struct clk_notifier_data.old_rate and struct
> + * clk_notifier_data.new_rate.
> + *
> + * Abort-change notifiers are effectively the opposite of pre-change
> + * notifiers: the original pre-change clk rate is passed in via struct
> + * clk_notifier_data.new_rate and the failed post-change rate is passed
> + * in via struct clk_notifier_data.old_rate.
> + *
> + * clk_notifier_register() must be called from non-atomic context.
> + * Returns -EINVAL if called with null arguments, -ENOMEM upon
> + * allocation failure; otherwise, passes along the return value of
> + * srcu_notifier_chain_register().
> + */
> +int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
> +{
> +	struct clk_notifier *cn;
> +	int ret = -ENOMEM;
> +
> +	if (!clk || !nb)
> +		return -EINVAL;
> +
> +	mutex_lock(&prepare_lock);
> +
> +	/* search the list of notifiers for this clk */
> +	list_for_each_entry(cn, &clk_notifier_list, node)
> +		if (cn->clk == clk)
> +			break;
> +
> +	/* if clk wasn't in the notifier list, allocate new clk_notifier */
> +	if (cn->clk != clk) {
> +		cn = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
> +		if (!cn)
> +			goto out;
> +
> +		cn->clk = clk;
> +		srcu_init_notifier_head(&cn->notifier_head);
> +
> +		list_add(&cn->node, &clk_notifier_list);
> +	}
why not embedd notifier_head to struct clk?
> +
> +	ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
> +
> +	clk->notifier_count++;
> +
> +out:
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_notifier_register);
> +
> +/**
> + * clk_notifier_unregister - remove a clk rate change notifier
> + * @clk: struct clk *
> + * @nb: struct notifier_block * with callback info
> + *
> + * Request no further notification for changes to 'clk' and frees memory
> + * allocated in clk_notifier_register.
> + *
> + * Returns -EINVAL if called with null arguments; otherwise, passes
> + * along the return value of srcu_notifier_chain_unregister().
> + */
> +int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
> +{
> +	struct clk_notifier *cn = NULL;
> +	int ret = -EINVAL;
> +
> +	if (!clk || !nb)
> +		return -EINVAL;
> +
> +	mutex_lock(&prepare_lock);
> +
> +	list_for_each_entry(cn, &clk_notifier_list, node)
> +		if (cn->clk == clk)
> +			break;
> +
> +	if (cn->clk == clk) {
> +		ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
> +
> +		clk->notifier_count--;
> +
> +		/* XXX the notifier code should handle this better */
> +		if (!cn->notifier_head.head) {
> +			srcu_cleanup_notifier_head(&cn->notifier_head);
> +			kfree(cn);
> +		}
> +
> +	} else {
> +		ret = -ENOENT;
> +	}
> +
> +	mutex_unlock(&prepare_lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_notifier_unregister);
> diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
> new file mode 100644
> index 0000000..33bf6a7
> --- /dev/null
> +++ b/include/linux/clk-private.h
> @@ -0,0 +1,68 @@
> +/*
> + *  linux/include/linux/clk-private.h
> + *
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
> + *  Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
> + *
> + * 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.
> + */
> +#ifndef __LINUX_CLK_PRIVATE_H
> +#define __LINUX_CLK_PRIVATE_H
> +
> +#include <linux/clk-provider.h>
> +#include <linux/list.h>
> +
> +/*
> + * WARNING: Do not include clk-private.h from any file that implements struct
> + * clk_ops.  Doing so is a layering violation!
> + *
> + * This header exists only to allow for statically initialized clock data.  Any
> + * static clock data must be defined in a separate file from the logic that
> + * implements the clock operations for that same data.
> + */
> +
> +#ifdef CONFIG_COMMON_CLK
> +
> +struct clk {
> +	const char		*name;
> +	const struct clk_ops	*ops;
> +	struct clk_hw		*hw;
> +	struct clk		*parent;
> +	char			**parent_names;
> +	struct clk		**parents;
> +	u8			num_parents;
> +	unsigned long		rate;
> +	unsigned long		flags;
> +	unsigned int		enable_count;
> +	unsigned int		prepare_count;
> +	struct hlist_head	children;
> +	struct hlist_node	child_node;
> +	unsigned int		notifier_count;
> +#ifdef CONFIG_COMMON_CLK_DEBUG
> +	struct dentry		*dentry;
> +#endif
> +};
> +
> +/**
> + * __clk_init - initialize the data structures in a struct clk
> + * @dev:	device initializing this clk, placeholder for now
> + * @clk:	clk being initialized
> + *
> + * Initializes the lists in struct clk, queries the hardware for the
> + * parent and rate and sets them both.
Add: clocks that call __clk_init don't need to call clk_register.
> + *
> + * Any struct clk passed into __clk_init must have the following members
> + * populated:
> + * 	.name
> + * 	.ops
> + * 	.hw
> + * 	.parent_names
> + * 	.num_parents
> + * 	.flags
> + */
> +void __clk_init(struct device *dev, struct clk *clk);
> +
> +#endif /* CONFIG_COMMON_CLK */
> +#endif /* CLK_PRIVATE_H */
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> new file mode 100644
> index 0000000..c9ed582
> --- /dev/null
> +++ b/include/linux/clk-provider.h
> @@ -0,0 +1,169 @@
> +/*
> + *  linux/include/linux/clk-provider.h
> + *
> + *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
> + *  Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
> + *
> + * 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.
> + */
> +#ifndef __LINUX_CLK_PROVIDER_H
> +#define __LINUX_CLK_PROVIDER_H
> +
> +#include <linux/clk.h>
> +
> +#ifdef CONFIG_COMMON_CLK
> +
> +/**
> + * struct clk_hw - handle for traversing from a struct clk to its corresponding
> + * hardware-specific structure.  struct clk_hw should be declared within struct
> + * clk_foo and then referenced by the struct clk instance that uses struct
> + * clk_foo's clk_ops
> + *
> + * clk: pointer to the struct clk instance that points back to this struct
> + * clk_hw instance
> + */
> +struct clk_hw {
> +	struct clk *clk;
> +};
> +
> +/*
> + * flags used across common struct clk.  these flags should only affect the
> + * top-level framework.  custom flags for dealing with hardware specifics
> + * belong in struct clk_foo
> + */
> +#define CLK_SET_RATE_GATE	BIT(0) /* must be gated across rate change */
> +#define CLK_SET_PARENT_GATE	BIT(1) /* must be gated across re-parent */
> +#define CLK_SET_RATE_PARENT	BIT(2) /* propagate rate change up one level */
> +#define CLK_IGNORE_UNUSED	BIT(3) /* do not gate even if unused */
I can not find anywhere check it.
> +#define CLK_IS_ROOT		BIT(4) /* root clk, has no parent */
> +
> +/**
> + * struct clk_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.  The
> + * 		parent rate is an input parameter.  It is up to the caller to
> + * 		insure that the prepare_mutex is held across this call.
> + * 		Returns the calculated rate.  Optional, but recommended - if
> + * 		this op is not set then clock rate will be initialized to 0.
> + *
> + * @round_rate:	Given a target rate as input, returns the closest rate actually
> + * 		supported by the clock.
> + *
> + * @get_parent:	Queries the hardware to determine the parent of a clock.  The
> + * 		return value is a u8 which specifies the index corresponding to
> + * 		the parent clock.  This index can be applied to either the
> + * 		.parent_names or .parents arrays.  In short, this function
> + * 		translates the parent value read from hardware into an array
> + * 		index.  Currently only called when the clock is initialized by
> + * 		__clk_init.  This callback is mandatory for clocks with
> + * 		multiple parents.  It is optional (and unnecessary) for clocks
> + * 		with 0 or 1 parents.
> + *
> + * @set_parent:	Change the input source of this clock; for clocks with multiple
> + * 		possible parents specify a new parent by passing in the index
> + * 		as a u8 corresponding to the parent in either the .parent_names
> + * 		or .parents arrays.  This function in affect translates an
> + * 		array index into the value programmed into the hardware.
> + * 		Returns 0 on success, -EERROR otherwise.
> + *
> + * @set_rate:	Change the rate of this clock. If this callback returns
> + * 		CLK_SET_RATE_PARENT, the rate change will be propagated to the
> + * 		parent clock (which may propagate again if the parent clock
> + * 		also sets this flag). The requested rate of the parent is
> + * 		passed back from the callback in the second 'unsigned long *'
> + * 		argument.  Note that it is up to the hardware clock's set_rate
> + * 		implementation to insure that clocks do not run out of spec
> + * 		when propgating the call to set_rate up to the parent.  One way
> + * 		to do this is to gate the clock (via clk_disable and/or
> + * 		clk_unprepare) before calling clk_set_rate, then ungating it
> + * 		afterward.  If your clock also has the CLK_GATE_SET_RATE flag
> + * 		set then this will insure safety.  Returns 0 on success,
> + * 		-EERROR otherwise.
> + *
> + * 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 enabling a clock requires code that might sleep,
> + * this must be done in clk_prepare.  Clock enable code that will never be
> + * called in a sleepable context may be implement 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_ops {
> +	int		(*prepare)(struct clk_hw *hw);
> +	void		(*unprepare)(struct clk_hw *hw);
> +	int		(*enable)(struct clk_hw *hw);
> +	void		(*disable)(struct clk_hw *hw);
> +	unsigned long	(*recalc_rate)(struct clk_hw *hw,
> +					unsigned long parent_rate);
> +	long		(*round_rate)(struct clk_hw *hw, unsigned long,
> +					unsigned long *);
> +	int		(*set_parent)(struct clk_hw *hw, u8 index);
> +	u8		(*get_parent)(struct clk_hw *hw);
> +	int		(*set_rate)(struct clk_hw *hw, unsigned long);
> +	void		(*init)(struct clk_hw *hw);
> +};
> +
> +
> +/**
> + * clk_register - allocate a new clock, register it and return an opaque cookie
> + * @dev: device that is registering this clock
> + * @name: clock name
> + * @ops: operations this clock supports
> + * @hw: link to hardware-specific clock data
> + * @parent_names: array of string names for all possible parents
> + * @num_parents: number of possible parents
> + * @flags: framework-level hints and quirks
> + *
> + * clk_register is the primary interface for populating the clock tree with new
> + * clock nodes.  It returns a pointer to the newly allocated struct clk which
> + * cannot be dereferenced by driver code but may be used in conjuction with the
> + * rest of the clock API.
> + */
> +struct clk *clk_register(struct device *dev, const char *name,
> +		const struct clk_ops *ops, struct clk_hw *hw,
> +		char **parent_names, u8 num_parents, unsigned long flags);
> +
> +/* helper functions */
> +const char *__clk_get_name(struct clk *clk);
> +struct clk_hw *__clk_get_hw(struct clk *clk);
> +u8 __clk_get_num_parents(struct clk *clk);
> +struct clk *__clk_get_parent(struct clk *clk);
> +unsigned long __clk_get_rate(struct clk *clk);
> +unsigned long __clk_get_flags(struct clk *clk);
> +struct clk *__clk_lookup(const char *name);
> +
> +/*
> + * FIXME clock api without lock protection
> + */
> +int __clk_prepare(struct clk *clk);
> +void __clk_unprepare(struct clk *clk);
> +void __clk_reparent(struct clk *clk, struct clk *new_parent);
It only notify POST_RATE_CHANGE without PRE_RATE_CHANGE. Mabe we need
to move PRE_RATE_CHANGE to __clk_reparent too?
> +unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
why're there no enable/disable functions?
> +
> +#endif /* CONFIG_COMMON_CLK */
> +#endif /* CLK_PROVIDER_H */
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index b9d46fa..b025272 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) 2011-2012 Linaro Ltd <mturquette@linaro.org>
>   *
>   * 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
> @@ -12,18 +13,75 @@
>  #define __LINUX_CLK_H
>  
>  #include <linux/kernel.h>
> +#include <linux/notifier.h>
>  
>  struct device;
>  
> -/*
> - * The base API.
> +struct clk;
> +
> +#ifdef CONFIG_COMMON_CLK
> +
> +/**
> + * DOC: clk notifier callback types
> + *
> + * PRE_RATE_CHANGE - called immediately before the clk rate is changed,
> + *     to indicate that the rate change will proceed.  Drivers must
> + *     immediately terminate any operations that will be affected by the
> + *     rate change.  Callbacks may either return NOTIFY_DONE or
> + *     NOTIFY_STOP.
> + *
> + * ABORT_RATE_CHANGE: called if the rate change failed for some reason
> + *     after PRE_RATE_CHANGE.  In this case, all registered notifiers on
> + *     the clk will be called with ABORT_RATE_CHANGE. Callbacks must
> + *     always return NOTIFY_DONE.
> + *
> + * POST_RATE_CHANGE - called after the clk rate change has successfully
> + *     completed.  Callbacks must always return NOTIFY_DONE.
> + *
>   */
> +#define PRE_RATE_CHANGE			BIT(0)
> +#define POST_RATE_CHANGE		BIT(1)
> +#define ABORT_RATE_CHANGE		BIT(2)
>  
> +/**
> + * struct clk_notifier - associate a clk with a notifier
> + * @clk: struct clk * to associate the notifier with
> + * @notifier_head: a blocking_notifier_head for this clk
> + * @node: linked list pointers
> + *
> + * A list of struct clk_notifier is maintained by the notifier code.
> + * An entry is created whenever code registers the first notifier on a
> + * particular @clk.  Future notifiers on that @clk are added to the
> + * @notifier_head.
> + */
> +struct clk_notifier {
> +	struct clk			*clk;
> +	struct srcu_notifier_head	notifier_head;
> +	struct list_head		node;
> +};
>  
> -/*
> - * struct clk - an machine class defined object / cookie.
> +/**
> + * struct clk_notifier_data - rate data to pass to the notifier callback
> + * @clk: struct clk * being changed
> + * @old_rate: previous rate of this clk
> + * @new_rate: new rate of this clk
> + *
> + * For a pre-notifier, old_rate is the clk's rate before this rate
> + * change, and new_rate is what the rate will be in the future.  For a
> + * post-notifier, old_rate and new_rate are both set to the clk's
> + * current rate (this was done to optimize the implementation).
>   */
> -struct clk;
> +struct clk_notifier_data {
> +	struct clk		*clk;
> +	unsigned long		old_rate;
> +	unsigned long		new_rate;
> +};
> +
> +int clk_notifier_register(struct clk *clk, struct notifier_block *nb);
> +
> +int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
> +
> +#endif /* !CONFIG_COMMON_CLK */
>  
>  /**
>   * clk_get - lookup and obtain a reference to a clock producer.

Thanks
Richard


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

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-05  8:48       ` Andrew Lunn
@ 2012-03-05  9:29         ` Sascha Hauer
  2012-03-05 10:17           ` Andrew Lunn
  0 siblings, 1 reply; 51+ messages in thread
From: Sascha Hauer @ 2012-03-05  9:29 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Turquette, Mike, Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Jeremy Kerr, Thomas Gleixner, Arnd Bergman,
	Paul Walmsley, Shawn Guo, Jamie Iles, Richard Zhao,
	Saravana Kannan, Magnus Damm, Rob Herring, Mark Brown,
	Linus Walleij, Stephen Boyd, Amit Kucheria, Deepak Saxena,
	Grant Likely, Rafael J. Wysocki

On Mon, Mar 05, 2012 at 09:48:23AM +0100, Andrew Lunn wrote:
> On Sun, Mar 04, 2012 at 04:30:08PM -0800, Turquette, Mike wrote:
> > On Sun, Mar 4, 2012 at 9:42 AM, Andrew Lunn <andrew@lunn.ch> wrote:
> > > On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
> > >> Many platforms support simple gateable clocks, fixed-rate clocks,
> > >> adjustable divider clocks and multi-parent multiplexer clocks.
> > >>
> > >> This patch introduces basic clock types for the above-mentioned hardware
> > >> which share some common characteristics.
> > >
> > > Hi Mike
> > >
> > > These basic clocks don't allow the use of prepare/unprepare, from the
> > > side of the clock provider. I think i need this.
> > 
> > This is an interesting point and might help us nail down exactly what
> > we expect from clk_prepare/clk_unprepare.
> > 
> > >
> > > The Orion Kirkwood SoC has clock gating for most of its on chip
> > > peripherals, which the other older Orion devices don't have. The SATA
> > > and PCIe also allows the PHY to be shut down, again which older Orion
> > > devices don't have. The current code links the clock and the PHY
> > > together, shutting both down are the same time. So i would like to
> > > perform the PHY shutdown in the unprepare() function of the clk
> > > driver.
> > 
> > Do you feel it is The Right Thing to enable/disable the phy from
> > clk_prepare/clk_unprepare?  
> 
> Humm, not sure yet. I don't know all the different possibilities,
> which is why i tried to describe my use case, rather than just assume
> i need prepare/unprepare.
> 
> I also realized i did not explain my use case properly. 
> 
> At boot, uboot is turning on various clocks and SATA/PCIe PHYs etc, in
> order to get the device booted. Linux takes over, and the
> Orion/kirkwood board files, ask the kirkwood or generic Orion code to
> create platform_data structures for the different devices that the
> board uses. The kirkwood code keeps a bitmap of devices for which it
> creates platform data for which there is a gated clock. Then in a
> lateinit call, it turns on clocks which are needed, and also turns off
> clocks which are no longer needed, because the board did not ask for a
> driver binding for that device. If it turns off a SATA or PCIe clock,
> it also turns off the PHY associated with it.
> 
> So we are talking about turning off hardware for which there is no
> driver. This seems to exclude pm_runtime_get(_sync), which is about
> hardware with drivers.
> 
> We touched on this subject a couple of months ago, at least with
> respect to clocks. You said that is what the flag CLK_IGNORE_UNUSED
> will be used for. In a lateinit call, you plan to iterate over all
> clocks and turn off any which don't have CLK_IGNORE_UNUSED and have
> not been enabled. I assume you will call both disable() and
> unprepare(), and if i've can put code into the unprepare to turn the
> PHY off, all is good.
> 
> > > Is allowing to pass prepare/unprepare functions to basic clocks
> > > something you want to support? If i prepare a patch would you consider
> > > it?
> > 
> > My original instinct was "no".  The simple gate clock was always
> > supposed to be "simple" and if you need more than it provides then it
> > might be best for your platform to implement a specific clock type.
> > Especially since the purpose of clk_prepare is still up in the air.
> 
> I think i can wrap your simple gate clock, to make my "complex" gate
> clock. What would help is if you would EXPORT_SYMBOL_GPL
> clk_gate_enable() and clk_gate_disable(), since they do exactly what i
> want. I can then build my own clk_ops structure, with my own
> unprepare() function. I would probably use DEFINE_CLK_GATE as is, and
> then at run time, before calling __clk_init() overwrite the .ops with
> my own version.

Maybe I don't get your point, but clk_unprepare should be used when
you have to sleep to disable your clock. When clk_gate_disable() is
exactly why do you want to use clk_unprepare instead of clk_disable?

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] 51+ messages in thread

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-05  9:29         ` Sascha Hauer
@ 2012-03-05 10:17           ` Andrew Lunn
  2012-03-09 23:38             ` Turquette, Mike
  0 siblings, 1 reply; 51+ messages in thread
From: Andrew Lunn @ 2012-03-05 10:17 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Andrew Lunn, Turquette, Mike, Russell King, patches, linaro-dev,
	linux-kernel, linux-arm-kernel, Jeremy Kerr, Thomas Gleixner,
	Arnd Bergman, Paul Walmsley, Shawn Guo, Jamie Iles, Richard Zhao,
	Saravana Kannan, Magnus Damm, Rob Herring, Mark Brown,
	Linus Walleij, Stephen Boyd, Amit Kucheria, Deepak Saxena,
	Grant Likely, Rafael J. Wysocki

> > I think i can wrap your simple gate clock, to make my "complex" gate
> > clock. What would help is if you would EXPORT_SYMBOL_GPL
> > clk_gate_enable() and clk_gate_disable(), since they do exactly what i
> > want. I can then build my own clk_ops structure, with my own
> > unprepare() function. I would probably use DEFINE_CLK_GATE as is, and
> > then at run time, before calling __clk_init() overwrite the .ops with
> > my own version.
> 
> Maybe I don't get your point, but clk_unprepare should be used when
> you have to sleep to disable your clock. When clk_gate_disable() is
> exactly why do you want to use clk_unprepare instead of clk_disable?

I'm trying to avoid having to implement a new clock provider. The
whole point of the generic clk code is to consolidate code. It seems
silly to create a new clk provider which is 95% identical to Mike's
gated provider, if i can avoid it.

If i stuff it into clk_disable(), it means i cannot use the basic gate
clock Mike provides in the generic clock framework. Which is a shame,
since it does exactly what i want in terms of gating the clock.

If i can use unprepare(), which basic gate does not use, i can use
Mikes code, and just extend it. It is there, it is unused, so why not
use it?

    Andrew

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

* Re: [PATCH v5 2/4] clk: Kconfig: add entry for HAVE_CLK_PREPARE
  2012-03-05  2:04   ` Richard Zhao
@ 2012-03-05 19:46     ` Turquette, Mike
  0 siblings, 0 replies; 51+ messages in thread
From: Turquette, Mike @ 2012-03-05 19:46 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Russell King, Grant Likely, Paul Walmsley, Linus Walleij,
	patches, Stephen Boyd, Mark Brown, Magnus Damm, linux-kernel,
	Rob Herring, Richard Zhao, Arnd Bergman, Deepak Saxena,
	Saravana Kannan, Andrew Lunn, Amit Kucheria, linaro-dev,
	Jeremy Kerr, Thomas Gleixner, linux-arm-kernel

On Sun, Mar 4, 2012 at 6:04 PM, Richard Zhao <richard.zhao@freescale.com> wrote:
> On Sat, Mar 03, 2012 at 12:28:59AM -0800, Mike Turquette wrote:
>> The common clk framework provides clk_prepare and clk_unprepare
>> implementations.  Create an entry for HAVE_CLK_PREPARE so that
>> COMMON_CLK can select it.
>>
>> Signed-off-by: Mike Turquette <mturquette@linaro.org>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> Acked-by: Shawn Guo <shawn.guo@linaro.org>
>> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Arnd Bergman <arnd.bergmann@linaro.org>
>> Cc: Paul Walmsley <paul@pwsan.com>
>> Cc: Richard Zhao <richard.zhao@linaro.org>
>> Cc: Saravana Kannan <skannan@codeaurora.org>
>> Cc: Magnus Damm <magnus.damm@gmail.com>
>> Cc: Rob Herring <rob.herring@calxeda.com>
>> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Cc: Linus Walleij <linus.walleij@stericsson.com>
>> Cc: Stephen Boyd <sboyd@codeaurora.org>
>> Cc: Amit Kucheria <amit.kucheria@linaro.org>
>> Cc: Deepak Saxena <dsaxena@linaro.org>
>> Cc: Grant Likely <grant.likely@secretlab.ca>
>> Cc: Andrew Lunn <andrew@lunn.ch>
>> ---
>>  drivers/clk/Kconfig |    3 +++
>>  1 files changed, 3 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index 9b3cd08..3912576 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -8,3 +8,6 @@ config HAVE_CLK_PREPARE
>>
>>  config HAVE_MACH_CLKDEV
>>       bool
>> +
>> +config HAVE_CLK_PREPARE
>> +     bool
> We've already had it. redundant?

I didn't realize that Shawn merged this in since the last posting of V4...

Will drop it.

Regards,
Mike

>
> Thanks
> Richard
>> --
>> 1.7.5.4
>>
>>
>> _______________________________________________
>> 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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-05  7:38           ` Sascha Hauer
@ 2012-03-05 20:03             ` Turquette, Mike
  2012-03-06 19:00               ` Sascha Hauer
  0 siblings, 1 reply; 51+ messages in thread
From: Turquette, Mike @ 2012-03-05 20:03 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Andrew Lunn, Paul Walmsley, linaro-dev, Linus Walleij, patches,
	Stephen Boyd, Mark Brown, Magnus Damm, linux-kernel, Rob Herring,
	Richard Zhao, Grant Likely, Deepak Saxena, Saravana Kannan,
	Thomas Gleixner, Shawn Guo, Amit Kucheria, Russell King,
	Jeremy Kerr, Arnd Bergman, linux-arm-kernel

On Sun, Mar 4, 2012 at 11:38 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Sun, Mar 04, 2012 at 04:12:21PM -0800, Turquette, Mike wrote:
>> >>
>> >> I believe this patch already does what you suggest, but I might be
>> >> missing your point.
>> >
>> > In include/linux/clk-private.h you expose struct clk outside the core.
>> > This has to be done to make static initializers possible. There is a big
>> > warning in this file that it must not be included from files implementing
>> > struct clk_ops. You can simply avoid this warning by declaring struct clk
>> > with only a single member:
>> >
>> > include/linux/clk.h:
>> >
>> > struct clk {
>> >        struct clk_internal *internal;
>> > };
>> >
>> > This way everybody knows struct clk (thus can embed it in their static
>> > initializers), but doesn't know anything about the internal members. Now
>> > in drivers/clk/clk.c you declare struct clk_internal exactly like struct
>> > clk was declared before:
>> >
>> > struct clk_internal {
>> >        const char              *name;
>> >        const struct clk_ops    *ops;
>> >        struct clk_hw           *hw;
>> >        struct clk              *parent;
>> >        char                    **parent_names;
>> >        struct clk              **parents;
>> >        u8                      num_parents;
>> >        unsigned long           rate;
>> >        unsigned long           flags;
>> >        unsigned int            enable_count;
>> >        unsigned int            prepare_count;
>> >        struct hlist_head       children;
>> >        struct hlist_node       child_node;
>> >        unsigned int            notifier_count;
>> > #ifdef CONFIG_COMMON_CLK_DEBUG
>> >        struct dentry           *dentry;
>> > #endif
>> > };
>> >
>> > An instance of struct clk_internal will be allocated in
>> > __clk_init/clk_register. Now the private data stays completely inside
>> > the core and noone can abuse it.
>>
>> Hi Sascha,
>>
>> I see the disconnect here.  For OMAP (and possibly other platforms) at
>> least some clock data is necessary during early boot, before the
>> regular allocation methods are available (timers for instance).
>
> We had this problem on i.MX aswell. It turned out that the timer clock
> is the only clock that is needed so early. We solved this by moving the
> clock init to the system timer init function.

When you say "mov[ed] the clock init to the system timer init
function" do you mean that you statically allocated struct clk and
used the clk framework api, or instead you just did some direct
register writes to initialize things properly?

>
>> Due
>> to this my idea of static initialization was to take care of
>> everything that would normally require an allocator, which includes
>> the internals of struct clk; thus exposing struct clk is useful here
>> as you can still use the clock framework during very early boot.  Your
>> method above doesn't satisfy this requirement.  I'm not sure what the
>> purpose would be of statically allocating your version of struct clk,
>> which will ultimately need to allocate memory for the clock internals
>> anyways.  Can you elaborate the benefit of this approach over just
>> using the clk_foo_register functions?
>
> As said the benefit is that you do not have to expose the internal
> layout of struct clk outside the clock framework. Note that in the

That is a benefit for sure, but if it does not solve the problem of
allowing for static allocation then we still have an issue.

> file you referenced here:
>
> http://git.linaro.org/gitweb?p=people/mturquette/linux.git;a=blob;f=arch/arm/mach-omap2/clock44xx_data.c;h=7f833a7b2dca84a52c2bd1e7c8d9cfe560771258;hb=v3.3-rc5-clkv5-omap#l205
>
> You violate what you have in a comment above clk-private.h:
>
> /* __clk_init is only exposed via clk-private.h and is intended for use with
>  * very large numbers of clocks that need to be statically initialized. It is
>  * a layering violation to include clk-private.h from any code which implements
>  * a clock's .ops; as such any statically initialized clock data MUST be in
>  * separate C file from the logic that implements it's operations.
>  */
>
> Well, the file is work in progress, you probably fix this before sending
> it out, but I bet people will include clk-private.h and nobody else
> notices it.

clock44xx_data.c does not violate that rule.  None of the logic that
implements ops for those clocks is present clock44xx_data.c.  All of
the code in that file is simply initialization and registration of
OMAP4 clocks.  Many of the clocks are basic clock types (divider,
multiplexer and fixed-rate are used in that file) with protected code
drivers/clk/clk-*.c and the remaining clocks are of the struct
clk_hw_omap variety, which has code spread across several files:

arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clkt_dpll.c
arch/arm/mach-omap2/clkt_clksel.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/dpll4xxx.c

All of the above files include linux/clk-provider.h, not
linux/clk-private.h.  That code makes heavy use of the
__clk_get_whatever helpers and shows how a platform might honor the
layer of separation between struct clk and stuct clk_ops/struct
clk_foo.  You are correct that the code is a work-in-progress, but
there are no layering violations that I can see.

I also think we are talking past each other to some degree.  One point
I would like to make (and maybe you already know this from code
review) is that it is unnecessary to have pointers to your parent
struct clk*'s when either initializing or registering your clocks.  In
fact the existing clk_register_foo functions don't even allow you to
pass in parent pointers and rely wholly on string name matching.  I
just wanted to point that out in case it went unnoticed, as it is a
new way of doing things from the previous series and was born out of
Thomas' review of V4 and multi-parent handling.  This also keeps
device-tree in mind where we might not know the struct clk *pointer at
compile time for "connecting" discrete devices.

Thanks,
Mike

>
> 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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-05 20:03             ` Turquette, Mike
@ 2012-03-06 19:00               ` Sascha Hauer
  2012-03-07 21:20                 ` Turquette, Mike
  0 siblings, 1 reply; 51+ messages in thread
From: Sascha Hauer @ 2012-03-06 19:00 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Andrew Lunn, Paul Walmsley, linaro-dev, Linus Walleij, patches,
	Stephen Boyd, Mark Brown, Magnus Damm, linux-kernel, Rob Herring,
	Richard Zhao, Grant Likely, Deepak Saxena, Saravana Kannan,
	Thomas Gleixner, Shawn Guo, Amit Kucheria, Russell King,
	Jeremy Kerr, Arnd Bergman, linux-arm-kernel

On Mon, Mar 05, 2012 at 12:03:15PM -0800, Turquette, Mike wrote:
> On Sun, Mar 4, 2012 at 11:38 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > On Sun, Mar 04, 2012 at 04:12:21PM -0800, Turquette, Mike wrote:
> >> >>
> >> >> I believe this patch already does what you suggest, but I might be
> >> >> missing your point.
> >> >
> >> > In include/linux/clk-private.h you expose struct clk outside the core.
> >> > This has to be done to make static initializers possible. There is a big
> >> > warning in this file that it must not be included from files implementing
> >> > struct clk_ops. You can simply avoid this warning by declaring struct clk
> >> > with only a single member:
> >> >
> >> > include/linux/clk.h:
> >> >
> >> > struct clk {
> >> >        struct clk_internal *internal;
> >> > };
> >> >
> >> > This way everybody knows struct clk (thus can embed it in their static
> >> > initializers), but doesn't know anything about the internal members. Now
> >> > in drivers/clk/clk.c you declare struct clk_internal exactly like struct
> >> > clk was declared before:
> >> >
> >> > struct clk_internal {
> >> >        const char              *name;
> >> >        const struct clk_ops    *ops;
> >> >        struct clk_hw           *hw;
> >> >        struct clk              *parent;
> >> >        char                    **parent_names;
> >> >        struct clk              **parents;
> >> >        u8                      num_parents;
> >> >        unsigned long           rate;
> >> >        unsigned long           flags;
> >> >        unsigned int            enable_count;
> >> >        unsigned int            prepare_count;
> >> >        struct hlist_head       children;
> >> >        struct hlist_node       child_node;
> >> >        unsigned int            notifier_count;
> >> > #ifdef CONFIG_COMMON_CLK_DEBUG
> >> >        struct dentry           *dentry;
> >> > #endif
> >> > };
> >> >
> >> > An instance of struct clk_internal will be allocated in
> >> > __clk_init/clk_register. Now the private data stays completely inside
> >> > the core and noone can abuse it.
> >>
> >> Hi Sascha,
> >>
> >> I see the disconnect here.  For OMAP (and possibly other platforms) at
> >> least some clock data is necessary during early boot, before the
> >> regular allocation methods are available (timers for instance).
> >
> > We had this problem on i.MX aswell. It turned out that the timer clock
> > is the only clock that is needed so early. We solved this by moving the
> > clock init to the system timer init function.
> 
> When you say "mov[ed] the clock init to the system timer init
> function" do you mean that you statically allocated struct clk and
> used the clk framework api, or instead you just did some direct
> register writes to initialize things properly?

I meant that on i.MX we do the clock tree initialization when kmalloc is
available, see the attached patch for omap4 based on your branch which
does the same for Omap. The first clock you need is the one for the
timer, so you can initialize the clocktree at the beginning of
time_init() and don't need statically initialized clocks anymore.

> >
> > Well, the file is work in progress, you probably fix this before sending
> > it out, but I bet people will include clk-private.h and nobody else
> > notices it.
> 
> clock44xx_data.c does not violate that rule.  None of the logic that
> implements ops for those clocks is present clock44xx_data.c.

Indeed, I missed that. It only has the ops but not the individual
functions.

> All of
> the code in that file is simply initialization and registration of
> OMAP4 clocks.  Many of the clocks are basic clock types (divider,
> multiplexer and fixed-rate are used in that file) with protected code
> drivers/clk/clk-*.c and the remaining clocks are of the struct
> clk_hw_omap variety, which has code spread across several files:
> 
> arch/arm/mach-omap2/clock.c
> arch/arm/mach-omap2/clock.h
> arch/arm/mach-omap2/clkt_dpll.c
> arch/arm/mach-omap2/clkt_clksel.c
> arch/arm/mach-omap2/dpll3xxx.c
> arch/arm/mach-omap2/dpll4xxx.c
> 
> All of the above files include linux/clk-provider.h, not
> linux/clk-private.h.  That code makes heavy use of the
> __clk_get_whatever helpers and shows how a platform might honor the
> layer of separation between struct clk and stuct clk_ops/struct
> clk_foo.  You are correct that the code is a work-in-progress, but
> there are no layering violations that I can see.
> 
> I also think we are talking past each other to some degree.  One point
> I would like to make (and maybe you already know this from code
> review) is that it is unnecessary to have pointers to your parent
> struct clk*'s when either initializing or registering your clocks.  In
> fact the existing clk_register_foo functions don't even allow you to
> pass in parent pointers and rely wholly on string name matching.  I
> just wanted to point that out in case it went unnoticed, as it is a
> new way of doing things from the previous series and was born out of
> Thomas' review of V4 and multi-parent handling.  This also keeps
> device-tree in mind where we might not know the struct clk *pointer at
> compile time for "connecting" discrete devices.

Yes, I've seen this and I really like it. Also the change that
multiplexers return an index to an array instead of the parent
clock is very nice.

Sascha


8<-----------------------------------------------------

ARM omap4: move clocktree init to timer init time so we don't need static clocks

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-omap2/clock44xx_data.c |    4 +++-
 arch/arm/mach-omap2/io.c             |    1 -
 arch/arm/mach-omap2/timer.c          |    3 +++
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
index 7f833a7..5aa8dd2 100644
--- a/arch/arm/mach-omap2/clock44xx_data.c
+++ b/arch/arm/mach-omap2/clock44xx_data.c
@@ -6032,7 +6032,9 @@ int __init omap4xxx_clk_init(void)
 		}
 # else
 		clkdev_add(c);
-		__clk_init(NULL, c->clk);
+
+		clk_register(NULL, c->clk->name, c->clk->ops, c->clk->hw,
+			c->clk->parent_names, c->clk->num_parents, c->clk->flags);
 #endif
 	}
 
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index eb50c29..8db4380 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -476,7 +476,6 @@ void __init omap4430_init_early(void)
 	omap44xx_clockdomains_init();
 	omap44xx_hwmod_init();
 	omap_hwmod_init_postsetup();
-	omap4xxx_clk_init();
 }
 #endif
 
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 5c9acea..2cca796 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -323,9 +323,12 @@ OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
 OMAP_SYS_TIMER(3_secure)
 #endif
 
+int __init omap4xxx_clk_init(void);
+
 #ifdef CONFIG_ARCH_OMAP4
 static void __init omap4_timer_init(void)
 {
+	omap4xxx_clk_init();
 #ifdef CONFIG_LOCAL_TIMERS
 	twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
 	BUG_ON(!twd_base);
-- 
1.7.9.1

-- 
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 related	[flat|nested] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-06 19:00               ` Sascha Hauer
@ 2012-03-07 21:20                 ` Turquette, Mike
  2012-03-08  6:27                   ` Andrew Lunn
                                     ` (2 more replies)
  0 siblings, 3 replies; 51+ messages in thread
From: Turquette, Mike @ 2012-03-07 21:20 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Andrew Lunn, Paul Walmsley, linaro-dev, Linus Walleij, patches,
	Stephen Boyd, Mark Brown, Magnus Damm, linux-kernel, Rob Herring,
	Richard Zhao, Grant Likely, Deepak Saxena, Saravana Kannan,
	Thomas Gleixner, Shawn Guo, Amit Kucheria, Russell King,
	Jeremy Kerr, Arnd Bergman, linux-arm-kernel

On Tue, Mar 6, 2012 at 11:00 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Mon, Mar 05, 2012 at 12:03:15PM -0800, Turquette, Mike wrote:
>> On Sun, Mar 4, 2012 at 11:38 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
>> > On Sun, Mar 04, 2012 at 04:12:21PM -0800, Turquette, Mike wrote:
>> >> >>
>> >> >> I believe this patch already does what you suggest, but I might be
>> >> >> missing your point.
>> >> >
>> >> > In include/linux/clk-private.h you expose struct clk outside the core.
>> >> > This has to be done to make static initializers possible. There is a big
>> >> > warning in this file that it must not be included from files implementing
>> >> > struct clk_ops. You can simply avoid this warning by declaring struct clk
>> >> > with only a single member:
>> >> >
>> >> > include/linux/clk.h:
>> >> >
>> >> > struct clk {
>> >> >        struct clk_internal *internal;
>> >> > };
>> >> >
>> >> > This way everybody knows struct clk (thus can embed it in their static
>> >> > initializers), but doesn't know anything about the internal members. Now
>> >> > in drivers/clk/clk.c you declare struct clk_internal exactly like struct
>> >> > clk was declared before:
>> >> >
>> >> > struct clk_internal {
>> >> >        const char              *name;
>> >> >        const struct clk_ops    *ops;
>> >> >        struct clk_hw           *hw;
>> >> >        struct clk              *parent;
>> >> >        char                    **parent_names;
>> >> >        struct clk              **parents;
>> >> >        u8                      num_parents;
>> >> >        unsigned long           rate;
>> >> >        unsigned long           flags;
>> >> >        unsigned int            enable_count;
>> >> >        unsigned int            prepare_count;
>> >> >        struct hlist_head       children;
>> >> >        struct hlist_node       child_node;
>> >> >        unsigned int            notifier_count;
>> >> > #ifdef CONFIG_COMMON_CLK_DEBUG
>> >> >        struct dentry           *dentry;
>> >> > #endif
>> >> > };
>> >> >
>> >> > An instance of struct clk_internal will be allocated in
>> >> > __clk_init/clk_register. Now the private data stays completely inside
>> >> > the core and noone can abuse it.
>> >>
>> >> Hi Sascha,
>> >>
>> >> I see the disconnect here.  For OMAP (and possibly other platforms) at
>> >> least some clock data is necessary during early boot, before the
>> >> regular allocation methods are available (timers for instance).
>> >
>> > We had this problem on i.MX aswell. It turned out that the timer clock
>> > is the only clock that is needed so early. We solved this by moving the
>> > clock init to the system timer init function.
>>
>> When you say "mov[ed] the clock init to the system timer init
>> function" do you mean that you statically allocated struct clk and
>> used the clk framework api, or instead you just did some direct
>> register writes to initialize things properly?
>
> I meant that on i.MX we do the clock tree initialization when kmalloc is
> available, see the attached patch for omap4 based on your branch which
> does the same for Omap. The first clock you need is the one for the
> timer, so you can initialize the clocktree at the beginning of
> time_init() and don't need statically initialized clocks anymore.
>
>> >
>> > Well, the file is work in progress, you probably fix this before sending
>> > it out, but I bet people will include clk-private.h and nobody else
>> > notices it.
>>
>> clock44xx_data.c does not violate that rule.  None of the logic that
>> implements ops for those clocks is present clock44xx_data.c.
>
> Indeed, I missed that. It only has the ops but not the individual
> functions.
>
>> All of
>> the code in that file is simply initialization and registration of
>> OMAP4 clocks.  Many of the clocks are basic clock types (divider,
>> multiplexer and fixed-rate are used in that file) with protected code
>> drivers/clk/clk-*.c and the remaining clocks are of the struct
>> clk_hw_omap variety, which has code spread across several files:
>>
>> arch/arm/mach-omap2/clock.c
>> arch/arm/mach-omap2/clock.h
>> arch/arm/mach-omap2/clkt_dpll.c
>> arch/arm/mach-omap2/clkt_clksel.c
>> arch/arm/mach-omap2/dpll3xxx.c
>> arch/arm/mach-omap2/dpll4xxx.c
>>
>> All of the above files include linux/clk-provider.h, not
>> linux/clk-private.h.  That code makes heavy use of the
>> __clk_get_whatever helpers and shows how a platform might honor the
>> layer of separation between struct clk and stuct clk_ops/struct
>> clk_foo.  You are correct that the code is a work-in-progress, but
>> there are no layering violations that I can see.
>>
>> I also think we are talking past each other to some degree.  One point
>> I would like to make (and maybe you already know this from code
>> review) is that it is unnecessary to have pointers to your parent
>> struct clk*'s when either initializing or registering your clocks.  In
>> fact the existing clk_register_foo functions don't even allow you to
>> pass in parent pointers and rely wholly on string name matching.  I
>> just wanted to point that out in case it went unnoticed, as it is a
>> new way of doing things from the previous series and was born out of
>> Thomas' review of V4 and multi-parent handling.  This also keeps
>> device-tree in mind where we might not know the struct clk *pointer at
>> compile time for "connecting" discrete devices.
>
> Yes, I've seen this and I really like it. Also the change that
> multiplexers return an index to an array instead of the parent
> clock is very nice.
>
> Sascha
>
>
> 8<-----------------------------------------------------
>
> ARM omap4: move clocktree init to timer init time so we don't need static clocks
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

Hi Sascha,

Thanks for the example code.  This is in fact something I had
considered doing before, but it is a bit complicated for my platform.

We set up all of the OMAP clocks with __clk_init because this is a
dependency of OMAP's hwmod code which models and interacts with
specific resources for hardware modules, such as clocks.  There are
other dependencies such as our clockdomain code, which needs the
clocks to be fully initialized.  Some aspects of these layers get
init'd before we can allocate memory.

Admittedly I think that the OMAP code could migrate some of these bits
to a lazy-registration model, specifically the hwmod object instances,
but that requires an awful lot of refactoring for a fairly large stack
of platform code.  This might be something to achieve in the future
but for now we *need* initialisation to be fully static.

Assuming that some day OMAP code can be refactored to allow for lazy
(or at least initcall-based) registration of clocks then perhaps your
suggestion can take root.  Which leads me to this question: are there
any other platforms out there that require the level of expose to
struct clk present in this patchset?  OMAP does, for now, but if that
changes then I need to know if others require this as well.

Regards,
Mike

> ---
>  arch/arm/mach-omap2/clock44xx_data.c |    4 +++-
>  arch/arm/mach-omap2/io.c             |    1 -
>  arch/arm/mach-omap2/timer.c          |    3 +++
>  3 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
> index 7f833a7..5aa8dd2 100644
> --- a/arch/arm/mach-omap2/clock44xx_data.c
> +++ b/arch/arm/mach-omap2/clock44xx_data.c
> @@ -6032,7 +6032,9 @@ int __init omap4xxx_clk_init(void)
>                }
>  # else
>                clkdev_add(c);
> -               __clk_init(NULL, c->clk);
> +
> +               clk_register(NULL, c->clk->name, c->clk->ops, c->clk->hw,
> +                       c->clk->parent_names, c->clk->num_parents, c->clk->flags);
>  #endif
>        }
>
> diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
> index eb50c29..8db4380 100644
> --- a/arch/arm/mach-omap2/io.c
> +++ b/arch/arm/mach-omap2/io.c
> @@ -476,7 +476,6 @@ void __init omap4430_init_early(void)
>        omap44xx_clockdomains_init();
>        omap44xx_hwmod_init();
>        omap_hwmod_init_postsetup();
> -       omap4xxx_clk_init();
>  }
>  #endif
>
> diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
> index 5c9acea..2cca796 100644
> --- a/arch/arm/mach-omap2/timer.c
> +++ b/arch/arm/mach-omap2/timer.c
> @@ -323,9 +323,12 @@ OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
>  OMAP_SYS_TIMER(3_secure)
>  #endif
>
> +int __init omap4xxx_clk_init(void);
> +
>  #ifdef CONFIG_ARCH_OMAP4
>  static void __init omap4_timer_init(void)
>  {
> +       omap4xxx_clk_init();
>  #ifdef CONFIG_LOCAL_TIMERS
>        twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
>        BUG_ON(!twd_base);
> --
> 1.7.9.1
>
> --
> 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] 51+ messages in thread

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-03  8:29 ` [PATCH v5 4/4] clk: basic clock hardware types Mike Turquette
                     ` (3 preceding siblings ...)
  2012-03-04 20:33   ` [PATCH] clk: Fix compile errors in DEFINE_CLK_GATE Andrew Lunn
@ 2012-03-07 21:20   ` Sascha Hauer
  2012-03-09 22:50     ` Turquette, Mike
  4 siblings, 1 reply; 51+ messages in thread
From: Sascha Hauer @ 2012-03-07 21:20 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jamie Iles, Jeremy Kerr, Mike Turquette,
	Magnus Damm, Deepak Saxena, linux-arm-kernel, Arnd Bergman,
	patches, Rob Herring, Thomas Gleixner, Richard Zhao, Shawn Guo,
	Paul Walmsley, Linus Walleij, Mark Brown, Stephen Boyd,
	linux-kernel, Amit Kucheria

On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
> +struct clk *clk_register_divider(struct device *dev, const char *name,
> +		const char *parent_name, unsigned long flags,
> +		void __iomem *reg, u8 shift, u8 width,
> +		u8 clk_divider_flags, spinlock_t *lock)
> +{
> +	struct clk_divider *div;
> +	char **parent_names = NULL;
> +	u8 len;
> +
> +	div = kmalloc(sizeof(struct clk_divider), GFP_KERNEL);
> +
> +	if (!div) {
> +		pr_err("%s: could not allocate divider clk\n", __func__);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	/* struct clk_divider assignments */
> +	div->reg = reg;
> +	div->shift = shift;
> +	div->width = width;
> +	div->flags = clk_divider_flags;
> +	div->lock = lock;
> +
> +	if (parent_name) {
> +		parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
> +
> +		if (! parent_names)
> +			goto out;
> +
> +		len = sizeof(char) * strlen(parent_name);
> +
> +		parent_names[0] = kmalloc(len, GFP_KERNEL);
> +
> +		if (!parent_names[0])
> +			goto out;
> +
> +		strncpy(parent_names[0], parent_name, len);
> +	}
> +
> +out:
> +	return clk_register(dev, name,
> +			&clk_divider_ops, &div->hw,
> +			parent_names,
> +			(parent_name ? 1 : 0),
> +			flags);
> +}

clk_register_divider and also clk_register_gate have some problems.
First you allocate memory with exactly the string length without
the terminating 0. Then the functions leak memory when clk_register
fails. Could you fold in the following patch to fix this?

Sascha

8<--------------------------------------------------

fix divider/gate registration

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/clk/clk-divider.c    |   34 +++++++++++++++-------------------
 drivers/clk/clk-gate.c       |   33 ++++++++++++++-------------------
 include/linux/clk-provider.h |    2 ++
 3 files changed, 31 insertions(+), 38 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 8f02930..99b6b55 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -156,14 +156,13 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
 		u8 clk_divider_flags, spinlock_t *lock)
 {
 	struct clk_divider *div;
-	char **parent_names = NULL;
-	u8 len;
+	struct clk *clk;
 
-	div = kmalloc(sizeof(struct clk_divider), GFP_KERNEL);
+	div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
 
 	if (!div) {
 		pr_err("%s: could not allocate divider clk\n", __func__);
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 	}
 
 	/* struct clk_divider assignments */
@@ -174,25 +173,22 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
 	div->lock = lock;
 
 	if (parent_name) {
-		parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
-
-		if (! parent_names)
-			goto out;
-
-		len = sizeof(char) * strlen(parent_name);
-
-		parent_names[0] = kmalloc(len, GFP_KERNEL);
-
-		if (!parent_names[0])
+		div->parent[0] = kstrdup(parent_name, GFP_KERNEL);
+		if (!div->parent[0])
 			goto out;
-
-		strncpy(parent_names[0], parent_name, len);
 	}
 
-out:
-	return clk_register(dev, name,
+	clk = clk_register(dev, name,
 			&clk_divider_ops, &div->hw,
-			parent_names,
+			div->parent,
 			(parent_name ? 1 : 0),
 			flags);
+	if (clk)
+		return clk;
+
+out:
+	kfree(div->parent[0]);
+	kfree(div);
+
+	return NULL;
 }
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index e831f7b..92c0489 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -80,14 +80,13 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 		u8 clk_gate_flags, spinlock_t *lock)
 {
 	struct clk_gate *gate;
-	char **parent_names = NULL;
-	u8 len;
+	struct clk *clk;
 
-	gate = kmalloc(sizeof(struct clk_gate), GFP_KERNEL);
+	gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
 
 	if (!gate) {
 		pr_err("%s: could not allocate gated clk\n", __func__);
-		return ERR_PTR(-ENOMEM);
+		return NULL;
 	}
 
 	/* struct clk_gate assignments */
@@ -97,25 +96,21 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
 	gate->lock = lock;
 
 	if (parent_name) {
-		parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
-
-		if (! parent_names)
-			goto out;
-
-		len = sizeof(char) * strlen(parent_name);
-
-		parent_names[0] = kmalloc(len, GFP_KERNEL);
-
-		if (!parent_names[0])
+		gate->parent[0] = kstrdup(parent_name, GFP_KERNEL);
+		if (!gate->parent[0])
 			goto out;
-
-		strncpy(parent_names[0], parent_name, len);
 	}
 
-out:
-	return clk_register(dev, name,
+	clk = clk_register(dev, name,
 			&clk_gate_ops, &gate->hw,
-			parent_names,
+			gate->parent,
 			(parent_name ? 1 : 0),
 			flags);
+	if (clk)
+		return clk;
+out:
+	kfree(gate->parent[0]);
+	kfree(gate);
+
+	return NULL;
 }
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 9b7dd5e..ed1f918 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -174,6 +174,7 @@ struct clk_gate {
 	u8		bit_idx;
 	u8		flags;
 	spinlock_t	*lock;
+	char		*parent[1];
 };
 
 #define CLK_GATE_SET_TO_DISABLE		BIT(0)
@@ -210,6 +211,7 @@ struct clk_divider {
 	u8		width;
 	u8		flags;
 	spinlock_t	*lock;
+	char		*parent[1];
 };
 
 #define CLK_DIVIDER_ONE_BASED		BIT(0)
-- 
1.7.9.1

-- 
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 related	[flat|nested] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-07 21:20                 ` Turquette, Mike
@ 2012-03-08  6:27                   ` Andrew Lunn
  2012-03-08 23:25                     ` Sascha Hauer
  2012-03-09 18:18                     ` Turquette, Mike
  2012-03-09  0:51                   ` Thomas Gleixner
  2012-03-17  3:23                   ` Saravana Kannan
  2 siblings, 2 replies; 51+ messages in thread
From: Andrew Lunn @ 2012-03-08  6:27 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Sascha Hauer, Andrew Lunn, Paul Walmsley, linaro-dev,
	Linus Walleij, patches, Stephen Boyd, Mark Brown, Magnus Damm,
	linux-kernel, Rob Herring, Richard Zhao, Grant Likely,
	Deepak Saxena, Saravana Kannan, Thomas Gleixner, Shawn Guo,
	Amit Kucheria, Russell King, Jeremy Kerr, Arnd Bergman,
	linux-arm-kernel

> Assuming that some day OMAP code can be refactored to allow for lazy
> (or at least initcall-based) registration of clocks then perhaps your
> suggestion can take root.  Which leads me to this question: are there
> any other platforms out there that require the level of expose to
> struct clk present in this patchset?  OMAP does, for now, but if that
> changes then I need to know if others require this as well.

Hi Mike

For kirkwood, i use static clk's for all but my root clock. I cannot
statically know the rate of the root clock, so i have to determine it
at boot time using heuristics, PCI ID, etc.

I used statics thinking it would be less code. No idea if it actually
is, and there is nothing stopping me moving to creating the clocks
after creating the root clock.

One comment i have about the current static clks. I completely missing
you need to call __clk_init() on them and so ended up with lots of
division by zero errors, since they did not have a parent, and so the
code seemed not be to able to determine the rate.

So 

1) Please add __clk_init() to the documentation in the section about
   static clocks.

2) Should maybe the name change? It seems strange having to call a
   __X() function. If this is a function which is supposed to be used,
   drop the __. Maybe clk_static_register()?

3) Maybe, if the parent is missing, clk_get_rate() should return an
   error?

Andrew

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-08  6:27                   ` Andrew Lunn
@ 2012-03-08 23:25                     ` Sascha Hauer
  2012-03-09  7:57                       ` Andrew Lunn
  2012-03-09 18:18                     ` Turquette, Mike
  1 sibling, 1 reply; 51+ messages in thread
From: Sascha Hauer @ 2012-03-08 23:25 UTC (permalink / raw)
  To: Turquette, Mike, Andrew Lunn, Paul Walmsley, linaro-dev,
	Linus Walleij, patches, Stephen Boyd, Mark Brown, Magnus Damm,
	linux-kernel, Rob Herring, Richard Zhao, Grant Likely,
	Deepak Saxena, Saravana Kannan, Thomas Gleixner, Shawn Guo,
	Amit Kucheria, Russell King, Jeremy Kerr, Arnd Bergman,
	linux-arm-kernel

On Thu, Mar 08, 2012 at 07:27:39AM +0100, Andrew Lunn wrote:
> > Assuming that some day OMAP code can be refactored to allow for lazy
> > (or at least initcall-based) registration of clocks then perhaps your
> > suggestion can take root.  Which leads me to this question: are there
> > any other platforms out there that require the level of expose to
> > struct clk present in this patchset?  OMAP does, for now, but if that
> > changes then I need to know if others require this as well.
> 
> Hi Mike
> 
> For kirkwood, i use static clk's for all but my root clock. I cannot
> statically know the rate of the root clock, so i have to determine it
> at boot time using heuristics, PCI ID, etc.
> 
> I used statics thinking it would be less code. No idea if it actually
> is, and there is nothing stopping me moving to creating the clocks
> after creating the root clock.

I'd say use the nonstatic ones. I think using the static initializers
will cause us much pain in the future. I've been through several rebases
on the i.MX clock rework and everytime I wish my sed foo would be
better. Now imagine what happens when it turns out that the internal
struct clk layout or the structs for the muxes/dividers/gates have to
be changed. This task is next to impossible when we have thousands of
clocks scattered around the tree.

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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-07 21:20                 ` Turquette, Mike
  2012-03-08  6:27                   ` Andrew Lunn
@ 2012-03-09  0:51                   ` Thomas Gleixner
  2012-03-17  3:23                   ` Saravana Kannan
  2 siblings, 0 replies; 51+ messages in thread
From: Thomas Gleixner @ 2012-03-09  0:51 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Sascha Hauer, Andrew Lunn, Paul Walmsley, linaro-dev,
	Linus Walleij, patches, Stephen Boyd, Mark Brown, Magnus Damm,
	linux-kernel, Rob Herring, Richard Zhao, Grant Likely,
	Deepak Saxena, Saravana Kannan, Shawn Guo, Amit Kucheria,
	Russell King, Jeremy Kerr, Arnd Bergman, linux-arm-kernel

On Wed, 7 Mar 2012, Turquette, Mike wrote:
> Assuming that some day OMAP code can be refactored to allow for lazy
> (or at least initcall-based) registration of clocks then perhaps your
> suggestion can take root.  Which leads me to this question: are there
> any other platforms out there that require the level of expose to
> struct clk present in this patchset?  OMAP does, for now, but if that
> changes then I need to know if others require this as well.

I can't see the problem, really. Other than existing code doing stuff
before the memory allocator is up and running.

We allocate interrupt data structures in the early boot process today
and I don't see a reason why you want clocks, which have not been
configured by the boot loader, accesible before that point.

Thanks,

	tglx

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

* Re: [PATCH v5 0/4] common clk framework
  2012-03-03  8:28 [PATCH v5 0/4] common clk framework Mike Turquette
                   ` (3 preceding siblings ...)
  2012-03-03  8:29 ` [PATCH v5 4/4] clk: basic clock hardware types Mike Turquette
@ 2012-03-09  2:34 ` Richard Zhao
  2012-03-09  9:19   ` Sascha Hauer
  2012-03-09 18:35   ` Turquette, Mike
  4 siblings, 2 replies; 51+ messages in thread
From: Richard Zhao @ 2012-03-09  2:34 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, Grant Likely, Paul Walmsley, linaro-dev,
	Linus Walleij, patches, Stephen Boyd, Mark Brown, Magnus Damm,
	linux-kernel, Rob Herring, Richard Zhao, Arnd Bergman,
	Deepak Saxena, Saravana Kannan, Andrew Lunn, Shawn Guo,
	Amit Kucheria, Jeremy Kerr, Thomas Gleixner, linux-arm-kernel,
	Mike Turquette

Hello Mike,

The main interface for clk implementer is to register clocks dynamically.
I think it highly depends on clk DT bindings. From the patch Grant sent
out, it looks like he doesn't like one node per clk. So how do we
register clocks dynamically? You have any sample code?

Thanks
Richard


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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-08 23:25                     ` Sascha Hauer
@ 2012-03-09  7:57                       ` Andrew Lunn
  2012-03-09 18:25                         ` Turquette, Mike
  0 siblings, 1 reply; 51+ messages in thread
From: Andrew Lunn @ 2012-03-09  7:57 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Turquette, Mike, Andrew Lunn, Paul Walmsley, linaro-dev,
	Linus Walleij, patches, Stephen Boyd, Mark Brown, Magnus Damm,
	linux-kernel, Rob Herring, Richard Zhao, Grant Likely,
	Deepak Saxena, Saravana Kannan, Thomas Gleixner, Shawn Guo,
	Amit Kucheria, Russell King, Jeremy Kerr, Arnd Bergman,
	linux-arm-kernel

> I'd say use the nonstatic ones. I think using the static initializers
> will cause us much pain in the future. I've been through several rebases
> on the i.MX clock rework and everytime I wish my sed foo would be
> better. Now imagine what happens when it turns out that the internal
> struct clk layout or the structs for the muxes/dividers/gates have to
> be changed.

/*****************************************************************************
 * CLK tree
 ****************************************************************************/
static DEFINE_SPINLOCK(gating_lock);

#define DEFINE_KIRKWOOD_CLK_GATE(_name, _bit)                           \
        DEFINE_CLK_GATE(_name, "tclk", NULL, 0,                         \
                        (void __iomem *)CLOCK_GATING_CTRL,              \
                        _bit, 0, &gating_lock)

DEFINE_KIRKWOOD_CLK_GATE(clk_ge0,    CGC_BIT_GE0);
DEFINE_KIRKWOOD_CLK_GATE(clk_pex0,   CGC_BIT_PEX0);
DEFINE_KIRKWOOD_CLK_GATE(clk_usb0,   CGC_BIT_USB0);
DEFINE_KIRKWOOD_CLK_GATE(clk_sdio,   CGC_BIT_SDIO);
DEFINE_KIRKWOOD_CLK_GATE(clk_tsu,    CGC_BIT_TSU);
DEFINE_KIRKWOOD_CLK_GATE(clk_dunit,  CGC_BIT_DUNIT);
DEFINE_KIRKWOOD_CLK_GATE(clk_runit,  CGC_BIT_RUNIT);

I've so far not had any problems, and not needed an sed foo.  I do
only have a dozen or so clocks, which helps. But even so, all the real
pain is hidden inside DEFINE_CLK_GATE() which Mike maintains.

I guess the problem comes when you are not using the basic clk
providers, but your own provider. What might help is if
linux/clk-provider.h could provide some macros to do most of the
generic definitions. Something like:

#define DEFINE_CLK_GENERIC(_name, _flags, _ops)                 \
        static struct clk _name;                                \
        static char *_name##_parent_names[] = {};               \
        static struct clk _name = {                             \
                .name = #_name,                                 \
                .ops = &_ops,                                   \
                .hw = &_name##_hw.hw,                           \
                .parent_names = _name##_parent_names,           \
                .num_parents =                                  \
                        ARRAY_SIZE(_name##_parent_names),       \
                .flags = _flags,                                \
        };

and then you have something like

#define DEFINE_CLK_IMX(_name, _flags, _foo, _bar)               \
        static struct clk_imx _name##_hw = {                    \
                .hw = {                                         \
                        .clk = &_name,                          \
                },                                              \
                .foo = _foo,                                    \
                .bar = _bar,                                    \
        };                                                      \
	DEFINE_CLK_GENERIC(_name, _flags, clk_imx_ops)           

	Andrew

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

* Re: [PATCH v5 0/4] common clk framework
  2012-03-09  2:34 ` [PATCH v5 0/4] common clk framework Richard Zhao
@ 2012-03-09  9:19   ` Sascha Hauer
  2012-03-09 18:35   ` Turquette, Mike
  1 sibling, 0 replies; 51+ messages in thread
From: Sascha Hauer @ 2012-03-09  9:19 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Mike Turquette, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jeremy Kerr, Mike Turquette, Russell King,
	Magnus Damm, Deepak Saxena, linux-arm-kernel, Arnd Bergman,
	patches, Rob Herring, Thomas Gleixner, Richard Zhao, Shawn Guo,
	Paul Walmsley, Linus Walleij, Mark Brown, Stephen Boyd,
	linux-kernel, Amit Kucheria

Hi Richard,

On Fri, Mar 09, 2012 at 10:34:19AM +0800, Richard Zhao wrote:
> Hello Mike,
> 
> The main interface for clk implementer is to register clocks dynamically.
> I think it highly depends on clk DT bindings. From the patch Grant sent
> out, it looks like he doesn't like one node per clk. So how do we
> register clocks dynamically? You have any sample code?

Find my current work based on this series here:

git://git.pengutronix.de/git/imx/linux-2.6.git work/imx-clkv5

This implements the generic clock support for the i.MX v4/v5 based
SoCs. i.MX1 and i.MX27 are runtime tested, i.MX21/25 are compile
tested only.

A typical clock file will then look like this, here the i.MX27
implementation:

8<-------------------------------------------------------


ARM i.MX27: implement clocks using common clock framework

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/Makefile    |    2 +-
 arch/arm/mach-imx/clk-imx27.c |  227 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 228 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-imx/clk-imx27.c

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index d96e2ce..b39f2d6 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -6,7 +6,7 @@ obj-$(CONFIG_SOC_IMX21) += clk-imx21.o mm-imx21.o
 obj-$(CONFIG_SOC_IMX25) += clk-imx25.o mm-imx25.o ehci-imx25.o cpu-imx25.o
 
 obj-$(CONFIG_SOC_IMX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_SOC_IMX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
+obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
 
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clock-imx31.o iomux-imx31.o ehci-imx31.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clock-imx35.o ehci-imx35.o
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
new file mode 100644
index 0000000..f54e4ee
--- /dev/null
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -0,0 +1,227 @@
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+
+#include <asm/div64.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include "clk.h"
+
+#define IO_ADDR_CCM(off)	(MX27_IO_ADDRESS(MX27_CCM_BASE_ADDR + (off)))
+
+/* Register offsets */
+#define CCM_CSCR		IO_ADDR_CCM(0x0)
+#define CCM_MPCTL0		IO_ADDR_CCM(0x4)
+#define CCM_MPCTL1		IO_ADDR_CCM(0x8)
+#define CCM_SPCTL0		IO_ADDR_CCM(0xc)
+#define CCM_SPCTL1		IO_ADDR_CCM(0x10)
+#define CCM_OSC26MCTL		IO_ADDR_CCM(0x14)
+#define CCM_PCDR0		IO_ADDR_CCM(0x18)
+#define CCM_PCDR1		IO_ADDR_CCM(0x1c)
+#define CCM_PCCR0		IO_ADDR_CCM(0x20)
+#define CCM_PCCR1		IO_ADDR_CCM(0x24)
+#define CCM_CCSR		IO_ADDR_CCM(0x28)
+#define CCM_PMCTL		IO_ADDR_CCM(0x2c)
+#define CCM_PMCOUNT		IO_ADDR_CCM(0x30)
+#define CCM_WKGDCTL		IO_ADDR_CCM(0x34)
+
+#define CCM_CSCR_UPDATE_DIS	(1 << 31)
+#define CCM_CSCR_SSI2		(1 << 23)
+#define CCM_CSCR_SSI1		(1 << 22)
+#define CCM_CSCR_VPU		(1 << 21)
+#define CCM_CSCR_MSHC           (1 << 20)
+#define CCM_CSCR_SPLLRES        (1 << 19)
+#define CCM_CSCR_MPLLRES        (1 << 18)
+#define CCM_CSCR_SP             (1 << 17)
+#define CCM_CSCR_MCU            (1 << 16)
+#define CCM_CSCR_OSC26MDIV      (1 << 4)
+#define CCM_CSCR_OSC26M         (1 << 3)
+#define CCM_CSCR_FPM            (1 << 2)
+#define CCM_CSCR_SPEN           (1 << 1)
+#define CCM_CSCR_MPEN           (1 << 0)
+
+/* i.MX27 TO 2+ */
+#define CCM_CSCR_ARM_SRC        (1 << 15)
+
+#define CCM_SPCTL1_LF           (1 << 15)
+#define CCM_SPCTL1_BRMO         (1 << 6)
+
+static char *vpu_sel_clks[] = { "spll", "mpll_main2", };
+static char *cpu_sel_clks[] = { "mpll_main2", "mpll", };
+
+struct clkl {
+	struct clk_lookup lookup;
+	const char *clkname;
+};
+
+#define clkdev(d, n, c) \
+	{ \
+		.lookup.dev_id = d, \
+		.lookup.con_id = n, \
+		.clkname = c, \
+	},
+
+static struct clkl lookups[] = {
+	clkdev("imx21-uart.0", "ipg", "uart1_ipg_gate")
+	clkdev("imx21-uart.0", "per", "per1_gate")
+	clkdev("imx21-uart.1", "ipg", "uart2_ipg_gate")
+	clkdev("imx21-uart.1", "per", "per1_gate")
+	clkdev("imx21-uart.2", "ipg", "uart3_ipg_gate")
+	clkdev("imx21-uart.2", "per", "per1_gate")
+	clkdev("imx21-uart.3", "ipg", "uart4_ipg_gate")
+	clkdev("imx21-uart.3", "per", "per1_gate")
+	clkdev("imx21-uart.4", "ipg", "uart5_ipg_gate")
+	clkdev("imx21-uart.4", "per", "per1_gate")
+	clkdev("imx21-uart.5", "ipg", "uart6_ipg_gate")
+	clkdev("imx21-uart.5", "per", "per1_gate")
+	clkdev("imx-gpt.0", "ipg", "gpt1_ipg_gate")
+	clkdev("imx-gpt.0", "per", "per1_gate")
+	clkdev("imx-gpt.1", "ipg", "gpt2_ipg_gate")
+	clkdev("imx-gpt.1", "per", "per1_gate")
+	clkdev("imx-gpt.2", "ipg", "gpt3_ipg_gate")
+	clkdev("imx-gpt.2", "per", "per1_gate")
+	clkdev("imx-gpt.3", "ipg", "gpt4_ipg_gate")
+	clkdev("imx-gpt.3", "per", "per1_gate")
+	clkdev("imx-gpt.4", "ipg", "gpt5_ipg_gate")
+	clkdev("imx-gpt.4", "per", "per1_gate")
+	clkdev("imx-gpt.5", "ipg", "gpt6_ipg_gate")
+	clkdev("imx-gpt.5", "per", "per1_gate")
+	clkdev("mxc_pwm.0", NULL, "pwm")
+	clkdev("mxc-mmc.0", "per", "per2_gate")
+	clkdev("mxc-mmc.0", "ipg", "sdhc1_ipg_gate")
+	clkdev("mxc-mmc.1", "per", "per2_gate")
+	clkdev("mxc-mmc.1", "ipg", "sdhc2_ipg_gate")
+	clkdev("mxc-mmc.2", "per", "per2_gate")
+	clkdev("mxc-mmc.2", "ipg", "sdhc2_ipg_gate")
+	clkdev("imx27-cspi.0", NULL, "cspi1")
+	clkdev("imx27-cspi.1", NULL, "cspi2")
+	clkdev("imx27-cspi.2", NULL, "cspi3")
+	clkdev("imx-fb.0", "per", "per3_gate")
+	clkdev("imx-fb.0", "ipg", "lcdc_ipg_gate")
+	clkdev("imx-fb.0", "ahb", "lcdc_ahb_gate")
+	clkdev("mx2-camera.0", NULL, "csi")
+	clkdev("fsl-usb2-udc", "usb", "usb")
+	clkdev("fsl-usb2-udc", "usb_ahb", "usb_ahb_gate")
+	clkdev("mxc-ehci.0", "usb", "usb")
+	clkdev("mxc-ehci.0", "usb_ahb", "usb_ahb_gate")
+	clkdev("mxc-ehci.1", "usb", "usb")
+	clkdev("mxc-ehci.1", "usb_ahb", "usb_ahb_gate")
+	clkdev("mxc-ehci.2", "usb", "usb")
+	clkdev("mxc-ehci.2", "usb_ahb", "usb_ahb_gate")
+	clkdev("imx-ssi.0", NULL, "ssi1_ipg_gate")
+	clkdev("imx-ssi.1", NULL, "ssi2_ipg_gate")
+	clkdev("mxc_nand.0", NULL, "nfc_baud_gate")
+	clkdev("imx-vpu", "per", "vpu_baud_gate")
+	clkdev("imx-vpu", "ahb", "vpu_ahb_gate")
+	clkdev("imx-dma", "ahb", "dma_ahb_gate")
+	clkdev("imx-dma", "ipg", "dma_ipg_gate")
+	clkdev("imx27-fec.0", "ipg", "fec_ipg_gate")
+	clkdev("imx27-fec.0", "ahb", "fec_ahb_gate")
+	clkdev("imx2-wdt.0", NULL, "wdog_ipg_gate")
+	clkdev("imx-i2c.0", NULL, "i2c1_ipg_gate")
+	clkdev("imx-i2c.1", NULL, "i2c2_ipg_gate")
+	clkdev("mxc_w1.0", NULL, "owire_ipg_gate")
+	clkdev("imx-keypad", NULL, "kpp_ipg_gate")
+	clkdev("imx-emma", "ahb", "emma_ahb_gate")
+	clkdev("imx-emma", "ipg", "emma_ipg_gate")
+	clkdev(NULL, "iim", "iim_ipg_gate")
+	clkdev(NULL, "gpio", "gpio_ipg_gate")
+	clkdev(NULL, "brom", "brom_ahb_gate")
+	clkdev(NULL, "ata", "ata_ahb_gate")
+	clkdev(NULL, "rtc", "rtc_ipg_gate")
+	clkdev(NULL, "scc", "scc_ipg_gate")
+	clkdev(NULL, "cpu", "cpu_div")
+};
+
+int __init mx27_clocks_init(unsigned long fref)
+{
+	int i;
+
+	imx_clk_fixed("dummy", 0);
+	imx_clk_fixed("ckih", fref);
+	imx_clk_pllv1("mpll", "ckih", CCM_MPCTL0);
+	imx_clk_pllv1("spll", "ckih", CCM_SPCTL0);
+	imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
+	imx_clk_divider("ahb", "mpll_main2", CCM_CSCR, 8, 2);
+	imx_clk_fixed_factor("ipg", "ahb", 1, 1);
+	imx_clk_divider("nfc_div", "ahb", CCM_PCDR0, 6, 4);
+	imx_clk_divider("per1_div", "mpll_main2", CCM_PCDR1, 0, 6);
+	imx_clk_divider("per2_div", "mpll_main2", CCM_PCDR1, 8, 6);
+	imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
+	imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
+	imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
+	imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
+	imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3);
+	imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
+	imx_clk_divider("cpu_div", "cpu_sel", CCM_CSCR, 12, 2);
+	imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
+	imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
+	imx_clk_gate("slcdc_ipg_gate", "ipg", CCM_PCCR0, 2);
+	imx_clk_gate("sdhc3_ipg_gate", "ipg", CCM_PCCR0, 3);
+	imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 4);
+	imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 5);
+	imx_clk_gate("scc_ipg_gate", "ipg", CCM_PCCR0, 6);
+	imx_clk_gate("sahara_ipg_gate", "ipg", CCM_PCCR0, 7);
+	imx_clk_gate("rtc_ipg_gate", "ipg", CCM_PCCR0, 9);
+	imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR0, 11);
+	imx_clk_gate("owire_ipg_gate", "ipg", CCM_PCCR0, 12);
+	imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 14);
+	imx_clk_gate("kpp_ipg_gate", "ipg", CCM_PCCR0, 15);
+	imx_clk_gate("iim_ipg_gate", "ipg", CCM_PCCR0, 16);
+	imx_clk_gate("i2c2_ipg_gate", "ipg", CCM_PCCR0, 17);
+	imx_clk_gate("i2c1_ipg_gate", "ipg", CCM_PCCR0, 18);
+	imx_clk_gate("gpt6_ipg_gate", "ipg", CCM_PCCR0, 19);
+	imx_clk_gate("gpt5_ipg_gate", "ipg", CCM_PCCR0, 20);
+	imx_clk_gate("gpt4_ipg_gate", "ipg", CCM_PCCR0, 21);
+	imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR0, 22);
+	imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR0, 23);
+	imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR0, 24);
+	imx_clk_gate("gpio_ipg_gate", "ipg", CCM_PCCR0, 25);
+	imx_clk_gate("fec_ipg_gate", "ipg", CCM_PCCR0, 26);
+	imx_clk_gate("emma_ipg_gate", "ipg", CCM_PCCR0, 27);
+	imx_clk_gate("dma_ipg_gate", "ipg", CCM_PCCR0, 28);
+	imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR0, 29);
+	imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 30);
+	imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 31);
+	imx_clk_gate("nfc_baud_gate", "nfc_div", CCM_PCCR1,  3);
+	imx_clk_gate("ssi2_baud_gate", "dummy", CCM_PCCR1,  4);
+	imx_clk_gate("ssi1_baud_gate", "dummy", CCM_PCCR1,  5);
+	imx_clk_gate("vpu_baud_gate", "vpu_div", CCM_PCCR1,  6);
+	imx_clk_gate("per4_gate", "per4_div", CCM_PCCR1,  7);
+	imx_clk_gate("per3_gate", "per3_div", CCM_PCCR1,  8);
+	imx_clk_gate("per2_gate", "per2_div", CCM_PCCR1,  9);
+	imx_clk_gate("per1_gate", "per1_div", CCM_PCCR1, 10);
+	imx_clk_gate("usb_ahb_gate", "ahb", CCM_PCCR1, 11);
+	imx_clk_gate("slcdc_ahb_gate", "ahb", CCM_PCCR1, 12);
+	imx_clk_gate("sahara_ahb_gate", "ahb", CCM_PCCR1, 13);
+	imx_clk_gate("lcdc_ahb_gate", "ahb", CCM_PCCR1, 15);
+	imx_clk_gate("vpu_ahb_gate", "ahb", CCM_PCCR1, 16);
+	imx_clk_gate("fec_ahb_gate", "ahb", CCM_PCCR1, 17);
+	imx_clk_gate("emma_ahb_gate", "ahb", CCM_PCCR1, 18);
+	imx_clk_gate("emi_ahb_gate", "ahb", CCM_PCCR1, 19);
+	imx_clk_gate("dma_ahb_gate", "ahb", CCM_PCCR1, 20);
+	imx_clk_gate("csi_ahb_gate", "ahb", CCM_PCCR1, 21);
+	imx_clk_gate("brom_ahb_gate", "ahb", CCM_PCCR1, 22);
+	imx_clk_gate("ata_ahb_gate", "ahb", CCM_PCCR1, 23);
+	imx_clk_gate("wdog_ipg_gate", "ipg", CCM_PCCR1, 24);
+	imx_clk_gate("usb_ipg_gate", "ipg", CCM_PCCR1, 25);
+	imx_clk_gate("uart6_ipg_gate", "ipg", CCM_PCCR1, 26);
+	imx_clk_gate("uart5_ipg_gate", "ipg", CCM_PCCR1, 27);
+	imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR1, 28);
+	imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR1, 29);
+	imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR1, 30);
+	imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR1, 31);
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++) {
+		struct clkl *l = &lookups[i];
+		l->lookup.clk = __clk_lookup(l->clkname);
+		clkdev_add(&l->lookup);
+	}
+
+	mxc_timer_init(NULL, MX27_IO_ADDRESS(MX27_GPT1_BASE_ADDR),
+			MX27_INT_GPT1);
+	return 0;
+}
-- 
1.7.9.1

-- 
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 related	[flat|nested] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-08  6:27                   ` Andrew Lunn
  2012-03-08 23:25                     ` Sascha Hauer
@ 2012-03-09 18:18                     ` Turquette, Mike
  1 sibling, 0 replies; 51+ messages in thread
From: Turquette, Mike @ 2012-03-09 18:18 UTC (permalink / raw)
  To: Turquette, Mike, Sascha Hauer, Andrew Lunn, Paul Walmsley,
	linaro-dev, Linus Walleij, patches, Stephen Boyd, Mark Brown,
	Magnus Damm, linux-kernel, Rob Herring, Richard Zhao,
	Grant Likely, Deepak Saxena, Saravana Kannan, Thomas Gleixner,
	Shawn Guo, Amit Kucheria, Russell King, Jeremy Kerr,
	Arnd Bergman, linux-arm-kernel

On Wed, Mar 7, 2012 at 10:27 PM, Andrew Lunn <andrew@lunn.ch> wrote:
>> Assuming that some day OMAP code can be refactored to allow for lazy
>> (or at least initcall-based) registration of clocks then perhaps your
>> suggestion can take root.  Which leads me to this question: are there
>> any other platforms out there that require the level of expose to
>> struct clk present in this patchset?  OMAP does, for now, but if that
>> changes then I need to know if others require this as well.
>
> Hi Mike
>
> For kirkwood, i use static clk's for all but my root clock. I cannot
> statically know the rate of the root clock, so i have to determine it
> at boot time using heuristics, PCI ID, etc.
>
> I used statics thinking it would be less code. No idea if it actually
> is, and there is nothing stopping me moving to creating the clocks
> after creating the root clock.
>
> One comment i have about the current static clks. I completely missing
> you need to call __clk_init() on them and so ended up with lots of
> division by zero errors, since they did not have a parent, and so the
> code seemed not be to able to determine the rate.
>
> So
>
> 1) Please add __clk_init() to the documentation in the section about
>   static clocks.

Done.

>
> 2) Should maybe the name change? It seems strange having to call a
>   __X() function. If this is a function which is supposed to be used,
>   drop the __. Maybe clk_static_register()?

That function is used internally by clk_register and is only exposed
by clk-private.h, so I think the naming scheme is sane.  I basically
want to create a sense of worry in anyone using clk-private.h :-)

>
> 3) Maybe, if the parent is missing, clk_get_rate() should return an
>   error?

Non-root, non-fixed-rate, orphan clocks can return an error in this
case.  Will update for V6.  Any idea on best -EERROR?  I'm thinking
ENODEV, but ECHILD and EPIPE are kinda funny in this context.

Regards,
Mike

>
> Andrew

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-09  7:57                       ` Andrew Lunn
@ 2012-03-09 18:25                         ` Turquette, Mike
  2012-03-19  7:01                           ` Shawn Guo
  0 siblings, 1 reply; 51+ messages in thread
From: Turquette, Mike @ 2012-03-09 18:25 UTC (permalink / raw)
  To: Sascha Hauer, Turquette, Mike, Andrew Lunn, Paul Walmsley,
	linaro-dev, Linus Walleij, patches, Stephen Boyd, Mark Brown,
	Magnus Damm, linux-kernel, Rob Herring, Richard Zhao,
	Grant Likely, Deepak Saxena, Saravana Kannan, Thomas Gleixner,
	Shawn Guo, Amit Kucheria, Russell King, Jeremy Kerr,
	Arnd Bergman, linux-arm-kernel

On Thu, Mar 8, 2012 at 11:57 PM, Andrew Lunn <andrew@lunn.ch> wrote:
>> I'd say use the nonstatic ones. I think using the static initializers
>> will cause us much pain in the future. I've been through several rebases
>> on the i.MX clock rework and everytime I wish my sed foo would be
>> better. Now imagine what happens when it turns out that the internal
>> struct clk layout or the structs for the muxes/dividers/gates have to
>> be changed.
>
> /*****************************************************************************
>  * CLK tree
>  ****************************************************************************/
> static DEFINE_SPINLOCK(gating_lock);
>
> #define DEFINE_KIRKWOOD_CLK_GATE(_name, _bit)                           \
>        DEFINE_CLK_GATE(_name, "tclk", NULL, 0,                         \
>                        (void __iomem *)CLOCK_GATING_CTRL,              \
>                        _bit, 0, &gating_lock)
>
> DEFINE_KIRKWOOD_CLK_GATE(clk_ge0,    CGC_BIT_GE0);
> DEFINE_KIRKWOOD_CLK_GATE(clk_pex0,   CGC_BIT_PEX0);
> DEFINE_KIRKWOOD_CLK_GATE(clk_usb0,   CGC_BIT_USB0);
> DEFINE_KIRKWOOD_CLK_GATE(clk_sdio,   CGC_BIT_SDIO);
> DEFINE_KIRKWOOD_CLK_GATE(clk_tsu,    CGC_BIT_TSU);
> DEFINE_KIRKWOOD_CLK_GATE(clk_dunit,  CGC_BIT_DUNIT);
> DEFINE_KIRKWOOD_CLK_GATE(clk_runit,  CGC_BIT_RUNIT);
>
> I've so far not had any problems, and not needed an sed foo.  I do
> only have a dozen or so clocks, which helps. But even so, all the real
> pain is hidden inside DEFINE_CLK_GATE() which Mike maintains.

It's true that if the argument list for the macros doesn't change then
the pain of static initialization is hidden from the platform data.

However if you have the ability to use the clk_foo_register functions
please do use them in place of static initialization.  The static init
stuff is only for folks backed into a corner and forced to use it...
for now.  I'm looking at ways to allow for kmalloc'ing in early boot,
as well as reducing the number of clocks that my platform registers
during early boot drastically.

>
> I guess the problem comes when you are not using the basic clk
> providers, but your own provider. What might help is if
> linux/clk-provider.h could provide some macros to do most of the
> generic definitions. Something like:

I'd rather people just used the registration functions instead.

Thanks,
Mike

>
> #define DEFINE_CLK_GENERIC(_name, _flags, _ops)                 \
>        static struct clk _name;                                \
>        static char *_name##_parent_names[] = {};               \
>        static struct clk _name = {                             \
>                .name = #_name,                                 \
>                .ops = &_ops,                                   \
>                .hw = &_name##_hw.hw,                           \
>                .parent_names = _name##_parent_names,           \
>                .num_parents =                                  \
>                        ARRAY_SIZE(_name##_parent_names),       \
>                .flags = _flags,                                \
>        };
>
> and then you have something like
>
> #define DEFINE_CLK_IMX(_name, _flags, _foo, _bar)               \
>        static struct clk_imx _name##_hw = {                    \
>                .hw = {                                         \
>                        .clk = &_name,                          \
>                },                                              \
>                .foo = _foo,                                    \
>                .bar = _bar,                                    \
>        };                                                      \
>        DEFINE_CLK_GENERIC(_name, _flags, clk_imx_ops)
>
>        Andrew

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

* Re: [PATCH v5 0/4] common clk framework
  2012-03-09  2:34 ` [PATCH v5 0/4] common clk framework Richard Zhao
  2012-03-09  9:19   ` Sascha Hauer
@ 2012-03-09 18:35   ` Turquette, Mike
  1 sibling, 0 replies; 51+ messages in thread
From: Turquette, Mike @ 2012-03-09 18:35 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Russell King, Grant Likely, Paul Walmsley, linaro-dev,
	Linus Walleij, patches, Stephen Boyd, Mark Brown, Magnus Damm,
	linux-kernel, Rob Herring, Richard Zhao, Arnd Bergman,
	Deepak Saxena, Saravana Kannan, Andrew Lunn, Shawn Guo,
	Amit Kucheria, Jeremy Kerr, Thomas Gleixner, linux-arm-kernel,
	Cousson, Benoit

On Thu, Mar 8, 2012 at 6:34 PM, Richard Zhao <richard.zhao@freescale.com> wrote:
> Hello Mike,
>
> The main interface for clk implementer is to register clocks dynamically.
> I think it highly depends on clk DT bindings. From the patch Grant sent
> out, it looks like he doesn't like one node per clk. So how do we
> register clocks dynamically? You have any sample code?

I can only speak for my own platform, but after talks with Paul W. and
Benoit C. I believe that OMAP will not push ALL of it's on-SoC clocks
into DT.  DT is meant to solve board-level integration problems and
the majority of OMAP clocks are SoC-level, not board level.  Some
clocks will migrate out to DT such as the primary oscillator (which
varies per board) as well as some leaf clocks and modules clocks that
depend on board-specific peripherals.

Otherwise the answer to your question is 'no'.  I don't have any
sample code for DT bindings.  It should not be hard to map some sample
clock bindings onto the existing registration functions... but it will
still be one clock per node.  I'm not really a fan of making clock
black-boxes where the details of the tree are hidden from the
framework anyways... that's something that clkdev already achieves to
some degree (by not exposing the entire tree to drivers, but only the
clocks that we want exposed).

Regards,
Mike

>
> Thanks
> Richard
>

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

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-07 21:20   ` [PATCH v5 4/4] clk: basic clock hardware types Sascha Hauer
@ 2012-03-09 22:50     ` Turquette, Mike
  0 siblings, 0 replies; 51+ messages in thread
From: Turquette, Mike @ 2012-03-09 22:50 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jamie Iles, Jeremy Kerr, Magnus Damm,
	Deepak Saxena, linux-arm-kernel, Arnd Bergman, patches,
	Rob Herring, Thomas Gleixner, Richard Zhao, Shawn Guo,
	Paul Walmsley, Linus Walleij, Mark Brown, Stephen Boyd,
	linux-kernel, Amit Kucheria

On Wed, Mar 7, 2012 at 1:20 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Sat, Mar 03, 2012 at 12:29:01AM -0800, Mike Turquette wrote:
>> +struct clk *clk_register_divider(struct device *dev, const char *name,
>> +             const char *parent_name, unsigned long flags,
>> +             void __iomem *reg, u8 shift, u8 width,
>> +             u8 clk_divider_flags, spinlock_t *lock)
>> +{
>> +     struct clk_divider *div;
>> +     char **parent_names = NULL;
>> +     u8 len;
>> +
>> +     div = kmalloc(sizeof(struct clk_divider), GFP_KERNEL);
>> +
>> +     if (!div) {
>> +             pr_err("%s: could not allocate divider clk\n", __func__);
>> +             return ERR_PTR(-ENOMEM);
>> +     }
>> +
>> +     /* struct clk_divider assignments */
>> +     div->reg = reg;
>> +     div->shift = shift;
>> +     div->width = width;
>> +     div->flags = clk_divider_flags;
>> +     div->lock = lock;
>> +
>> +     if (parent_name) {
>> +             parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
>> +
>> +             if (! parent_names)
>> +                     goto out;
>> +
>> +             len = sizeof(char) * strlen(parent_name);
>> +
>> +             parent_names[0] = kmalloc(len, GFP_KERNEL);
>> +
>> +             if (!parent_names[0])
>> +                     goto out;
>> +
>> +             strncpy(parent_names[0], parent_name, len);
>> +     }
>> +
>> +out:
>> +     return clk_register(dev, name,
>> +                     &clk_divider_ops, &div->hw,
>> +                     parent_names,
>> +                     (parent_name ? 1 : 0),
>> +                     flags);
>> +}
>
> clk_register_divider and also clk_register_gate have some problems.
> First you allocate memory with exactly the string length without
> the terminating 0. Then the functions leak memory when clk_register
> fails. Could you fold in the following patch to fix this?

Thanks for the patch Sascha.  This has been pulled into v6 and tested.

Regards,
Mike

>
> Sascha
>
> 8<--------------------------------------------------
>
> fix divider/gate registration
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
>  drivers/clk/clk-divider.c    |   34 +++++++++++++++-------------------
>  drivers/clk/clk-gate.c       |   33 ++++++++++++++-------------------
>  include/linux/clk-provider.h |    2 ++
>  3 files changed, 31 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 8f02930..99b6b55 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -156,14 +156,13 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
>                u8 clk_divider_flags, spinlock_t *lock)
>  {
>        struct clk_divider *div;
> -       char **parent_names = NULL;
> -       u8 len;
> +       struct clk *clk;
>
> -       div = kmalloc(sizeof(struct clk_divider), GFP_KERNEL);
> +       div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
>
>        if (!div) {
>                pr_err("%s: could not allocate divider clk\n", __func__);
> -               return ERR_PTR(-ENOMEM);
> +               return NULL;
>        }
>
>        /* struct clk_divider assignments */
> @@ -174,25 +173,22 @@ struct clk *clk_register_divider(struct device *dev, const char *name,
>        div->lock = lock;
>
>        if (parent_name) {
> -               parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
> -
> -               if (! parent_names)
> -                       goto out;
> -
> -               len = sizeof(char) * strlen(parent_name);
> -
> -               parent_names[0] = kmalloc(len, GFP_KERNEL);
> -
> -               if (!parent_names[0])
> +               div->parent[0] = kstrdup(parent_name, GFP_KERNEL);
> +               if (!div->parent[0])
>                        goto out;
> -
> -               strncpy(parent_names[0], parent_name, len);
>        }
>
> -out:
> -       return clk_register(dev, name,
> +       clk = clk_register(dev, name,
>                        &clk_divider_ops, &div->hw,
> -                       parent_names,
> +                       div->parent,
>                        (parent_name ? 1 : 0),
>                        flags);
> +       if (clk)
> +               return clk;
> +
> +out:
> +       kfree(div->parent[0]);
> +       kfree(div);
> +
> +       return NULL;
>  }
> diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
> index e831f7b..92c0489 100644
> --- a/drivers/clk/clk-gate.c
> +++ b/drivers/clk/clk-gate.c
> @@ -80,14 +80,13 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
>                u8 clk_gate_flags, spinlock_t *lock)
>  {
>        struct clk_gate *gate;
> -       char **parent_names = NULL;
> -       u8 len;
> +       struct clk *clk;
>
> -       gate = kmalloc(sizeof(struct clk_gate), GFP_KERNEL);
> +       gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
>
>        if (!gate) {
>                pr_err("%s: could not allocate gated clk\n", __func__);
> -               return ERR_PTR(-ENOMEM);
> +               return NULL;
>        }
>
>        /* struct clk_gate assignments */
> @@ -97,25 +96,21 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
>        gate->lock = lock;
>
>        if (parent_name) {
> -               parent_names = kmalloc(sizeof(char *), GFP_KERNEL);
> -
> -               if (! parent_names)
> -                       goto out;
> -
> -               len = sizeof(char) * strlen(parent_name);
> -
> -               parent_names[0] = kmalloc(len, GFP_KERNEL);
> -
> -               if (!parent_names[0])
> +               gate->parent[0] = kstrdup(parent_name, GFP_KERNEL);
> +               if (!gate->parent[0])
>                        goto out;
> -
> -               strncpy(parent_names[0], parent_name, len);
>        }
>
> -out:
> -       return clk_register(dev, name,
> +       clk = clk_register(dev, name,
>                        &clk_gate_ops, &gate->hw,
> -                       parent_names,
> +                       gate->parent,
>                        (parent_name ? 1 : 0),
>                        flags);
> +       if (clk)
> +               return clk;
> +out:
> +       kfree(gate->parent[0]);
> +       kfree(gate);
> +
> +       return NULL;
>  }
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 9b7dd5e..ed1f918 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -174,6 +174,7 @@ struct clk_gate {
>        u8              bit_idx;
>        u8              flags;
>        spinlock_t      *lock;
> +       char            *parent[1];
>  };
>
>  #define CLK_GATE_SET_TO_DISABLE                BIT(0)
> @@ -210,6 +211,7 @@ struct clk_divider {
>        u8              width;
>        u8              flags;
>        spinlock_t      *lock;
> +       char            *parent[1];
>  };
>
>  #define CLK_DIVIDER_ONE_BASED          BIT(0)
> --
> 1.7.9.1
>
> --
> 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] 51+ messages in thread

* Re: [PATCH v5 4/4] clk: basic clock hardware types
  2012-03-05 10:17           ` Andrew Lunn
@ 2012-03-09 23:38             ` Turquette, Mike
  0 siblings, 0 replies; 51+ messages in thread
From: Turquette, Mike @ 2012-03-09 23:38 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Sascha Hauer, Russell King, patches, linaro-dev, linux-kernel,
	linux-arm-kernel, Jeremy Kerr, Thomas Gleixner, Arnd Bergman,
	Paul Walmsley, Shawn Guo, Jamie Iles, Richard Zhao,
	Saravana Kannan, Magnus Damm, Rob Herring, Mark Brown,
	Linus Walleij, Stephen Boyd, Amit Kucheria, Deepak Saxena,
	Grant Likely, Rafael J. Wysocki

On Mon, Mar 5, 2012 at 2:17 AM, Andrew Lunn <andrew@lunn.ch> wrote:
>> > I think i can wrap your simple gate clock, to make my "complex" gate
>> > clock. What would help is if you would EXPORT_SYMBOL_GPL
>> > clk_gate_enable() and clk_gate_disable(), since they do exactly what i
>> > want. I can then build my own clk_ops structure, with my own
>> > unprepare() function. I would probably use DEFINE_CLK_GATE as is, and
>> > then at run time, before calling __clk_init() overwrite the .ops with
>> > my own version.
>>
>> Maybe I don't get your point, but clk_unprepare should be used when
>> you have to sleep to disable your clock. When clk_gate_disable() is
>> exactly why do you want to use clk_unprepare instead of clk_disable?
>
> I'm trying to avoid having to implement a new clock provider. The
> whole point of the generic clk code is to consolidate code. It seems
> silly to create a new clk provider which is 95% identical to Mike's
> gated provider, if i can avoid it.

I will export the operations in my next patchset, but I'm concerned
over how useful this might be...

Using your example of struct clk_gate, both clk_gate_enable and
clk_gate_disable call to_clk_gate.  So you would either have to re-use
struct clk_gate for your own needs (which involves hacking up a
specific struct clk_gate_foo_ops for your needs) or you could not use
struct clk_gate and pack your data identically (struct clk_hw must be
the first member) which is too horrible to imagine.

Hmm, or you could re-use struct clk_gate but provide your own struct
clk_ops AND your own registration functions (since you won't be able
to pass in the ops to your clk_register_gate).  So that sounds sane,
if a bit convoluted.  It does re-use code though...

Regards,
Mike

>
> If i stuff it into clk_disable(), it means i cannot use the basic gate
> clock Mike provides in the generic clock framework. Which is a shame,
> since it does exactly what i want in terms of gating the clock.
>
> If i can use unprepare(), which basic gate does not use, i can use
> Mikes code, and just extend it. It is there, it is unused, so why not
> use it?
>
>    Andrew

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-03  8:29 ` [PATCH v5 3/4] clk: introduce the common clock framework Mike Turquette
  2012-03-03 13:31   ` Sascha Hauer
  2012-03-05  9:22   ` Richard Zhao
@ 2012-03-13 11:24   ` Sascha Hauer
  2012-03-13 23:43     ` Turquette, Mike
  2 siblings, 1 reply; 51+ messages in thread
From: Sascha Hauer @ 2012-03-13 11:24 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jeremy Kerr, Mike Turquette, Magnus Damm,
	Deepak Saxena, linux-arm-kernel, Arnd Bergman, patches,
	Rob Herring, Thomas Gleixner, Richard Zhao, Shawn Guo,
	Paul Walmsley, Linus Walleij, Mark Brown, Stephen Boyd,
	linux-kernel, Amit Kucheria

On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:
> The common clock framework defines a common struct clk useful across
> most platforms as well as an implementation of the clk api that drivers
> can use safely for managing clocks.
> 
> The net result is consolidation of many different struct clk definitions
> and platform-specific clock framework implementations.
> 
> This patch introduces the common struct clk, struct clk_ops and an
> implementation of the well-known clock api in include/clk/clk.h.
> Platforms may define their own hardware-specific clock structure and
> their own clock operation callbacks, so long as it wraps an instance of
> struct clk_hw.
> 
> See Documentation/clk.txt for more details.
> 
> This patch is based on the work of Jeremy Kerr, which in turn was based
> on the work of Ben Herrenschmidt.
> 
> Signed-off-by: Mike Turquette <mturquette@linaro.org>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Arnd Bergman <arnd.bergmann@linaro.org>
> Cc: Paul Walmsley <paul@pwsan.com>
> Cc: Shawn Guo <shawn.guo@freescale.com>
> Cc: Richard Zhao <richard.zhao@linaro.org>
> Cc: Saravana Kannan <skannan@codeaurora.org>
> Cc: Magnus Damm <magnus.damm@gmail.com>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> Cc: Linus Walleij <linus.walleij@stericsson.com>
> Cc: Stephen Boyd <sboyd@codeaurora.org>
> Cc: Amit Kucheria <amit.kucheria@linaro.org>
> Cc: Deepak Saxena <dsaxena@linaro.org>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Andrew Lunn <andrew@lunn.ch>
> ---
>  drivers/clk/Kconfig          |   28 +
>  drivers/clk/Makefile         |    1 +
>  drivers/clk/clk.c            | 1323 ++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk-private.h  |   68 +++
>  include/linux/clk-provider.h |  169 ++++++
>  include/linux/clk.h          |   68 ++-
>  6 files changed, 1652 insertions(+), 5 deletions(-)
>  create mode 100644 drivers/clk/clk.c
>  create mode 100644 include/linux/clk-private.h
>  create mode 100644 include/linux/clk-provider.h
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 3912576..18eb8c2 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -11,3 +11,31 @@ config HAVE_MACH_CLKDEV
>  
>  config HAVE_CLK_PREPARE
>  	bool
> +
> +menuconfig COMMON_CLK
> +	bool "Common Clock Framework"
> +	select HAVE_CLK_PREPARE
> +	---help---
> +	  The common clock framework is a single definition of struct
> +	  clk, useful across many platforms, as well as an
> +	  implementation of the clock API in include/linux/clk.h.
> +	  Architectures utilizing the common struct clk should select
> +	  this automatically, but it may be necessary to manually select
> +	  this option for loadable modules requiring the common clock
> +	  framework.
> +
> +	  If in doubt, say "N".
> +
> +if COMMON_CLK
> +
> +config COMMON_CLK_DEBUG
> +	bool "DebugFS representation of clock tree"
> +	depends on COMMON_CLK
> +	---help---
> +	  Creates a directory hierchy in debugfs for visualizing the clk
> +	  tree structure.  Each directory contains read-only members
> +	  that export information specific to that clk node: clk_rate,
> +	  clk_flags, clk_prepare_count, clk_enable_count &
> +	  clk_notifier_count.
> +
> +endif
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..ff362c4 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_COMMON_CLK)	+= clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..b979d74
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,1323 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> + * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
> + *
> + * 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.  See Documentation/clk.txt
> + */
> +
> +#include <linux/clk-private.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/spinlock.h>
> +#include <linux/err.h>
> +#include <linux/list.h>
> +#include <linux/slab.h>
> +
> +static DEFINE_SPINLOCK(enable_lock);
> +static DEFINE_MUTEX(prepare_lock);
> +
> +static HLIST_HEAD(clk_root_list);
> +static HLIST_HEAD(clk_orphan_list);
> +static LIST_HEAD(clk_notifier_list);
> +
> +/***        debugfs support        ***/
> +
> +#ifdef CONFIG_COMMON_CLK_DEBUG
> +#include <linux/debugfs.h>
> +
> +static struct dentry *rootdir;
> +static struct dentry *orphandir;
> +static int inited = 0;
> +
> +/* caller must hold prepare_lock */
> +static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
> +{
> +	struct dentry *d;
> +	int ret = -ENOMEM;
> +
> +	if (!clk || !pdentry) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	d = debugfs_create_dir(clk->name, pdentry);
> +	if (!d)
> +		goto out;
> +
> +	clk->dentry = d;
> +
> +	d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry,
> +			(u32 *)&clk->rate);
> +	if (!d)
> +		goto err_out;
> +
> +	d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
> +			(u32 *)&clk->flags);
> +	if (!d)
> +		goto err_out;
> +
> +	d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry,
> +			(u32 *)&clk->prepare_count);
> +	if (!d)
> +		goto err_out;
> +
> +	d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry,
> +			(u32 *)&clk->enable_count);
> +	if (!d)
> +		goto err_out;
> +
> +	d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry,
> +			(u32 *)&clk->notifier_count);
> +	if (!d)
> +		goto err_out;
> +
> +	ret = 0;
> +	goto out;
> +
> +err_out:
> +	debugfs_remove(clk->dentry);
> +out:
> +	return ret;
> +}
> +
> +/* caller must hold prepare_lock */
> +static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
> +{
> +	struct clk *child;
> +	struct hlist_node *tmp;
> +	int ret = -EINVAL;;
> +
> +	if (!clk || !pdentry)
> +		goto out;
> +
> +	ret = clk_debug_create_one(clk, pdentry);
> +
> +	if (ret)
> +		goto out;
> +
> +	hlist_for_each_entry(child, tmp, &clk->children, child_node)
> +		clk_debug_create_subtree(child, clk->dentry);
> +
> +	ret = 0;
> +out:
> +	return ret;
> +}
> +
> +/**
> + * clk_debug_register - add a clk node to the debugfs clk tree
> + * @clk: the clk being added to the debugfs clk tree
> + *
> + * Dynamically adds a clk to the debugfs clk tree if debugfs has been
> + * initialized.  Otherwise it bails out early since the debugfs clk tree
> + * will be created lazily by clk_debug_init as part of a late_initcall.
> + *
> + * Caller must hold prepare_lock.  Only clk_init calls this function (so
> + * far) so this is taken care.
> + */
> +static int clk_debug_register(struct clk *clk)
> +{
> +	struct clk *parent;
> +	struct dentry *pdentry;
> +	int ret = 0;
> +
> +	if (!inited)
> +		goto out;
> +
> +	parent = clk->parent;
> +
> +	/*
> +	 * Check to see if a clk is a root clk.  Also check that it is
> +	 * safe to add this clk to debugfs
> +	 */
> +	if (!parent)
> +		if (clk->flags & CLK_IS_ROOT)
> +			pdentry = rootdir;
> +		else
> +			pdentry = orphandir;
> +	else
> +		if (parent->dentry)
> +			pdentry = parent->dentry;
> +		else
> +			goto out;
> +
> +	ret = clk_debug_create_subtree(clk, pdentry);
> +
> +out:
> +	return ret;
> +}
> +
> +/**
> + * clk_debug_init - lazily create the debugfs clk tree visualization
> + *
> + * clks are often initialized very early during boot before memory can
> + * be dynamically allocated and well before debugfs is setup.
> + * clk_debug_init walks the clk tree hierarchy while holding
> + * prepare_lock and creates the topology as part of a late_initcall,
> + * thus insuring that clks initialized very early will still be
> + * represented in the debugfs clk tree.  This function should only be
> + * called once at boot-time, and all other clks added dynamically will
> + * be done so with clk_debug_register.
> + */
> +static int __init clk_debug_init(void)
> +{
> +	struct clk *clk;
> +	struct hlist_node *tmp;
> +
> +	rootdir = debugfs_create_dir("clk", NULL);
> +
> +	if (!rootdir)
> +		return -ENOMEM;
> +
> +	orphandir = debugfs_create_dir("orphans", rootdir);
> +
> +	if (!orphandir)
> +		return -ENOMEM;
> +
> +	mutex_lock(&prepare_lock);
> +
> +	hlist_for_each_entry(clk, tmp, &clk_root_list, child_node)
> +		clk_debug_create_subtree(clk, rootdir);
> +
> +	hlist_for_each_entry(clk, tmp, &clk_orphan_list, child_node)
> +		clk_debug_create_subtree(clk, orphandir);
> +
> +	inited = 1;
> +
> +	mutex_unlock(&prepare_lock);
> +
> +	return 0;
> +}
> +late_initcall(clk_debug_init);
> +#else
> +static inline int clk_debug_register(struct clk *clk) { return 0; }
> +#endif /* CONFIG_COMMON_CLK_DEBUG */
> +
> +/***    helper functions   ***/
> +
> +inline const char *__clk_get_name(struct clk *clk)
> +{
> +	return !clk ? NULL : clk->name;
> +}
> +
> +inline struct clk_hw *__clk_get_hw(struct clk *clk)
> +{
> +	return !clk ? NULL : clk->hw;
> +}
> +
> +inline u8 __clk_get_num_parents(struct clk *clk)
> +{
> +	return !clk ? -EINVAL : clk->num_parents;
> +}
> +
> +inline struct clk *__clk_get_parent(struct clk *clk)
> +{
> +	return !clk ? NULL : clk->parent;
> +}
> +
> +inline unsigned long __clk_get_rate(struct clk *clk)
> +{
> +	return !clk ? -EINVAL : clk->rate;
> +}
> +
> +inline unsigned long __clk_get_flags(struct clk *clk)
> +{
> +	return !clk ? -EINVAL : clk->flags;
> +}
> +
> +static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
> +{
> +	struct clk *child;
> +	struct clk *ret;
> +	struct hlist_node *tmp;
> +
> +	if (!strcmp(clk->name, name))
> +		return clk;
> +
> +	hlist_for_each_entry(child, tmp, &clk->children, child_node) {
> +		ret = __clk_lookup_subtree(name, child);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return NULL;
> +}
> +
> +struct clk *__clk_lookup(const char *name)
> +{
> +	struct clk *root_clk;
> +	struct clk *ret;
> +	struct hlist_node *tmp;
> +

This should have a check for NULL pointers. NULL pointers can happen
here if a mux has holes in it. In this case the parent name array would
look like this:

{ "parentclk1", "parentclk2", NULL /* reserved */, "parentclk3" }

Without checking for NULL pointers we dereference the NULL pointer here.

> +
> +/**
> + * __clk_round_rate - round the given rate for a clk
> + * @clk: round the rate of this clock
> + *
> + * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
> + */
> +unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	if (!clk && !clk->ops->round_rate)
> +		return -EINVAL;

This should return the parents rate if the clock itself does not
have a round_rate function. Also, must be || instead of &&

> +
> +	return clk->ops->round_rate(clk->hw, rate, NULL);
> +}
> +
-- 
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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-13 11:24   ` Sascha Hauer
@ 2012-03-13 23:43     ` Turquette, Mike
  2012-03-14  8:48       ` Sascha Hauer
  0 siblings, 1 reply; 51+ messages in thread
From: Turquette, Mike @ 2012-03-13 23:43 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jeremy Kerr, Magnus Damm, Deepak Saxena,
	linux-arm-kernel, Arnd Bergman, patches, Rob Herring,
	Thomas Gleixner, Richard Zhao, Shawn Guo, Paul Walmsley,
	Linus Walleij, Mark Brown, Stephen Boyd, linux-kernel,
	Amit Kucheria

On Tue, Mar 13, 2012 at 4:24 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:
>> The common clock framework defines a common struct clk useful across
>> most platforms as well as an implementation of the clk api that drivers
>> can use safely for managing clocks.
>>
>> The net result is consolidation of many different struct clk definitions
>> and platform-specific clock framework implementations.
>>
>> This patch introduces the common struct clk, struct clk_ops and an
>> implementation of the well-known clock api in include/clk/clk.h.
>> Platforms may define their own hardware-specific clock structure and
>> their own clock operation callbacks, so long as it wraps an instance of
>> struct clk_hw.
>>
>> See Documentation/clk.txt for more details.
>>
>> This patch is based on the work of Jeremy Kerr, which in turn was based
>> on the work of Ben Herrenschmidt.
>>
>> Signed-off-by: Mike Turquette <mturquette@linaro.org>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Arnd Bergman <arnd.bergmann@linaro.org>
>> Cc: Paul Walmsley <paul@pwsan.com>
>> Cc: Shawn Guo <shawn.guo@freescale.com>
>> Cc: Richard Zhao <richard.zhao@linaro.org>
>> Cc: Saravana Kannan <skannan@codeaurora.org>
>> Cc: Magnus Damm <magnus.damm@gmail.com>
>> Cc: Rob Herring <rob.herring@calxeda.com>
>> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Cc: Linus Walleij <linus.walleij@stericsson.com>
>> Cc: Stephen Boyd <sboyd@codeaurora.org>
>> Cc: Amit Kucheria <amit.kucheria@linaro.org>
>> Cc: Deepak Saxena <dsaxena@linaro.org>
>> Cc: Grant Likely <grant.likely@secretlab.ca>
>> Cc: Andrew Lunn <andrew@lunn.ch>
>> ---
>>  drivers/clk/Kconfig          |   28 +
>>  drivers/clk/Makefile         |    1 +
>>  drivers/clk/clk.c            | 1323 ++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/clk-private.h  |   68 +++
>>  include/linux/clk-provider.h |  169 ++++++
>>  include/linux/clk.h          |   68 ++-
>>  6 files changed, 1652 insertions(+), 5 deletions(-)
>>  create mode 100644 drivers/clk/clk.c
>>  create mode 100644 include/linux/clk-private.h
>>  create mode 100644 include/linux/clk-provider.h
>>
>> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> index 3912576..18eb8c2 100644
>> --- a/drivers/clk/Kconfig
>> +++ b/drivers/clk/Kconfig
>> @@ -11,3 +11,31 @@ config HAVE_MACH_CLKDEV
>>
>>  config HAVE_CLK_PREPARE
>>       bool
>> +
>> +menuconfig COMMON_CLK
>> +     bool "Common Clock Framework"
>> +     select HAVE_CLK_PREPARE
>> +     ---help---
>> +       The common clock framework is a single definition of struct
>> +       clk, useful across many platforms, as well as an
>> +       implementation of the clock API in include/linux/clk.h.
>> +       Architectures utilizing the common struct clk should select
>> +       this automatically, but it may be necessary to manually select
>> +       this option for loadable modules requiring the common clock
>> +       framework.
>> +
>> +       If in doubt, say "N".
>> +
>> +if COMMON_CLK
>> +
>> +config COMMON_CLK_DEBUG
>> +     bool "DebugFS representation of clock tree"
>> +     depends on COMMON_CLK
>> +     ---help---
>> +       Creates a directory hierchy in debugfs for visualizing the clk
>> +       tree structure.  Each directory contains read-only members
>> +       that export information specific to that clk node: clk_rate,
>> +       clk_flags, clk_prepare_count, clk_enable_count &
>> +       clk_notifier_count.
>> +
>> +endif
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index 07613fa..ff362c4 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -1,2 +1,3 @@
>>
>>  obj-$(CONFIG_CLKDEV_LOOKUP)  += clkdev.o
>> +obj-$(CONFIG_COMMON_CLK)     += clk.o
>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>> new file mode 100644
>> index 0000000..b979d74
>> --- /dev/null
>> +++ b/drivers/clk/clk.c
>> @@ -0,0 +1,1323 @@
>> +/*
>> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
>> + * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
>> + *
>> + * 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.  See Documentation/clk.txt
>> + */
>> +
>> +#include <linux/clk-private.h>
>> +#include <linux/module.h>
>> +#include <linux/mutex.h>
>> +#include <linux/spinlock.h>
>> +#include <linux/err.h>
>> +#include <linux/list.h>
>> +#include <linux/slab.h>
>> +
>> +static DEFINE_SPINLOCK(enable_lock);
>> +static DEFINE_MUTEX(prepare_lock);
>> +
>> +static HLIST_HEAD(clk_root_list);
>> +static HLIST_HEAD(clk_orphan_list);
>> +static LIST_HEAD(clk_notifier_list);
>> +
>> +/***        debugfs support        ***/
>> +
>> +#ifdef CONFIG_COMMON_CLK_DEBUG
>> +#include <linux/debugfs.h>
>> +
>> +static struct dentry *rootdir;
>> +static struct dentry *orphandir;
>> +static int inited = 0;
>> +
>> +/* caller must hold prepare_lock */
>> +static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
>> +{
>> +     struct dentry *d;
>> +     int ret = -ENOMEM;
>> +
>> +     if (!clk || !pdentry) {
>> +             ret = -EINVAL;
>> +             goto out;
>> +     }
>> +
>> +     d = debugfs_create_dir(clk->name, pdentry);
>> +     if (!d)
>> +             goto out;
>> +
>> +     clk->dentry = d;
>> +
>> +     d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry,
>> +                     (u32 *)&clk->rate);
>> +     if (!d)
>> +             goto err_out;
>> +
>> +     d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
>> +                     (u32 *)&clk->flags);
>> +     if (!d)
>> +             goto err_out;
>> +
>> +     d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry,
>> +                     (u32 *)&clk->prepare_count);
>> +     if (!d)
>> +             goto err_out;
>> +
>> +     d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry,
>> +                     (u32 *)&clk->enable_count);
>> +     if (!d)
>> +             goto err_out;
>> +
>> +     d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry,
>> +                     (u32 *)&clk->notifier_count);
>> +     if (!d)
>> +             goto err_out;
>> +
>> +     ret = 0;
>> +     goto out;
>> +
>> +err_out:
>> +     debugfs_remove(clk->dentry);
>> +out:
>> +     return ret;
>> +}
>> +
>> +/* caller must hold prepare_lock */
>> +static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
>> +{
>> +     struct clk *child;
>> +     struct hlist_node *tmp;
>> +     int ret = -EINVAL;;
>> +
>> +     if (!clk || !pdentry)
>> +             goto out;
>> +
>> +     ret = clk_debug_create_one(clk, pdentry);
>> +
>> +     if (ret)
>> +             goto out;
>> +
>> +     hlist_for_each_entry(child, tmp, &clk->children, child_node)
>> +             clk_debug_create_subtree(child, clk->dentry);
>> +
>> +     ret = 0;
>> +out:
>> +     return ret;
>> +}
>> +
>> +/**
>> + * clk_debug_register - add a clk node to the debugfs clk tree
>> + * @clk: the clk being added to the debugfs clk tree
>> + *
>> + * Dynamically adds a clk to the debugfs clk tree if debugfs has been
>> + * initialized.  Otherwise it bails out early since the debugfs clk tree
>> + * will be created lazily by clk_debug_init as part of a late_initcall.
>> + *
>> + * Caller must hold prepare_lock.  Only clk_init calls this function (so
>> + * far) so this is taken care.
>> + */
>> +static int clk_debug_register(struct clk *clk)
>> +{
>> +     struct clk *parent;
>> +     struct dentry *pdentry;
>> +     int ret = 0;
>> +
>> +     if (!inited)
>> +             goto out;
>> +
>> +     parent = clk->parent;
>> +
>> +     /*
>> +      * Check to see if a clk is a root clk.  Also check that it is
>> +      * safe to add this clk to debugfs
>> +      */
>> +     if (!parent)
>> +             if (clk->flags & CLK_IS_ROOT)
>> +                     pdentry = rootdir;
>> +             else
>> +                     pdentry = orphandir;
>> +     else
>> +             if (parent->dentry)
>> +                     pdentry = parent->dentry;
>> +             else
>> +                     goto out;
>> +
>> +     ret = clk_debug_create_subtree(clk, pdentry);
>> +
>> +out:
>> +     return ret;
>> +}
>> +
>> +/**
>> + * clk_debug_init - lazily create the debugfs clk tree visualization
>> + *
>> + * clks are often initialized very early during boot before memory can
>> + * be dynamically allocated and well before debugfs is setup.
>> + * clk_debug_init walks the clk tree hierarchy while holding
>> + * prepare_lock and creates the topology as part of a late_initcall,
>> + * thus insuring that clks initialized very early will still be
>> + * represented in the debugfs clk tree.  This function should only be
>> + * called once at boot-time, and all other clks added dynamically will
>> + * be done so with clk_debug_register.
>> + */
>> +static int __init clk_debug_init(void)
>> +{
>> +     struct clk *clk;
>> +     struct hlist_node *tmp;
>> +
>> +     rootdir = debugfs_create_dir("clk", NULL);
>> +
>> +     if (!rootdir)
>> +             return -ENOMEM;
>> +
>> +     orphandir = debugfs_create_dir("orphans", rootdir);
>> +
>> +     if (!orphandir)
>> +             return -ENOMEM;
>> +
>> +     mutex_lock(&prepare_lock);
>> +
>> +     hlist_for_each_entry(clk, tmp, &clk_root_list, child_node)
>> +             clk_debug_create_subtree(clk, rootdir);
>> +
>> +     hlist_for_each_entry(clk, tmp, &clk_orphan_list, child_node)
>> +             clk_debug_create_subtree(clk, orphandir);
>> +
>> +     inited = 1;
>> +
>> +     mutex_unlock(&prepare_lock);
>> +
>> +     return 0;
>> +}
>> +late_initcall(clk_debug_init);
>> +#else
>> +static inline int clk_debug_register(struct clk *clk) { return 0; }
>> +#endif /* CONFIG_COMMON_CLK_DEBUG */
>> +
>> +/***    helper functions   ***/
>> +
>> +inline const char *__clk_get_name(struct clk *clk)
>> +{
>> +     return !clk ? NULL : clk->name;
>> +}
>> +
>> +inline struct clk_hw *__clk_get_hw(struct clk *clk)
>> +{
>> +     return !clk ? NULL : clk->hw;
>> +}
>> +
>> +inline u8 __clk_get_num_parents(struct clk *clk)
>> +{
>> +     return !clk ? -EINVAL : clk->num_parents;
>> +}
>> +
>> +inline struct clk *__clk_get_parent(struct clk *clk)
>> +{
>> +     return !clk ? NULL : clk->parent;
>> +}
>> +
>> +inline unsigned long __clk_get_rate(struct clk *clk)
>> +{
>> +     return !clk ? -EINVAL : clk->rate;
>> +}
>> +
>> +inline unsigned long __clk_get_flags(struct clk *clk)
>> +{
>> +     return !clk ? -EINVAL : clk->flags;
>> +}
>> +
>> +static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
>> +{
>> +     struct clk *child;
>> +     struct clk *ret;
>> +     struct hlist_node *tmp;
>> +
>> +     if (!strcmp(clk->name, name))
>> +             return clk;
>> +
>> +     hlist_for_each_entry(child, tmp, &clk->children, child_node) {
>> +             ret = __clk_lookup_subtree(name, child);
>> +             if (ret)
>> +                     return ret;
>> +     }
>> +
>> +     return NULL;
>> +}
>> +
>> +struct clk *__clk_lookup(const char *name)
>> +{
>> +     struct clk *root_clk;
>> +     struct clk *ret;
>> +     struct hlist_node *tmp;
>> +
>
> This should have a check for NULL pointers. NULL pointers can happen
> here if a mux has holes in it. In this case the parent name array would
> look like this:
>
> { "parentclk1", "parentclk2", NULL /* reserved */, "parentclk3" }
>
> Without checking for NULL pointers we dereference the NULL pointer here.

I will add the check.  I had not considered having NULL as one of the
parent names.  It seems to me that the only time this would happen is
if we are wiring up discrete devices.  For instance:

Device A has a fixed-rate clock named "dpll"
Device B has a mux clock named "leaf" with parent_names = { "32k",
"oscillator", "clkin" }

On a given board, leaf's "pll" parent might map to the output of the
dpll clock.  I had considered that DT would step in here by creating
an intermediate clock with no functional clk_ops that would "connect"
these two clocks.  The benefit of this is that it is easier to match
up clock names when staring at some data sheets.  It is common for a
downstream device's data sheets to assign names to the external inputs
originating from some unknown device; unsurprisingly the data sheet
for the device supplying the external upstream clocks often has
different names for the output signals than the one in the downstream
device's data sheet.  Using the method described above it is easy for
a person with both data sheets to see how the devices are wired up
since all of the clock names are represented by nodes in the clock
tree.  In short, the final outcome would looking something like:

dpll (device a's driver registered this clock)
  |
clkin (one of device b's possible parents)
  |    (it is a dummy clock from DT since it is board-level topology)
  |
leaf (device b's driver registered this clock)

clkin would have a single parent named "dpll" in this case, and again,
it would have no meaningful clk_ops.

A caveat to the above scenario is that parent_names shouldn't have
holes in it, but a null pointer check is reasonable anyways.

What do you think?  Even if we allow for muxes to have holes in
parent_names we'll still have to solve these sort of device
integration issues and DT will likely play a roll here.  I'll roll in
the null pointer check regardless.

Also, do you forsee needing hole in parent_names for any reason other
than described above?

Thanks,
Mike

>
>> +
>> +/**
>> + * __clk_round_rate - round the given rate for a clk
>> + * @clk: round the rate of this clock
>> + *
>> + * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
>> + */
>> +unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
>> +{
>> +     if (!clk && !clk->ops->round_rate)
>> +             return -EINVAL;
>
> This should return the parents rate if the clock itself does not
> have a round_rate function. Also, must be || instead of &&
>
>> +
>> +     return clk->ops->round_rate(clk->hw, rate, NULL);
>> +}
>> +
> --
> 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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-05  9:22   ` Richard Zhao
@ 2012-03-14  2:03     ` Turquette, Mike
  0 siblings, 0 replies; 51+ messages in thread
From: Turquette, Mike @ 2012-03-14  2:03 UTC (permalink / raw)
  To: Richard Zhao
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jeremy Kerr, Magnus Damm, Deepak Saxena,
	linux-arm-kernel, Arnd Bergman, patches, Rob Herring,
	Thomas Gleixner, Richard Zhao, Shawn Guo, Paul Walmsley,
	Linus Walleij, Mark Brown, Stephen Boyd, linux-kernel,
	Amit Kucheria

On Mon, Mar 5, 2012 at 1:22 AM, Richard Zhao <richard.zhao@freescale.com> wrote:
> Hi Mike,

Hi Richard,

Sorry for missing this earlier.  I've taken in most of your
suggestions and commented on some of them below.  Any of your feedback
that I cut from this mail was taken in as a fix in v7 :-)

> On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:
>> +/**
>> + * __clk_round_rate - round the given rate for a clk
>> + * @clk: round the rate of this clock
>> + *
>> + * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
>> + */
>> +unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
>> +{
>> +     if (!clk && !clk->ops->round_rate)
> be               || ?

This is fixed in v7 by a refactor of how clk_round_rate and
__clk_round_rate work.

>> +long clk_round_rate(struct clk *clk, unsigned long rate)
>> +{
>> +     unsigned long ret = rate;
>> +
>> +     mutex_lock(&prepare_lock);
>> +     if (clk && clk->ops->round_rate)
>> +             ret = __clk_round_rate(clk, rate);
>> +     mutex_unlock(&prepare_lock);
>> +
>> +     return ret;
> If clk is NULL, clk_round_rate and __clk_round_rate return different
> values. Do you mean it?

This also is fixed in v7 by a refactor of how clk_round_rate and
__clk_round_rate work.

>> +static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
>> +{
>> +     struct hlist_node *tmp;
>> +     struct clk *child;
>> +     unsigned long new_rate;
>> +     int ret = NOTIFY_DONE;
>> +
>> +     if (!clk->ops->recalc_rate)
>> +             goto out;
> When recalc_rate is NULL, it's possible for it and its children to have
> notifier too.

Fixed by assuming parent rate without .recalc_rate callback.  This
mirrors __clk_recalc_rates.

>> +
>> +     new_rate = clk->ops->recalc_rate(clk->hw, parent_rate);
>> +
>> +     /* abort the rate change if a driver returns NOTIFY_BAD */
>> +     if (clk->notifier_count)
>> +             ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
>> +
>> +     if (ret == NOTIFY_BAD)
>> +             goto out;
>> +
>> +     hlist_for_each_entry(child, tmp, &clk->children, child_node) {
>> +             ret = __clk_speculate_rates(child, new_rate);
>> +             if (ret == NOTIFY_BAD)
>> +                     break;
>> +     }
> Tell the notifier that already receive PRE_RATE_CHANGE abort?

All of this stuff might change due to existing thread with Sascha on
how clk_set_rate should propagate parent rate changes.  But for
completeness sake, a single ABORT goes out at the end of clk_set_rate
in this implementation, so there isn't a problem here.

>> +static struct clk *__clk_set_rate(struct clk *clk, unsigned long rate)
>> +{
>> +     struct clk *fail_clk = NULL;
>> +     int ret = NOTIFY_DONE;
>> +     unsigned long old_rate = clk->rate;
>> +     unsigned long new_rate;
>> +     unsigned long parent_old_rate;
>> +     unsigned long parent_new_rate = 0;
>> +     struct clk *child;
>> +     struct hlist_node *tmp;
>> +
>> +     /* bail early if we can't change rate while clk is enabled */
>> +     if ((clk->flags & CLK_SET_RATE_GATE) && clk->enable_count)
>> +             return clk;
>> +
>> +     /* find the new rate and see if parent rate should change too */
>> +     WARN_ON(!clk->ops->round_rate);
>> +
>> +     new_rate = clk->ops->round_rate(clk->hw, rate, &parent_new_rate);
>> +
>> +     /* NOTE: pre-rate change notifications will stack */
>> +     if (clk->notifier_count)
>> +             ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate);
>
> if ((clk->flags & CLK_SET_RATE_PARENT) && parent_new_rate)
>        dowstream notify from parent clk?

The pre-rate change notifiers stack; also no problem here.

>> +
>> +     if (ret == NOTIFY_BAD)
>> +             return clk;
>> +
>> +     /* speculate rate changes down the tree */
>> +     hlist_for_each_entry(child, tmp, &clk->children, child_node) {
>> +             ret = __clk_speculate_rates(child, new_rate);
>> +             if (ret == NOTIFY_BAD)
> roll back?

Similar to the above.  The post-rate change notifiers are sent out
once from the top of the subtree in __clk_set_rate; no problem here.

>> +                     return clk;
>> +     }
>> +
>> +     /* change the rate of this clk */
>> +     if (clk->ops->set_rate)
> If set_rate is NULL, it can fail at the beginning of this function.

We don't want to fail.  In the conditional block below we allow for
propagating the rate request up to the parent.  This would allow for a
gate clock at the bottom of the tree to have clk_set_rate called
against it, even though its hardware doesn't support it, and it will
propagate the request up the tree until it finds a clock that can
adjust the rate.  This feature is very desirable for driver folks who
do not want to know about the tree topology in their driver beyond the
clocks needed by their device.

>> +             ret = clk->ops->set_rate(clk->hw, new_rate);
>> +
>> +     if (ret == NOTIFY_BAD)
> you mean to check set_rate fail? Notify ABORT_RATE_CHANGE?

As stated, this happens once in clk_set_rate.

>> +             return clk;
>> +
>> +     /*
>> +      * change the rate of the parent clk if necessary
>> +      *
>> +      * hitting the nested 'if' path implies we have hit a .set_rate
>> +      * failure somewhere upstream while propagating __clk_set_rate
>> +      * up the clk tree.  roll back the clk rates one by one and
>> +      * return the pointer to the clk that failed.  clk_set_rate will
>> +      * use the pointer to propagate a rate-change abort notifier
>> +      * from the "highest" point.
>> +      */
>> +     if ((clk->flags & CLK_SET_RATE_PARENT) && parent_new_rate) {
>> +             parent_old_rate = clk->parent->rate;
>> +             fail_clk = __clk_set_rate(clk->parent, parent_new_rate);
>> +
>> +             /* roll back changes if parent rate change failed */
>> +             if (fail_clk) {
>> +                     pr_warn("%s: failed to set parent %s rate to %lu\n",
>> +                                     __func__, fail_clk->name,
>> +                                     parent_new_rate);
>> +
>> +                     /*
>> +                      * Send PRE_RATE_CHANGE notifiers down the tree
>> +                      * again, since we're rolling back the rate
>> +                      * changes due to the abort.
>> +                      *
>> +                      * Ignore any NOTIFY_BAD's since this *is* the
>> +                      * exception handler.
>> +                      *
>> +                      * NOTE: pre-rate change notifications will stack
>> +                      */
>> +                     __clk_speculate_rates(clk, clk->parent->rate);
> IMHO, driver can not be happy to receive multiple PRE_RATE_CHANGE.
> Notify ABORT_RATE_CHANGE?

This is getting looked at again in the v6 thread :-)

>> +int clk_set_rate(struct clk *clk, unsigned long rate)
>> +{
>> +     struct clk *fail_clk;
>> +     int ret = 0;
>> +
>> +     /* prevent racing with updates to the clock topology */
>> +     mutex_lock(&prepare_lock);
>> +
>> +     /* bail early if nothing to do */
>> +     if (rate == clk->rate)
>> +             goto out;
>> +
>> +     fail_clk = __clk_set_rate(clk, rate);
>> +     if (fail_clk) {
>> +             pr_warn("%s: failed to set %s rate\n", __func__,
>> +                             fail_clk->name);
>> +             __clk_recalc_rates(clk, ABORT_RATE_CHANGE);
> It might need to begin from parent clk. move it to __clk_set_rate?

That should be __clk_recalc_rates(fail_clk, ABORT_RATE_CHANGE), which
is the parent clk.  Thanks for catching that.

>> +void __clk_init(struct device *dev, struct clk *clk)
>> +{
...
>> +     /*
>> +      * walk the list of orphan clocks and reparent any that are children of
>> +      * this clock
>> +      */
>> +     hlist_for_each_entry(orphan, tmp, &clk_orphan_list, child_node)
>> +             __clk_reparent(orphan, __clk_init_parent(orphan));
> check whether orphan->parent is the value of  __clk_init_parent(orphan)
> before reparent?

Good point.  I cleaned this up a bit to only check orphan's parents
against the clock being registered.  I can't think of any reason why
that wouldn't be adequate.

>> +int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
>> +{
>> +     struct clk_notifier *cn;
>> +     int ret = -ENOMEM;
>> +
>> +     if (!clk || !nb)
>> +             return -EINVAL;
>> +
>> +     mutex_lock(&prepare_lock);
>> +
>> +     /* search the list of notifiers for this clk */
>> +     list_for_each_entry(cn, &clk_notifier_list, node)
>> +             if (cn->clk == clk)
>> +                     break;
>> +
>> +     /* if clk wasn't in the notifier list, allocate new clk_notifier */
>> +     if (cn->clk != clk) {
>> +             cn = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
>> +             if (!cn)
>> +                     goto out;
>> +
>> +             cn->clk = clk;
>> +             srcu_init_notifier_head(&cn->notifier_head);
>> +
>> +             list_add(&cn->node, &clk_notifier_list);
>> +     }
> why not embedd notifier_head to struct clk?

It is assumed that the vast majority of clocks will not have drivers
subscribed to their notifiers.  This saves space over having the
notifier_head in every single struct clk.

Thanks for the great review.

Mike

> Thanks
> Richard
>

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-13 23:43     ` Turquette, Mike
@ 2012-03-14  8:48       ` Sascha Hauer
  2012-03-14 20:47         ` Turquette, Mike
  0 siblings, 1 reply; 51+ messages in thread
From: Sascha Hauer @ 2012-03-14  8:48 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jeremy Kerr, Magnus Damm, Deepak Saxena,
	linux-arm-kernel, Arnd Bergman, patches, Rob Herring,
	Thomas Gleixner, Richard Zhao, Shawn Guo, Paul Walmsley,
	Linus Walleij, Mark Brown, Stephen Boyd, linux-kernel,
	Amit Kucheria

On Tue, Mar 13, 2012 at 04:43:57PM -0700, Turquette, Mike wrote:
> On Tue, Mar 13, 2012 at 4:24 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> > On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:
> >> The common clock framework defines a common struct clk useful across
> >> most platforms as well as an implementation of the clk api that drivers
> >> can use safely for managing clocks.
> >>
> >> The net result is consolidation of many different struct clk definitions
> >> and platform-specific clock framework implementations.
> >>
> >> This patch introduces the common struct clk, struct clk_ops and an
> >> implementation of the well-known clock api in include/clk/clk.h.
> >> Platforms may define their own hardware-specific clock structure and
> >> their own clock operation callbacks, so long as it wraps an instance of
> >> struct clk_hw.
> >>
> >> See Documentation/clk.txt for more details.
> >>
> >> This patch is based on the work of Jeremy Kerr, which in turn was based
> >> on the work of Ben Herrenschmidt.
> >>
> >> Signed-off-by: Mike Turquette <mturquette@linaro.org>
> >> Signed-off-by: Mike Turquette <mturquette@ti.com>
> >> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> >> Cc: Thomas Gleixner <tglx@linutronix.de>
> >> Cc: Arnd Bergman <arnd.bergmann@linaro.org>
> >> Cc: Paul Walmsley <paul@pwsan.com>
> >> Cc: Shawn Guo <shawn.guo@freescale.com>
> >> Cc: Richard Zhao <richard.zhao@linaro.org>
> >> Cc: Saravana Kannan <skannan@codeaurora.org>
> >> Cc: Magnus Damm <magnus.damm@gmail.com>
> >> Cc: Rob Herring <rob.herring@calxeda.com>
> >> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
> >> Cc: Linus Walleij <linus.walleij@stericsson.com>
> >> Cc: Stephen Boyd <sboyd@codeaurora.org>
> >> Cc: Amit Kucheria <amit.kucheria@linaro.org>
> >> Cc: Deepak Saxena <dsaxena@linaro.org>
> >> Cc: Grant Likely <grant.likely@secretlab.ca>
> >> Cc: Andrew Lunn <andrew@lunn.ch>
> >> ---
> >>  drivers/clk/Kconfig          |   28 +
> >>  drivers/clk/Makefile         |    1 +
> >>  drivers/clk/clk.c            | 1323 ++++++++++++++++++++++++++++++++++++++++++
> >>  include/linux/clk-private.h  |   68 +++
> >>  include/linux/clk-provider.h |  169 ++++++
> >>  include/linux/clk.h          |   68 ++-
> >>  6 files changed, 1652 insertions(+), 5 deletions(-)
> >>  create mode 100644 drivers/clk/clk.c
> >>  create mode 100644 include/linux/clk-private.h
> >>  create mode 100644 include/linux/clk-provider.h
> >>
> >> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> >> index 3912576..18eb8c2 100644
> >> --- a/drivers/clk/Kconfig
> >> +++ b/drivers/clk/Kconfig
> >> @@ -11,3 +11,31 @@ config HAVE_MACH_CLKDEV
> >>
> >>  config HAVE_CLK_PREPARE
> >>       bool
> >> +
> >> +menuconfig COMMON_CLK
> >> +     bool "Common Clock Framework"
> >> +     select HAVE_CLK_PREPARE
> >> +     ---help---
> >> +       The common clock framework is a single definition of struct
> >> +       clk, useful across many platforms, as well as an
> >> +       implementation of the clock API in include/linux/clk.h.
> >> +       Architectures utilizing the common struct clk should select
> >> +       this automatically, but it may be necessary to manually select
> >> +       this option for loadable modules requiring the common clock
> >> +       framework.
> >> +
> >> +       If in doubt, say "N".
> >> +
> >> +if COMMON_CLK
> >> +
> >> +config COMMON_CLK_DEBUG
> >> +     bool "DebugFS representation of clock tree"
> >> +     depends on COMMON_CLK
> >> +     ---help---
> >> +       Creates a directory hierchy in debugfs for visualizing the clk
> >> +       tree structure.  Each directory contains read-only members
> >> +       that export information specific to that clk node: clk_rate,
> >> +       clk_flags, clk_prepare_count, clk_enable_count &
> >> +       clk_notifier_count.
> >> +
> >> +endif
> >> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> >> index 07613fa..ff362c4 100644
> >> --- a/drivers/clk/Makefile
> >> +++ b/drivers/clk/Makefile
> >> @@ -1,2 +1,3 @@
> >>
> >>  obj-$(CONFIG_CLKDEV_LOOKUP)  += clkdev.o
> >> +obj-$(CONFIG_COMMON_CLK)     += clk.o
> >> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> >> new file mode 100644
> >> index 0000000..b979d74
> >> --- /dev/null
> >> +++ b/drivers/clk/clk.c
> >> @@ -0,0 +1,1323 @@
> >> +/*
> >> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
> >> + * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
> >> + *
> >> + * 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.  See Documentation/clk.txt
> >> + */
> >> +
> >> +#include <linux/clk-private.h>
> >> +#include <linux/module.h>
> >> +#include <linux/mutex.h>
> >> +#include <linux/spinlock.h>
> >> +#include <linux/err.h>
> >> +#include <linux/list.h>
> >> +#include <linux/slab.h>
> >> +
> >> +static DEFINE_SPINLOCK(enable_lock);
> >> +static DEFINE_MUTEX(prepare_lock);
> >> +
> >> +static HLIST_HEAD(clk_root_list);
> >> +static HLIST_HEAD(clk_orphan_list);
> >> +static LIST_HEAD(clk_notifier_list);
> >> +
> >> +/***        debugfs support        ***/
> >> +
> >> +#ifdef CONFIG_COMMON_CLK_DEBUG
> >> +#include <linux/debugfs.h>
> >> +
> >> +static struct dentry *rootdir;
> >> +static struct dentry *orphandir;
> >> +static int inited = 0;
> >> +
> >> +/* caller must hold prepare_lock */
> >> +static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
> >> +{
> >> +     struct dentry *d;
> >> +     int ret = -ENOMEM;
> >> +
> >> +     if (!clk || !pdentry) {
> >> +             ret = -EINVAL;
> >> +             goto out;
> >> +     }
> >> +
> >> +     d = debugfs_create_dir(clk->name, pdentry);
> >> +     if (!d)
> >> +             goto out;
> >> +
> >> +     clk->dentry = d;
> >> +
> >> +     d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry,
> >> +                     (u32 *)&clk->rate);
> >> +     if (!d)
> >> +             goto err_out;
> >> +
> >> +     d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
> >> +                     (u32 *)&clk->flags);
> >> +     if (!d)
> >> +             goto err_out;
> >> +
> >> +     d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry,
> >> +                     (u32 *)&clk->prepare_count);
> >> +     if (!d)
> >> +             goto err_out;
> >> +
> >> +     d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry,
> >> +                     (u32 *)&clk->enable_count);
> >> +     if (!d)
> >> +             goto err_out;
> >> +
> >> +     d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry,
> >> +                     (u32 *)&clk->notifier_count);
> >> +     if (!d)
> >> +             goto err_out;
> >> +
> >> +     ret = 0;
> >> +     goto out;
> >> +
> >> +err_out:
> >> +     debugfs_remove(clk->dentry);
> >> +out:
> >> +     return ret;
> >> +}
> >> +
> >> +/* caller must hold prepare_lock */
> >> +static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
> >> +{
> >> +     struct clk *child;
> >> +     struct hlist_node *tmp;
> >> +     int ret = -EINVAL;;
> >> +
> >> +     if (!clk || !pdentry)
> >> +             goto out;
> >> +
> >> +     ret = clk_debug_create_one(clk, pdentry);
> >> +
> >> +     if (ret)
> >> +             goto out;
> >> +
> >> +     hlist_for_each_entry(child, tmp, &clk->children, child_node)
> >> +             clk_debug_create_subtree(child, clk->dentry);
> >> +
> >> +     ret = 0;
> >> +out:
> >> +     return ret;
> >> +}
> >> +
> >> +/**
> >> + * clk_debug_register - add a clk node to the debugfs clk tree
> >> + * @clk: the clk being added to the debugfs clk tree
> >> + *
> >> + * Dynamically adds a clk to the debugfs clk tree if debugfs has been
> >> + * initialized.  Otherwise it bails out early since the debugfs clk tree
> >> + * will be created lazily by clk_debug_init as part of a late_initcall.
> >> + *
> >> + * Caller must hold prepare_lock.  Only clk_init calls this function (so
> >> + * far) so this is taken care.
> >> + */
> >> +static int clk_debug_register(struct clk *clk)
> >> +{
> >> +     struct clk *parent;
> >> +     struct dentry *pdentry;
> >> +     int ret = 0;
> >> +
> >> +     if (!inited)
> >> +             goto out;
> >> +
> >> +     parent = clk->parent;
> >> +
> >> +     /*
> >> +      * Check to see if a clk is a root clk.  Also check that it is
> >> +      * safe to add this clk to debugfs
> >> +      */
> >> +     if (!parent)
> >> +             if (clk->flags & CLK_IS_ROOT)
> >> +                     pdentry = rootdir;
> >> +             else
> >> +                     pdentry = orphandir;
> >> +     else
> >> +             if (parent->dentry)
> >> +                     pdentry = parent->dentry;
> >> +             else
> >> +                     goto out;
> >> +
> >> +     ret = clk_debug_create_subtree(clk, pdentry);
> >> +
> >> +out:
> >> +     return ret;
> >> +}
> >> +
> >> +/**
> >> + * clk_debug_init - lazily create the debugfs clk tree visualization
> >> + *
> >> + * clks are often initialized very early during boot before memory can
> >> + * be dynamically allocated and well before debugfs is setup.
> >> + * clk_debug_init walks the clk tree hierarchy while holding
> >> + * prepare_lock and creates the topology as part of a late_initcall,
> >> + * thus insuring that clks initialized very early will still be
> >> + * represented in the debugfs clk tree.  This function should only be
> >> + * called once at boot-time, and all other clks added dynamically will
> >> + * be done so with clk_debug_register.
> >> + */
> >> +static int __init clk_debug_init(void)
> >> +{
> >> +     struct clk *clk;
> >> +     struct hlist_node *tmp;
> >> +
> >> +     rootdir = debugfs_create_dir("clk", NULL);
> >> +
> >> +     if (!rootdir)
> >> +             return -ENOMEM;
> >> +
> >> +     orphandir = debugfs_create_dir("orphans", rootdir);
> >> +
> >> +     if (!orphandir)
> >> +             return -ENOMEM;
> >> +
> >> +     mutex_lock(&prepare_lock);
> >> +
> >> +     hlist_for_each_entry(clk, tmp, &clk_root_list, child_node)
> >> +             clk_debug_create_subtree(clk, rootdir);
> >> +
> >> +     hlist_for_each_entry(clk, tmp, &clk_orphan_list, child_node)
> >> +             clk_debug_create_subtree(clk, orphandir);
> >> +
> >> +     inited = 1;
> >> +
> >> +     mutex_unlock(&prepare_lock);
> >> +
> >> +     return 0;
> >> +}
> >> +late_initcall(clk_debug_init);
> >> +#else
> >> +static inline int clk_debug_register(struct clk *clk) { return 0; }
> >> +#endif /* CONFIG_COMMON_CLK_DEBUG */
> >> +
> >> +/***    helper functions   ***/
> >> +
> >> +inline const char *__clk_get_name(struct clk *clk)
> >> +{
> >> +     return !clk ? NULL : clk->name;
> >> +}
> >> +
> >> +inline struct clk_hw *__clk_get_hw(struct clk *clk)
> >> +{
> >> +     return !clk ? NULL : clk->hw;
> >> +}
> >> +
> >> +inline u8 __clk_get_num_parents(struct clk *clk)
> >> +{
> >> +     return !clk ? -EINVAL : clk->num_parents;
> >> +}
> >> +
> >> +inline struct clk *__clk_get_parent(struct clk *clk)
> >> +{
> >> +     return !clk ? NULL : clk->parent;
> >> +}
> >> +
> >> +inline unsigned long __clk_get_rate(struct clk *clk)
> >> +{
> >> +     return !clk ? -EINVAL : clk->rate;
> >> +}
> >> +
> >> +inline unsigned long __clk_get_flags(struct clk *clk)
> >> +{
> >> +     return !clk ? -EINVAL : clk->flags;
> >> +}
> >> +
> >> +static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
> >> +{
> >> +     struct clk *child;
> >> +     struct clk *ret;
> >> +     struct hlist_node *tmp;
> >> +
> >> +     if (!strcmp(clk->name, name))
> >> +             return clk;
> >> +
> >> +     hlist_for_each_entry(child, tmp, &clk->children, child_node) {
> >> +             ret = __clk_lookup_subtree(name, child);
> >> +             if (ret)
> >> +                     return ret;
> >> +     }
> >> +
> >> +     return NULL;
> >> +}
> >> +
> >> +struct clk *__clk_lookup(const char *name)
> >> +{
> >> +     struct clk *root_clk;
> >> +     struct clk *ret;
> >> +     struct hlist_node *tmp;
> >> +
> >
> > This should have a check for NULL pointers. NULL pointers can happen
> > here if a mux has holes in it. In this case the parent name array would
> > look like this:
> >
> > { "parentclk1", "parentclk2", NULL /* reserved */, "parentclk3" }
> >
> > Without checking for NULL pointers we dereference the NULL pointer here.
> 
> I will add the check.  I had not considered having NULL as one of the
> parent names.  It seems to me that the only time this would happen is
> if we are wiring up discrete devices.  For instance:
> 
> Device A has a fixed-rate clock named "dpll"
> Device B has a mux clock named "leaf" with parent_names = { "32k",
> "oscillator", "clkin" }
> 
> On a given board, leaf's "pll" parent might map to the output of the
> dpll clock.  I had considered that DT would step in here by creating
> an intermediate clock with no functional clk_ops that would "connect"
> these two clocks.  The benefit of this is that it is easier to match
> up clock names when staring at some data sheets.  It is common for a
> downstream device's data sheets to assign names to the external inputs
> originating from some unknown device; unsurprisingly the data sheet
> for the device supplying the external upstream clocks often has
> different names for the output signals than the one in the downstream
> device's data sheet.  Using the method described above it is easy for
> a person with both data sheets to see how the devices are wired up
> since all of the clock names are represented by nodes in the clock
> tree.  In short, the final outcome would looking something like:
> 
> dpll (device a's driver registered this clock)
>   |
> clkin (one of device b's possible parents)
>   |    (it is a dummy clock from DT since it is board-level topology)
>   |
> leaf (device b's driver registered this clock)
> 
> clkin would have a single parent named "dpll" in this case, and again,
> it would have no meaningful clk_ops.
> 
> A caveat to the above scenario is that parent_names shouldn't have
> holes in it, but a null pointer check is reasonable anyways.
> 
> What do you think?  Even if we allow for muxes to have holes in
> parent_names we'll still have to solve these sort of device
> integration issues and DT will likely play a roll here.  I'll roll in
> the null pointer check regardless.
> 
> Also, do you forsee needing hole in parent_names for any reason other
> than described above?

I need it only for the case where a some values in the mux are marked as
reserved in the datasheet or we simply do not have the corresponding
clock in our tree (yet). We could also say that NULL pointers are not
allowed in parent arrays, but instead "orphan" or "dummy" should be
used. Then __clk_init should check for NULL pointers to make this clear.

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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-14  8:48       ` Sascha Hauer
@ 2012-03-14 20:47         ` Turquette, Mike
  2012-03-14 21:28           ` Thomas Gleixner
  0 siblings, 1 reply; 51+ messages in thread
From: Turquette, Mike @ 2012-03-14 20:47 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Russell King, Andrew Lunn, linaro-dev, Grant Likely,
	Saravana Kannan, Jeremy Kerr, Magnus Damm, Deepak Saxena,
	linux-arm-kernel, Arnd Bergman, patches, Rob Herring,
	Thomas Gleixner, Richard Zhao, Shawn Guo, Paul Walmsley,
	Linus Walleij, Mark Brown, Stephen Boyd, linux-kernel,
	Amit Kucheria

On Wed, Mar 14, 2012 at 1:48 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Tue, Mar 13, 2012 at 04:43:57PM -0700, Turquette, Mike wrote:
>> On Tue, Mar 13, 2012 at 4:24 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
>> > On Sat, Mar 03, 2012 at 12:29:00AM -0800, Mike Turquette wrote:
>> >> The common clock framework defines a common struct clk useful across
>> >> most platforms as well as an implementation of the clk api that drivers
>> >> can use safely for managing clocks.
>> >>
>> >> The net result is consolidation of many different struct clk definitions
>> >> and platform-specific clock framework implementations.
>> >>
>> >> This patch introduces the common struct clk, struct clk_ops and an
>> >> implementation of the well-known clock api in include/clk/clk.h.
>> >> Platforms may define their own hardware-specific clock structure and
>> >> their own clock operation callbacks, so long as it wraps an instance of
>> >> struct clk_hw.
>> >>
>> >> See Documentation/clk.txt for more details.
>> >>
>> >> This patch is based on the work of Jeremy Kerr, which in turn was based
>> >> on the work of Ben Herrenschmidt.
>> >>
>> >> Signed-off-by: Mike Turquette <mturquette@linaro.org>
>> >> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> >> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
>> >> Cc: Thomas Gleixner <tglx@linutronix.de>
>> >> Cc: Arnd Bergman <arnd.bergmann@linaro.org>
>> >> Cc: Paul Walmsley <paul@pwsan.com>
>> >> Cc: Shawn Guo <shawn.guo@freescale.com>
>> >> Cc: Richard Zhao <richard.zhao@linaro.org>
>> >> Cc: Saravana Kannan <skannan@codeaurora.org>
>> >> Cc: Magnus Damm <magnus.damm@gmail.com>
>> >> Cc: Rob Herring <rob.herring@calxeda.com>
>> >> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> >> Cc: Linus Walleij <linus.walleij@stericsson.com>
>> >> Cc: Stephen Boyd <sboyd@codeaurora.org>
>> >> Cc: Amit Kucheria <amit.kucheria@linaro.org>
>> >> Cc: Deepak Saxena <dsaxena@linaro.org>
>> >> Cc: Grant Likely <grant.likely@secretlab.ca>
>> >> Cc: Andrew Lunn <andrew@lunn.ch>
>> >> ---
>> >>  drivers/clk/Kconfig          |   28 +
>> >>  drivers/clk/Makefile         |    1 +
>> >>  drivers/clk/clk.c            | 1323 ++++++++++++++++++++++++++++++++++++++++++
>> >>  include/linux/clk-private.h  |   68 +++
>> >>  include/linux/clk-provider.h |  169 ++++++
>> >>  include/linux/clk.h          |   68 ++-
>> >>  6 files changed, 1652 insertions(+), 5 deletions(-)
>> >>  create mode 100644 drivers/clk/clk.c
>> >>  create mode 100644 include/linux/clk-private.h
>> >>  create mode 100644 include/linux/clk-provider.h
>> >>
>> >> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
>> >> index 3912576..18eb8c2 100644
>> >> --- a/drivers/clk/Kconfig
>> >> +++ b/drivers/clk/Kconfig
>> >> @@ -11,3 +11,31 @@ config HAVE_MACH_CLKDEV
>> >>
>> >>  config HAVE_CLK_PREPARE
>> >>       bool
>> >> +
>> >> +menuconfig COMMON_CLK
>> >> +     bool "Common Clock Framework"
>> >> +     select HAVE_CLK_PREPARE
>> >> +     ---help---
>> >> +       The common clock framework is a single definition of struct
>> >> +       clk, useful across many platforms, as well as an
>> >> +       implementation of the clock API in include/linux/clk.h.
>> >> +       Architectures utilizing the common struct clk should select
>> >> +       this automatically, but it may be necessary to manually select
>> >> +       this option for loadable modules requiring the common clock
>> >> +       framework.
>> >> +
>> >> +       If in doubt, say "N".
>> >> +
>> >> +if COMMON_CLK
>> >> +
>> >> +config COMMON_CLK_DEBUG
>> >> +     bool "DebugFS representation of clock tree"
>> >> +     depends on COMMON_CLK
>> >> +     ---help---
>> >> +       Creates a directory hierchy in debugfs for visualizing the clk
>> >> +       tree structure.  Each directory contains read-only members
>> >> +       that export information specific to that clk node: clk_rate,
>> >> +       clk_flags, clk_prepare_count, clk_enable_count &
>> >> +       clk_notifier_count.
>> >> +
>> >> +endif
>> >> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> >> index 07613fa..ff362c4 100644
>> >> --- a/drivers/clk/Makefile
>> >> +++ b/drivers/clk/Makefile
>> >> @@ -1,2 +1,3 @@
>> >>
>> >>  obj-$(CONFIG_CLKDEV_LOOKUP)  += clkdev.o
>> >> +obj-$(CONFIG_COMMON_CLK)     += clk.o
>> >> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>> >> new file mode 100644
>> >> index 0000000..b979d74
>> >> --- /dev/null
>> >> +++ b/drivers/clk/clk.c
>> >> @@ -0,0 +1,1323 @@
>> >> +/*
>> >> + * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
>> >> + * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org>
>> >> + *
>> >> + * 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.  See Documentation/clk.txt
>> >> + */
>> >> +
>> >> +#include <linux/clk-private.h>
>> >> +#include <linux/module.h>
>> >> +#include <linux/mutex.h>
>> >> +#include <linux/spinlock.h>
>> >> +#include <linux/err.h>
>> >> +#include <linux/list.h>
>> >> +#include <linux/slab.h>
>> >> +
>> >> +static DEFINE_SPINLOCK(enable_lock);
>> >> +static DEFINE_MUTEX(prepare_lock);
>> >> +
>> >> +static HLIST_HEAD(clk_root_list);
>> >> +static HLIST_HEAD(clk_orphan_list);
>> >> +static LIST_HEAD(clk_notifier_list);
>> >> +
>> >> +/***        debugfs support        ***/
>> >> +
>> >> +#ifdef CONFIG_COMMON_CLK_DEBUG
>> >> +#include <linux/debugfs.h>
>> >> +
>> >> +static struct dentry *rootdir;
>> >> +static struct dentry *orphandir;
>> >> +static int inited = 0;
>> >> +
>> >> +/* caller must hold prepare_lock */
>> >> +static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
>> >> +{
>> >> +     struct dentry *d;
>> >> +     int ret = -ENOMEM;
>> >> +
>> >> +     if (!clk || !pdentry) {
>> >> +             ret = -EINVAL;
>> >> +             goto out;
>> >> +     }
>> >> +
>> >> +     d = debugfs_create_dir(clk->name, pdentry);
>> >> +     if (!d)
>> >> +             goto out;
>> >> +
>> >> +     clk->dentry = d;
>> >> +
>> >> +     d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry,
>> >> +                     (u32 *)&clk->rate);
>> >> +     if (!d)
>> >> +             goto err_out;
>> >> +
>> >> +     d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
>> >> +                     (u32 *)&clk->flags);
>> >> +     if (!d)
>> >> +             goto err_out;
>> >> +
>> >> +     d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry,
>> >> +                     (u32 *)&clk->prepare_count);
>> >> +     if (!d)
>> >> +             goto err_out;
>> >> +
>> >> +     d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry,
>> >> +                     (u32 *)&clk->enable_count);
>> >> +     if (!d)
>> >> +             goto err_out;
>> >> +
>> >> +     d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry,
>> >> +                     (u32 *)&clk->notifier_count);
>> >> +     if (!d)
>> >> +             goto err_out;
>> >> +
>> >> +     ret = 0;
>> >> +     goto out;
>> >> +
>> >> +err_out:
>> >> +     debugfs_remove(clk->dentry);
>> >> +out:
>> >> +     return ret;
>> >> +}
>> >> +
>> >> +/* caller must hold prepare_lock */
>> >> +static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
>> >> +{
>> >> +     struct clk *child;
>> >> +     struct hlist_node *tmp;
>> >> +     int ret = -EINVAL;;
>> >> +
>> >> +     if (!clk || !pdentry)
>> >> +             goto out;
>> >> +
>> >> +     ret = clk_debug_create_one(clk, pdentry);
>> >> +
>> >> +     if (ret)
>> >> +             goto out;
>> >> +
>> >> +     hlist_for_each_entry(child, tmp, &clk->children, child_node)
>> >> +             clk_debug_create_subtree(child, clk->dentry);
>> >> +
>> >> +     ret = 0;
>> >> +out:
>> >> +     return ret;
>> >> +}
>> >> +
>> >> +/**
>> >> + * clk_debug_register - add a clk node to the debugfs clk tree
>> >> + * @clk: the clk being added to the debugfs clk tree
>> >> + *
>> >> + * Dynamically adds a clk to the debugfs clk tree if debugfs has been
>> >> + * initialized.  Otherwise it bails out early since the debugfs clk tree
>> >> + * will be created lazily by clk_debug_init as part of a late_initcall.
>> >> + *
>> >> + * Caller must hold prepare_lock.  Only clk_init calls this function (so
>> >> + * far) so this is taken care.
>> >> + */
>> >> +static int clk_debug_register(struct clk *clk)
>> >> +{
>> >> +     struct clk *parent;
>> >> +     struct dentry *pdentry;
>> >> +     int ret = 0;
>> >> +
>> >> +     if (!inited)
>> >> +             goto out;
>> >> +
>> >> +     parent = clk->parent;
>> >> +
>> >> +     /*
>> >> +      * Check to see if a clk is a root clk.  Also check that it is
>> >> +      * safe to add this clk to debugfs
>> >> +      */
>> >> +     if (!parent)
>> >> +             if (clk->flags & CLK_IS_ROOT)
>> >> +                     pdentry = rootdir;
>> >> +             else
>> >> +                     pdentry = orphandir;
>> >> +     else
>> >> +             if (parent->dentry)
>> >> +                     pdentry = parent->dentry;
>> >> +             else
>> >> +                     goto out;
>> >> +
>> >> +     ret = clk_debug_create_subtree(clk, pdentry);
>> >> +
>> >> +out:
>> >> +     return ret;
>> >> +}
>> >> +
>> >> +/**
>> >> + * clk_debug_init - lazily create the debugfs clk tree visualization
>> >> + *
>> >> + * clks are often initialized very early during boot before memory can
>> >> + * be dynamically allocated and well before debugfs is setup.
>> >> + * clk_debug_init walks the clk tree hierarchy while holding
>> >> + * prepare_lock and creates the topology as part of a late_initcall,
>> >> + * thus insuring that clks initialized very early will still be
>> >> + * represented in the debugfs clk tree.  This function should only be
>> >> + * called once at boot-time, and all other clks added dynamically will
>> >> + * be done so with clk_debug_register.
>> >> + */
>> >> +static int __init clk_debug_init(void)
>> >> +{
>> >> +     struct clk *clk;
>> >> +     struct hlist_node *tmp;
>> >> +
>> >> +     rootdir = debugfs_create_dir("clk", NULL);
>> >> +
>> >> +     if (!rootdir)
>> >> +             return -ENOMEM;
>> >> +
>> >> +     orphandir = debugfs_create_dir("orphans", rootdir);
>> >> +
>> >> +     if (!orphandir)
>> >> +             return -ENOMEM;
>> >> +
>> >> +     mutex_lock(&prepare_lock);
>> >> +
>> >> +     hlist_for_each_entry(clk, tmp, &clk_root_list, child_node)
>> >> +             clk_debug_create_subtree(clk, rootdir);
>> >> +
>> >> +     hlist_for_each_entry(clk, tmp, &clk_orphan_list, child_node)
>> >> +             clk_debug_create_subtree(clk, orphandir);
>> >> +
>> >> +     inited = 1;
>> >> +
>> >> +     mutex_unlock(&prepare_lock);
>> >> +
>> >> +     return 0;
>> >> +}
>> >> +late_initcall(clk_debug_init);
>> >> +#else
>> >> +static inline int clk_debug_register(struct clk *clk) { return 0; }
>> >> +#endif /* CONFIG_COMMON_CLK_DEBUG */
>> >> +
>> >> +/***    helper functions   ***/
>> >> +
>> >> +inline const char *__clk_get_name(struct clk *clk)
>> >> +{
>> >> +     return !clk ? NULL : clk->name;
>> >> +}
>> >> +
>> >> +inline struct clk_hw *__clk_get_hw(struct clk *clk)
>> >> +{
>> >> +     return !clk ? NULL : clk->hw;
>> >> +}
>> >> +
>> >> +inline u8 __clk_get_num_parents(struct clk *clk)
>> >> +{
>> >> +     return !clk ? -EINVAL : clk->num_parents;
>> >> +}
>> >> +
>> >> +inline struct clk *__clk_get_parent(struct clk *clk)
>> >> +{
>> >> +     return !clk ? NULL : clk->parent;
>> >> +}
>> >> +
>> >> +inline unsigned long __clk_get_rate(struct clk *clk)
>> >> +{
>> >> +     return !clk ? -EINVAL : clk->rate;
>> >> +}
>> >> +
>> >> +inline unsigned long __clk_get_flags(struct clk *clk)
>> >> +{
>> >> +     return !clk ? -EINVAL : clk->flags;
>> >> +}
>> >> +
>> >> +static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
>> >> +{
>> >> +     struct clk *child;
>> >> +     struct clk *ret;
>> >> +     struct hlist_node *tmp;
>> >> +
>> >> +     if (!strcmp(clk->name, name))
>> >> +             return clk;
>> >> +
>> >> +     hlist_for_each_entry(child, tmp, &clk->children, child_node) {
>> >> +             ret = __clk_lookup_subtree(name, child);
>> >> +             if (ret)
>> >> +                     return ret;
>> >> +     }
>> >> +
>> >> +     return NULL;
>> >> +}
>> >> +
>> >> +struct clk *__clk_lookup(const char *name)
>> >> +{
>> >> +     struct clk *root_clk;
>> >> +     struct clk *ret;
>> >> +     struct hlist_node *tmp;
>> >> +
>> >
>> > This should have a check for NULL pointers. NULL pointers can happen
>> > here if a mux has holes in it. In this case the parent name array would
>> > look like this:
>> >
>> > { "parentclk1", "parentclk2", NULL /* reserved */, "parentclk3" }
>> >
>> > Without checking for NULL pointers we dereference the NULL pointer here.
>>
>> I will add the check.  I had not considered having NULL as one of the
>> parent names.  It seems to me that the only time this would happen is
>> if we are wiring up discrete devices.  For instance:
>>
>> Device A has a fixed-rate clock named "dpll"
>> Device B has a mux clock named "leaf" with parent_names = { "32k",
>> "oscillator", "clkin" }
>>
>> On a given board, leaf's "pll" parent might map to the output of the
>> dpll clock.  I had considered that DT would step in here by creating
>> an intermediate clock with no functional clk_ops that would "connect"
>> these two clocks.  The benefit of this is that it is easier to match
>> up clock names when staring at some data sheets.  It is common for a
>> downstream device's data sheets to assign names to the external inputs
>> originating from some unknown device; unsurprisingly the data sheet
>> for the device supplying the external upstream clocks often has
>> different names for the output signals than the one in the downstream
>> device's data sheet.  Using the method described above it is easy for
>> a person with both data sheets to see how the devices are wired up
>> since all of the clock names are represented by nodes in the clock
>> tree.  In short, the final outcome would looking something like:
>>
>> dpll (device a's driver registered this clock)
>>   |
>> clkin (one of device b's possible parents)
>>   |    (it is a dummy clock from DT since it is board-level topology)
>>   |
>> leaf (device b's driver registered this clock)
>>
>> clkin would have a single parent named "dpll" in this case, and again,
>> it would have no meaningful clk_ops.
>>
>> A caveat to the above scenario is that parent_names shouldn't have
>> holes in it, but a null pointer check is reasonable anyways.
>>
>> What do you think?  Even if we allow for muxes to have holes in
>> parent_names we'll still have to solve these sort of device
>> integration issues and DT will likely play a roll here.  I'll roll in
>> the null pointer check regardless.
>>
>> Also, do you forsee needing hole in parent_names for any reason other
>> than described above?
>
> I need it only for the case where a some values in the mux are marked as
> reserved in the datasheet or we simply do not have the corresponding
> clock in our tree (yet). We could also say that NULL pointers are not
> allowed in parent arrays, but instead "orphan" or "dummy" should be
> used. Then __clk_init should check for NULL pointers to make this clear.

I've added a WARN in __clk_init if any entries in .parent_names are
NULL.  I think it best to populate it with "dummy", or maybe a
platform-specific name if it helps you during development.

Regards,
Mike

>
> 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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-14 20:47         ` Turquette, Mike
@ 2012-03-14 21:28           ` Thomas Gleixner
  2012-03-14 22:13             ` Turquette, Mike
  0 siblings, 1 reply; 51+ messages in thread
From: Thomas Gleixner @ 2012-03-14 21:28 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Sascha Hauer, Russell King, Andrew Lunn, linaro-dev,
	Grant Likely, Saravana Kannan, Jeremy Kerr, Magnus Damm,
	Deepak Saxena, linux-arm-kernel, Arnd Bergman, patches,
	Rob Herring, Richard Zhao, Shawn Guo, Paul Walmsley,
	Linus Walleij, Mark Brown, Stephen Boyd, linux-kernel,
	Amit Kucheria

On Wed, 14 Mar 2012, Turquette, Mike wrote:

Could you folks please trim your replies? It's annoying to page down a
gazillion of lines to find the gist.

> On Wed, Mar 14, 2012 at 1:48 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> >> Also, do you forsee needing hole in parent_names for any reason other
> >> than described above?
> >
> > I need it only for the case where a some values in the mux are marked as
> > reserved in the datasheet or we simply do not have the corresponding
> > clock in our tree (yet). We could also say that NULL pointers are not
> > allowed in parent arrays, but instead "orphan" or "dummy" should be
> > used. Then __clk_init should check for NULL pointers to make this clear.
> 
> I've added a WARN in __clk_init if any entries in .parent_names are
> NULL.  I think it best to populate it with "dummy", or maybe a
> platform-specific name if it helps you during development.

There is no guarantee that the selection of a parent can be mapped
linear to register values.

So the right way to deal with it is to have an array of valid names
with no holes and NULL pointers allowed and have a mapping from the
array index to the register value.

That makes the core code robust and allows to handle all corner cases
including reserved bits, not implemented clocks and weird register
layouts.

Thanks,

	tglx

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-14 21:28           ` Thomas Gleixner
@ 2012-03-14 22:13             ` Turquette, Mike
  2012-03-14 22:18               ` Thomas Gleixner
  0 siblings, 1 reply; 51+ messages in thread
From: Turquette, Mike @ 2012-03-14 22:13 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Sascha Hauer, Russell King, Andrew Lunn, linaro-dev,
	Grant Likely, Saravana Kannan, Jeremy Kerr, Magnus Damm,
	Deepak Saxena, linux-arm-kernel, Arnd Bergman, patches,
	Rob Herring, Richard Zhao, Shawn Guo, Paul Walmsley,
	Linus Walleij, Mark Brown, Stephen Boyd, linux-kernel,
	Amit Kucheria

On Wed, Mar 14, 2012 at 2:28 PM, Thomas Gleixner <tglx@linutronix.de> wrote:
> On Wed, 14 Mar 2012, Turquette, Mike wrote:
>
> Could you folks please trim your replies? It's annoying to page down a
> gazillion of lines to find the gist.

Sure.  My mailer does this for me so I forget to do it sometimes...

>> On Wed, Mar 14, 2012 at 1:48 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
>> >> Also, do you forsee needing hole in parent_names for any reason other
>> >> than described above?
>> >
>> > I need it only for the case where a some values in the mux are marked as
>> > reserved in the datasheet or we simply do not have the corresponding
>> > clock in our tree (yet). We could also say that NULL pointers are not
>> > allowed in parent arrays, but instead "orphan" or "dummy" should be
>> > used. Then __clk_init should check for NULL pointers to make this clear.
>>
>> I've added a WARN in __clk_init if any entries in .parent_names are
>> NULL.  I think it best to populate it with "dummy", or maybe a
>> platform-specific name if it helps you during development.
>
> There is no guarantee that the selection of a parent can be mapped
> linear to register values.

Agreed.  I have always viewed .parent_names as only a list of the
names of all possible parents, nothing more.  And of course its array
indexing should line up with struct clk **parents.

> So the right way to deal with it is to have an array of valid names
> with no holes and NULL pointers allowed and have a mapping from the
> array index to the register value.

This is essentially what the .set_rate callback does.  It takes as
input "u8 index" and peforms the hardware specific magic to select the
correct parent clock.  This might be a register write using that exact
same index, or it might be a single-bit register write using that
index as the shift value, or it might translate that index into the
data sent to an i2c device (where the address would be stored in
struct clk_foo), etc etc.

We both agree that .parent_names must contain valid names and should
not have holes.  What I don't understand is if you are saying that we
should allow NULL ptrs as names; that seems contradictory but I want
to make sure I'm reading you correctly.

Thanks,
Mike

> That makes the core code robust and allows to handle all corner cases
> including reserved bits, not implemented clocks and weird register
> layouts.
>
> Thanks,
>
>        tglx

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-14 22:13             ` Turquette, Mike
@ 2012-03-14 22:18               ` Thomas Gleixner
  0 siblings, 0 replies; 51+ messages in thread
From: Thomas Gleixner @ 2012-03-14 22:18 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Sascha Hauer, Russell King, Andrew Lunn, linaro-dev,
	Grant Likely, Saravana Kannan, Jeremy Kerr, Magnus Damm,
	Deepak Saxena, linux-arm-kernel, Arnd Bergman, patches,
	Rob Herring, Richard Zhao, Shawn Guo, Paul Walmsley,
	Linus Walleij, Mark Brown, Stephen Boyd, linux-kernel,
	Amit Kucheria

On Wed, 14 Mar 2012, Turquette, Mike wrote:
> On Wed, Mar 14, 2012 at 2:28 PM, Thomas Gleixner <tglx@linutronix.de> wrote:
> > So the right way to deal with it is to have an array of valid names
> > with no holes and NULL pointers allowed and have a mapping from the
> > array index to the register value.
> 
> This is essentially what the .set_rate callback does.  It takes as
> input "u8 index" and peforms the hardware specific magic to select the
> correct parent clock.  This might be a register write using that exact
> same index, or it might be a single-bit register write using that
> index as the shift value, or it might translate that index into the
> data sent to an i2c device (where the address would be stored in
> struct clk_foo), etc etc.
> 
> We both agree that .parent_names must contain valid names and should
> not have holes.  What I don't understand is if you are saying that we
> should allow NULL ptrs as names; that seems contradictory but I want
> to make sure I'm reading you correctly.

I should have said: no holes and no NULL pointers, just an array of
valid names.

Thanks,

	tglx

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-07 21:20                 ` Turquette, Mike
  2012-03-08  6:27                   ` Andrew Lunn
  2012-03-09  0:51                   ` Thomas Gleixner
@ 2012-03-17  3:23                   ` Saravana Kannan
  2012-03-19  5:38                     ` Shawn Guo
  2012-03-19  7:42                     ` Shawn Guo
  2 siblings, 2 replies; 51+ messages in thread
From: Saravana Kannan @ 2012-03-17  3:23 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Sascha Hauer, Jeremy Kerr, Andrew Lunn, Paul Walmsley,
	linaro-dev, Linus Walleij, linux-arm-kernel, patches,
	Magnus Damm, Mark Brown, Stephen Boyd, linux-kernel, Rob Herring,
	Grant Likely, Deepak Saxena, Amit Kucheria, Russell King,
	Thomas Gleixner, Richard Zhao, Shawn Guo, Arnd Bergman

On 03/07/2012 01:20 PM, Turquette, Mike wrote:
> On Tue, Mar 6, 2012 at 11:00 AM, Sascha Hauer<s.hauer@pengutronix.de>  wrote:
>> On Mon, Mar 05, 2012 at 12:03:15PM -0800, Turquette, Mike wrote:
>>> On Sun, Mar 4, 2012 at 11:38 PM, Sascha Hauer<s.hauer@pengutronix.de>  wrote:
>>>> On Sun, Mar 04, 2012 at 04:12:21PM -0800, Turquette, Mike wrote:
>>>>>>>
>>>>>>> I believe this patch already does what you suggest, but I might be
>>>>>>> missing your point.
>>>>>>
>>>>>> In include/linux/clk-private.h you expose struct clk outside the core.
>>>>>> This has to be done to make static initializers possible. There is a big
>>>>>> warning in this file that it must not be included from files implementing
>>>>>> struct clk_ops. You can simply avoid this warning by declaring struct clk
>>>>>> with only a single member:
>>>>>>
>>>>>> include/linux/clk.h:
>>>>>>
>>>>>> struct clk {
>>>>>>         struct clk_internal *internal;
>>>>>> };
>>>>>>
>>>>>> This way everybody knows struct clk (thus can embed it in their static
>>>>>> initializers), but doesn't know anything about the internal members. Now
>>>>>> in drivers/clk/clk.c you declare struct clk_internal exactly like struct
>>>>>> clk was declared before:
>>>>>>
>>>>>> struct clk_internal {
>>>>>>         const char              *name;
>>>>>>         const struct clk_ops    *ops;
>>>>>>         struct clk_hw           *hw;
>>>>>>         struct clk              *parent;
>>>>>>         char                    **parent_names;
>>>>>>         struct clk              **parents;
>>>>>>         u8                      num_parents;
>>>>>>         unsigned long           rate;
>>>>>>         unsigned long           flags;
>>>>>>         unsigned int            enable_count;
>>>>>>         unsigned int            prepare_count;
>>>>>>         struct hlist_head       children;
>>>>>>         struct hlist_node       child_node;
>>>>>>         unsigned int            notifier_count;
>>>>>> #ifdef CONFIG_COMMON_CLK_DEBUG
>>>>>>         struct dentry           *dentry;
>>>>>> #endif
>>>>>> };
>>>>>>
>>>>>> An instance of struct clk_internal will be allocated in
>>>>>> __clk_init/clk_register. Now the private data stays completely inside
>>>>>> the core and noone can abuse it.
>>>>>
>>>>> Hi Sascha,
>>>>>
>>>>> I see the disconnect here.  For OMAP (and possibly other platforms) at
>>>>> least some clock data is necessary during early boot, before the
>>>>> regular allocation methods are available (timers for instance).
>>>>
>>>> We had this problem on i.MX aswell. It turned out that the timer clock
>>>> is the only clock that is needed so early. We solved this by moving the
>>>> clock init to the system timer init function.
>>>
>>> When you say "mov[ed] the clock init to the system timer init
>>> function" do you mean that you statically allocated struct clk and
>>> used the clk framework api, or instead you just did some direct
>>> register writes to initialize things properly?
>>
>> I meant that on i.MX we do the clock tree initialization when kmalloc is
>> available, see the attached patch for omap4 based on your branch which
>> does the same for Omap. The first clock you need is the one for the
>> timer, so you can initialize the clocktree at the beginning of
>> time_init() and don't need statically initialized clocks anymore.
>>
>>>>
>>>> Well, the file is work in progress, you probably fix this before sending
>>>> it out, but I bet people will include clk-private.h and nobody else
>>>> notices it.
>>>
>>> clock44xx_data.c does not violate that rule.  None of the logic that
>>> implements ops for those clocks is present clock44xx_data.c.
>>
>> Indeed, I missed that. It only has the ops but not the individual
>> functions.
>>
>>> All of
>>> the code in that file is simply initialization and registration of
>>> OMAP4 clocks.  Many of the clocks are basic clock types (divider,
>>> multiplexer and fixed-rate are used in that file) with protected code
>>> drivers/clk/clk-*.c and the remaining clocks are of the struct
>>> clk_hw_omap variety, which has code spread across several files:
>>>
>>> arch/arm/mach-omap2/clock.c
>>> arch/arm/mach-omap2/clock.h
>>> arch/arm/mach-omap2/clkt_dpll.c
>>> arch/arm/mach-omap2/clkt_clksel.c
>>> arch/arm/mach-omap2/dpll3xxx.c
>>> arch/arm/mach-omap2/dpll4xxx.c
>>>
>>> All of the above files include linux/clk-provider.h, not
>>> linux/clk-private.h.  That code makes heavy use of the
>>> __clk_get_whatever helpers and shows how a platform might honor the
>>> layer of separation between struct clk and stuct clk_ops/struct
>>> clk_foo.  You are correct that the code is a work-in-progress, but
>>> there are no layering violations that I can see.
>>>
>>> I also think we are talking past each other to some degree.  One point
>>> I would like to make (and maybe you already know this from code
>>> review) is that it is unnecessary to have pointers to your parent
>>> struct clk*'s when either initializing or registering your clocks.  In
>>> fact the existing clk_register_foo functions don't even allow you to
>>> pass in parent pointers and rely wholly on string name matching.  I
>>> just wanted to point that out in case it went unnoticed, as it is a
>>> new way of doing things from the previous series and was born out of
>>> Thomas' review of V4 and multi-parent handling.  This also keeps
>>> device-tree in mind where we might not know the struct clk *pointer at
>>> compile time for "connecting" discrete devices.
>>
>> Yes, I've seen this and I really like it. Also the change that
>> multiplexers return an index to an array instead of the parent
>> clock is very nice.
>>
>> Sascha
>>
>>
>> 8<-----------------------------------------------------
>>
>> ARM omap4: move clocktree init to timer init time so we don't need static clocks
>>
>> Signed-off-by: Sascha Hauer<s.hauer@pengutronix.de>
>

Hi Mike,

I already took a quick look at the v7 series, but I thought this thread 
has more relevant context for my response. So, responding here.

I'm with Sascha on creating a clk_internal/clk_initializer and removing 
clk_hw. You had asked about the benefits of his suggestion in one of the 
earlier threads. I'm sure I have told some of these reasons I don't like 
clk_hw, but repeating my points here for others to chime in.

I used to be a huge proponent for using macros for clocks in our 
internal tree. All the clocks were constructed using macros (you will 
see it in the history of tree we publish in CAF). They quickly became 
unreadable when you have several hundreds of clocks. The biggest problem 
is that you can't quickly look at a clock's macro and figure out what 
the register offset or bit mask or shift value is. Our eyes/brains 
aren't meant for quickly parsing the commas and finding the n-th field 
or even remembering what the n-th field of each macro corresponds to. If 
it's actually broken out as fields in a struct, it's much easier to 
read. So, long story short, I think the well-intentioned helper macros 
will make code quite unreadable.

I also don't want to maintain such helper macros for the platform 
specific clock types that I will have to create for MSM if I were to go 
with macros.

If I choose not to use the helper macros, then I need to define three 
separate declarations for each clock. That looks messy when you have 
100s of clocks.

With clk_initializer, we also don't have to keep changing the 
clk_init/clk_register APIs whenever we add any other optional fields in 
the future. You just add it to clk_initializer and if people care for 
those fields, they can add it to the static/dynamic clocks.

Whether we use a macro or not, the current approach also adds twice the 
the no. of symbols in the debug info and increases the size of the 
kernel. When we go for a single ARM kernel, this is going to be 
noticeable. I agree that the point about debuginfo size increase might 
not matter to most.

> Hi Sascha,
>
> Thanks for the example code.  This is in fact something I had
> considered doing before, but it is a bit complicated for my platform.
>
> We set up all of the OMAP clocks with __clk_init because this is a
> dependency of OMAP's hwmod code which models and interacts with
> specific resources for hardware modules, such as clocks.  There are
> other dependencies such as our clockdomain code, which needs the
> clocks to be fully initialized.  Some aspects of these layers get
> init'd before we can allocate memory.

I know there is a version of OMAP hwmod in upstream, but is this 
dependency of fully initialized clock struct a requirement for the 
upstream version of hwmod or an internal OMAP tree? I will explain the 
reason for this question further down.

> Admittedly I think that the OMAP code could migrate some of these bits
> to a lazy-registration model, specifically the hwmod object instances,
> but that requires an awful lot of refactoring for a fairly large stack
> of platform code.  This might be something to achieve in the future
> but for now we *need* initialisation to be fully static.

When we work on moving clocks to device tree, wouldn't you face the same 
problem? You will have to dynamically create most of the clocks in that 
case too.

> Assuming that some day OMAP code can be refactored to allow for lazy
> (or at least initcall-based) registration of clocks then perhaps your
> suggestion can take root.  Which leads me to this question: are there
> any other platforms out there that require the level of expose to
> struct clk present in this patchset?  OMAP does, for now, but if that
> changes then I need to know if others require this as well.

MSM platform doesn't need exposure to clk_internal or the corresponding 
fields in clk. We too have the timer issue, but I would rather deal with 
the timer separately (using register writes from the timer code) than 
ugly up the 200+ clocks we have on each SoC.

Getting to suggesting a solution, how about we go with something similar 
to Sasha's suggestion:
* Put clk_inititalizer in clk-provider.h
* clk-provider.h has a forward declaration to clk (struct clk;)
* Put struct clk and struct clk_internal in a clk-private.h or whatever.
* Add a struct *clk field to struct clk_initializer (this is temporary).


For platforms that don't have the static init limitations you mention, 
they can do something like this:

#include <linux/clk-provider.h>

struct clk_complex {
	struct clk_initializer i;
	u32 foo;
	u32 bar;
	u8 baz;
};

struct clk_complex mmc1_clk {
	foo = 5,
	bar = 10,
	baz = 3,
	. i = {
		.name = mmc,
		.ops = &complex_ops,
	}
};

clk_register(NULL, &mmc1_clk.i);

But platforms that have the limitations you mention can do something like:

#include <clk-provider.h>
#include <clk-private.h>

struct clk __mmc1_clk;

struct clk_complex mmc1_clk {
	foo = 5,
	bar = 10,
	baz = 3,
	. i = {
		.name = mmc,
		.ops = &complex_ops,
		.clk = &__mmc1_clk;
	}
};

clk_init(NULL, &mmc1_clk.i);

I guess another way to look at this is: move all the inputs params in 
clk_register() to clk_hw and rename clk_hw to clk_initializer.

With the above solutions, those that don't have the OMAP-like 
limitations can have their code look much cleaner, and OMAP can still 
continue to work. After the initial conversion of all platform to the 
common clock framework, we don't allow anyone to ever include 
clk-private.h. We could even add it to check_patch.pl. Then once 
everyone fixes their static initialization limitations, we can delete 
the clk field from clk_initializer and move struct clk to clk.c.

Thoughts?

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] 51+ messages in thread

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-17  3:23                   ` Saravana Kannan
@ 2012-03-19  5:38                     ` Shawn Guo
  2012-03-19  7:42                     ` Shawn Guo
  1 sibling, 0 replies; 51+ messages in thread
From: Shawn Guo @ 2012-03-19  5:38 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Turquette, Mike, Sascha Hauer, Jeremy Kerr, Andrew Lunn,
	Paul Walmsley, linaro-dev, Linus Walleij, linux-arm-kernel,
	patches, Magnus Damm, Mark Brown, Stephen Boyd, linux-kernel,
	Rob Herring, Grant Likely, Deepak Saxena, Amit Kucheria,
	Russell King, Thomas Gleixner, Richard Zhao, Shawn Guo,
	Arnd Bergman

On Fri, Mar 16, 2012 at 08:23:57PM -0700, Saravana Kannan wrote:
...
> Hi Mike,
> 
> I already took a quick look at the v7 series, but I thought this
> thread has more relevant context for my response. So, responding
> here.
> 
> I'm with Sascha on creating a clk_internal/clk_initializer and
> removing clk_hw. You had asked about the benefits of his suggestion
> in one of the earlier threads. I'm sure I have told some of these
> reasons I don't like clk_hw, but repeating my points here for others
> to chime in.
> 
> I used to be a huge proponent for using macros for clocks in our
> internal tree. All the clocks were constructed using macros (you
> will see it in the history of tree we publish in CAF). They quickly
> became unreadable when you have several hundreds of clocks. The
> biggest problem is that you can't quickly look at a clock's macro
> and figure out what the register offset or bit mask or shift value
> is. Our eyes/brains aren't meant for quickly parsing the commas and
> finding the n-th field or even remembering what the n-th field of
> each macro corresponds to. If it's actually broken out as fields in
> a struct, it's much easier to read. So, long story short, I think
> the well-intentioned helper macros will make code quite unreadable.
> 
While I second the idea of clk_initializer, using macros is not really
the thing to complain.  You can save using those macro helpers by
calling APIs clk_register_*().  But that does not solve the problem,
because those APIs also have a long argument list to fill.

-- 
Regards,
Shawn

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-09 18:25                         ` Turquette, Mike
@ 2012-03-19  7:01                           ` Shawn Guo
  2012-03-19 11:22                             ` Sascha Hauer
  0 siblings, 1 reply; 51+ messages in thread
From: Shawn Guo @ 2012-03-19  7:01 UTC (permalink / raw)
  To: Turquette, Mike
  Cc: Sascha Hauer, Andrew Lunn, Paul Walmsley, linaro-dev,
	Linus Walleij, patches, Stephen Boyd, Mark Brown, Magnus Damm,
	linux-kernel, Rob Herring, Richard Zhao, Grant Likely,
	Deepak Saxena, Saravana Kannan, Thomas Gleixner, Shawn Guo,
	Amit Kucheria, Russell King, Jeremy Kerr, Arnd Bergman,
	linux-arm-kernel

On Fri, Mar 09, 2012 at 10:25:00AM -0800, Turquette, Mike wrote:
...
> However if you have the ability to use the clk_foo_register functions
> please do use them in place of static initialization.  The static init
> stuff is only for folks backed into a corner and forced to use it...
> for now.  I'm looking at ways to allow for kmalloc'ing in early boot,
> as well as reducing the number of clocks that my platform registers
> during early boot drastically.
> 
While I agree using registration functions rather than static
initialization will help make "struct clk" an opaque cookie, I also
see some benefit with using static initialization over registration
functions.  That is we will be able to initialize parents statically
rather than calling expensive __clk_lookup() to find them when using
registration functions.

I'm not sure if this will be a concern with the platforms that have
hundreds of clocks.  Keep it in mind, when we say one clock, there
are generally 3 clks behind it, clk_gate, clk_divider and clk_mux.

-- 
Regards,
Shawn

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-17  3:23                   ` Saravana Kannan
  2012-03-19  5:38                     ` Shawn Guo
@ 2012-03-19  7:42                     ` Shawn Guo
  1 sibling, 0 replies; 51+ messages in thread
From: Shawn Guo @ 2012-03-19  7:42 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Turquette, Mike, Sascha Hauer, Jeremy Kerr, Andrew Lunn,
	Paul Walmsley, linaro-dev, Linus Walleij, linux-arm-kernel,
	patches, Magnus Damm, Mark Brown, Stephen Boyd, linux-kernel,
	Rob Herring, Grant Likely, Deepak Saxena, Amit Kucheria,
	Russell King, Thomas Gleixner, Richard Zhao, Shawn Guo,
	Arnd Bergman

On Fri, Mar 16, 2012 at 08:23:57PM -0700, Saravana Kannan wrote:
> On 03/07/2012 01:20 PM, Turquette, Mike wrote:
...
> >Admittedly I think that the OMAP code could migrate some of these bits
> >to a lazy-registration model, specifically the hwmod object instances,
> >but that requires an awful lot of refactoring for a fairly large stack
> >of platform code.  This might be something to achieve in the future
> >but for now we *need* initialisation to be fully static.
> 
> When we work on moving clocks to device tree, wouldn't you face the
> same problem? You will have to dynamically create most of the clocks
> in that case too.
> 
>From what I heard from Mike[1], Omap will not have most of the clocks
encoded in device tree. 

Although my original preference was to have all the clocks represented
in device tree and dynamically registered to clk framework, I've heard
people including Grant incline to only have oscillator and leaf modules
clocks in device tree.  I somehow agree with that now, because having
all the clocks in there will bloat device tree dramatically, considering
there will be 3 clks, clk_gate, clk_divider and clk_mux backing one
clock in general.

Assuming we would agree to have most SoC internal clocks registered
from clock driver rather than device tree, I would like to hear about
how we should have these clock registered from clock driver, static
initialization or using register function?

-- 
Regards,
Shawn

[1] http://article.gmane.org/gmane.linux.linaro.devel/10554

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

* Re: [PATCH v5 3/4] clk: introduce the common clock framework
  2012-03-19  7:01                           ` Shawn Guo
@ 2012-03-19 11:22                             ` Sascha Hauer
  0 siblings, 0 replies; 51+ messages in thread
From: Sascha Hauer @ 2012-03-19 11:22 UTC (permalink / raw)
  To: Shawn Guo
  Cc: Turquette, Mike, Andrew Lunn, Paul Walmsley, linaro-dev,
	Linus Walleij, patches, Stephen Boyd, Mark Brown, Magnus Damm,
	linux-kernel, Rob Herring, Richard Zhao, Grant Likely,
	Deepak Saxena, Saravana Kannan, Thomas Gleixner, Shawn Guo,
	Amit Kucheria, Russell King, Jeremy Kerr, Arnd Bergman,
	linux-arm-kernel

On Mon, Mar 19, 2012 at 03:01:17PM +0800, Shawn Guo wrote:
> On Fri, Mar 09, 2012 at 10:25:00AM -0800, Turquette, Mike wrote:
> ...
> > However if you have the ability to use the clk_foo_register functions
> > please do use them in place of static initialization.  The static init
> > stuff is only for folks backed into a corner and forced to use it...
> > for now.  I'm looking at ways to allow for kmalloc'ing in early boot,
> > as well as reducing the number of clocks that my platform registers
> > during early boot drastically.
> > 
> While I agree using registration functions rather than static
> initialization will help make "struct clk" an opaque cookie, I also
> see some benefit with using static initialization over registration
> functions.  That is we will be able to initialize parents statically
> rather than calling expensive __clk_lookup() to find them when using
> registration functions.
> 
> I'm not sure if this will be a concern with the platforms that have
> hundreds of clocks.  Keep it in mind, when we say one clock, there
> are generally 3 clks behind it, clk_gate, clk_divider and clk_mux.

On an i.MX51 with a fully dynamically allocated clock tree it takes
about 10ms to initialize the tree which I think is acceptable. The
clock tree is not complete, but I would think that about 70% of the
clocks are there.
Normally less performant platforms will have less clocks, so I assume
the times will be comparable.

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] 51+ messages in thread

end of thread, other threads:[~2012-03-19 11:23 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-03  8:28 [PATCH v5 0/4] common clk framework Mike Turquette
2012-03-03  8:28 ` [PATCH v5 1/4] Documentation: common clk API Mike Turquette
2012-03-03  8:28 ` [PATCH v5 2/4] clk: Kconfig: add entry for HAVE_CLK_PREPARE Mike Turquette
2012-03-05  2:04   ` Richard Zhao
2012-03-05 19:46     ` Turquette, Mike
2012-03-03  8:29 ` [PATCH v5 3/4] clk: introduce the common clock framework Mike Turquette
2012-03-03 13:31   ` Sascha Hauer
2012-03-03 17:14     ` Turquette, Mike
2012-03-04 11:52       ` Sascha Hauer
2012-03-05  0:12         ` Turquette, Mike
2012-03-05  7:38           ` Sascha Hauer
2012-03-05 20:03             ` Turquette, Mike
2012-03-06 19:00               ` Sascha Hauer
2012-03-07 21:20                 ` Turquette, Mike
2012-03-08  6:27                   ` Andrew Lunn
2012-03-08 23:25                     ` Sascha Hauer
2012-03-09  7:57                       ` Andrew Lunn
2012-03-09 18:25                         ` Turquette, Mike
2012-03-19  7:01                           ` Shawn Guo
2012-03-19 11:22                             ` Sascha Hauer
2012-03-09 18:18                     ` Turquette, Mike
2012-03-09  0:51                   ` Thomas Gleixner
2012-03-17  3:23                   ` Saravana Kannan
2012-03-19  5:38                     ` Shawn Guo
2012-03-19  7:42                     ` Shawn Guo
2012-03-05  9:22   ` Richard Zhao
2012-03-14  2:03     ` Turquette, Mike
2012-03-13 11:24   ` Sascha Hauer
2012-03-13 23:43     ` Turquette, Mike
2012-03-14  8:48       ` Sascha Hauer
2012-03-14 20:47         ` Turquette, Mike
2012-03-14 21:28           ` Thomas Gleixner
2012-03-14 22:13             ` Turquette, Mike
2012-03-14 22:18               ` Thomas Gleixner
2012-03-03  8:29 ` [PATCH v5 4/4] clk: basic clock hardware types Mike Turquette
2012-03-04 14:26   ` Andrew Lunn
2012-03-04 14:35   ` Andrew Lunn
2012-03-05  0:15     ` Turquette, Mike
2012-03-04 17:42   ` Andrew Lunn
2012-03-05  0:30     ` Turquette, Mike
2012-03-05  8:48       ` Andrew Lunn
2012-03-05  9:29         ` Sascha Hauer
2012-03-05 10:17           ` Andrew Lunn
2012-03-09 23:38             ` Turquette, Mike
2012-03-04 20:33   ` [PATCH] clk: Fix compile errors in DEFINE_CLK_GATE Andrew Lunn
2012-03-05  0:31     ` Turquette, Mike
2012-03-07 21:20   ` [PATCH v5 4/4] clk: basic clock hardware types Sascha Hauer
2012-03-09 22:50     ` Turquette, Mike
2012-03-09  2:34 ` [PATCH v5 0/4] common clk framework Richard Zhao
2012-03-09  9:19   ` Sascha Hauer
2012-03-09 18:35   ` Turquette, Mike

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).