All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] sanitizing crazy clock data files
@ 2011-04-15 19:08 Sascha Hauer
  2011-04-15 19:08 ` [PATCH 01/10] Add a common struct clk Sascha Hauer
                   ` (12 more replies)
  0 siblings, 13 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

The following tries to solve the chicken-egg problem we have with the
common struct clk support and its users. It switches i.MX51 clock support
to the new API. Included are some generic clock helpers for dividers and
multiplexer. I first made them i.MX specific but after looking round in
the other architectures I found them useful enough for other architectures
aswell. If you could use the helpers but missing some bits please speak up.

There is one thing missing in Jeremys series and this series does not fix
it. Once I add the new (un)prepare calls to drivers they won't compile
without common struct clk support anymore. Maybe a

#ifndef CONFIG_USE_COMMON_STRUCT_CLK
#define clk_prepare()
#define clk_unprepare()
#endif

will do.

Sascha

The following changes since commit de4a95bc9025f0566ade64dc35e5e3014e640b85:

  clk: Generic support for fixed-rate clocks (2011-04-15 20:39:48 +0200)

are available in the git repository at:
  git://git.pengutronix.de/git/imx/linux-2.6.git clk-common

Sascha Hauer (8):
      clk: Make NULL a valid clock again
      clk: implement parent pass through functions
      clk: Add support for simple dividers
      clk: Add support for a generic clock multiplexer
      ARM i.MX: Support for clock building blocks.
      ARM i.MX: Add generic support for pllv2
      ARM i.MX51/53: reimplement clock support
      ARM i.MX51/53: remove old clock support

 arch/arm/mach-mx5/Kconfig               |    6 +
 arch/arm/mach-mx5/Makefile              |    2 +-
 arch/arm/mach-mx5/clock-imx51-imx53.c   |  420 ++++++++
 arch/arm/mach-mx5/clock-mx51-mx53.c     | 1579 -------------------------------
 arch/arm/mach-mx5/crm_regs.h            |  249 +-----
 arch/arm/plat-mxc/Makefile              |    1 +
 arch/arm/plat-mxc/clock.c               |  182 ++++
 arch/arm/plat-mxc/include/mach/clkdev.h |    2 +
 arch/arm/plat-mxc/include/mach/clock.h  |  153 +++-
 arch/arm/plat-mxc/pllv2.c               |  228 +++++
 drivers/clk/Kconfig                     |    6 +
 drivers/clk/Makefile                    |    2 +
 drivers/clk/clk-divider.c               |  132 +++
 drivers/clk/clk-mux.c                   |   92 ++
 drivers/clk/clk.c                       |  104 ++
 include/linux/clk.h                     |   68 ++
 16 files changed, 1395 insertions(+), 1831 deletions(-)
 create mode 100644 arch/arm/mach-mx5/clock-imx51-imx53.c
 delete mode 100644 arch/arm/mach-mx5/clock-mx51-mx53.c
 create mode 100644 arch/arm/plat-mxc/pllv2.c
 create mode 100644 drivers/clk/clk-divider.c
 create mode 100644 drivers/clk/clk-mux.c

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

* [PATCH 01/10] Add a common struct clk
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-21 19:48   ` Thomas Gleixner
                     ` (2 more replies)
  2011-04-15 19:08 ` [PATCH 02/10] clk: Generic support for fixed-rate clocks Sascha Hauer
                   ` (11 subsequent siblings)
  12 siblings, 3 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

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

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

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

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

Platforms can enable the generic struct clock through
CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
consists of a common struct clk:

struct clk {
	const struct clk_ops	*ops;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	spinlock_t		enable_lock;
	struct mutex		prepare_lock;
};

And a set of clock operations (defined per type of clock):

struct clk_ops {
	int             (*enable)(struct clk *);
	void            (*disable)(struct clk *);
	unsigned long   (*get_rate)(struct clk *);
	[...]
};

To define a hardware-specific clock, machine code can "subclass" the
struct clock into a new struct (adding any device-specific data), and
provide a set of operations:

struct clk_foo {
	struct clk	clk;
	void __iomem	*some_register;
};

struct clk_ops clk_foo_ops = {
	.get_rate = clk_foo_get_rate,
};

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

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 drivers/clk/Kconfig  |    3 +
 drivers/clk/Makefile |    1 +
 drivers/clk/clk.c    |  132 ++++++++++++++++++++++++++++++++++++++++
 drivers/clk/clkdev.c |    7 ++
 include/linux/clk.h  |  164 +++++++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 298 insertions(+), 9 deletions(-)
 create mode 100644 drivers/clk/clk.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 4168c88..6e3ae54 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -2,3 +2,6 @@
 config CLKDEV_LOOKUP
 	bool
 	select HAVE_CLK
+
+config USE_COMMON_STRUCT_CLK
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 07613fa..a1a06d3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,2 +1,3 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
new file mode 100644
index 0000000..0bc9c6f
--- /dev/null
+++ b/drivers/clk/clk.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+
+#include <linux/clk.h>
+#include <linux/module.h>
+
+int clk_prepare(struct clk *clk)
+{
+	int ret = 0;
+
+	mutex_lock(&clk->prepare_lock);
+	if (clk->prepare_count == 0 && clk->ops->prepare)
+		ret = clk->ops->prepare(clk);
+
+	if (!ret)
+		clk->prepare_count++;
+	mutex_unlock(&clk->prepare_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_prepare);
+
+void clk_unprepare(struct clk *clk)
+{
+	mutex_lock(&clk->prepare_lock);
+
+	WARN_ON(clk->prepare_count == 0);
+
+	if (--clk->prepare_count == 0 && clk->ops->unprepare) {
+		WARN_ON(clk->enable_count != 0);
+		clk->ops->unprepare(clk);
+	}
+
+	mutex_unlock(&clk->prepare_lock);
+}
+EXPORT_SYMBOL_GPL(clk_unprepare);
+
+int clk_enable(struct clk *clk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	WARN_ON(clk->prepare_count == 0);
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+	if (clk->enable_count == 0 && clk->ops->enable)
+		ret = clk->ops->enable(clk);
+
+	if (!ret)
+		clk->enable_count++;
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk->enable_lock, flags);
+
+	WARN_ON(clk->enable_count == 0);
+
+	if (!--clk->enable_count == 0 && clk->ops->disable)
+		clk->ops->disable(clk);
+
+	spin_unlock_irqrestore(&clk->enable_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	if (clk->ops->get_rate)
+		return clk->ops->get_rate(clk);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk->ops->round_rate)
+		return clk->ops->round_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	might_sleep();
+
+	if (clk->ops->set_rate)
+		return clk->ops->set_rate(clk, rate);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	if (clk->ops->set_parent)
+		return clk->ops->set_parent(clk, parent);
+	return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+	if (clk->ops->get_parent)
+		return clk->ops->get_parent(clk);
+	return ERR_PTR(-ENOSYS);
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+int __clk_get(struct clk *clk)
+{
+	if (clk->ops->get)
+		return clk->ops->get(clk);
+	return 1;
+}
+
+void __clk_put(struct clk *clk)
+{
+	if (clk->ops->put)
+		clk->ops->put(clk);
+}
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..a7999d2 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -23,6 +23,13 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+/* For USE_COMMON_STRUCT_CLK, these are provided in clk.c, but not exported
+ * through other headers; we don't want them used anywhere but here. */
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+extern int __clk_get(struct clk *clk);
+extern void __clk_put(struct clk *clk);
+#endif
+
 /*
  * Find the correct struct clk for the device and connection ID.
  * We do slightly fuzzy matching here:
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 1d37f42..7b406bd 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2004 ARM Limited.
  *  Written by Deep Blue Solutions Limited.
+ *  Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -11,18 +12,168 @@
 #ifndef __LINUX_CLK_H
 #define __LINUX_CLK_H
 
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+
 struct device;
 
-/*
- * The base API.
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+/* If we're using the common struct clk, we define the base clk object here */
+
+/**
+ * struct clk - hardware independent clock structure
+ * @ops:		implementation-specific ops for this clock
+ * @enable_count:	count of clk_enable() calls active on this clock
+ * @enable_lock:	lock for atomic enable
+ * @prepare_count:	count of clk_prepare() calls active on this clock
+ * @prepare_lock:	lock for sleepable prepare
+ *
+ * The base clock object, used by drivers for hardware-independent manipulation
+ * of clock lines. This will be 'subclassed' by device-specific implementations,
+ * which add device-specific data to struct clk. For example:
+ *
+ *  struct clk_foo {
+ *      struct clk;
+ *      [device specific fields]
+ *  };
+ *
+ * The clock driver code will manage the device-specific data, and pass
+ * clk_foo.clk to the common clock code. The clock driver will be called
+ * through the @ops callbacks.
+ *
+ * The @enable_lock and @prepare_lock members are used to serialise accesses
+ * to the ops->enable and ops->prepare functions (and the corresponding
+ * ops->disable and ops->unprepare functions).
  */
+struct clk {
+	const struct clk_ops	*ops;
+	unsigned int		enable_count;
+	unsigned int		prepare_count;
+	spinlock_t		enable_lock;
+	struct mutex		prepare_lock;
+};
 
+/* static initialiser for clocks. */
+#define INIT_CLK(name, o) {						\
+	.ops		= &o,						\
+	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
+	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
+}
+
+/**
+ * struct clk_ops -  Callback operations for 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
+ *		clk->prepare_lock held.
+ *
+ * @unprepare:	Release the clock from its prepared state. This will typically
+ *		undo any work done in the @prepare callback. Called with
+ *		clk->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 clk->enable_lock held. This function
+ *		must not sleep.
+ *
+ * @disable:	Disable the clock atomically. Called with clk->enable_lock held.
+ *		This function must not sleep.
+ *
+ * @get:	Called by the core clock code when a device driver acquires a
+ *		clock via clk_get(). Optional.
+ *
+ * @put:	Called by the core clock code when a devices driver releases a
+ *		clock via clk_put(). Optional.
+ *
+ * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
+ * implementations to split any work between atomic (enable) and sleepable
+ * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
+ * should be done in clk_prepare. Switching that will not sleep should be done
+ * in clk_enable.
+ *
+ * Typically, drivers will call clk_prepare when a clock may be needed later
+ * (eg. when a device is opened), and clk_enable when the clock is actually
+ * required (eg. from an interrupt). Note that clk_prepare *must* have been
+ * called before clk_enable.
+ *
+ * For other callbacks, see the corresponding clk_* functions. Parameters and
+ * return values are passed directly from/to these API functions, or
+ * -ENOSYS (or zero, in the case of clk_get_rate) is returned if the callback
+ * is NULL, see drivers/clk/clk.c for implementation details. All are optional.
+ */
+struct clk_ops {
+	int		(*prepare)(struct clk *);
+	void		(*unprepare)(struct clk *);
+	int		(*enable)(struct clk *);
+	void		(*disable)(struct clk *);
+	int		(*get)(struct clk *);
+	void		(*put)(struct clk *);
+	unsigned long	(*get_rate)(struct clk *);
+	long		(*round_rate)(struct clk *, unsigned long);
+	int		(*set_rate)(struct clk *, unsigned long);
+	int		(*set_parent)(struct clk *, struct clk *);
+	struct clk *	(*get_parent)(struct clk *);
+};
+
+/**
+ * clk_prepare - prepare clock for atomic enabling.
+ *
+ * @clk: The clock to prepare
+ *
+ * Do any possibly sleeping initialisation on @clk, allowing the clock to be
+ * later enabled atomically (via clk_enable). This function may sleep.
+ */
+int clk_prepare(struct clk *clk);
+
+/**
+ * clk_unprepare - release clock from prepared state
+ *
+ * @clk: The clock to release
+ *
+ * Do any (possibly sleeping) cleanup on clk. This function may sleep.
+ */
+void clk_unprepare(struct clk *clk);
+
+/**
+ * clk_common_init - initialise a clock for driver usage
+ *
+ * @clk: The clock to initialise
+ *
+ * Used for runtime intialization of clocks; you don't need to call this
+ * if your clock has been (statically) initialized with INIT_CLK.
+ */
+static inline void clk_common_init(struct clk *clk)
+{
+	clk->enable_count = clk->prepare_count = 0;
+	spin_lock_init(&clk->enable_lock);
+	mutex_init(&clk->prepare_lock);
+}
+
+#else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
- * struct clk - an machine class defined object / cookie.
+ * Global clock object, actual structure is declared per-machine
  */
 struct clk;
 
+static inline void clk_common_init(struct clk *clk) { }
+
+/*
+ * For !CONFIG_USE_COMMON_STRUCT_CLK, we don't enforce any atomicity
+ * requirements for clk_enable/clk_disable, so the prepare and unprepare
+ * functions are no-ops
+ */
+static inline int clk_prepare(struct clk *clk) { return 0; }
+static inline void clk_unprepare(struct clk *clk) { }
+
+#endif /* !CONFIG_USE_COMMON_STRUCT_CLK */
+
 /**
  * clk_get - lookup and obtain a reference to a clock producer.
  * @dev: device for clock "consumer"
@@ -67,6 +218,7 @@ void clk_disable(struct clk *clk);
 /**
  * clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
  *		  This is only valid once the clock source has been enabled.
+ *		  Returns zero if the clock rate is unknown.
  * @clk: clock source
  */
 unsigned long clk_get_rate(struct clk *clk);
@@ -83,12 +235,6 @@ unsigned long clk_get_rate(struct clk *clk);
  */
 void clk_put(struct clk *clk);
 
-
-/*
- * The remaining APIs are optional for machine class support.
- */
-
-
 /**
  * clk_round_rate - adjust a rate to the exact rate a clock can provide
  * @clk: clock source
-- 
1.7.4.1

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

* [PATCH 02/10] clk: Generic support for fixed-rate clocks
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
  2011-04-15 19:08 ` [PATCH 01/10] Add a common struct clk Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-15 19:08 ` [PATCH 03/10] clk: Make NULL a valid clock again Sascha Hauer
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

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

Since most platforms will need a fixed-rate clock, add one. This will
also serve as a basic example of an implementation of struct clk.

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 drivers/clk/clk.c   |   14 ++++++++++++++
 include/linux/clk.h |   16 ++++++++++++++++
 2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0bc9c6f..0da0bb9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -130,3 +130,17 @@ void __clk_put(struct clk *clk)
 	if (clk->ops->put)
 		clk->ops->put(clk);
 }
+
+/* clk_fixed support */
+
+#define to_clk_fixed(clk) (container_of(clk, struct clk_fixed, clk))
+
+static unsigned long clk_fixed_get_rate(struct clk *clk)
+{
+	return to_clk_fixed(clk)->rate;
+}
+
+struct clk_ops clk_fixed_ops = {
+	.get_rate = clk_fixed_get_rate,
+};
+EXPORT_SYMBOL_GPL(clk_fixed_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 7b406bd..d2f0db0 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -155,6 +155,22 @@ static inline void clk_common_init(struct clk *clk)
 	mutex_init(&clk->prepare_lock);
 }
 
+/* Simple fixed-rate clock */
+struct clk_fixed {
+	struct clk	clk;
+	unsigned long	rate;
+};
+
+extern struct clk_ops clk_fixed_ops;
+
+#define INIT_CLK_FIXED(name, r) { \
+	.clk = INIT_CLK(name.clk, clk_fixed_ops), \
+	.rate = (r) \
+}
+
+#define DEFINE_CLK_FIXED(name, r) \
+	struct clk_fixed name = INIT_CLK_FIXED(name, r)
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
-- 
1.7.4.1

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

* [PATCH 03/10] clk: Make NULL a valid clock again
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
  2011-04-15 19:08 ` [PATCH 01/10] Add a common struct clk Sascha Hauer
  2011-04-15 19:08 ` [PATCH 02/10] clk: Generic support for fixed-rate clocks Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-19  0:53   ` Jeremy Kerr
  2011-04-20 12:53   ` Uwe Kleine-König
  2011-04-15 19:08 ` [PATCH 04/10] clk: implement parent pass through functions Sascha Hauer
                   ` (9 subsequent siblings)
  12 siblings, 2 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

NULL used to be a valid clock. This patch makes the common struct
clk stuff work with this. Instead of crashing we return sane default
values for this dummy clock, that is: can always be prepared, enabled,
rate unkown and no set rate.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
---
 drivers/clk/clk.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 0da0bb9..264c809 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -15,6 +15,9 @@ int clk_prepare(struct clk *clk)
 {
 	int ret = 0;
 
+	if (!clk)
+		return 0;
+
 	mutex_lock(&clk->prepare_lock);
 	if (clk->prepare_count == 0 && clk->ops->prepare)
 		ret = clk->ops->prepare(clk);
@@ -29,6 +32,9 @@ EXPORT_SYMBOL_GPL(clk_prepare);
 
 void clk_unprepare(struct clk *clk)
 {
+	if (!clk)
+		return;
+
 	mutex_lock(&clk->prepare_lock);
 
 	WARN_ON(clk->prepare_count == 0);
@@ -47,6 +53,9 @@ int clk_enable(struct clk *clk)
 	unsigned long flags;
 	int ret = 0;
 
+	if (!clk)
+		return 0;
+
 	WARN_ON(clk->prepare_count == 0);
 
 	spin_lock_irqsave(&clk->enable_lock, flags);
@@ -65,6 +74,9 @@ void clk_disable(struct clk *clk)
 {
 	unsigned long flags;
 
+	if (!clk)
+		return;
+
 	spin_lock_irqsave(&clk->enable_lock, flags);
 
 	WARN_ON(clk->enable_count == 0);
@@ -78,6 +90,9 @@ EXPORT_SYMBOL_GPL(clk_disable);
 
 unsigned long clk_get_rate(struct clk *clk)
 {
+	if (!clk)
+		return 0;
+
 	if (clk->ops->get_rate)
 		return clk->ops->get_rate(clk);
 	return 0;
@@ -86,6 +101,9 @@ EXPORT_SYMBOL_GPL(clk_get_rate);
 
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
+	if (!clk)
+		return -ENOSYS;
+
 	if (clk->ops->round_rate)
 		return clk->ops->round_rate(clk, rate);
 	return -ENOSYS;
@@ -94,6 +112,9 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
+	if (!clk)
+		return -ENOSYS;
+
 	might_sleep();
 
 	if (clk->ops->set_rate)
@@ -104,6 +125,9 @@ EXPORT_SYMBOL_GPL(clk_set_rate);
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
+	if (!clk)
+		return -ENOSYS;
+
 	if (clk->ops->set_parent)
 		return clk->ops->set_parent(clk, parent);
 	return -ENOSYS;
@@ -112,6 +136,9 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
 
 struct clk *clk_get_parent(struct clk *clk)
 {
+	if (!clk)
+		return ERR_PTR(-ENOSYS);
+
 	if (clk->ops->get_parent)
 		return clk->ops->get_parent(clk);
 	return ERR_PTR(-ENOSYS);
-- 
1.7.4.1

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (2 preceding siblings ...)
  2011-04-15 19:08 ` [PATCH 03/10] clk: Make NULL a valid clock again Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-18  9:25   ` Uwe Kleine-König
  2011-04-19 17:20   ` Stephen Boyd
  2011-04-15 19:08 ` [PATCH 05/10] clk: Add support for simple dividers Sascha Hauer
                   ` (8 subsequent siblings)
  12 siblings, 2 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

A common case for clocks is that certain operations are not implemented
and shall be passed through to the parent. Add convenience functions
for this purpose

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
---
 drivers/clk/clk.c   |   77 +++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h |    9 ++++++
 2 files changed, 86 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 264c809..7e2c182 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -171,3 +171,80 @@ struct clk_ops clk_fixed_ops = {
 	.get_rate = clk_fixed_get_rate,
 };
 EXPORT_SYMBOL_GPL(clk_fixed_ops);
+
+int clk_parent_prepare(struct clk *clk)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (IS_ERR(parent))
+		return -ENOSYS;
+
+	return clk_prepare(parent);
+}
+EXPORT_SYMBOL_GPL(clk_parent_prepare);
+
+void clk_parent_unprepare(struct clk *clk)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (IS_ERR(parent))
+		return;
+
+	clk_unprepare(parent);
+}
+EXPORT_SYMBOL_GPL(clk_parent_unprepare);
+
+int clk_parent_enable(struct clk *clk)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (IS_ERR(parent))
+		return 0;
+
+	return clk_enable(parent);
+}
+EXPORT_SYMBOL_GPL(clk_parent_enable);
+
+void clk_parent_disable(struct clk *clk)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (IS_ERR(parent))
+		return;
+
+	clk_disable(parent);
+}
+EXPORT_SYMBOL_GPL(clk_parent_disable);
+
+unsigned long clk_parent_get_rate(struct clk *clk)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (IS_ERR(parent))
+		return 0;
+
+	return clk_get_rate(parent);
+}
+EXPORT_SYMBOL_GPL(clk_parent_get_rate);
+
+long clk_parent_round_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (IS_ERR(parent))
+		return -ENOSYS;
+
+	return clk_round_rate(parent, rate);
+}
+EXPORT_SYMBOL_GPL(clk_parent_round_rate);
+
+int clk_parent_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (IS_ERR(parent))
+		return -ENOSYS;
+
+	return clk_set_rate(parent, rate);
+}
+EXPORT_SYMBOL_GPL(clk_parent_set_rate);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index d2f0db0..d014341 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -171,6 +171,15 @@ extern struct clk_ops clk_fixed_ops;
 #define DEFINE_CLK_FIXED(name, r) \
 	struct clk_fixed name = INIT_CLK_FIXED(name, r)
 
+/* generic pass-through-to-parent functions */
+int clk_parent_prepare(struct clk *clk);
+void clk_parent_unprepare(struct clk *clk);
+int clk_parent_enable(struct clk *clk);
+void clk_parent_disable(struct clk *clk);
+unsigned long clk_parent_get_rate(struct clk *clk);
+long clk_parent_round_rate(struct clk *clk, unsigned long rate);
+int clk_parent_set_rate(struct clk *clk, unsigned long rate);
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
-- 
1.7.4.1

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (3 preceding siblings ...)
  2011-04-15 19:08 ` [PATCH 04/10] clk: implement parent pass through functions Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-18  9:49   ` Uwe Kleine-König
                     ` (2 more replies)
  2011-04-15 19:08 ` [PATCH 06/10] clk: Add support for a generic clock multiplexer Sascha Hauer
                   ` (7 subsequent siblings)
  12 siblings, 3 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds support for the most common type of divider,
which expects a register, width and shift values to desacribe
the location of the divider. The divider can be zero based
or one based (div = reg_val + 1 vs. div = reg_val).

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
---
 drivers/clk/Kconfig       |    3 +
 drivers/clk/Makefile      |    1 +
 drivers/clk/clk-divider.c |  132 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h       |   31 +++++++++++
 4 files changed, 167 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/clk-divider.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 6e3ae54..76bb4c9 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
 
 config USE_COMMON_STRUCT_CLK
 	bool
+
+config USE_COMMON_CLK_DIVIDER
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index a1a06d3..723d884 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,3 +1,4 @@
 
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
+obj-$(CONFIG_USE_COMMON_CLK_DIVIDER) += clk-divider.o
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
new file mode 100644
index 0000000..2de94df
--- /dev/null
+++ b/drivers/clk/clk-divider.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#define to_clk_divider(clk) (container_of(clk, struct clk_divider, clk))
+
+static unsigned long clk_divider_get_rate(struct clk *clk)
+{
+	struct clk_divider *divider = to_clk_divider(clk);
+	unsigned long rate = clk_get_rate(divider->parent);
+	unsigned int div;
+
+	div = readl(divider->reg) >> divider->shift;
+	div &= (1 << divider->width) - 1;
+
+	if (!(divider->flags & CLK_DIVIDER_FLAG_ONE_BASED))
+		div++;
+
+	return rate / div;
+}
+
+static int clk_divider_bestdiv(struct clk *clk, unsigned long rate,
+		unsigned long *best_parent_rate)
+{
+	struct clk_divider *divider = to_clk_divider(clk);
+	int i, bestdiv = 0;
+	unsigned long parent_rate, best = 0, now, maxdiv;
+
+	maxdiv = (1 << divider->width);
+
+	if (divider->flags & CLK_DIVIDER_FLAG_ONE_BASED)
+		maxdiv--;
+
+	/*
+	 * 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++) {
+		parent_rate = clk_round_rate(divider->parent, (rate + 1) * i);
+		now = parent_rate / i;
+
+		if (now <= rate && now >= best) {
+			bestdiv = i;
+			best = now;
+		}
+	}
+
+	if (!bestdiv) {
+		bestdiv = (1 << divider->width);
+		parent_rate = clk_round_rate(divider->parent, 1);
+	} else {
+		parent_rate = best * bestdiv;
+	}
+
+	if (best_parent_rate)
+		*best_parent_rate = parent_rate;
+
+	return bestdiv;
+}
+
+static long clk_divider_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long best_parent_rate;
+	int div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
+
+	return best_parent_rate / div;
+}
+
+static int clk_divider_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long best_parent_rate;
+	struct clk_divider *divider = to_clk_divider(clk);
+	unsigned int div;
+	int ret;
+	unsigned long flags = 0;
+	u32 val;
+
+	div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
+
+	if (rate != best_parent_rate / div)
+		return -EINVAL;
+
+	ret = clk_set_rate(divider->parent, best_parent_rate);
+	if (ret)
+		return ret;
+
+	if (divider->lock)
+		spin_lock_irqsave(divider->lock, flags);
+
+	if (!(divider->flags & CLK_DIVIDER_FLAG_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;
+}
+
+static struct clk *clk_divider_get_parent(struct clk *clk)
+{
+	struct clk_divider *divider = to_clk_divider(clk);
+
+	return divider->parent;
+}
+
+struct clk_ops clk_divider_ops = {
+	.prepare = clk_parent_prepare,
+	.unprepare = clk_parent_unprepare,
+	.enable = clk_parent_enable,
+	.disable = clk_parent_disable,
+	.get_rate = clk_divider_get_rate,
+	.round_rate = clk_divider_round_rate,
+	.set_rate = clk_divider_set_rate,
+	.get_parent = clk_divider_get_parent,
+};
+EXPORT_SYMBOL_GPL(clk_divider_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index d014341..6f9771b 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -180,6 +180,37 @@ unsigned long clk_parent_get_rate(struct clk *clk);
 long clk_parent_round_rate(struct clk *clk, unsigned long rate);
 int clk_parent_set_rate(struct clk *clk, unsigned long rate);
 
+/**
+ * clock divider
+ *
+ * @clk		clock source
+ * @reg		register containing the divider
+ * @shift	shift to the divider
+ * @width	width of the divider
+ * @lock	register lock
+ * @parent	parent clock
+ *
+ * This clock implements get_rate/set_rate/round_rate. prepare/unprepare and
+ * enable/disable are passed through to the parent.
+ *
+ * The divider is calculated as div = reg_val + 1
+ * or if CLK_DIVIDER_FLAG_ONE_BASED is set as div = reg_val
+ * (with reg_val == 0 considered invalid)
+ */
+struct clk_divider {
+	struct clk	clk;
+	void __iomem	*reg;
+	unsigned char	shift;
+	unsigned char	width;
+	unsigned int	div;
+	struct clk	*parent;
+	spinlock_t	*lock;
+#define CLK_DIVIDER_FLAG_ONE_BASED	(1 << 0)
+	unsigned int	flags;
+};
+
+extern struct clk_ops clk_divider_ops;
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
-- 
1.7.4.1

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

* [PATCH 06/10] clk: Add support for a generic clock multiplexer
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (4 preceding siblings ...)
  2011-04-15 19:08 ` [PATCH 05/10] clk: Add support for simple dividers Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-18 13:15   ` Uwe Kleine-König
  2011-04-15 19:08 ` [PATCH 07/10] ARM i.MX: Support for clock building blocks Sascha Hauer
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds support for a common type of clock multiplexer.
The multiplexer is described with register, shift and width and
an array of clocks which correspond to the bit value.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
---
 drivers/clk/Kconfig       |    3 +
 drivers/clk/Makefile      |    1 +
 drivers/clk/clk-divider.c |    2 +-
 drivers/clk/clk-mux.c     |   92 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h       |   28 ++++++++++++++
 5 files changed, 125 insertions(+), 1 deletions(-)
 create mode 100644 drivers/clk/clk-mux.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 76bb4c9..710d73d 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -8,3 +8,6 @@ config USE_COMMON_STRUCT_CLK
 
 config USE_COMMON_CLK_DIVIDER
 	bool
+
+config USE_COMMON_CLK_MUX
+	bool
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 723d884..195a434 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
 obj-$(CONFIG_USE_COMMON_CLK_DIVIDER) += clk-divider.o
+obj-$(CONFIG_USE_COMMON_CLK_MUX) += clk-mux.o
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 2de94df..e3f5b7a 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de>
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
  *
  * 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
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
new file mode 100644
index 0000000..d33b15f
--- /dev/null
+++ b/drivers/clk/clk-mux.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Standard functionality for the common clock API.
+ */
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#define to_clk_mux(clk) (container_of(clk, struct clk_mux, clk))
+
+static struct clk *clk_mux_get_parent(struct clk *clk)
+{
+	struct clk_mux *mux = to_clk_mux(clk);
+	u32 val;
+
+	val = readl(mux->reg) >> mux->shift;
+	val &= (1 << mux->width) - 1;
+
+	if (val >= mux->num_clks)
+		return ERR_PTR(-EINVAL);
+
+	return mux->clks[val];
+}
+
+static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
+{
+	struct clk_mux *mux = to_clk_mux(clk);
+	u32 val;
+	int i;
+	unsigned long flags = 0;
+
+	for (i = 0; i < mux->num_clks; i++)
+		if (mux->clks[i] == parent)
+			break;
+
+	if (i == mux->num_clks)
+		return -EINVAL;
+
+	if (mux->lock)
+		spin_lock_irqsave(mux->lock, flags);
+
+	val = readl(mux->reg);
+	val &= ~(((1 << mux->width) - 1) << mux->shift);
+	val |= i << mux->shift;
+	writel(val, mux->reg);
+
+	if (mux->lock)
+		spin_unlock_irqrestore(mux->lock, flags);
+
+	return 0;
+}
+
+static long clk_mux_round_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (IS_ERR(parent))
+		return PTR_ERR(parent);
+
+	return clk_get_rate(parent);
+}
+
+static int clk_mux_set_rate(struct clk *clk, unsigned long desired)
+{
+	struct clk *parent = clk_get_parent(clk);
+
+	if (IS_ERR(parent))
+		return PTR_ERR(parent);
+
+	if (desired != clk_get_rate(parent))
+		return -EINVAL;
+
+	return 0;
+}
+
+struct clk_ops clk_mux_ops = {
+	.prepare = clk_parent_prepare,
+	.unprepare = clk_parent_unprepare,
+	.enable = clk_parent_enable,
+	.disable = clk_parent_disable,
+	.get_rate = clk_parent_get_rate,
+	.round_rate = clk_mux_round_rate,
+	.set_rate = clk_mux_set_rate,
+	.get_parent = clk_mux_get_parent,
+	.set_parent = clk_mux_set_parent,
+};
+EXPORT_SYMBOL_GPL(clk_mux_ops);
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 6f9771b..fb2c2f5 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -211,6 +211,34 @@ struct clk_divider {
 
 extern struct clk_ops clk_divider_ops;
 
+/**
+ * clock multiplexer
+ *
+ * @clk		clock source
+ * @reg		the register this multiplexer can be configured with
+ * @shift	the shift to the start bit of this multiplexer
+ * @width	the width in bits of this multiplexer
+ * @num_clks	number of parent clocks
+ * @lock	register lock
+ * @clks	array of possible parents for this multiplexer. Can contain
+ *		holes with NULL in it for invalid register settings
+ *
+ * This clock implements get_parent/set_parent. prepare/unprepare,
+ * enable/disable and get_rate operations are passed through to the parent,
+ * the rate is not adjustable.
+ */
+struct clk_mux {
+	struct clk	clk;
+	void __iomem	*reg;
+	unsigned char	shift;
+	unsigned char	width;
+	unsigned char	num_clks;
+	spinlock_t	*lock;
+	struct clk	**clks;
+};
+
+extern struct clk_ops clk_mux_ops;
+
 #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
 
 /*
-- 
1.7.4.1

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

* [PATCH 07/10] ARM i.MX: Support for clock building blocks.
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (5 preceding siblings ...)
  2011-04-15 19:08 ` [PATCH 06/10] clk: Add support for a generic clock multiplexer Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-15 19:08 ` [PATCH 08/10] ARM i.MX: Add generic support for pllv2 Sascha Hauer
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds generic code to handle different common patterns
in i.MX clock code.

* gates         clk_[en|dis]able
* groups        Group together clocks which should be enabled at once.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/plat-mxc/clock.c              |  182 ++++++++++++++++++++++++++++++++
 arch/arm/plat-mxc/include/mach/clock.h |  126 +++++++++++++++++++++-
 2 files changed, 305 insertions(+), 3 deletions(-)

diff --git a/arch/arm/plat-mxc/clock.c b/arch/arm/plat-mxc/clock.c
index 2ed3ab1..e881ab2 100644
--- a/arch/arm/plat-mxc/clock.c
+++ b/arch/arm/plat-mxc/clock.c
@@ -44,6 +44,8 @@
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
 
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
+
 /*-------------------------------------------------------------------------
  * Standard clock functions defined in include/linux/clk.h
  *-------------------------------------------------------------------------*/
@@ -199,6 +201,7 @@ struct clk *clk_get_parent(struct clk *clk)
 	return clk->parent;
 }
 EXPORT_SYMBOL(clk_get_parent);
+#endif
 
 /*
  * Get the resulting clock rate from a PLL register value and the input
@@ -244,3 +247,182 @@ unsigned long mxc_decode_pll(unsigned int reg_val, u32 freq)
 
 	return ll;
 }
+
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+
+DEFINE_SPINLOCK(imx_ccm_lock);
+
+/* clk gate support */
+
+#define to_clk_gate(clk) (container_of(clk, struct clk_gate, clk))
+
+static int clk_gate_enable(struct clk *clk)
+{
+	struct clk_gate *gate = to_clk_gate(clk);
+	u32 val;
+	int ret;
+	unsigned long flags;
+
+	if (gate->parent) {
+		ret = clk_parent_enable(gate->parent);
+		if (ret)
+			return ret;
+	}
+
+	spin_lock_irqsave(&imx_ccm_lock, flags);
+
+	val = readl(gate->reg);
+
+	if (gate->flags & CLK_GATE_TWO_BITS) {
+		if (gate->flags & CLK_GATE_ENABLE_WAIT) {
+			val &= ~(3 << (gate->shift * 2));
+			val |= 1 << (gate->shift * 2);
+		} else {
+			val |= 3 << (gate->shift * 2);
+		}
+	} else {
+		val |= 1 << (gate->shift);
+	}
+
+	writel(val, gate->reg);
+
+	spin_unlock_irqrestore(&imx_ccm_lock, flags);
+
+	return 0;
+}
+
+static void clk_gate_disable(struct clk *clk)
+{
+	struct clk_gate *gate = to_clk_gate(clk);
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&imx_ccm_lock, flags);
+
+	val = readl(gate->reg);
+
+	if (gate->flags & CLK_GATE_TWO_BITS) {
+		if (gate->flags & CLK_GATE_DISABLE_WAIT) {
+			val &= ~(3 << (gate->shift * 2));
+			val |= 1 << (gate->shift * 2);
+		} else {
+			val &= ~(3 << (gate->shift * 2));
+		}
+	} else {
+		val &= ~(1 << (gate->shift));
+	}
+
+	writel(val, gate->reg);
+
+	spin_unlock_irqrestore(&imx_ccm_lock, flags);
+
+	if (gate->parent)
+		clk_parent_disable(gate->parent);
+}
+
+static struct clk *clk_gate_get_parent(struct clk *clk)
+{
+	struct clk_gate *gate = to_clk_gate(clk);
+
+	return gate->parent;
+}
+
+struct clk_ops clk_gate_ops = {
+	.prepare = clk_parent_prepare,
+	.unprepare = clk_parent_unprepare,
+	.enable = clk_gate_enable,
+	.disable = clk_gate_disable,
+	.get_rate = clk_parent_get_rate,
+	.round_rate = clk_parent_round_rate,
+	.set_rate = clk_parent_set_rate,
+	.get_parent = clk_gate_get_parent,
+};
+EXPORT_SYMBOL_GPL(clk_gate_ops);
+
+#define to_clk_group(clk) (container_of(clk, struct clk_group, clk))
+
+static int clk_group_prepare(struct clk *clk)
+{
+	struct clk_group *group = to_clk_group(clk);
+	int i, ret;
+
+	for (i = 0; i < group->num_clks; i++) {
+		ret = clk_prepare(group->clks[i]);
+			if (ret)
+				goto out;
+	}
+
+	return 0;
+out:
+	while (i-- > 0)
+		clk_disable(group->clks[i]);
+	return ret;
+}
+
+static void clk_group_unprepare(struct clk *clk)
+{
+	struct clk_group *group = to_clk_group(clk);
+	int i;
+
+	for (i = 0; i < group->num_clks; i++)
+		clk_disable(group->clks[i]);
+}
+
+static int clk_group_enable(struct clk *clk)
+{
+	struct clk_group *group = to_clk_group(clk);
+	int i, ret;
+
+	for (i = 0; i < group->num_clks; i++) {
+		ret = clk_enable(group->clks[i]);
+			if (ret)
+				goto out;
+	}
+
+	return 0;
+out:
+	while (i-- > 0)
+		clk_disable(group->clks[i]);
+	return ret;
+}
+
+static void clk_group_disable(struct clk *clk)
+{
+	struct clk_group *group = to_clk_group(clk);
+	int i;
+
+	for (i = 0; i < group->num_clks; i++)
+		clk_disable(group->clks[i]);
+}
+
+static unsigned long clk_group_get_rate(struct clk *clk)
+{
+	struct clk_group *group = to_clk_group(clk);
+
+	return clk_get_rate(group->clks[0]);
+}
+
+static long clk_group_round_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_group *group = to_clk_group(clk);
+
+	return clk_round_rate(group->clks[0], rate);
+}
+
+static int clk_group_set_rate(struct clk *clk, unsigned long rate)
+{
+	struct clk_group *group = to_clk_group(clk);
+
+	return clk_set_rate(group->clks[0], rate);
+}
+
+struct clk_ops clk_group_ops = {
+	.prepare = clk_group_prepare,
+	.unprepare = clk_group_unprepare,
+	.enable = clk_group_enable,
+	.disable = clk_group_disable,
+	.get_rate = clk_group_get_rate,
+	.round_rate = clk_group_round_rate,
+	.set_rate = clk_group_set_rate,
+};
+#endif /* CONFIG_USE_COMMON_STRUCT_CLK */
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 753a598..73a72af 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -57,10 +57,130 @@ struct clk {
 	int (*set_parent) (struct clk *, struct clk *);
 };
 
-int clk_register(struct clk *clk);
-void clk_unregister(struct clk *clk);
-
 unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref);
 
+/**
+ * clock gate
+ *
+ * @clk		clock source
+ * @reg		register containing the gate
+ * @shift	shift to the gate
+ * @parent	parent clock
+ * @flags	flags
+ *
+ * This clock implements clk_enable/clk_disable. The rate functions are passed
+ * through to the parent.
+ * When CLK_GATE_TWO_BITS is given each gate is two bits wide. Used on i.MX51.
+ */
+struct clk_gate {
+	struct clk	clk;
+	void __iomem	*reg;
+	unsigned	shift;
+	struct clk	*parent;
+	unsigned long	flags;
+};
+
+extern struct clk_ops clk_gate_ops;
+
+#define DEFINE_CLK_GATE_FLAGS(name, _parent, _reg, _shift, _flags) \
+	struct clk_gate name = { \
+		.clk = INIT_CLK(name.clk, clk_gate_ops), \
+		.parent = (_parent), \
+		.reg = (_reg), \
+		.shift = (_shift), \
+		.flags = (_flags), \
+	}
+
+#define CLK_GATE_TWO_BITS	(1 << 0)
+#define CLK_GATE_ENABLE_WAIT	(1 << 1)
+#define CLK_GATE_DISABLE_WAIT	(1 << 2)
+
+#define DEFINE_CLK_GATE(name, _parent, _reg, _shift) \
+	DEFINE_CLK_GATE_FLAGS(name, _parent, _reg, _shift, 0)
+#define DEFINE_CLK_GATE_2(name, _parent, _reg, _shift) \
+	DEFINE_CLK_GATE_FLAGS(name, _parent, _reg, _shift, CLK_GATE_TWO_BITS)
+#define DEFINE_CLK_GATE_ENABLE_WAIT(name, _parent, _reg, _shift) \
+	DEFINE_CLK_GATE_FLAGS(name, _parent, _reg, _shift, CLK_GATE_TWO_BITS | CLK_GATE_ENABLE_WAIT)
+#define DEFINE_CLK_GATE_DISABLE_WAIT(name, _parent, _reg, _shift) \
+	DEFINE_CLK_GATE_FLAGS(name, _parent, _reg, _shift, CLK_GATE_TWO_BITS | CLK_GATE_DISABLE_WAIT)
+
+extern spinlock_t imx_ccm_lock;
+
+#define DEFINE_CLK_DIVIDER(name, _parent, _reg, _shift, _width) \
+	struct clk_divider name = { \
+		.clk = INIT_CLK(name.clk, clk_divider_ops), \
+		.parent = (_parent), \
+		.reg = (_reg), \
+		.shift = (_shift), \
+		.width = (_width), \
+		.lock = &imx_ccm_lock, \
+	}
+
+/**
+ * fixed clock divider
+ *
+ * @clk		clock source
+ * @mult	fixed multiplier value
+ * @div		fixed divider value
+ * @parent	parent clock
+ *
+ * This clock implements a fixed divider with an additional multiplier to
+ * specify fractional values. clk_enable/clk_disable are passed through
+ * to the parent. Note that the divider is applied before the multiplier
+ * to prevent overflows. This may result in a less accurat result.
+ */
+struct clk_divider_fixed {
+	struct clk	clk;
+	unsigned int	mult;
+	unsigned int	div;
+	struct clk	*parent;
+};
+
+#define DEFINE_CLK_DIVIDER_FIXED(name, _parent, _mult, _div) \
+	struct clk_divider name = { \
+		.clk = INIT_CLK(name.clk, clk_divider_ops), \
+		.parent = (_parent), \
+		.mult = (_mult), \
+		.div = (_div), \
+	}
+
+#define DEFINE_CLK_MUX(name, _reg, _shift, _width, _clks) \
+	struct clk_mux name = { \
+		.clk = INIT_CLK(name.clk, clk_mux_ops), \
+		.reg = (_reg), \
+		.shift = (_shift), \
+		.width = (_width), \
+		.clks = (_clks), \
+		.num_clks = ARRAY_SIZE(_clks), \
+		.lock = &imx_ccm_lock, \
+	}
+
+/**
+ * clock group
+ *
+ * @clk		clock source
+ * @num_clks	number of parent clocks to enable
+ * @clks	array of parents to enable/disable
+ *
+ * This clock is a groups of clocks useful for specifying clocks for
+ * drivers which consist of multiple clocks. it enables/disables
+ * all clocks in @clks, clk_get_rate/clk_set_rate are passed through
+ * to the first member of @clks.
+ */
+struct clk_group {
+	struct clk	clk;
+	unsigned char	num_clks;
+	struct clk	**clks;
+};
+
+extern struct clk_ops clk_group_ops;
+
+#define DEFINE_CLK_GROUP(name, _clks) \
+	struct clk_group name = { \
+		.clk = INIT_CLK(name.clk, clk_group_ops), \
+		.clks = (_clks), \
+		.num_clks = ARRAY_SIZE(_clks), \
+	}
+
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_ARCH_MXC_CLOCK_H__ */
-- 
1.7.4.1

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

* [PATCH 08/10] ARM i.MX: Add generic support for pllv2
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (6 preceding siblings ...)
  2011-04-15 19:08 ` [PATCH 07/10] ARM i.MX: Support for clock building blocks Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-15 19:08 ` [PATCH 09/10] ARM i.MX51/53: reimplement clock support Sascha Hauer
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

The pllv2 is found on i.MX5 SoCs.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/plat-mxc/Makefile             |    1 +
 arch/arm/plat-mxc/include/mach/clock.h |   24 ++++
 arch/arm/plat-mxc/pllv2.c              |  228 ++++++++++++++++++++++++++++++++
 3 files changed, 253 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/plat-mxc/pllv2.c

diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index a138787..c5ea019 100644
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -5,6 +5,7 @@
 # Common support
 obj-y := clock.o gpio.o time.o devices.o cpu.o system.o irq-common.o
 
+obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += pllv2.o
 # MX51 uses the TZIC interrupt controller, older platforms use AVIC
 obj-$(CONFIG_MXC_TZIC) += tzic.o
 obj-$(CONFIG_MXC_AVIC) += avic.o
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 73a72af..4943ab0 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -182,5 +182,29 @@ extern struct clk_ops clk_group_ops;
 		.num_clks = ARRAY_SIZE(_clks), \
 	}
 
+/**
+ * pll v2
+ *
+ * @clk		clock source
+ * @parent	the parent clock
+ * @base	base address of pll registers
+ *
+ * PLL clock version two, found on i.MX50/51/53
+ */
+struct clk_pllv2 {
+	struct clk	clk;
+	struct clk	*parent;
+	void __iomem	*base;
+};
+
+extern struct clk_ops clk_pllv2_ops;
+
+#define DEFINE_CLK_PLLV2(name, _parent, _base) \
+	struct clk_pllv2 name = { \
+		.clk = INIT_CLK(name.clk, clk_pllv2_ops), \
+		.parent = (_parent), \
+		.base = (_base), \
+	}
+
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_ARCH_MXC_CLOCK_H__ */
diff --git a/arch/arm/plat-mxc/pllv2.c b/arch/arm/plat-mxc/pllv2.c
new file mode 100644
index 0000000..a554f64
--- /dev/null
+++ b/arch/arm/plat-mxc/pllv2.c
@@ -0,0 +1,228 @@
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <asm/div64.h>
+
+#include <mach/clock.h>
+
+#define to_clk_pllv2(clk) (container_of(clk, struct clk_pllv2, clk))
+
+/* PLL Register Offsets */
+#define MXC_PLL_DP_CTL			0x00
+#define MXC_PLL_DP_CONFIG		0x04
+#define MXC_PLL_DP_OP			0x08
+#define MXC_PLL_DP_MFD			0x0C
+#define MXC_PLL_DP_MFN			0x10
+#define MXC_PLL_DP_MFNMINUS		0x14
+#define MXC_PLL_DP_MFNPLUS		0x18
+#define MXC_PLL_DP_HFS_OP		0x1C
+#define MXC_PLL_DP_HFS_MFD		0x20
+#define MXC_PLL_DP_HFS_MFN		0x24
+#define MXC_PLL_DP_MFN_TOGC		0x28
+#define MXC_PLL_DP_DESTAT		0x2c
+
+/* PLL Register Bit definitions */
+#define MXC_PLL_DP_CTL_MUL_CTRL		0x2000
+#define MXC_PLL_DP_CTL_DPDCK0_2_EN	0x1000
+#define MXC_PLL_DP_CTL_DPDCK0_2_OFFSET	12
+#define MXC_PLL_DP_CTL_ADE		0x800
+#define MXC_PLL_DP_CTL_REF_CLK_DIV	0x400
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_MASK	(3 << 8)
+#define MXC_PLL_DP_CTL_REF_CLK_SEL_OFFSET	8
+#define MXC_PLL_DP_CTL_HFSM		0x80
+#define MXC_PLL_DP_CTL_PRE		0x40
+#define MXC_PLL_DP_CTL_UPEN		0x20
+#define MXC_PLL_DP_CTL_RST		0x10
+#define MXC_PLL_DP_CTL_RCP		0x8
+#define MXC_PLL_DP_CTL_PLM		0x4
+#define MXC_PLL_DP_CTL_BRM0		0x2
+#define MXC_PLL_DP_CTL_LRF		0x1
+
+#define MXC_PLL_DP_CONFIG_BIST		0x8
+#define MXC_PLL_DP_CONFIG_SJC_CE	0x4
+#define MXC_PLL_DP_CONFIG_AREN		0x2
+#define MXC_PLL_DP_CONFIG_LDREQ		0x1
+
+#define MXC_PLL_DP_OP_MFI_OFFSET	4
+#define MXC_PLL_DP_OP_MFI_MASK		(0xF << 4)
+#define MXC_PLL_DP_OP_PDF_OFFSET	0
+#define MXC_PLL_DP_OP_PDF_MASK		0xF
+
+#define MXC_PLL_DP_MFD_OFFSET		0
+#define MXC_PLL_DP_MFD_MASK		0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_OFFSET		0x0
+#define MXC_PLL_DP_MFN_MASK		0x07FFFFFF
+
+#define MXC_PLL_DP_MFN_TOGC_TOG_DIS	(1 << 17)
+#define MXC_PLL_DP_MFN_TOGC_TOG_EN	(1 << 16)
+#define MXC_PLL_DP_MFN_TOGC_CNT_OFFSET	0x0
+#define MXC_PLL_DP_MFN_TOGC_CNT_MASK	0xFFFF
+
+#define MXC_PLL_DP_DESTAT_TOG_SEL	(1 << 31)
+#define MXC_PLL_DP_DESTAT_MFN		0x07FFFFFF
+
+#define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
+
+static unsigned long clk_pllv2_get_rate(struct clk *clk)
+{
+	long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
+	unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
+	void __iomem *pllbase;
+	s64 temp;
+	unsigned long parent_rate;
+	struct clk_pllv2 *pll = to_clk_pllv2(clk);
+
+	parent_rate = clk_get_rate(clk_get_parent(clk));
+
+	pllbase = pll->base;
+
+	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+	dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
+
+	if (pll_hfsm == 0) {
+		dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
+		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
+		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
+	} else {
+		dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
+		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
+		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
+	}
+	pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
+	mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
+	mfi = (mfi <= 5) ? 5 : mfi;
+	mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
+	mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
+	/* Sign extend to 32-bits */
+	if (mfn >= 0x04000000) {
+		mfn |= 0xFC000000;
+		mfn_abs = -mfn;
+	}
+
+	ref_clk = 2 * parent_rate;
+	if (dbl != 0)
+		ref_clk *= 2;
+
+	ref_clk /= (pdf + 1);
+	temp = (u64) ref_clk * mfn_abs;
+	do_div(temp, mfd + 1);
+	if (mfn < 0)
+		temp = -temp;
+	temp = (ref_clk * mfi) + temp;
+
+	return temp;
+}
+
+static int clk_pllv2_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg;
+	void __iomem *pllbase;
+	struct clk_pllv2 *pll = to_clk_pllv2(clk);
+
+	long mfi, pdf, mfn, mfd = 999999;
+	s64 temp64;
+	unsigned long quad_parent_rate;
+	unsigned long pll_hfsm, dp_ctl;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk_get_parent(clk));
+
+	pllbase = pll->base;
+
+	quad_parent_rate = 4 * parent_rate;
+	pdf = mfi = -1;
+	while (++pdf < 16 && mfi < 5)
+		mfi = rate * (pdf+1) / quad_parent_rate;
+	if (mfi > 15)
+		return -EINVAL;
+	pdf--;
+
+	temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
+	do_div(temp64, quad_parent_rate/1000000);
+	mfn = (long)temp64;
+
+	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+	/* use dpdck0_2 */
+	__raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
+	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
+	if (pll_hfsm == 0) {
+		reg = mfi << 4 | pdf;
+		__raw_writel(reg, pllbase + MXC_PLL_DP_OP);
+		__raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
+		__raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
+	} else {
+		reg = mfi << 4 | pdf;
+		__raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
+		__raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
+		__raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
+	}
+
+	return 0;
+}
+
+static long clk_pllv2_round_rate(struct clk *clk, unsigned long rate)
+{
+	return rate;
+}
+
+static int clk_pllv2_enable(struct clk *clk)
+{
+	struct clk_pllv2 *pll = to_clk_pllv2(clk);
+	u32 reg;
+	void __iomem *pllbase;
+	int i = 0;
+
+	pllbase = pll->base;
+	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
+	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+
+	/* Wait for lock */
+	do {
+		reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
+		if (reg & MXC_PLL_DP_CTL_LRF)
+			break;
+
+		udelay(1);
+	} while (++i < MAX_DPLL_WAIT_TRIES);
+
+	if (i == MAX_DPLL_WAIT_TRIES) {
+		pr_err("MX5: pll locking failed\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void clk_pllv2_disable(struct clk *clk)
+{
+	struct clk_pllv2 *pll = to_clk_pllv2(clk);
+	u32 reg;
+	void __iomem *pllbase;
+
+	pllbase = pll->base;
+	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
+	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
+}
+
+static struct clk *clk_pllv2_get_parent(struct clk *clk)
+{
+	struct clk_pllv2 *pll = to_clk_pllv2(clk);
+
+	return pll->parent;
+}
+
+struct clk_ops clk_pllv2_ops = {
+	.enable = clk_pllv2_enable,
+	.disable = clk_pllv2_disable,
+	.get_rate = clk_pllv2_get_rate,
+	.round_rate = clk_pllv2_round_rate,
+	.set_rate = clk_pllv2_set_rate,
+	.get_parent = clk_pllv2_get_parent,
+//	.set_parent = clk_parent_set_parent,
+};
+
-- 
1.7.4.1

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

* [PATCH 09/10] ARM i.MX51/53: reimplement clock support
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (7 preceding siblings ...)
  2011-04-15 19:08 ` [PATCH 08/10] ARM i.MX: Add generic support for pllv2 Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-15 19:08 ` [PATCH 10/10] ARM i.MX51/53: remove old " Sascha Hauer
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

Reimplement i.MX51/53 clock support. This is tested with a babbage
board and a loco board up to the point that UARTs, FEC and USB work.
There are surely bugs left in the code, but I found several in the
old code while reimplementing it, so who cares...
The implementation is mostly based on the datasheet and not the old
code.

The old code is left in the tree and removed in the next patch.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-mx5/Kconfig               |    6 +
 arch/arm/mach-mx5/Makefile              |    2 +-
 arch/arm/mach-mx5/clock-imx51-imx53.c   |  420 +++++++++++++++++++++++++++++++
 arch/arm/plat-mxc/include/mach/clkdev.h |    2 +
 arch/arm/plat-mxc/include/mach/clock.h  |    3 +
 5 files changed, 432 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-mx5/clock-imx51-imx53.c

diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 159340d..c39cf42 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -26,12 +26,18 @@ config	SOC_IMX51
 	select ARCH_MXC_AUDMUX_V2
 	select ARCH_HAS_CPUFREQ
 	select ARCH_MX51
+	select USE_COMMON_STRUCT_CLK
+	select USE_COMMON_CLK_DIVIDER
+	select USE_COMMON_CLK_MUX
 
 config	SOC_IMX53
 	bool
 	select MXC_TZIC
 	select ARCH_MXC_IOMUX_V3
 	select ARCH_MX53
+	select USE_COMMON_STRUCT_CLK
+	select USE_COMMON_CLK_DIVIDER
+        select USE_COMMON_CLK_MUX
 
 comment "MX5 platforms:"
 
diff --git a/arch/arm/mach-mx5/Makefile b/arch/arm/mach-mx5/Makefile
index 0b9338c..164d300 100644
--- a/arch/arm/mach-mx5/Makefile
+++ b/arch/arm/mach-mx5/Makefile
@@ -3,7 +3,7 @@
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
+obj-y   := cpu.o mm.o clock-imx51-imx53.o devices.o ehci.o system.o
 obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
diff --git a/arch/arm/mach-mx5/clock-imx51-imx53.c b/arch/arm/mach-mx5/clock-imx51-imx53.c
new file mode 100644
index 0000000..27b6c63
--- /dev/null
+++ b/arch/arm/mach-mx5/clock-imx51-imx53.c
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2010 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/clkdev.h>
+
+#include <asm/div64.h>
+
+#include <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/clock.h>
+
+#include "crm_regs.h"
+
+static DEFINE_CLK_FIXED(ckil, 0);
+static DEFINE_CLK_FIXED(osc, 0);
+static DEFINE_CLK_FIXED(ckih1, 0);
+static DEFINE_CLK_FIXED(ckih2, 0);
+
+static DEFINE_CLK_PLLV2(pll1_sw, &osc.clk, MX51_DPLL1_BASE);
+static DEFINE_CLK_PLLV2(pll2_sw, &osc.clk, MX51_DPLL2_BASE);
+static DEFINE_CLK_PLLV2(pll3_sw, &osc.clk, MX51_DPLL3_BASE);
+static DEFINE_CLK_PLLV2(pll4_sw, &osc.clk, MX53_DPLL4_BASE);
+
+static DEFINE_CLK_FIXED(dummy, 0);
+
+/* Low-power Audio Playback Mode clock */
+static struct clk *lp_apm_sel[] = {
+	&osc.clk,
+	NULL,
+};
+static DEFINE_CLK_MUX(lp_apm, MXC_CCM_CCSR, 9, 1, lp_apm_sel);
+
+/* This is used multiple times */
+static struct clk *standard_pll_sel_clks[] = {
+	&pll1_sw.clk,
+	&pll2_sw.clk,
+	&pll3_sw.clk,
+	&lp_apm.clk,
+};
+
+static struct clk *periph_apm_sel[] = {
+	&pll1_sw.clk,
+	&pll3_sw.clk,
+	&lp_apm.clk,
+	NULL,
+};
+static DEFINE_CLK_MUX(periph_apm, MXC_CCM_CBCMR, 12, 2, periph_apm_sel);
+
+static struct clk *main_bus_sel[] = {
+	&pll2_sw.clk,
+	&periph_apm.clk,
+};
+static DEFINE_CLK_MUX(main_bus, MXC_CCM_CBCDR, 25, 1, main_bus_sel);
+
+static DEFINE_CLK_DIVIDER(ahb_root, &main_bus.clk, MXC_CCM_CBCDR, 10, 3);
+static DEFINE_CLK_DIVIDER(ipg, &ahb_root.clk, MXC_CCM_CBCDR, 8, 2);
+
+static DEFINE_CLK_MUX(uart_sel, MXC_CCM_CSCMR1, 24, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(uart_pred, &uart_sel.clk, MXC_CCM_CSCDR1, 3, 3);
+static DEFINE_CLK_DIVIDER(uart_root, &uart_pred.clk, MXC_CCM_CSCDR1, 0, 3);
+
+static DEFINE_CLK_MUX(esdhc1_sel, MXC_CCM_CSCMR1, 20, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(esdhc1_pred, &esdhc1_sel.clk, MXC_CCM_CSCDR1, 16, 3);
+static DEFINE_CLK_DIVIDER(esdhc1_podf, &esdhc1_pred.clk, MXC_CCM_CSCDR1, 11, 3);
+
+/* This is routed to esdhc3 in the i.MX53 datasheet */
+static DEFINE_CLK_MUX(esdhc2_sel, MXC_CCM_CSCMR1, 16, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(esdhc2_pred, &esdhc2_sel.clk, MXC_CCM_CSCDR1, 22, 3);
+static DEFINE_CLK_DIVIDER(esdhc2_podf, &esdhc2_pred.clk, MXC_CCM_CSCDR1, 19, 3);
+
+static struct clk *esdhc3_sel_clks[] = {
+	&esdhc1_podf.clk,
+	&esdhc2_podf.clk,
+};
+static DEFINE_CLK_MUX(esdhc3_sel, MXC_CCM_CSCMR1, 19, 1, esdhc3_sel_clks);
+
+static struct clk *esdhc4_sel_clks[] = {
+	&esdhc1_podf.clk,
+	&esdhc2_podf.clk,
+};
+static DEFINE_CLK_MUX(esdhc4_sel, MXC_CCM_CSCMR1, 18, 1, esdhc4_sel_clks);
+
+static struct clk *emi_slow_sel_clks[] = {
+	&main_bus.clk,
+	&ahb_root.clk,
+};
+static DEFINE_CLK_MUX(emi_sel, MXC_CCM_CBCDR, 26, 1, emi_slow_sel_clks);
+static DEFINE_CLK_DIVIDER(emi_slow_podf, &emi_sel.clk, MXC_CCM_CBCDR, 22, 3);
+static DEFINE_CLK_DIVIDER(nfc_podf, &emi_slow_podf.clk, MXC_CCM_CBCDR, 13, 3);
+
+static DEFINE_CLK_MUX(ecspi_sel, MXC_CCM_CSCMR1, 4, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(ecspi_pred, &ecspi_sel.clk, MXC_CCM_CSCDR2, 25, 3);
+static DEFINE_CLK_DIVIDER(ecspi_podf, &ecspi_pred.clk, MXC_CCM_CSCDR2, 19, 6);
+
+static DEFINE_CLK_MUX(usboh3_sel, MXC_CCM_CSCMR1, 22, 2, standard_pll_sel_clks);
+static DEFINE_CLK_DIVIDER(usboh3_pred, &usboh3_sel.clk, MXC_CCM_CSCDR1, 8, 3);
+static DEFINE_CLK_DIVIDER(usboh3_podf, &usboh3_pred.clk, MXC_CCM_CSCDR1, 6, 2);
+
+static DEFINE_CLK_DIVIDER(usb_phy_pred, &pll3_sw.clk, MXC_CCM_CDCDR, 3, 3);
+static DEFINE_CLK_DIVIDER(usb_phy_podf, &usb_phy_pred.clk, MXC_CCM_CDCDR, 0, 3);
+static struct clk *usb_phy_sel_clks[] = {
+	&osc.clk,
+	&usb_phy_podf.clk,
+};
+static DEFINE_CLK_MUX(usb_phy_sel, MXC_CCM_CSCMR1, 26, 1, usb_phy_sel_clks);
+
+static DEFINE_CLK_DIVIDER(cpu_podf, &pll1_sw.clk, MXC_CCM_CACRR, 0, 3);
+
+static struct clk *ipu_di0_sel_clks[] = {
+	&pll3_sw.clk,
+	&osc.clk,
+	&ckih1.clk,
+	NULL, /* &tve_di.clk */
+	NULL, /* ipp di0 (iomux) */
+	NULL, /* ldp di0 */
+};
+static DEFINE_CLK_MUX(ipu_di0_sel, MXC_CCM_CSCMR2, 26, 3, ipu_di0_sel_clks);
+
+static struct clk *ipu_di1_sel_clks[] = {
+	&pll3_sw.clk,
+	&osc.clk,
+	&ckih1.clk,
+	NULL, /* &tve_di.clk */
+	NULL, /* ipp di1 (iomux) */
+	NULL, /* ldp di1 */
+};
+static DEFINE_CLK_MUX(ipu_di1_sel, MXC_CCM_CSCMR2, 29, 3, ipu_di1_sel_clks);
+
+static struct clk *tve_ext_sel_clks[] = {
+	&osc.clk,
+	&ckih1.clk,
+};
+static DEFINE_CLK_MUX(tve_ext_sel, MXC_CCM_CSCMR1, 6, 1, tve_ext_sel_clks);
+
+static DEFINE_CLK_DIVIDER(tve_pred, &pll3_sw.clk, MXC_CCM_CDCDR, 28, 3);
+
+static struct clk *tve_sel_clks[] = {
+	&tve_pred.clk,
+	&tve_ext_sel.clk,
+};
+static DEFINE_CLK_MUX(tve_sel, MXC_CCM_CSCMR1, 7, 1, tve_sel_clks);
+
+static DEFINE_CLK_GATE_2(iim_gate, &ipg.clk, MXC_CCM_CCGR0, 30);
+
+static DEFINE_CLK_GATE_2(uart1_ipg_gate, &ipg.clk, MXC_CCM_CCGR1, 6);
+static DEFINE_CLK_GATE_2(uart1_per_gate, &uart_root.clk, MXC_CCM_CCGR1, 8);
+static DEFINE_CLK_GATE_2(uart2_ipg_gate, &ipg.clk, MXC_CCM_CCGR1, 10);
+static DEFINE_CLK_GATE_2(uart2_per_gate, &uart_root.clk, MXC_CCM_CCGR1, 12);
+static DEFINE_CLK_GATE_2(uart3_ipg_gate, &ipg.clk, MXC_CCM_CCGR1, 14);
+static DEFINE_CLK_GATE_2(uart3_per_gate, &uart_root.clk, MXC_CCM_CCGR1, 16);
+static DEFINE_CLK_GATE_2(i2c1_gate, &ipg.clk, MXC_CCM_CCGR1, 18);
+static DEFINE_CLK_GATE_2(i2c2_gate, &ipg.clk, MXC_CCM_CCGR1, 20);
+static DEFINE_CLK_GATE_2(hsi2c_gate, &ipg.clk, MXC_CCM_CCGR1, 22);
+
+static DEFINE_CLK_GATE_2(mx51_usb_phy_gate, &usb_phy_sel.clk, MXC_CCM_CCGR2, 0);
+static DEFINE_CLK_GATE_2(gpt_ipg_gate, &ipg.clk, MXC_CCM_CCGR2, 20);
+static DEFINE_CLK_GATE_2(pwm1_ipg_gate, &ipg.clk, MXC_CCM_CCGR2, 10);
+static DEFINE_CLK_GATE_2(pwm1_hf_gate, &ipg.clk, MXC_CCM_CCGR2, 12);
+static DEFINE_CLK_GATE_2(pwm2_ipg_gate, &ipg.clk, MXC_CCM_CCGR2, 14);
+static DEFINE_CLK_GATE_2(pwm2_hf_gate, &ipg.clk, MXC_CCM_CCGR2, 16);
+static DEFINE_CLK_GATE_2(gpt_gate, &ipg.clk, MXC_CCM_CCGR2, 18);
+static DEFINE_CLK_GATE_2(fec_gate, &ipg.clk, MXC_CCM_CCGR2, 24);
+static DEFINE_CLK_GATE_2(usboh3_ahb_gate, &ipg.clk, MXC_CCM_CCGR2, 26);
+static DEFINE_CLK_GATE_2(usboh3_gate, &usboh3_podf.clk, MXC_CCM_CCGR2, 28);
+static DEFINE_CLK_GATE_2(tve_gate, &tve_sel.clk, MXC_CCM_CCGR2, 30);
+
+static DEFINE_CLK_GATE_2(esdhc1_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 0);
+static DEFINE_CLK_GATE_2(esdhc1_per_gate, &esdhc1_podf.clk, MXC_CCM_CCGR3, 2);
+static DEFINE_CLK_GATE_2(esdhc2_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 4);
+static DEFINE_CLK_GATE_2(esdhc2_per_gate, &esdhc2_podf.clk, MXC_CCM_CCGR3, 6);
+static DEFINE_CLK_GATE_2(esdhc3_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 8);
+static DEFINE_CLK_GATE_2(esdhc3_per_gate, &esdhc3_sel.clk, MXC_CCM_CCGR3, 10);
+static DEFINE_CLK_GATE_2(esdhc4_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 12);
+static DEFINE_CLK_GATE_2(esdhc4_per_gate, &esdhc4_sel.clk, MXC_CCM_CCGR3, 14);
+static DEFINE_CLK_GATE_2(ssi1_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 16);
+static DEFINE_CLK_GATE_2(ssi2_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 18);
+static DEFINE_CLK_GATE_2(ssi3_ipg_gate, &ipg.clk, MXC_CCM_CCGR3, 20);
+
+static DEFINE_CLK_GATE_2(mx51_mipi_hsc1_gate, &ipg.clk, MXC_CCM_CCGR4, 6);
+static DEFINE_CLK_GATE_2(mx51_mipi_hsc2_gate, &ipg.clk, MXC_CCM_CCGR4, 8);
+static DEFINE_CLK_GATE_2(mx51_mipi_esc_gate, &ipg.clk, MXC_CCM_CCGR4, 10);
+static DEFINE_CLK_GATE_2(mx51_mipi_hsp_gate, &ipg.clk, MXC_CCM_CCGR4, 12);
+
+static DEFINE_CLK_GATE_2(mx53_usb_phy1_gate, &usb_phy_sel.clk, MXC_CCM_CCGR4, 10);
+static DEFINE_CLK_GATE_2(mx53_usb_phy2_gate, &usb_phy_sel.clk, MXC_CCM_CCGR4, 12);
+static DEFINE_CLK_GATE_2(ecspi1_ipg_gate, &ipg.clk, MXC_CCM_CCGR4, 18);
+static DEFINE_CLK_GATE_2(ecspi1_per_gate, &ecspi_podf.clk, MXC_CCM_CCGR4, 20);
+static DEFINE_CLK_GATE_2(ecspi2_ipg_gate, &ipg.clk, MXC_CCM_CCGR4, 22);
+static DEFINE_CLK_GATE_2(ecspi2_per_gate, &ecspi_podf.clk, MXC_CCM_CCGR4, 24);
+static DEFINE_CLK_GATE_2(cspi_ipg_gate, &ipg.clk, MXC_CCM_CCGR4, 26);
+static DEFINE_CLK_GATE_2(sdma_gate, &ipg.clk, MXC_CCM_CCGR4, 30);
+
+static DEFINE_CLK_GATE_2(ipu_gate, &ahb_root.clk, MXC_CCM_CCGR5, 10);
+static DEFINE_CLK_GATE_2(emi_fast_gate, &dummy.clk, MXC_CCM_CCGR5, 16);
+static DEFINE_CLK_GATE_2(emi_slow_gate, &emi_slow_podf.clk, MXC_CCM_CCGR5, 16);
+static DEFINE_CLK_GATE_2(nfc_gate, &nfc_podf.clk, MXC_CCM_CCGR5, 20);
+
+static DEFINE_CLK_GATE_2(ipu_di0_gate, &ipu_di0_sel.clk, MXC_CCM_CCGR6, 10);
+static DEFINE_CLK_GATE_2(ipu_di1_gate, &ipu_di1_sel.clk, MXC_CCM_CCGR6, 12);
+
+static struct clk *uart1_group[] = {
+	&uart1_per_gate.clk,
+	&uart1_ipg_gate.clk
+};
+static DEFINE_CLK_GROUP(uart1, uart1_group);
+
+static struct clk *uart2_group[] = {
+	&uart2_per_gate.clk,
+	&uart2_ipg_gate.clk
+};
+static DEFINE_CLK_GROUP(uart2, uart2_group);
+
+static struct clk *uart3_group[] = {
+	&uart3_per_gate.clk,
+	&uart3_ipg_gate.clk
+};
+static DEFINE_CLK_GROUP(uart3, uart3_group);
+
+static struct clk *gpt_group[] = {
+	&gpt_gate.clk,
+	&gpt_ipg_gate.clk,
+};
+static DEFINE_CLK_GROUP(gpt, gpt_group);
+
+static struct clk *esdhc1_group[] = {
+	&esdhc1_per_gate.clk,
+	&esdhc1_ipg_gate.clk,
+};
+static DEFINE_CLK_GROUP(esdhc1, esdhc1_group);
+
+static struct clk *esdhc2_group[] = {
+	&esdhc2_per_gate.clk,
+	&esdhc2_ipg_gate.clk,
+};
+static DEFINE_CLK_GROUP(esdhc2, esdhc2_group);
+
+static struct clk *esdhc3_group[] = {
+	&esdhc3_per_gate.clk,
+	&esdhc3_ipg_gate.clk,
+};
+static DEFINE_CLK_GROUP(esdhc3, esdhc3_group);
+
+static struct clk *esdhc4_group[] = {
+	&esdhc4_per_gate.clk,
+	&esdhc4_ipg_gate.clk,
+};
+static DEFINE_CLK_GROUP(esdhc4, esdhc4_group);
+
+static struct clk *ecspi1_group[] = {
+	&ecspi1_per_gate.clk,
+	&ecspi1_ipg_gate.clk,
+};
+static DEFINE_CLK_GROUP(ecspi1, ecspi1_group);
+
+static struct clk *ecspi2_group[] = {
+	&ecspi2_per_gate.clk,
+	&ecspi2_ipg_gate.clk,
+};
+static DEFINE_CLK_GROUP(ecspi2, ecspi2_group);
+
+static struct clk *cspi_group[] = {
+	&ecspi1_per_gate.clk,
+	&cspi_ipg_gate.clk,
+};
+static DEFINE_CLK_GROUP(cspi, cspi_group);
+
+static struct clk *mx51_mipi_group[] = {
+	&mx51_mipi_hsp_gate.clk,
+	&mx51_mipi_hsc1_gate.clk,
+	&mx51_mipi_hsc2_gate.clk,
+	&mx51_mipi_esc_gate.clk,
+};
+static DEFINE_CLK_GROUP(mx51_mipi, mx51_mipi_group);
+
+static struct clk *ipu_group_clks[] = {
+	&ipu_gate.clk,
+	&emi_fast_gate.clk,
+};
+static DEFINE_CLK_GROUP(ipu, ipu_group_clks);
+
+#define _REGISTER_CLOCK(d, n, c) \
+       { \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = c,   \
+       },
+
+static struct clk_lookup mx5_lookups[] = {
+	_REGISTER_CLOCK("imx-uart.0", NULL, &uart1.clk)
+	_REGISTER_CLOCK("imx-uart.1", NULL, &uart2.clk)
+	_REGISTER_CLOCK("imx-uart.2", NULL, &uart3.clk)
+	_REGISTER_CLOCK("fec.0", NULL, &fec_gate.clk)
+	_REGISTER_CLOCK("mxc_pwm.0", "pwm", &pwm1_ipg_gate.clk)
+	_REGISTER_CLOCK("mxc_pwm.1", "pwm", &pwm2_ipg_gate.clk)
+	_REGISTER_CLOCK("imx-i2c.0", NULL, &i2c1_gate.clk)
+	_REGISTER_CLOCK("imx-i2c.1", NULL, &i2c2_gate.clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb", &usboh3_gate.clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", &usboh3_ahb_gate.clk)
+	_REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", &mx53_usb_phy1_gate.clk)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb", &usboh3_gate.clk)
+	_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", &usboh3_ahb_gate.clk)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb", &usboh3_gate.clk)
+	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", &usboh3_ahb_gate.clk)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb", &usboh3_gate.clk)
+	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", &usboh3_ahb_gate.clk)
+	_REGISTER_CLOCK("mxc_nand", NULL, &nfc_gate.clk)
+	_REGISTER_CLOCK("imx-ssi.0", NULL, &ssi1_ipg_gate.clk)
+	_REGISTER_CLOCK("imx-ssi.1", NULL, &ssi1_ipg_gate.clk)
+	_REGISTER_CLOCK("imx-ssi.2", NULL, &ssi1_ipg_gate.clk)
+	_REGISTER_CLOCK("imx-sdma", NULL, &sdma_gate.clk)
+	_REGISTER_CLOCK("imx51-ecspi.0", NULL, &ecspi1.clk)
+	_REGISTER_CLOCK("imx51-ecspi.1", NULL, &ecspi2.clk)
+	_REGISTER_CLOCK("imx51-cspi.0", NULL, &cspi.clk)
+	_REGISTER_CLOCK(NULL, "cpu", &cpu_podf.clk)
+	_REGISTER_CLOCK(NULL, "iim", &iim_gate.clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, &esdhc1.clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, &esdhc2.clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, &esdhc3.clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, &esdhc4.clk)
+	_REGISTER_CLOCK("imx-ipuv3", NULL, &ipu.clk)
+	_REGISTER_CLOCK("imx-ipuv3", "di0", &ipu_di0_gate.clk)
+	_REGISTER_CLOCK("imx-ipuv3", "di1", &ipu_di1_gate.clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, &dummy.clk)
+	_REGISTER_CLOCK("imx2-wdt.1", NULL, &dummy.clk)
+	_REGISTER_CLOCK("imx-keypad", NULL, &dummy.clk)
+};
+
+static struct clk_lookup mx51_lookups[] = {
+	_REGISTER_CLOCK("imx-i2c.2", NULL, &hsi2c_gate.clk)
+	_REGISTER_CLOCK(NULL, "mipi_hsp", &mx51_mipi.clk)
+};
+
+static void clkdev_add_array(struct clk_lookup *lookup, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++)
+		clkdev_add(&lookup[i]);
+}
+
+static void mx5_clocks_common_init(unsigned long rate_ckil, unsigned long rate_osc,
+			unsigned long rate_ckih1, unsigned long rate_ckih2)
+{
+	ckil.rate = rate_ckil;
+	osc.rate = rate_osc;
+	ckih1.rate = rate_ckih1;
+	ckih2.rate = rate_ckih2;
+
+	clkdev_add_array(mx5_lookups, ARRAY_SIZE(mx5_lookups));
+
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_sel.clk, &pll2_sw.clk);
+	clk_set_parent(&esdhc2_sel.clk, &pll2_sw.clk);
+}
+
+int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
+			unsigned long rate_ckih1, unsigned long rate_ckih2)
+{
+	/* Clock tree has i.MX51 layout. i.MX53 needs some fixups */
+	pll1_sw.base = MX53_DPLL1_BASE;
+	pll2_sw.base = MX53_DPLL2_BASE;
+	pll3_sw.base = MX53_DPLL3_BASE;
+	esdhc3_per_gate.parent = &esdhc2_podf.clk;
+	esdhc2_per_gate.parent = &esdhc3_sel.clk;
+	tve_gate.parent = &tve_pred.clk;
+	tve_pred.parent = &tve_ext_sel.clk;
+	tve_ext_sel_clks[0] = &pll4_sw.clk;
+	tve_ext_sel_clks[1] = &ckih1.clk;
+
+	mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
+
+	/* set SDHC root clock to 200MHZ*/
+	clk_set_rate(&esdhc1_podf.clk, 200000000);
+	clk_set_rate(&esdhc2_podf.clk, 200000000);
+
+	/* System timer */
+	mxc_timer_init(&gpt.clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
+		MX53_INT_GPT);
+
+	clk_prepare(&iim_gate.clk);
+	clk_enable(&iim_gate.clk);
+	mx53_revision();
+	clk_disable(&iim_gate.clk);
+
+	return 0;
+}
+
+int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
+			unsigned long rate_ckih1, unsigned long rate_ckih2)
+{
+	mx5_clocks_common_init(rate_ckil, rate_osc, rate_ckih1, rate_ckih2);
+	clkdev_add_array(mx51_lookups, ARRAY_SIZE(mx51_lookups));
+
+	/* set SDHC root clock to 166.25MHZ*/
+	clk_set_rate(&esdhc1_podf.clk, 166250000);
+	clk_set_rate(&esdhc2_podf.clk, 166250000);
+
+	/* System timer */
+	mxc_timer_init(&gpt.clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
+		MX51_MXC_INT_GPT);
+
+	clk_prepare(&iim_gate.clk);
+	clk_enable(&iim_gate.clk);
+	mx51_revision();
+	clk_disable(&iim_gate.clk);
+	mx51_display_revision();
+
+	return 0;
+}
diff --git a/arch/arm/plat-mxc/include/mach/clkdev.h b/arch/arm/plat-mxc/include/mach/clkdev.h
index 04b37a8..ad1e227 100644
--- a/arch/arm/plat-mxc/include/mach/clkdev.h
+++ b/arch/arm/plat-mxc/include/mach/clkdev.h
@@ -1,7 +1,9 @@
 #ifndef __ASM_MACH_CLKDEV_H
 #define __ASM_MACH_CLKDEV_H
 
+#ifndef CONFIG_USE_COMMON_STRUCT_CLK
 #define __clk_get(clk) ({ 1; })
 #define __clk_put(clk) do { } while (0)
+#endif
 
 #endif
diff --git a/arch/arm/plat-mxc/include/mach/clock.h b/arch/arm/plat-mxc/include/mach/clock.h
index 4943ab0..cc11577 100644
--- a/arch/arm/plat-mxc/include/mach/clock.h
+++ b/arch/arm/plat-mxc/include/mach/clock.h
@@ -25,6 +25,8 @@
 
 struct module;
 
+#ifdef CONFIG_USE_COMMON_STRUCT_CLK
+#else
 struct clk {
 	int id;
 	/* Source clock this clk depends on */
@@ -56,6 +58,7 @@ struct clk {
 	/* Function ptr to set the parent clock of the clock. */
 	int (*set_parent) (struct clk *, struct clk *);
 };
+#endif
 
 unsigned long mxc_decode_pll(unsigned int pll, u32 f_ref);
 
-- 
1.7.4.1

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

* [PATCH 10/10] ARM i.MX51/53: remove old clock support
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (8 preceding siblings ...)
  2011-04-15 19:08 ` [PATCH 09/10] ARM i.MX51/53: reimplement clock support Sascha Hauer
@ 2011-04-15 19:08 ` Sascha Hauer
  2011-04-15 19:36 ` [RFC] sanitizing crazy clock data files Russell King - ARM Linux
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 19:08 UTC (permalink / raw)
  To: linux-arm-kernel

reimplemented and not used anymore.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-mx5/clock-mx51-mx53.c | 1579 -----------------------------------
 arch/arm/mach-mx5/crm_regs.h        |  249 +------
 2 files changed, 1 insertions(+), 1827 deletions(-)
 delete mode 100644 arch/arm/mach-mx5/clock-mx51-mx53.c

diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
deleted file mode 100644
index fdbc05e..0000000
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ /dev/null
@@ -1,1579 +0,0 @@
-/*
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2009-2010 Amit Kucheria <amit.kucheria@canonical.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-
-#include <asm/div64.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/clock.h>
-
-#include "crm_regs.h"
-
-/* External clock values passed-in by the board code */
-static unsigned long external_high_reference, external_low_reference;
-static unsigned long oscillator_reference, ckih2_reference;
-
-static struct clk osc_clk;
-static struct clk pll1_main_clk;
-static struct clk pll1_sw_clk;
-static struct clk pll2_sw_clk;
-static struct clk pll3_sw_clk;
-static struct clk mx53_pll4_sw_clk;
-static struct clk lp_apm_clk;
-static struct clk periph_apm_clk;
-static struct clk ahb_clk;
-static struct clk ipg_clk;
-static struct clk usboh3_clk;
-static struct clk emi_fast_clk;
-static struct clk ipu_clk;
-static struct clk mipi_hsc1_clk;
-static struct clk esdhc1_clk;
-static struct clk esdhc2_clk;
-static struct clk esdhc3_mx53_clk;
-
-#define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
-
-/* calculate best pre and post dividers to get the required divider */
-static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,
-	u32 max_pre, u32 max_post)
-{
-	if (div >= max_pre * max_post) {
-		*pre = max_pre;
-		*post = max_post;
-	} else if (div >= max_pre) {
-		u32 min_pre, temp_pre, old_err, err;
-		min_pre = DIV_ROUND_UP(div, max_post);
-		old_err = max_pre;
-		for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {
-			err = div % temp_pre;
-			if (err == 0) {
-				*pre = temp_pre;
-				break;
-			}
-			err = temp_pre - err;
-			if (err < old_err) {
-				old_err = err;
-				*pre = temp_pre;
-			}
-		}
-		*post = DIV_ROUND_UP(div, *pre);
-	} else {
-		*pre = div;
-		*post = 1;
-	}
-}
-
-static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
-{
-	u32 reg = __raw_readl(clk->enable_reg);
-
-	reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);
-	reg |= mode << clk->enable_shift;
-
-	__raw_writel(reg, clk->enable_reg);
-}
-
-static int _clk_ccgr_enable(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);
-	return 0;
-}
-
-static void _clk_ccgr_disable(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);
-}
-
-static int _clk_ccgr_enable_inrun(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
-	return 0;
-}
-
-static void _clk_ccgr_disable_inwait(struct clk *clk)
-{
-	_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);
-}
-
-/*
- * For the 4-to-1 muxed input clock
- */
-static inline u32 _get_mux(struct clk *parent, struct clk *m0,
-			   struct clk *m1, struct clk *m2, struct clk *m3)
-{
-	if (parent == m0)
-		return 0;
-	else if (parent == m1)
-		return 1;
-	else if (parent == m2)
-		return 2;
-	else if (parent == m3)
-		return 3;
-	else
-		BUG();
-
-	return -EINVAL;
-}
-
-static inline void __iomem *_mx51_get_pll_base(struct clk *pll)
-{
-	if (pll == &pll1_main_clk)
-		return MX51_DPLL1_BASE;
-	else if (pll == &pll2_sw_clk)
-		return MX51_DPLL2_BASE;
-	else if (pll == &pll3_sw_clk)
-		return MX51_DPLL3_BASE;
-	else
-		BUG();
-
-	return NULL;
-}
-
-static inline void __iomem *_mx53_get_pll_base(struct clk *pll)
-{
-	if (pll == &pll1_main_clk)
-		return MX53_DPLL1_BASE;
-	else if (pll == &pll2_sw_clk)
-		return MX53_DPLL2_BASE;
-	else if (pll == &pll3_sw_clk)
-		return MX53_DPLL3_BASE;
-	else if (pll == &mx53_pll4_sw_clk)
-		return MX53_DPLL4_BASE;
-	else
-		BUG();
-
-	return NULL;
-}
-
-static inline void __iomem *_get_pll_base(struct clk *pll)
-{
-	if (cpu_is_mx51())
-		return _mx51_get_pll_base(pll);
-	else
-		return _mx53_get_pll_base(pll);
-}
-
-static unsigned long clk_pll_get_rate(struct clk *clk)
-{
-	long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
-	unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;
-	void __iomem *pllbase;
-	s64 temp;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	pllbase = _get_pll_base(clk);
-
-	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
-	dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
-
-	if (pll_hfsm == 0) {
-		dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
-		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
-		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
-	} else {
-		dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
-		dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
-		dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
-	}
-	pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
-	mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
-	mfi = (mfi <= 5) ? 5 : mfi;
-	mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
-	mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
-	/* Sign extend to 32-bits */
-	if (mfn >= 0x04000000) {
-		mfn |= 0xFC000000;
-		mfn_abs = -mfn;
-	}
-
-	ref_clk = 2 * parent_rate;
-	if (dbl != 0)
-		ref_clk *= 2;
-
-	ref_clk /= (pdf + 1);
-	temp = (u64) ref_clk * mfn_abs;
-	do_div(temp, mfd + 1);
-	if (mfn < 0)
-		temp = -temp;
-	temp = (ref_clk * mfi) + temp;
-
-	return temp;
-}
-
-static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg;
-	void __iomem *pllbase;
-
-	long mfi, pdf, mfn, mfd = 999999;
-	s64 temp64;
-	unsigned long quad_parent_rate;
-	unsigned long pll_hfsm, dp_ctl;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	pllbase = _get_pll_base(clk);
-
-	quad_parent_rate = 4 * parent_rate;
-	pdf = mfi = -1;
-	while (++pdf < 16 && mfi < 5)
-		mfi = rate * (pdf+1) / quad_parent_rate;
-	if (mfi > 15)
-		return -EINVAL;
-	pdf--;
-
-	temp64 = rate * (pdf+1) - quad_parent_rate * mfi;
-	do_div(temp64, quad_parent_rate/1000000);
-	mfn = (long)temp64;
-
-	dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-	/* use dpdck0_2 */
-	__raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);
-	pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;
-	if (pll_hfsm == 0) {
-		reg = mfi << 4 | pdf;
-		__raw_writel(reg, pllbase + MXC_PLL_DP_OP);
-		__raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);
-		__raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);
-	} else {
-		reg = mfi << 4 | pdf;
-		__raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);
-		__raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);
-		__raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);
-	}
-
-	return 0;
-}
-
-static int _clk_pll_enable(struct clk *clk)
-{
-	u32 reg;
-	void __iomem *pllbase;
-	int i = 0;
-
-	pllbase = _get_pll_base(clk);
-	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;
-	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-
-	/* Wait for lock */
-	do {
-		reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);
-		if (reg & MXC_PLL_DP_CTL_LRF)
-			break;
-
-		udelay(1);
-	} while (++i < MAX_DPLL_WAIT_TRIES);
-
-	if (i == MAX_DPLL_WAIT_TRIES) {
-		pr_err("MX5: pll locking failed\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void _clk_pll_disable(struct clk *clk)
-{
-	u32 reg;
-	void __iomem *pllbase;
-
-	pllbase = _get_pll_base(clk);
-	reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;
-	__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
-}
-
-static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, step;
-
-	reg = __raw_readl(MXC_CCM_CCSR);
-
-	/* When switching from pll_main_clk to a bypass clock, first select a
-	 * multiplexed clock in 'step_sel', then shift the glitchless mux
-	 * 'pll1_sw_clk_sel'.
-	 *
-	 * When switching back, do it in reverse order
-	 */
-	if (parent == &pll1_main_clk) {
-		/* Switch to pll1_main_clk */
-		reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
-		__raw_writel(reg, MXC_CCM_CCSR);
-		/* step_clk mux switched to lp_apm, to save power. */
-		reg = __raw_readl(MXC_CCM_CCSR);
-		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
-		reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<
-				MXC_CCM_CCSR_STEP_SEL_OFFSET);
-	} else {
-		if (parent == &lp_apm_clk) {
-			step = MXC_CCM_CCSR_STEP_SEL_LP_APM;
-		} else  if (parent == &pll2_sw_clk) {
-			step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;
-		} else  if (parent == &pll3_sw_clk) {
-			step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;
-		} else
-			return -EINVAL;
-
-		reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;
-		reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);
-
-		__raw_writel(reg, MXC_CCM_CCSR);
-		/* Switch to step_clk */
-		reg = __raw_readl(MXC_CCM_CCSR);
-		reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
-	}
-	__raw_writel(reg, MXC_CCM_CCSR);
-	return 0;
-}
-
-static unsigned long clk_pll1_sw_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CCSR);
-
-	if (clk->parent == &pll2_sw_clk) {
-		div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>
-		       MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;
-	} else if (clk->parent == &pll3_sw_clk) {
-		div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>
-		       MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;
-	} else
-		div = 1;
-	return parent_rate / div;
-}
-
-static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CCSR);
-
-	if (parent == &pll2_sw_clk)
-		reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-	else
-		reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;
-
-	__raw_writel(reg, MXC_CCM_CCSR);
-	return 0;
-}
-
-static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	if (parent == &osc_clk)
-		reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;
-	else
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_CCSR);
-
-	return 0;
-}
-
-static unsigned long clk_cpu_get_rate(struct clk *clk)
-{
-	u32 cacrr, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-	cacrr = __raw_readl(MXC_CCM_CACRR);
-	div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;
-
-	return parent_rate / div;
-}
-
-static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, cpu_podf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-	cpu_podf = parent_rate / rate - 1;
-	/* use post divider to change freq */
-	reg = __raw_readl(MXC_CCM_CACRR);
-	reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;
-	reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_CACRR);
-
-	return 0;
-}
-
-static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, mux;
-	int i = 0;
-
-	mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);
-
-	reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;
-	reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;
-	__raw_writel(reg, MXC_CCM_CBCMR);
-
-	/* Wait for lock */
-	do {
-		reg = __raw_readl(MXC_CCM_CDHIPR);
-		if (!(reg &  MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))
-			break;
-
-		udelay(1);
-	} while (++i < MAX_DPLL_WAIT_TRIES);
-
-	if (i == MAX_DPLL_WAIT_TRIES) {
-		pr_err("MX5: Set parent for periph_apm clock failed\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-
-	if (parent == &pll2_sw_clk)
-		reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-	else if (parent == &periph_apm_clk)
-		reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;
-	else
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_CBCDR);
-
-	return 0;
-}
-
-static struct clk main_bus_clk = {
-	.parent = &pll2_sw_clk,
-	.set_parent = _clk_main_bus_set_parent,
-};
-
-static unsigned long clk_ahb_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>
-	       MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;
-	return parent_rate / div;
-}
-
-
-static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-	int i = 0;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	div = parent_rate / rate;
-	if (div > 8 || div < 1 || ((parent_rate / div) != rate))
-		return -EINVAL;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;
-	reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_CBCDR);
-
-	/* Wait for lock */
-	do {
-		reg = __raw_readl(MXC_CCM_CDHIPR);
-		if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))
-			break;
-
-		udelay(1);
-	} while (++i < MAX_DPLL_WAIT_TRIES);
-
-	if (i == MAX_DPLL_WAIT_TRIES) {
-		pr_err("MX5: clk_ahb_set_rate failed\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static unsigned long _clk_ahb_round_rate(struct clk *clk,
-						unsigned long rate)
-{
-	u32 div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	div = parent_rate / rate;
-	if (div > 8)
-		div = 8;
-	else if (div == 0)
-		div++;
-	return parent_rate / div;
-}
-
-
-static int _clk_max_enable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_enable(clk);
-
-	/* Handshake with MAX when LPM is entered. */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	if (cpu_is_mx51())
-		reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	else if (cpu_is_mx53())
-		reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-
-	return 0;
-}
-
-static void _clk_max_disable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_disable_inwait(clk);
-
-	/* No Handshake with MAX when LPM is entered as its disabled. */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	if (cpu_is_mx51())
-		reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	else if (cpu_is_mx53())
-		reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static unsigned long clk_ipg_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>
-	       MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;
-
-	return parent_rate / div;
-}
-
-static unsigned long clk_ipg_per_get_rate(struct clk *clk)
-{
-	u32 reg, prediv1, prediv2, podf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {
-		/* the main_bus_clk is the one before the DVFS engine */
-		reg = __raw_readl(MXC_CCM_CBCDR);
-		prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>
-			   MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;
-		prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>
-			   MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;
-		podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>
-			MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;
-		return parent_rate / (prediv1 * prediv2 * podf);
-	} else if (clk->parent == &ipg_clk)
-		return parent_rate;
-	else
-		BUG();
-}
-
-static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CBCMR);
-
-	reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-	reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-
-	if (parent == &ipg_clk)
-		reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;
-	else if (parent == &lp_apm_clk)
-		reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;
-	else if (parent != &main_bus_clk)
-		return -EINVAL;
-
-	__raw_writel(reg, MXC_CCM_CBCMR);
-
-	return 0;
-}
-
-#define clk_nfc_set_parent	NULL
-
-static unsigned long clk_nfc_get_rate(struct clk *clk)
-{
-	unsigned long rate;
-	u32 reg, div;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>
-	       MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;
-	rate = clk_get_rate(clk->parent) / div;
-	WARN_ON(rate == 0);
-	return rate;
-}
-
-static unsigned long clk_nfc_round_rate(struct clk *clk,
-						unsigned long rate)
-{
-	u32 div;
-	unsigned long parent_rate = clk_get_rate(clk->parent);
-
-	if (!rate)
-		return -EINVAL;
-
-	div = parent_rate / rate;
-
-	if (parent_rate % rate)
-		div++;
-
-	if (div > 8)
-		return -EINVAL;
-
-	return parent_rate / div;
-
-}
-
-static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
-{
-	u32 reg, div;
-
-	div = clk_get_rate(clk->parent) / rate;
-	if (div == 0)
-		div++;
-	if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))
-		return -EINVAL;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;
-	reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;
-	__raw_writel(reg, MXC_CCM_CBCDR);
-
-	while (__raw_readl(MXC_CCM_CDHIPR) &
-			MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){
-	}
-
-	return 0;
-}
-
-static unsigned long get_high_reference_clock_rate(struct clk *clk)
-{
-	return external_high_reference;
-}
-
-static unsigned long get_low_reference_clock_rate(struct clk *clk)
-{
-	return external_low_reference;
-}
-
-static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)
-{
-	return oscillator_reference;
-}
-
-static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)
-{
-	return ckih2_reference;
-}
-
-static unsigned long clk_emi_slow_get_rate(struct clk *clk)
-{
-	u32 reg, div;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>
-	       MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;
-
-	return clk_get_rate(clk->parent) / div;
-}
-
-static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)
-{
-	unsigned long rate;
-	u32 reg, div;
-
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>
-		MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;
-	rate = clk_get_rate(clk->parent) / div;
-
-	return rate;
-}
-
-/* External high frequency clock */
-static struct clk ckih_clk = {
-	.get_rate = get_high_reference_clock_rate,
-};
-
-static struct clk ckih2_clk = {
-	.get_rate = get_ckih2_reference_clock_rate,
-};
-
-static struct clk osc_clk = {
-	.get_rate = get_oscillator_reference_clock_rate,
-};
-
-/* External low frequency (32kHz) clock */
-static struct clk ckil_clk = {
-	.get_rate = get_low_reference_clock_rate,
-};
-
-static struct clk pll1_main_clk = {
-	.parent = &osc_clk,
-	.get_rate = clk_pll_get_rate,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* Clock tree block diagram (WIP):
- * 	CCM: Clock Controller Module
- *
- * PLL output -> |
- *               | CCM Switcher -> CCM_CLK_ROOT_GEN ->
- * PLL bypass -> |
- *
- */
-
-/* PLL1 SW supplies to ARM core */
-static struct clk pll1_sw_clk = {
-	.parent = &pll1_main_clk,
-	.set_parent = _clk_pll1_sw_set_parent,
-	.get_rate = clk_pll1_sw_get_rate,
-};
-
-/* PLL2 SW supplies to AXI/AHB/IP buses */
-static struct clk pll2_sw_clk = {
-	.parent = &osc_clk,
-	.get_rate = clk_pll_get_rate,
-	.set_rate = _clk_pll_set_rate,
-	.set_parent = _clk_pll2_sw_set_parent,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */
-static struct clk pll3_sw_clk = {
-	.parent = &osc_clk,
-	.set_rate = _clk_pll_set_rate,
-	.get_rate = clk_pll_get_rate,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* PLL4 SW supplies to LVDS Display Bridge(LDB) */
-static struct clk mx53_pll4_sw_clk = {
-	.parent = &osc_clk,
-	.set_rate = _clk_pll_set_rate,
-	.enable = _clk_pll_enable,
-	.disable = _clk_pll_disable,
-};
-
-/* Low-power Audio Playback Mode clock */
-static struct clk lp_apm_clk = {
-	.parent = &osc_clk,
-	.set_parent = _clk_lp_apm_set_parent,
-};
-
-static struct clk periph_apm_clk = {
-	.parent = &pll1_sw_clk,
-	.set_parent = _clk_periph_apm_set_parent,
-};
-
-static struct clk cpu_clk = {
-	.parent = &pll1_sw_clk,
-	.get_rate = clk_cpu_get_rate,
-	.set_rate = clk_cpu_set_rate,
-};
-
-static struct clk ahb_clk = {
-	.parent = &main_bus_clk,
-	.get_rate = clk_ahb_get_rate,
-	.set_rate = _clk_ahb_set_rate,
-	.round_rate = _clk_ahb_round_rate,
-};
-
-static struct clk iim_clk = {
-	.parent = &ipg_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,
-};
-
-/* Main IP interface clock for access to registers */
-static struct clk ipg_clk = {
-	.parent = &ahb_clk,
-	.get_rate = clk_ipg_get_rate,
-};
-
-static struct clk ipg_perclk = {
-	.parent = &lp_apm_clk,
-	.get_rate = clk_ipg_per_get_rate,
-	.set_parent = _clk_ipg_per_set_parent,
-};
-
-static struct clk ahb_max_clk = {
-	.parent = &ahb_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
-	.enable = _clk_max_enable,
-	.disable = _clk_max_disable,
-};
-
-static struct clk aips_tz1_clk = {
-	.parent = &ahb_clk,
-	.secondary = &ahb_max_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk aips_tz2_clk = {
-	.parent = &ahb_clk,
-	.secondary = &ahb_max_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk gpc_dvfs_clk = {
-	.enable_reg = MXC_CCM_CCGR5,
-	.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable,
-};
-
-static struct clk gpt_32k_clk = {
-	.id = 0,
-	.parent = &ckil_clk,
-};
-
-static struct clk dummy_clk = {
-	.id = 0,
-};
-
-static struct clk emi_slow_clk = {
-	.parent = &pll2_sw_clk,
-	.enable_reg = MXC_CCM_CCGR5,
-	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-	.get_rate = clk_emi_slow_get_rate,
-};
-
-static int clk_ipu_enable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_enable(clk);
-
-	/* Enable handshake with IPU when certain clock rates are changed */
-	reg = __raw_readl(MXC_CCM_CCDR);
-	reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
-	__raw_writel(reg, MXC_CCM_CCDR);
-
-	/* Enable handshake with IPU when LPM is entered */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-
-	return 0;
-}
-
-static void clk_ipu_disable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_disable(clk);
-
-	/* Disable handshake with IPU whe dividers are changed */
-	reg = __raw_readl(MXC_CCM_CCDR);
-	reg |= MXC_CCM_CCDR_IPU_HS_MASK;
-	__raw_writel(reg, MXC_CCM_CCDR);
-
-	/* Disable handshake with IPU when LPM is entered */
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static struct clk ahbmux1_clk = {
-	.parent = &ahb_clk,
-	.secondary = &ahb_max_clk,
-	.enable_reg = MXC_CCM_CCGR0,
-	.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable_inwait,
-};
-
-static struct clk ipu_sec_clk = {
-	.parent = &emi_fast_clk,
-	.secondary = &ahbmux1_clk,
-};
-
-static struct clk ddr_hf_clk = {
-	.parent = &pll1_sw_clk,
-	.get_rate = _clk_ddr_hf_get_rate,
-};
-
-static struct clk ddr_clk = {
-	.parent = &ddr_hf_clk,
-};
-
-/* clock definitions for MIPI HSC unit which has been removed
- * from documentation, but not from hardware
- */
-static int _clk_hsc_enable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_enable(clk);
-	/* Handshake with IPU when certain clock rates are changed. */
-	reg = __raw_readl(MXC_CCM_CCDR);
-	reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;
-	__raw_writel(reg, MXC_CCM_CCDR);
-
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-
-	return 0;
-}
-
-static void _clk_hsc_disable(struct clk *clk)
-{
-	u32 reg;
-
-	_clk_ccgr_disable(clk);
-	/* No handshake with HSC as its not enabled. */
-	reg = __raw_readl(MXC_CCM_CCDR);
-	reg |= MXC_CCM_CCDR_HSC_HS_MASK;
-	__raw_writel(reg, MXC_CCM_CCDR);
-
-	reg = __raw_readl(MXC_CCM_CLPCR);
-	reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;
-	__raw_writel(reg, MXC_CCM_CLPCR);
-}
-
-static struct clk mipi_hsp_clk = {
-	.parent = &ipu_clk,
-	.enable_reg = MXC_CCM_CCGR4,
-	.enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,
-	.enable = _clk_hsc_enable,
-	.disable = _clk_hsc_disable,
-	.secondary = &mipi_hsc1_clk,
-};
-
-#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
-	static struct clk name = {			\
-		.id		= i,			\
-		.enable_reg	= er,			\
-		.enable_shift	= es,			\
-		.get_rate	= pfx##_get_rate,	\
-		.set_rate	= pfx##_set_rate,	\
-		.round_rate	= pfx##_round_rate,	\
-		.set_parent	= pfx##_set_parent,	\
-		.enable		= _clk_ccgr_enable,	\
-		.disable	= _clk_ccgr_disable,	\
-		.parent		= p,			\
-		.secondary	= s,			\
-	}
-
-#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)	\
-	static struct clk name = {			\
-		.id		= i,			\
-		.enable_reg	= er,			\
-		.enable_shift	= es,			\
-		.get_rate	= pfx##_get_rate,	\
-		.set_rate	= pfx##_set_rate,	\
-		.set_parent	= pfx##_set_parent,	\
-		.enable		= _clk_max_enable,	\
-		.disable	= _clk_max_disable,	\
-		.parent		= p,			\
-		.secondary	= s,			\
-	}
-
-#define CLK_GET_RATE(name, nr, bitsname)				\
-static unsigned long clk_##name##_get_rate(struct clk *clk)		\
-{									\
-	u32 reg, pred, podf;						\
-									\
-	reg = __raw_readl(MXC_CCM_CSCDR##nr);				\
-	pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)	\
-		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
-	podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)	\
-		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
-									\
-	return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),		\
-			(pred + 1) * (podf + 1));			\
-}
-
-#define CLK_SET_PARENT(name, nr, bitsname)				\
-static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
-{									\
-	u32 reg, mux;							\
-									\
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,		\
-			&pll3_sw_clk, &lp_apm_clk);			\
-	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
-		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
-	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
-	__raw_writel(reg, MXC_CCM_CSCMR##nr);				\
-									\
-	return 0;							\
-}
-
-#define CLK_SET_RATE(name, nr, bitsname)				\
-static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)	\
-{									\
-	u32 reg, div, parent_rate;					\
-	u32 pre = 0, post = 0;						\
-									\
-	parent_rate = clk_get_rate(clk->parent);			\
-	div = parent_rate / rate;					\
-									\
-	if ((parent_rate / div) != rate)				\
-		return -EINVAL;						\
-									\
-	__calc_pre_post_dividers(div, &pre, &post,			\
-		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >>	\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1,	\
-		(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >>	\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\
-									\
-	/* Set sdhc1 clock divider */					\
-	reg = __raw_readl(MXC_CCM_CSCDR##nr) &				\
-		~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK	\
-		| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);	\
-	reg |= (post - 1) <<						\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
-	reg |= (pre - 1) <<						\
-		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
-	__raw_writel(reg, MXC_CCM_CSCDR##nr);				\
-									\
-	return 0;							\
-}
-
-/* UART */
-CLK_GET_RATE(uart, 1, UART)
-CLK_SET_PARENT(uart, 1, UART)
-
-static struct clk uart_root_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_uart_get_rate,
-	.set_parent = clk_uart_set_parent,
-};
-
-/* USBOH3 */
-CLK_GET_RATE(usboh3, 1, USBOH3)
-CLK_SET_PARENT(usboh3, 1, USBOH3)
-
-static struct clk usboh3_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_usboh3_get_rate,
-	.set_parent = clk_usboh3_set_parent,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable,
-	.enable_reg = MXC_CCM_CCGR2,
-	.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,
-};
-
-static struct clk usb_ahb_clk = {
-	.parent = &ipg_clk,
-	.enable = _clk_ccgr_enable,
-	.disable = _clk_ccgr_disable,
-	.enable_reg = MXC_CCM_CCGR2,
-	.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
-};
-
-static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;
-
-	if (parent == &pll3_sw_clk)
-		reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;
-
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-static struct clk usb_phy1_clk = {
-	.parent = &pll3_sw_clk,
-	.set_parent = clk_usb_phy1_set_parent,
-	.enable = _clk_ccgr_enable,
-	.enable_reg = MXC_CCM_CCGR2,
-	.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
-	.disable = _clk_ccgr_disable,
-};
-
-/* eCSPI */
-CLK_GET_RATE(ecspi, 2, CSPI)
-CLK_SET_PARENT(ecspi, 1, CSPI)
-
-static struct clk ecspi_main_clk = {
-	.parent = &pll3_sw_clk,
-	.get_rate = clk_ecspi_get_rate,
-	.set_parent = clk_ecspi_set_parent,
-};
-
-/* eSDHC */
-CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
-CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
-
-/* mx51 specific */
-CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
-CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
-
-static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1);
-	if (parent == &esdhc1_clk)
-		reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
-	else if (parent == &esdhc2_clk)
-		reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
-	else
-		return -EINVAL;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1);
-	if (parent == &esdhc1_clk)
-		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-	else if (parent == &esdhc2_clk)
-		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-	else
-		return -EINVAL;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-/* mx53 specific */
-static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1);
-	if (parent == &esdhc1_clk)
-		reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
-	else if (parent == &esdhc3_mx53_clk)
-		reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
-	else
-		return -EINVAL;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
-CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
-CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
-
-static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg;
-
-	reg = __raw_readl(MXC_CCM_CSCMR1);
-	if (parent == &esdhc1_clk)
-		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-	else if (parent == &esdhc3_mx53_clk)
-		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
-	else
-		return -EINVAL;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
-#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
-	static struct clk name = {					\
-		.id		= i,					\
-		.enable_reg	= er,					\
-		.enable_shift	= es,					\
-		.get_rate	= gr,					\
-		.set_rate	= sr,					\
-		.enable		= e,					\
-		.disable	= d,					\
-		.parent		= p,					\
-		.secondary	= s,					\
-	}
-
-#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s)			\
-	DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)
-
-/* Shared peripheral bus arbiter */
-DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
-
-/* UART */
-DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,
-	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,
-	NULL,  NULL, &ipg_clk, &aips_tz1_clk);
-DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
-	NULL,  NULL, &ipg_clk, &spba_clk);
-DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart1_ipg_clk);
-DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart2_ipg_clk);
-DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL,  NULL, &uart_root_clk, &uart3_ipg_clk);
-
-/* GPT */
-DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
-
-DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-
-/* I2C */
-DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-
-/* FEC */
-DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
-	NULL,  NULL, &ipg_clk, NULL);
-
-/* NFC */
-DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
-	clk_nfc, &emi_slow_clk, NULL);
-
-/* SSI */
-DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,
-	NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);
-DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,
-	NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);
-DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,
-	NULL, NULL, &ipg_clk, NULL);
-DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,
-	NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);
-
-/* eCSPI */
-DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
-		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
-		&ipg_clk, &spba_clk);
-DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,
-		NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);
-DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,
-		NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,
-		&ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,
-		NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);
-
-/* CSPI */
-DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,
-		NULL, NULL, &ipg_clk, &aips_tz2_clk);
-DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
-		NULL, NULL, &ipg_clk, &cspi_ipg_clk);
-
-/* SDMA */
-DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
-		NULL, NULL, &ahb_clk, NULL);
-
-/* eSDHC */
-DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
-	clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
-DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
-	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
-
-/* mx51 specific */
-DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
-	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
-
-static struct clk esdhc3_clk = {
-	.id = 2,
-	.parent = &esdhc1_clk,
-	.set_parent = clk_esdhc3_set_parent,
-	.enable_reg = MXC_CCM_CCGR3,
-	.enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
-	.enable  = _clk_max_enable,
-	.disable = _clk_max_disable,
-	.secondary = &esdhc3_ipg_clk,
-};
-static struct clk esdhc4_clk = {
-	.id = 3,
-	.parent = &esdhc1_clk,
-	.set_parent = clk_esdhc4_set_parent,
-	.enable_reg = MXC_CCM_CCGR3,
-	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
-	.enable  = _clk_max_enable,
-	.disable = _clk_max_disable,
-	.secondary = &esdhc4_ipg_clk,
-};
-
-/* mx53 specific */
-static struct clk esdhc2_mx53_clk = {
-	.id = 2,
-	.parent = &esdhc1_clk,
-	.set_parent = clk_esdhc2_mx53_set_parent,
-	.enable_reg = MXC_CCM_CCGR3,
-	.enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
-	.enable  = _clk_max_enable,
-	.disable = _clk_max_disable,
-	.secondary = &esdhc3_ipg_clk,
-};
-
-DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
-	clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
-
-static struct clk esdhc4_mx53_clk = {
-	.id = 3,
-	.parent = &esdhc1_clk,
-	.set_parent = clk_esdhc4_mx53_set_parent,
-	.enable_reg = MXC_CCM_CCGR3,
-	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
-	.enable  = _clk_max_enable,
-	.disable = _clk_max_disable,
-	.secondary = &esdhc4_ipg_clk,
-};
-
-DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
-DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
-DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
-
-/* IPU */
-DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,
-	NULL,  NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);
-
-DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,
-		NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,
-		&ddr_clk, NULL);
-
-DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,
-		NULL, NULL, &pll3_sw_clk, NULL);
-DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,
-		NULL, NULL, &pll3_sw_clk, NULL);
-
-#define _REGISTER_CLOCK(d, n, c) \
-       { \
-		.dev_id = d, \
-		.con_id = n, \
-		.clk = &c,   \
-       },
-
-static struct clk_lookup mx51_lookups[] = {
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
-	_REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
-	_REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
-	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
-	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
-	_REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)
-	_REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)
-	_REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)
-	_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)
-	_REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)
-	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
-	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
-	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
-	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
-	_REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
-	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
-	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
-	_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)
-	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
-	_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
-	_REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)
-	_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)
-	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
-	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
-	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_clk)
-	_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
-	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
-	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
-	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
-	_REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
-	_REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
-	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
-	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
-	_REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
-};
-
-static struct clk_lookup mx53_lookups[] = {
-	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
-	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
-	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
-	_REGISTER_CLOCK(NULL, "gpt", gpt_clk)
-	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
-	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
-	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
-	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)
-	_REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)
-	_REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)
-	_REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)
-	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
-	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
-};
-
-static void clk_tree_init(void)
-{
-	u32 reg;
-
-	ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);
-
-	/*
-	 * Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at
-	 * 8MHz, its derived from lp_apm.
-	 *
-	 * FIXME: Verify if true for all boards
-	 */
-	reg = __raw_readl(MXC_CCM_CBCDR);
-	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;
-	reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;
-	reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;
-	reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);
-	__raw_writel(reg, MXC_CCM_CBCDR);
-}
-
-int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
-			unsigned long ckih1, unsigned long ckih2)
-{
-	int i;
-
-	external_low_reference = ckil;
-	external_high_reference = ckih1;
-	ckih2_reference = ckih2;
-	oscillator_reference = osc;
-
-	for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)
-		clkdev_add(&mx51_lookups[i]);
-
-	clk_tree_init();
-
-	clk_enable(&cpu_clk);
-	clk_enable(&main_bus_clk);
-
-	clk_enable(&iim_clk);
-	mx51_revision();
-	clk_disable(&iim_clk);
-	mx51_display_revision();
-
-	/* move usb_phy_clk to 24MHz */
-	clk_set_parent(&usb_phy1_clk, &osc_clk);
-
-	/* set the usboh3_clk parent to pll2_sw_clk */
-	clk_set_parent(&usboh3_clk, &pll2_sw_clk);
-
-	/* Set SDHC parents to be PLL2 */
-	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
-	clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
-
-	/* set SDHC root clock as 166.25MHZ*/
-	clk_set_rate(&esdhc1_clk, 166250000);
-	clk_set_rate(&esdhc2_clk, 166250000);
-
-	/* System timer */
-	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
-		MX51_MXC_INT_GPT);
-	return 0;
-}
-
-int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
-			unsigned long ckih1, unsigned long ckih2)
-{
-	int i;
-
-	external_low_reference = ckil;
-	external_high_reference = ckih1;
-	ckih2_reference = ckih2;
-	oscillator_reference = osc;
-
-	for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)
-		clkdev_add(&mx53_lookups[i]);
-
-	clk_tree_init();
-
-	clk_set_parent(&uart_root_clk, &pll3_sw_clk);
-	clk_enable(&cpu_clk);
-	clk_enable(&main_bus_clk);
-
-	clk_enable(&iim_clk);
-	mx53_revision();
-	clk_disable(&iim_clk);
-
-	/* Set SDHC parents to be PLL2 */
-	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
-	clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
-
-	/* set SDHC root clock as 200MHZ*/
-	clk_set_rate(&esdhc1_clk, 200000000);
-	clk_set_rate(&esdhc3_mx53_clk, 200000000);
-
-	/* System timer */
-	mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
-		MX53_INT_GPT);
-	return 0;
-}
diff --git a/arch/arm/mach-mx5/crm_regs.h b/arch/arm/mach-mx5/crm_regs.h
index 87c0c58..5a5d82d 100644
--- a/arch/arm/mach-mx5/crm_regs.h
+++ b/arch/arm/mach-mx5/crm_regs.h
@@ -23,7 +23,7 @@
 #define MX53_DPLL1_BASE		MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR)
 #define MX53_DPLL2_BASE		MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR)
 #define MX53_DPLL3_BASE		MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
-#define MX53_DPLL4_BASE		MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR)
+#define MX53_DPLL4_BASE		MX53_IO_ADDRESS(MX53_PLL4_BASE_ADDR)
 
 /* PLL Register Offsets */
 #define MXC_PLL_DP_CTL			0x00
@@ -159,221 +159,6 @@
 #define MXC_CCM_CACRR_ARM_PODF_OFFSET	(0)
 #define MXC_CCM_CACRR_ARM_PODF_MASK	(0x7)
 
-/* Define the bits in register CBCDR */
-#define MXC_CCM_CBCDR_EMI_CLK_SEL		(0x1 << 26)
-#define MXC_CCM_CBCDR_PERIPH_CLK_SEL		(0x1 << 25)
-#define MXC_CCM_CBCDR_DDR_HF_SEL_OFFSET		(30)
-#define MXC_CCM_CBCDR_DDR_HF_SEL		(0x1 << 30)
-#define MXC_CCM_CBCDR_DDR_PODF_OFFSET		(27)
-#define MXC_CCM_CBCDR_DDR_PODF_MASK		(0x7 << 27)
-#define MXC_CCM_CBCDR_EMI_PODF_OFFSET		(22)
-#define MXC_CCM_CBCDR_EMI_PODF_MASK		(0x7 << 22)
-#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET		(19)
-#define MXC_CCM_CBCDR_AXI_B_PODF_MASK		(0x7 << 19)
-#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET		(16)
-#define MXC_CCM_CBCDR_AXI_A_PODF_MASK		(0x7 << 16)
-#define MXC_CCM_CBCDR_NFC_PODF_OFFSET		(13)
-#define MXC_CCM_CBCDR_NFC_PODF_MASK		(0x7 << 13)
-#define MXC_CCM_CBCDR_AHB_PODF_OFFSET		(10)
-#define MXC_CCM_CBCDR_AHB_PODF_MASK		(0x7 << 10)
-#define MXC_CCM_CBCDR_IPG_PODF_OFFSET		(8)
-#define MXC_CCM_CBCDR_IPG_PODF_MASK		(0x3 << 8)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET	(6)
-#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK		(0x3 << 6)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET	(3)
-#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK		(0x7 << 3)
-#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET	(0)
-#define MXC_CCM_CBCDR_PERCLK_PODF_MASK		(0x7)
-
-/* Define the bits in register CBCMR */
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET	(14)
-#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK	(0x3 << 14)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET	(12)
-#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK	(0x3 << 12)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET	(10)
-#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK		(0x3 << 10)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET	(8)
-#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK	(0x3 << 8)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET	(6)
-#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK	(0x3 << 6)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET	(4)
-#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK		(0x3 << 4)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_OFFSET	(14)
-#define MXC_CCM_CBCMR_GPU2D_CLK_SEL_MASK	(0x3 << 14)
-#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL	(0x1 << 1)
-#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL	(0x1 << 0)
-
-/* Define the bits in register CSCMR1 */
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET		(30)
-#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK		(0x3 << 30)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET		(28)
-#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK		(0x3 << 28)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET		(26)
-#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL			(0x1 << 26)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET		(24)
-#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK		(0x3 << 24)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET		(22)
-#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK		(0x3 << 22)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET	(20)
-#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK	(0x3 << 20)
-#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL			(0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL	(0x1 << 19)
-#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL			(0x1 << 18)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET	(16)
-#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK	(0x3 << 16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET	(16)
-#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK		(0x3 << 16)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET		(14)
-#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK		(0x3 << 14)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET		(12)
-#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK		(0x3 << 12)
-#define MXC_CCM_CSCMR1_SSI3_CLK_SEL			(0x1 << 11)
-#define MXC_CCM_CSCMR1_VPU_RCLK_SEL			(0x1 << 10)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET		(8)
-#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK		(0x3 << 8)
-#define MXC_CCM_CSCMR1_TVE_CLK_SEL			(0x1 << 7)
-#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL			(0x1 << 6)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET		(4)
-#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK		(0x3 << 4)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET		(2)
-#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK		(0x3 << 2)
-#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL		(0x1 << 1)
-#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL		(0x1)
-
-/* Define the bits in register CSCMR2 */
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_OFFSET(n)		(26+n*3)
-#define MXC_CCM_CSCMR2_DI_CLK_SEL_MASK(n)		(0x7 << (26+n*3))
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_OFFSET		(24)
-#define MXC_CCM_CSCMR2_CSI_MCLK2_CLK_SEL_MASK		(0x3 << 24)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_OFFSET		(22)
-#define MXC_CCM_CSCMR2_CSI_MCLK1_CLK_SEL_MASK		(0x3 << 22)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_OFFSET		(20)
-#define MXC_CCM_CSCMR2_ESC_CLK_SEL_MASK			(0x3 << 20)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_OFFSET		(18)
-#define MXC_CCM_CSCMR2_HSC2_CLK_SEL_MASK		(0x3 << 18)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_OFFSET		(16)
-#define MXC_CCM_CSCMR2_HSC1_CLK_SEL_MASK		(0x3 << 16)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_OFFSET		(14)
-#define MXC_CCM_CSCMR2_HSI2C_CLK_SEL_MASK		(0x3 << 14)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_OFFSET		(12)
-#define MXC_CCM_CSCMR2_FIRI_CLK_SEL_MASK		(0x3 << 12)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_OFFSET		(10)
-#define MXC_CCM_CSCMR2_SIM_CLK_SEL_MASK			(0x3 << 10)
-#define MXC_CCM_CSCMR2_SLIMBUS_COM			(0x1 << 9)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_OFFSET		(6)
-#define MXC_CCM_CSCMR2_SLIMBUS_CLK_SEL_MASK		(0x7 << 6)
-#define MXC_CCM_CSCMR2_SPDIF1_COM			(1 << 5)
-#define MXC_CCM_CSCMR2_SPDIF0_COM			(1 << 4)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_OFFSET		(2)
-#define MXC_CCM_CSCMR2_SPDIF1_CLK_SEL_MASK		(0x3 << 2)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_OFFSET		(0)
-#define MXC_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK		(0x3)
-
-/* Define the bits in register CSCDR1 */
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET	(22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK	(0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET	(19)
-#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK	(0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET	(22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK	(0x7 << 22)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET	(19)
-#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK	(0x7 << 19)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET	(16)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK	(0x7 << 16)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET		(14)
-#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK		(0x3 << 14)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET	(11)
-#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK	(0x7 << 11)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET		(8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK		(0x7 << 8)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET		(6)
-#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK		(0x3 << 6)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET		(3)
-#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK		(0x7 << 3)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK		(0x7)
-
-/* Define the bits in register CS1CDR and CS2CDR */
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_OFFSET		(22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PRED_MASK		(0x7 << 22)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_OFFSET		(16)
-#define MXC_CCM_CS1CDR_SSI_EXT1_CLK_PODF_MASK		(0x3F << 16)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CS1CDR_SSI1_CLK_PODF_MASK		(0x3F)
-
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_OFFSET		(22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PRED_MASK		(0x7 << 22)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_OFFSET		(16)
-#define MXC_CCM_CS2CDR_SSI_EXT2_CLK_PODF_MASK		(0x3F << 16)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CS2CDR_SSI2_CLK_PODF_MASK		(0x3F)
-
-/* Define the bits in register CDCDR */
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_OFFSET		(28)
-#define MXC_CCM_CDCDR_TVE_CLK_PRED_MASK			(0x7 << 28)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_OFFSET		(25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PRED_MASK		(0x7 << 25)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_OFFSET		(19)
-#define MXC_CCM_CDCDR_SPDIF0_CLK_PODF_MASK		(0x3F << 19)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_OFFSET		(16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_OFFSET		(9)
-#define MXC_CCM_CDCDR_SPDIF1_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CDCDR_DI_CLK_PRED_MASK			(0x7 << 6)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_OFFSET		(3)
-#define MXC_CCM_CDCDR_USB_PHY_PRED_MASK			(0x7 << 3)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_OFFSET		(0)
-#define MXC_CCM_CDCDR_USB_PHY_PODF_MASK			(0x7)
-
-/* Define the bits in register CHSCCDR */
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_OFFSET		(12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PRED_MASK		(0x7 << 12)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_OFFSET		(6)
-#define MXC_CCM_CHSCCDR_ESC_CLK_PODF_MASK		(0x3F << 6)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_OFFSET		(3)
-#define MXC_CCM_CHSCCDR_HSC2_CLK_PODF_MASK		(0x7 << 3)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CHSCCDR_HSC1_CLK_PODF_MASK		(0x7)
-
-/* Define the bits in register CSCDR2 */
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET		(25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK		(0x7 << 25)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET		(19)
-#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK		(0x3F << 19)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET		(16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET		(9)
-#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET		(0)
-#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK		(0x3F)
-
-/* Define the bits in register CSCDR3 */
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_OFFSET		(16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_OFFSET		(9)
-#define MXC_CCM_CSCDR3_HSI2C_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_OFFSET		(6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_OFFSET		(0)
-#define MXC_CCM_CSCDR3_FIRI_CLK_PODF_MASK		(0x3F)
-
-/* Define the bits in register CSCDR4 */
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_OFFSET	(16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PRED_MASK		(0x7 << 16)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_OFFSET	(9)
-#define MXC_CCM_CSCDR4_CSI_MCLK2_CLK_PODF_MASK		(0x3F << 9)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_OFFSET	(6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PRED_MASK		(0x7 << 6)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_OFFSET	(0)
-#define MXC_CCM_CSCDR4_CSI_MCLK1_CLK_PODF_MASK		(0x3F)
-
 /* Define the bits in register CDHIPR */
 #define MXC_CCM_CDHIPR_ARM_PODF_BUSY			(1 << 16)
 #define MXC_CCM_CDHIPR_DDR_HF_CLK_SEL_BUSY		(1 << 8)
@@ -468,38 +253,6 @@
 #define MXC_CCM_CCGRx_MOD_ON				0x3
 #define MXC_CCM_CCGRx_MOD_IDLE				0x1
 
-#define MXC_CCM_CCGRx_CG15_MASK				(0x3 << 30)
-#define MXC_CCM_CCGRx_CG14_MASK				(0x3 << 28)
-#define MXC_CCM_CCGRx_CG13_MASK				(0x3 << 26)
-#define MXC_CCM_CCGRx_CG12_MASK				(0x3 << 24)
-#define MXC_CCM_CCGRx_CG11_MASK				(0x3 << 22)
-#define MXC_CCM_CCGRx_CG10_MASK				(0x3 << 20)
-#define MXC_CCM_CCGRx_CG9_MASK				(0x3 << 18)
-#define MXC_CCM_CCGRx_CG8_MASK				(0x3 << 16)
-#define MXC_CCM_CCGRx_CG5_MASK				(0x3 << 10)
-#define MXC_CCM_CCGRx_CG4_MASK				(0x3 << 8)
-#define MXC_CCM_CCGRx_CG3_MASK				(0x3 << 6)
-#define MXC_CCM_CCGRx_CG2_MASK				(0x3 << 4)
-#define MXC_CCM_CCGRx_CG1_MASK				(0x3 << 2)
-#define MXC_CCM_CCGRx_CG0_MASK				(0x3 << 0)
-
-#define MXC_CCM_CCGRx_CG15_OFFSET			30
-#define MXC_CCM_CCGRx_CG14_OFFSET			28
-#define MXC_CCM_CCGRx_CG13_OFFSET			26
-#define MXC_CCM_CCGRx_CG12_OFFSET			24
-#define MXC_CCM_CCGRx_CG11_OFFSET			22
-#define MXC_CCM_CCGRx_CG10_OFFSET			20
-#define MXC_CCM_CCGRx_CG9_OFFSET			18
-#define MXC_CCM_CCGRx_CG8_OFFSET			16
-#define MXC_CCM_CCGRx_CG7_OFFSET			14
-#define MXC_CCM_CCGRx_CG6_OFFSET			12
-#define MXC_CCM_CCGRx_CG5_OFFSET			10
-#define MXC_CCM_CCGRx_CG4_OFFSET			8
-#define MXC_CCM_CCGRx_CG3_OFFSET			6
-#define MXC_CCM_CCGRx_CG2_OFFSET			4
-#define MXC_CCM_CCGRx_CG1_OFFSET			2
-#define MXC_CCM_CCGRx_CG0_OFFSET			0
-
 #define MXC_DPTC_LP_BASE	(MX51_GPC_BASE + 0x80)
 #define MXC_DPTC_GP_BASE	(MX51_GPC_BASE + 0x100)
 #define MXC_DVFS_CORE_BASE	(MX51_GPC_BASE + 0x180)
-- 
1.7.4.1

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

* [RFC] sanitizing crazy clock data files
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (9 preceding siblings ...)
  2011-04-15 19:08 ` [PATCH 10/10] ARM i.MX51/53: remove old " Sascha Hauer
@ 2011-04-15 19:36 ` Russell King - ARM Linux
  2011-04-15 20:12   ` Sascha Hauer
  2011-04-15 20:45 ` Uwe Kleine-König
  2011-04-18  7:42 ` Sascha Hauer
  12 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-15 19:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:08:05PM +0200, Sascha Hauer wrote:
> The following tries to solve the chicken-egg problem we have with the
> common struct clk support and its users.

Thanks for doing this.  This really shows exactly what I wanted to know.

>  drivers/clk/Kconfig                     |    6 +
>  drivers/clk/Makefile                    |    2 +
>  drivers/clk/clk-divider.c               |  132 +++
>  drivers/clk/clk-mux.c                   |   92 ++
>  drivers/clk/clk.c                       |  104 ++
>  include/linux/clk.h                     |   68 ++
>  16 files changed, 1395 insertions(+), 1831 deletions(-)

If we can have more people using the generic mux and divider stuff,
that should cut many more hundreds of LOC from arch/arm.

This is exactly the kind of stuff we need to be seeing.

1. How does this fit in with the other MX stuff?
2. Is it based upon Jeremy's git tree, and is Jeremy's git tree a stable
   base for this?
3. Is this sufficiently separated that it can be pulled as-is?

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

* [RFC] sanitizing crazy clock data files
  2011-04-15 19:36 ` [RFC] sanitizing crazy clock data files Russell King - ARM Linux
@ 2011-04-15 20:12   ` Sascha Hauer
  2011-04-15 20:25     ` Russell King - ARM Linux
  2011-04-18  4:07     ` Shawn Guo
  0 siblings, 2 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-15 20:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 08:36:54PM +0100, Russell King - ARM Linux wrote:
> On Fri, Apr 15, 2011 at 09:08:05PM +0200, Sascha Hauer wrote:
> > The following tries to solve the chicken-egg problem we have with the
> > common struct clk support and its users.
> 
> Thanks for doing this.  This really shows exactly what I wanted to know.
> 
> >  drivers/clk/Kconfig                     |    6 +
> >  drivers/clk/Makefile                    |    2 +
> >  drivers/clk/clk-divider.c               |  132 +++
> >  drivers/clk/clk-mux.c                   |   92 ++
> >  drivers/clk/clk.c                       |  104 ++
> >  include/linux/clk.h                     |   68 ++
> >  16 files changed, 1395 insertions(+), 1831 deletions(-)
> 
> If we can have more people using the generic mux and divider stuff,
> that should cut many more hundreds of LOC from arch/arm.
> 
> This is exactly the kind of stuff we need to be seeing.
> 
> 1. How does this fit in with the other MX stuff?

The other regular i.MXs should fit into this fine, they have the same
patterns. mxs is different though, instead of enable bits they have
disable bits and dividers are one based instead of zero. We can probably
extend the patterns to handle some additional flags, but I haven't
looked deeply into it.

> 2. Is it based upon Jeremy's git tree, and is Jeremy's git tree a stable
>    base for this?

It's a very late series from Jeremy, I don't know if it's exactly the
latest. I'll rebase it. Jeremys git tree is here:

git://kernel.ubuntu.com/jk/dt/linux-2.6.git

> 3. Is this sufficiently separated that it can be pulled as-is?

Should be, but it's the result of a long day, so I hesitate to say yes.

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

* [RFC] sanitizing crazy clock data files
  2011-04-15 20:12   ` Sascha Hauer
@ 2011-04-15 20:25     ` Russell King - ARM Linux
  2011-04-15 20:28       ` Russell King - ARM Linux
  2011-04-18  4:07     ` Shawn Guo
  1 sibling, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-15 20:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 10:12:32PM +0200, Sascha Hauer wrote:
> The other regular i.MXs should fit into this fine, they have the same
> patterns. mxs is different though, instead of enable bits they have
> disable bits and dividers are one based instead of zero. We can probably
> extend the patterns to handle some additional flags, but I haven't
> looked deeply into it.

A suggestion from work tglx is currently doing - name the two functions
which manipulate the mask bits 'set' and 'clear' rather than 'enable'
and 'disable'.

Then, the clk ops can do this:

	.clk_enable	= clk_gate_mask_set,
	.clk_disable	= clk_gate_mask_clear,

for ones with positive logic, and:

	.clk_enable	= clk_gate_mask_clear,
	.clk_disable	= clk_gate_mask_set,

for negative logic.  No additional code required, just a variance in data
structure.

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

* [RFC] sanitizing crazy clock data files
  2011-04-15 20:25     ` Russell King - ARM Linux
@ 2011-04-15 20:28       ` Russell King - ARM Linux
  2011-04-15 20:49         ` Uwe Kleine-König
  0 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-15 20:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:25:35PM +0100, Russell King - ARM Linux wrote:
> On Fri, Apr 15, 2011 at 10:12:32PM +0200, Sascha Hauer wrote:
> > The other regular i.MXs should fit into this fine, they have the same
> > patterns. mxs is different though, instead of enable bits they have
> > disable bits and dividers are one based instead of zero. We can probably
> > extend the patterns to handle some additional flags, but I haven't
> > looked deeply into it.
> 
> A suggestion from work tglx is currently doing - name the two functions
> which manipulate the mask bits 'set' and 'clear' rather than 'enable'
> and 'disable'.
> 
> Then, the clk ops can do this:
> 
> 	.clk_enable	= clk_gate_mask_set,
> 	.clk_disable	= clk_gate_mask_clear,
> 
> for ones with positive logic, and:
> 
> 	.clk_enable	= clk_gate_mask_clear,
> 	.clk_disable	= clk_gate_mask_set,
> 
> for negative logic.  No additional code required, just a variance in data
> structure.

Bah.  Except they may need to reference the parent... which kills that
idea.

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

* [RFC] sanitizing crazy clock data files
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (10 preceding siblings ...)
  2011-04-15 19:36 ` [RFC] sanitizing crazy clock data files Russell King - ARM Linux
@ 2011-04-15 20:45 ` Uwe Kleine-König
  2011-04-18  7:42 ` Sascha Hauer
  12 siblings, 0 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-15 20:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:08:05PM +0200, Sascha Hauer wrote:
> The following tries to solve the chicken-egg problem we have with the
> common struct clk support and its users. It switches i.MX51 clock support
> to the new API. Included are some generic clock helpers for dividers and
> multiplexer. I first made them i.MX specific but after looking round in
> the other architectures I found them useful enough for other architectures
> aswell. If you could use the helpers but missing some bits please speak up.
> 
> There is one thing missing in Jeremys series and this series does not fix
> it. Once I add the new (un)prepare calls to drivers they won't compile
> without common struct clk support anymore. Maybe a
> 
> #ifndef CONFIG_USE_COMMON_STRUCT_CLK
> #define clk_prepare()
> #define clk_unprepare()
> #endif
> 
> will do.
This already exists in the latest version and works since v14[1].

Best regards
Uwe

[1]
http://thread.gmane.org/gmane.linux.ports.sh.devel/9755/focus=10241
has:

+static inline int clk_prepare(struct clk *clk) { return 0; }
+static inline void clk_unprepare(struct clk *clk) { }

in a !CONFIG_USE_COMMON_STRUCT_CLK cpp branch.

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [RFC] sanitizing crazy clock data files
  2011-04-15 20:28       ` Russell King - ARM Linux
@ 2011-04-15 20:49         ` Uwe Kleine-König
  0 siblings, 0 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-15 20:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:28:58PM +0100, Russell King - ARM Linux wrote:
> On Fri, Apr 15, 2011 at 09:25:35PM +0100, Russell King - ARM Linux wrote:
> > On Fri, Apr 15, 2011 at 10:12:32PM +0200, Sascha Hauer wrote:
> > > The other regular i.MXs should fit into this fine, they have the same
> > > patterns. mxs is different though, instead of enable bits they have
> > > disable bits and dividers are one based instead of zero. We can probably
> > > extend the patterns to handle some additional flags, but I haven't
> > > looked deeply into it.
> > 
> > A suggestion from work tglx is currently doing - name the two functions
> > which manipulate the mask bits 'set' and 'clear' rather than 'enable'
> > and 'disable'.
> > 
> > Then, the clk ops can do this:
> > 
> > 	.clk_enable	= clk_gate_mask_set,
> > 	.clk_disable	= clk_gate_mask_clear,
> > 
> > for ones with positive logic, and:
> > 
> > 	.clk_enable	= clk_gate_mask_clear,
> > 	.clk_disable	= clk_gate_mask_set,
> > 
> > for negative logic.  No additional code required, just a variance in data
> > structure.
> 
> Bah.  Except they may need to reference the parent... which kills that
> idea.
Then the actuall en/disabling needs to be a seperate callback.

clk_gate_enable(clk) then does

	clk_enable(clk->parent)
	clk->sensiblename_enable(clk)

with sensiblename_enable pointing to clk_gate_mask_set or
clk_gate_mask_clear.

Just my 2 cents before going to bed,
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [RFC] sanitizing crazy clock data files
  2011-04-15 20:12   ` Sascha Hauer
  2011-04-15 20:25     ` Russell King - ARM Linux
@ 2011-04-18  4:07     ` Shawn Guo
  1 sibling, 0 replies; 165+ messages in thread
From: Shawn Guo @ 2011-04-18  4:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sascha,

On Fri, Apr 15, 2011 at 10:12:32PM +0200, Sascha Hauer wrote:
> On Fri, Apr 15, 2011 at 08:36:54PM +0100, Russell King - ARM Linux wrote:
> > On Fri, Apr 15, 2011 at 09:08:05PM +0200, Sascha Hauer wrote:
> > > The following tries to solve the chicken-egg problem we have with the
> > > common struct clk support and its users.
> > 
> > Thanks for doing this.  This really shows exactly what I wanted to know.
> > 
> > >  drivers/clk/Kconfig                     |    6 +
> > >  drivers/clk/Makefile                    |    2 +
> > >  drivers/clk/clk-divider.c               |  132 +++
> > >  drivers/clk/clk-mux.c                   |   92 ++
> > >  drivers/clk/clk.c                       |  104 ++
> > >  include/linux/clk.h                     |   68 ++
> > >  16 files changed, 1395 insertions(+), 1831 deletions(-)
> > 
> > If we can have more people using the generic mux and divider stuff,
> > that should cut many more hundreds of LOC from arch/arm.
> > 
> > This is exactly the kind of stuff we need to be seeing.
> > 
> > 1. How does this fit in with the other MX stuff?
> 
> The other regular i.MXs should fit into this fine, they have the same
> patterns. mxs is different though, instead of enable bits they have
> disable bits and dividers are one based instead of zero. We can probably
> extend the patterns to handle some additional flags, but I haven't
> looked deeply into it.
> 
I will try to migrate mxs clock to it and let you know where we need
to extend.

-- 
Regards,
Shawn

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

* [RFC] sanitizing crazy clock data files
  2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
                   ` (11 preceding siblings ...)
  2011-04-15 20:45 ` Uwe Kleine-König
@ 2011-04-18  7:42 ` Sascha Hauer
  12 siblings, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-18  7:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:08:05PM +0200, Sascha Hauer wrote:
> The following tries to solve the chicken-egg problem we have with the
> common struct clk support and its users. It switches i.MX51 clock support
> to the new API. Included are some generic clock helpers for dividers and
> multiplexer. I first made them i.MX specific but after looking round in
> the other architectures I found them useful enough for other architectures
> aswell. If you could use the helpers but missing some bits please speak up.

Note that this series also changes the way clocks are organized. We have
many clocks on i.MX which implemenent set_parent and set_rate at
once. Now with the split into building blocks only the multiplexers
implement set_parent. It's no longer possible in general to call
set_parent on clocks given to drivers as these are mostly dividers and
gates which do not allow to change its parent.

The upside of this change is that it's really simple and straight
forward to implement a clock tree which can be easily reviewed with
the datasheet.

There will be updates to this series as I found some leftovers from
earlier versions of this series.

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-15 19:08 ` [PATCH 04/10] clk: implement parent pass through functions Sascha Hauer
@ 2011-04-18  9:25   ` Uwe Kleine-König
  2011-04-18  9:48     ` Sascha Hauer
  2011-04-19 17:20   ` Stephen Boyd
  1 sibling, 1 reply; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-18  9:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:08:09PM +0200, Sascha Hauer wrote:
> A common case for clocks is that certain operations are not implemented
> and shall be passed through to the parent. Add convenience functions
> for this purpose
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> ---
>  drivers/clk/clk.c   |   77 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h |    9 ++++++
>  2 files changed, 86 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 264c809..7e2c182 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -171,3 +171,80 @@ struct clk_ops clk_fixed_ops = {
>  	.get_rate = clk_fixed_get_rate,
>  };
>  EXPORT_SYMBOL_GPL(clk_fixed_ops);
> +
> +int clk_parent_prepare(struct clk *clk)
> +{
> +	struct clk *parent = clk_get_parent(clk);
> +
> +	if (IS_ERR(parent))
> +		return -ENOSYS;
> +
> +	return clk_prepare(parent);
> +}
> +EXPORT_SYMBOL_GPL(clk_parent_prepare);
> +
> +void clk_parent_unprepare(struct clk *clk)
> +{
> +	struct clk *parent = clk_get_parent(clk);
> +
> +	if (IS_ERR(parent))
> +		return;
> +
> +	clk_unprepare(parent);
> +}
> +EXPORT_SYMBOL_GPL(clk_parent_unprepare);
> +
> +int clk_parent_enable(struct clk *clk)
> +{
> +	struct clk *parent = clk_get_parent(clk);
> +
> +	if (IS_ERR(parent))
> +		return 0;
Do you really want to return 0 here? IMHO something is fishy if a clock
has .enable = clk_parent_enable but has no parent.

> +
> +	return clk_enable(parent);
> +}
> +EXPORT_SYMBOL_GPL(clk_parent_enable);
> +
> +void clk_parent_disable(struct clk *clk)
> +{
> +	struct clk *parent = clk_get_parent(clk);
> +
> +	if (IS_ERR(parent))
> +		return;
> +
> +	clk_disable(parent);
> +}
> +EXPORT_SYMBOL_GPL(clk_parent_disable);
> +
> +unsigned long clk_parent_get_rate(struct clk *clk)
> +{
> +	struct clk *parent = clk_get_parent(clk);
> +
> +	if (IS_ERR(parent))
> +		return 0;
> +
> +	return clk_get_rate(parent);
> +}
> +EXPORT_SYMBOL_GPL(clk_parent_get_rate);
> +
> +long clk_parent_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	struct clk *parent = clk_get_parent(clk);
> +
> +	if (IS_ERR(parent))
> +		return -ENOSYS;
> +
> +	return clk_round_rate(parent, rate);
> +}
> +EXPORT_SYMBOL_GPL(clk_parent_round_rate);
> +
> +int clk_parent_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	struct clk *parent = clk_get_parent(clk);
> +
> +	if (IS_ERR(parent))
> +		return -ENOSYS;
> +
> +	return clk_set_rate(parent, rate);
> +}
> +EXPORT_SYMBOL_GPL(clk_parent_set_rate);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index d2f0db0..d014341 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -171,6 +171,15 @@ extern struct clk_ops clk_fixed_ops;
>  #define DEFINE_CLK_FIXED(name, r) \
>  	struct clk_fixed name = INIT_CLK_FIXED(name, r)
>  
> +/* generic pass-through-to-parent functions */
> +int clk_parent_prepare(struct clk *clk);
> +void clk_parent_unprepare(struct clk *clk);
> +int clk_parent_enable(struct clk *clk);
> +void clk_parent_disable(struct clk *clk);
> +unsigned long clk_parent_get_rate(struct clk *clk);
> +long clk_parent_round_rate(struct clk *clk, unsigned long rate);
> +int clk_parent_set_rate(struct clk *clk, unsigned long rate);
> +
Technically they don't need to depend on USE_COMMON_STRUCT_CLK.

>  #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-18  9:25   ` Uwe Kleine-König
@ 2011-04-18  9:48     ` Sascha Hauer
  0 siblings, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-18  9:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 18, 2011 at 11:25:04AM +0200, Uwe Kleine-K?nig wrote:
> On Fri, Apr 15, 2011 at 09:08:09PM +0200, Sascha Hauer wrote:
> > A common case for clocks is that certain operations are not implemented
> > and shall be passed through to the parent. Add convenience functions
> > for this purpose
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> > ---
> >  drivers/clk/clk.c   |   77 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk.h |    9 ++++++
> >  2 files changed, 86 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 264c809..7e2c182 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -171,3 +171,80 @@ struct clk_ops clk_fixed_ops = {
> >  	.get_rate = clk_fixed_get_rate,
> >  };
> >  EXPORT_SYMBOL_GPL(clk_fixed_ops);
> > +
> > +int clk_parent_prepare(struct clk *clk)
> > +{
> > +	struct clk *parent = clk_get_parent(clk);
> > +
> > +	if (IS_ERR(parent))
> > +		return -ENOSYS;
> > +
> > +	return clk_prepare(parent);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_parent_prepare);
> > +
> > +void clk_parent_unprepare(struct clk *clk)
> > +{
> > +	struct clk *parent = clk_get_parent(clk);
> > +
> > +	if (IS_ERR(parent))
> > +		return;
> > +
> > +	clk_unprepare(parent);
> > +}
> > +EXPORT_SYMBOL_GPL(clk_parent_unprepare);
> > +
> > +int clk_parent_enable(struct clk *clk)
> > +{
> > +	struct clk *parent = clk_get_parent(clk);
> > +
> > +	if (IS_ERR(parent))
> > +		return 0;
> Do you really want to return 0 here? IMHO something is fishy if a clock
> has .enable = clk_parent_enable but has no parent.

However we decide, it should return the same value as clk_parent_prepare
above. Yes, -ENOSYS seems better here.

> >  
> > +/* generic pass-through-to-parent functions */
> > +int clk_parent_prepare(struct clk *clk);
> > +void clk_parent_unprepare(struct clk *clk);
> > +int clk_parent_enable(struct clk *clk);
> > +void clk_parent_disable(struct clk *clk);
> > +unsigned long clk_parent_get_rate(struct clk *clk);
> > +long clk_parent_round_rate(struct clk *clk, unsigned long rate);
> > +int clk_parent_set_rate(struct clk *clk, unsigned long rate);
> > +
> Technically they don't need to depend on USE_COMMON_STRUCT_CLK.

Indeed. Maybe this dependency can add some motivation to switch to
common struct clk.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-15 19:08 ` [PATCH 05/10] clk: Add support for simple dividers Sascha Hauer
@ 2011-04-18  9:49   ` Uwe Kleine-König
  2011-04-18 10:07     ` Sascha Hauer
  2011-04-28 15:22     ` Russell King - ARM Linux
  2011-04-18 22:40   ` Stephen Boyd
  2011-04-24 13:48   ` Richard Zhao
  2 siblings, 2 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-18  9:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:08:10PM +0200, Sascha Hauer wrote:
> This patch adds support for the most common type of divider,
> which expects a register, width and shift values to desacribe
> the location of the divider. The divider can be zero based
> or one based (div = reg_val + 1 vs. div = reg_val).
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> ---
>  drivers/clk/Kconfig       |    3 +
>  drivers/clk/Makefile      |    1 +
>  drivers/clk/clk-divider.c |  132 +++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h       |   31 +++++++++++
>  4 files changed, 167 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-divider.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 6e3ae54..76bb4c9 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
>  
>  config USE_COMMON_STRUCT_CLK
>  	bool
> +
> +config USE_COMMON_CLK_DIVIDER
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index a1a06d3..723d884 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,3 +1,4 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>  obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> +obj-$(CONFIG_USE_COMMON_CLK_DIVIDER) += clk-divider.o
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> new file mode 100644
> index 0000000..2de94df
> --- /dev/null
> +++ b/drivers/clk/clk-divider.c
> @@ -0,0 +1,132 @@
> +/*
> + * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +#include <linux/module.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +
> +#define to_clk_divider(clk) (container_of(clk, struct clk_divider, clk))
> +
> +static unsigned long clk_divider_get_rate(struct clk *clk)
> +{
> +	struct clk_divider *divider = to_clk_divider(clk);
> +	unsigned long rate = clk_get_rate(divider->parent);
> +	unsigned int div;
> +
> +	div = readl(divider->reg) >> divider->shift;
> +	div &= (1 << divider->width) - 1;
> +
> +	if (!(divider->flags & CLK_DIVIDER_FLAG_ONE_BASED))
> +		div++;
> +
> +	return rate / div;
DIV_ROUND_UP(rate, div)? (There is DIV_ROUND_CLOSEST, too, but I think
you need to round up, see below.)

> +}
> +
> +static int clk_divider_bestdiv(struct clk *clk, unsigned long rate,
> +		unsigned long *best_parent_rate)
conceptually this returns an unsigned value

> +{
> +	struct clk_divider *divider = to_clk_divider(clk);
> +	int i, bestdiv = 0;
> +	unsigned long parent_rate, best = 0, now, maxdiv;
> +
> +	maxdiv = (1 << divider->width);
Is divider->width == 32 a valid scenario? If so, this overflows.

> +
> +	if (divider->flags & CLK_DIVIDER_FLAG_ONE_BASED)
> +		maxdiv--;
> +
> +	/*
> +	 * 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++) {
> +		parent_rate = clk_round_rate(divider->parent, (rate + 1) * i);
> +		now = parent_rate / i;
This is buggy, take rate = 25, i = 4. You request the parent to set
104. If you get that, the resulting rate is 26. (And even if
clk_round_rate only return 101 this might be too much.)

I think you need:

	parent_rate = clk_round_rate(divider->parent, rate * i)
	now = DIV_ROUND_UP(parent_rate, i);

I think you really need DIV_ROUND_UP here, DIV_ROUND_CLOSEST won't work.
Consider that a rate of 25 is requested, again with i=4. So the parent
is asked for 100 and might return 97. With DIV_ROUND_CLOSEST you report
to be able to set 24 now, but in fact it's more (24.25). If now further
up in the recursion another divider considers 24 to be a great value to
make 12Hz the value actually provided is too big.

> +
> +		if (now <= rate && now >= best) {
> +			bestdiv = i;
> +			best = now;
> +		}
> +	}
> +
> +	if (!bestdiv) {
> +		bestdiv = (1 << divider->width);
> +		parent_rate = clk_round_rate(divider->parent, 1);
> +	} else {
> +		parent_rate = best * bestdiv;
> +	}
> +
> +	if (best_parent_rate)
> +		*best_parent_rate = parent_rate;
> +
> +	return bestdiv;
> +}
> +
> +static long clk_divider_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	unsigned long best_parent_rate;
> +	int div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
> +
> +	return best_parent_rate / div;
> +}
> +
> +static int clk_divider_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	unsigned long best_parent_rate;
> +	struct clk_divider *divider = to_clk_divider(clk);
> +	unsigned int div;
> +	int ret;
> +	unsigned long flags = 0;
> +	u32 val;
> +
> +	div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
> +
> +	if (rate != best_parent_rate / div)
> +		return -EINVAL;
This is too harsh, isn't it. Or can you expect to only get values that
are returned by round_rate? Again you need DIV_ROUND_UP.

> +
> +	ret = clk_set_rate(divider->parent, best_parent_rate);
> +	if (ret)
> +		return ret;
> +
> +	if (divider->lock)
> +		spin_lock_irqsave(divider->lock, flags);
> +
> +	if (!(divider->flags & CLK_DIVIDER_FLAG_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;
> +}
> +
> +static struct clk *clk_divider_get_parent(struct clk *clk)
> +{
> +	struct clk_divider *divider = to_clk_divider(clk);
> +
> +	return divider->parent;
> +}
> +
> +struct clk_ops clk_divider_ops = {
> +	.prepare = clk_parent_prepare,
> +	.unprepare = clk_parent_unprepare,
> +	.enable = clk_parent_enable,
> +	.disable = clk_parent_disable,
> +	.get_rate = clk_divider_get_rate,
> +	.round_rate = clk_divider_round_rate,
> +	.set_rate = clk_divider_set_rate,
> +	.get_parent = clk_divider_get_parent,
> +};
> +EXPORT_SYMBOL_GPL(clk_divider_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index d014341..6f9771b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -180,6 +180,37 @@ unsigned long clk_parent_get_rate(struct clk *clk);
>  long clk_parent_round_rate(struct clk *clk, unsigned long rate);
>  int clk_parent_set_rate(struct clk *clk, unsigned long rate);
>  
> +/**
> + * clock divider
> + *
> + * @clk		clock source
> + * @reg		register containing the divider
> + * @shift	shift to the divider
> + * @width	width of the divider
> + * @lock	register lock
"optional register lock"?

> + * @parent	parent clock
@flags is missing here. Maybe use the same ordering as in the struct?

> + *
> + * This clock implements get_rate/set_rate/round_rate. prepare/unprepare and
> + * enable/disable are passed through to the parent.
> + *
> + * The divider is calculated as div = reg_val + 1
> + * or if CLK_DIVIDER_FLAG_ONE_BASED is set as div = reg_val
> + * (with reg_val == 0 considered invalid)
> + */
> +struct clk_divider {
> +	struct clk	clk;
> +	void __iomem	*reg;
> +	unsigned char	shift;
> +	unsigned char	width;
> +	unsigned int	div;
> +	struct clk	*parent;
> +	spinlock_t	*lock;
> +#define CLK_DIVIDER_FLAG_ONE_BASED	(1 << 0)
> +	unsigned int	flags;
> +};
> +
> +extern struct clk_ops clk_divider_ops;
> +
>  #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-18  9:49   ` Uwe Kleine-König
@ 2011-04-18 10:07     ` Sascha Hauer
  2011-04-19  2:45       ` Saravana Kannan
  2011-04-28 15:22     ` Russell King - ARM Linux
  1 sibling, 1 reply; 165+ messages in thread
From: Sascha Hauer @ 2011-04-18 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 18, 2011 at 11:49:09AM +0200, Uwe Kleine-K?nig wrote:
> On Fri, Apr 15, 2011 at 09:08:10PM +0200, Sascha Hauer wrote:
> > This patch adds support for the most common type of divider,
> > which expects a register, width and shift values to desacribe
> > the location of the divider. The divider can be zero based
> > or one based (div = reg_val + 1 vs. div = reg_val).
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> > ---
> >  drivers/clk/Kconfig       |    3 +
> >  drivers/clk/Makefile      |    1 +
> >  drivers/clk/clk-divider.c |  132 +++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk.h       |   31 +++++++++++
> >  4 files changed, 167 insertions(+), 0 deletions(-)
> >  create mode 100644 drivers/clk/clk-divider.c
> > 
> > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> > index 6e3ae54..76bb4c9 100644
> > --- a/drivers/clk/Kconfig
> > +++ b/drivers/clk/Kconfig
> > @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
> >  
> >  config USE_COMMON_STRUCT_CLK
> >  	bool
> > +
> > +config USE_COMMON_CLK_DIVIDER
> > +	bool
> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> > index a1a06d3..723d884 100644
> > --- a/drivers/clk/Makefile
> > +++ b/drivers/clk/Makefile
> > @@ -1,3 +1,4 @@
> >  
> >  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> >  obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> > +obj-$(CONFIG_USE_COMMON_CLK_DIVIDER) += clk-divider.o
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > new file mode 100644
> > index 0000000..2de94df
> > --- /dev/null
> > +++ b/drivers/clk/clk-divider.c
> > @@ -0,0 +1,132 @@
> > +/*
> > + * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * Standard functionality for the common clock API.
> > + */
> > +#include <linux/module.h>
> > +#include <linux/clk.h>
> > +#include <linux/io.h>
> > +
> > +#define to_clk_divider(clk) (container_of(clk, struct clk_divider, clk))
> > +
> > +static unsigned long clk_divider_get_rate(struct clk *clk)
> > +{
> > +	struct clk_divider *divider = to_clk_divider(clk);
> > +	unsigned long rate = clk_get_rate(divider->parent);
> > +	unsigned int div;
> > +
> > +	div = readl(divider->reg) >> divider->shift;
> > +	div &= (1 << divider->width) - 1;
> > +
> > +	if (!(divider->flags & CLK_DIVIDER_FLAG_ONE_BASED))
> > +		div++;
> > +
> > +	return rate / div;
> DIV_ROUND_UP(rate, div)? (There is DIV_ROUND_CLOSEST, too, but I think
> you need to round up, see below.)
> 
> > +}
> > +
> > +static int clk_divider_bestdiv(struct clk *clk, unsigned long rate,
> > +		unsigned long *best_parent_rate)
> conceptually this returns an unsigned value
> 
> > +{
> > +	struct clk_divider *divider = to_clk_divider(clk);
> > +	int i, bestdiv = 0;
> > +	unsigned long parent_rate, best = 0, now, maxdiv;
> > +
> > +	maxdiv = (1 << divider->width);
> Is divider->width == 32 a valid scenario? If so, this overflows.
> 
> > +
> > +	if (divider->flags & CLK_DIVIDER_FLAG_ONE_BASED)
> > +		maxdiv--;
> > +
> > +	/*
> > +	 * 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++) {
> > +		parent_rate = clk_round_rate(divider->parent, (rate + 1) * i);
> > +		now = parent_rate / i;
> This is buggy, take rate = 25, i = 4. You request the parent to set
> 104. If you get that, the resulting rate is 26. (And even if
> clk_round_rate only return 101 this might be too much.)
> 
> I think you need:
> 
> 	parent_rate = clk_round_rate(divider->parent, rate * i)
> 	now = DIV_ROUND_UP(parent_rate, i);
> 
> I think you really need DIV_ROUND_UP here, DIV_ROUND_CLOSEST won't work.
> Consider that a rate of 25 is requested, again with i=4. So the parent
> is asked for 100 and might return 97. With DIV_ROUND_CLOSEST you report
> to be able to set 24 now, but in fact it's more (24.25). If now further
> up in the recursion another divider considers 24 to be a great value to
> make 12Hz the value actually provided is too big.

I will give it a try using the DIV_ROUND_ macros. I had problems with
two cascaded dividers where due to rounding errors while dividing I
got got the next smaller divider value when passing in a value which
I could exactly get.

> > +static int clk_divider_set_rate(struct clk *clk, unsigned long rate)
> > +{
> > +	unsigned long best_parent_rate;
> > +	struct clk_divider *divider = to_clk_divider(clk);
> > +	unsigned int div;
> > +	int ret;
> > +	unsigned long flags = 0;
> > +	u32 val;
> > +
> > +	div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
> > +
> > +	if (rate != best_parent_rate / div)
> > +		return -EINVAL;
> This is too harsh, isn't it. Or can you expect to only get values that
> are returned by round_rate? Again you need DIV_ROUND_UP.

AFAIK there are two different implementation types in the tree. Some
implementations only allow to set to the exact rate round_rate returns
while others round down in set_rate.

Has this been specified what behaviour is expected?

> >  
> > +/**
> > + * clock divider
> > + *
> > + * @clk		clock source
> > + * @reg		register containing the divider
> > + * @shift	shift to the divider
> > + * @width	width of the divider
> > + * @lock	register lock
> "optional register lock"?

ok.

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

* [PATCH 06/10] clk: Add support for a generic clock multiplexer
  2011-04-15 19:08 ` [PATCH 06/10] clk: Add support for a generic clock multiplexer Sascha Hauer
@ 2011-04-18 13:15   ` Uwe Kleine-König
  2011-04-18 13:33     ` Sascha Hauer
  0 siblings, 1 reply; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-18 13:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:08:11PM +0200, Sascha Hauer wrote:
> This patch adds support for a common type of clock multiplexer.
> The multiplexer is described with register, shift and width and
> an array of clocks which correspond to the bit value.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> ---
>  drivers/clk/Kconfig       |    3 +
>  drivers/clk/Makefile      |    1 +
>  drivers/clk/clk-divider.c |    2 +-
>  drivers/clk/clk-mux.c     |   92 +++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h       |   28 ++++++++++++++
>  5 files changed, 125 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/clk/clk-mux.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 76bb4c9..710d73d 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -8,3 +8,6 @@ config USE_COMMON_STRUCT_CLK
>  
>  config USE_COMMON_CLK_DIVIDER
>  	bool
> +
> +config USE_COMMON_CLK_MUX
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 723d884..195a434 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -2,3 +2,4 @@
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>  obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
>  obj-$(CONFIG_USE_COMMON_CLK_DIVIDER) += clk-divider.o
> +obj-$(CONFIG_USE_COMMON_CLK_MUX) += clk-mux.o
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index 2de94df..e3f5b7a 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de>
> + * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
This should go into an earlier patch.

>   *
>   * 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
> diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
> new file mode 100644
> index 0000000..d33b15f
> --- /dev/null
> +++ b/drivers/clk/clk-mux.c
> @@ -0,0 +1,92 @@
> +/*
> + * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +#include <linux/module.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +
> +#define to_clk_mux(clk) (container_of(clk, struct clk_mux, clk))
> +
> +static struct clk *clk_mux_get_parent(struct clk *clk)
> +{
> +	struct clk_mux *mux = to_clk_mux(clk);
> +	u32 val;
> +
> +	val = readl(mux->reg) >> mux->shift;
> +	val &= (1 << mux->width) - 1;
> +
> +	if (val >= mux->num_clks)
> +		return ERR_PTR(-EINVAL);
> +
> +	return mux->clks[val];
> +}
> +
> +static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	struct clk_mux *mux = to_clk_mux(clk);
> +	u32 val;
> +	int i;
> +	unsigned long flags = 0;
= 0 isn't needed. (Or does gcc wail without it?)

> +
> +	for (i = 0; i < mux->num_clks; i++)
> +		if (mux->clks[i] == parent)
> +			break;
> +
> +	if (i == mux->num_clks)
> +		return -EINVAL;
> +
> +	if (mux->lock)
> +		spin_lock_irqsave(mux->lock, flags);
> +
> +	val = readl(mux->reg);
> +	val &= ~(((1 << mux->width) - 1) << mux->shift);
> +	val |= i << mux->shift;
> +	writel(val, mux->reg);
> +
> +	if (mux->lock)
> +		spin_unlock_irqrestore(mux->lock, flags);
> +
> +	return 0;
> +}
> +
> +static long clk_mux_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	struct clk *parent = clk_get_parent(clk);
> +
> +	if (IS_ERR(parent))
> +		return PTR_ERR(parent);
> +
> +	return clk_get_rate(parent);
> +}
> +
> +static int clk_mux_set_rate(struct clk *clk, unsigned long desired)
> +{
> +	struct clk *parent = clk_get_parent(clk);
> +
> +	if (IS_ERR(parent))
> +		return PTR_ERR(parent);
> +
> +	if (desired != clk_get_rate(parent))
> +		return -EINVAL;
> +
> +	return 0;
> +}
Isn't not implementing set_rate good enough? Ditto for .round_rate.

> +struct clk_ops clk_mux_ops = {
> +	.prepare = clk_parent_prepare,
> +	.unprepare = clk_parent_unprepare,
> +	.enable = clk_parent_enable,
> +	.disable = clk_parent_disable,
> +	.get_rate = clk_parent_get_rate,
> +	.round_rate = clk_mux_round_rate,
> +	.set_rate = clk_mux_set_rate,
> +	.get_parent = clk_mux_get_parent,
> +	.set_parent = clk_mux_set_parent,
> +};
> +EXPORT_SYMBOL_GPL(clk_mux_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 6f9771b..fb2c2f5 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -211,6 +211,34 @@ struct clk_divider {
>  
>  extern struct clk_ops clk_divider_ops;
>  
> +/**
> + * clock multiplexer
> + *
> + * @clk		clock source
> + * @reg		the register this multiplexer can be configured with
> + * @shift	the shift to the start bit of this multiplexer
> + * @width	the width in bits of this multiplexer
> + * @num_clks	number of parent clocks
> + * @lock	register lock
> + * @clks	array of possible parents for this multiplexer. Can contain
> + *		holes with NULL in it for invalid register settings
NULL is a valid clk, isn't it?

> + *
> + * This clock implements get_parent/set_parent. prepare/unprepare,
> + * enable/disable and get_rate operations are passed through to the parent,
> + * the rate is not adjustable.
> + */
> +struct clk_mux {
> +	struct clk	clk;
> +	void __iomem	*reg;
> +	unsigned char	shift;
> +	unsigned char	width;
> +	unsigned char	num_clks;
> +	spinlock_t	*lock;
> +	struct clk	**clks;
> +};
> +
> +extern struct clk_ops clk_mux_ops;
> +
>  #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 06/10] clk: Add support for a generic clock multiplexer
  2011-04-18 13:15   ` Uwe Kleine-König
@ 2011-04-18 13:33     ` Sascha Hauer
  2011-04-18 13:54       ` Uwe Kleine-König
  2011-04-18 17:54       ` Stephen Boyd
  0 siblings, 2 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-18 13:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 18, 2011 at 03:15:27PM +0200, Uwe Kleine-K?nig wrote:
> On Fri, Apr 15, 2011 at 09:08:11PM +0200, Sascha Hauer wrote:
> > This patch adds support for a common type of clock multiplexer.
> > The multiplexer is described with register, shift and width and
> > an array of clocks which correspond to the bit value.
> > 
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> > ---
> >  drivers/clk/Kconfig       |    3 +
> >  drivers/clk/Makefile      |    1 +
> >  drivers/clk/clk-divider.c |    2 +-
> >  drivers/clk/clk-mux.c     |   92 +++++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk.h       |   28 ++++++++++++++
> >  5 files changed, 125 insertions(+), 1 deletions(-)
> >  create mode 100644 drivers/clk/clk-mux.c
> > 
> > diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> > index 76bb4c9..710d73d 100644
> > --- a/drivers/clk/Kconfig
> > +++ b/drivers/clk/Kconfig
> > @@ -8,3 +8,6 @@ config USE_COMMON_STRUCT_CLK
> >  
> >  config USE_COMMON_CLK_DIVIDER
> >  	bool
> > +
> > +config USE_COMMON_CLK_MUX
> > +	bool
> > diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> > index 723d884..195a434 100644
> > --- a/drivers/clk/Makefile
> > +++ b/drivers/clk/Makefile
> > @@ -2,3 +2,4 @@
> >  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> >  obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> >  obj-$(CONFIG_USE_COMMON_CLK_DIVIDER) += clk-divider.o
> > +obj-$(CONFIG_USE_COMMON_CLK_MUX) += clk-mux.o
> > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> > index 2de94df..e3f5b7a 100644
> > --- a/drivers/clk/clk-divider.c
> > +++ b/drivers/clk/clk-divider.c
> > @@ -1,5 +1,5 @@
> >  /*
> > - * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de>
> > + * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
> This should go into an earlier patch.

Indeed, already fixed.

> > +
> > +static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
> > +{
> > +	struct clk_mux *mux = to_clk_mux(clk);
> > +	u32 val;
> > +	int i;
> > +	unsigned long flags = 0;
> = 0 isn't needed. (Or does gcc wail without it?)

At least my gcc is not smart engough for this. flags may be used unitialized.

> 
> > +
> > +	for (i = 0; i < mux->num_clks; i++)
> > +		if (mux->clks[i] == parent)
> > +			break;
> > +
> > +	if (i == mux->num_clks)
> > +		return -EINVAL;
> > +
> > +	if (mux->lock)
> > +		spin_lock_irqsave(mux->lock, flags);
> > +
> > +	val = readl(mux->reg);
> > +	val &= ~(((1 << mux->width) - 1) << mux->shift);
> > +	val |= i << mux->shift;
> > +	writel(val, mux->reg);
> > +
> > +	if (mux->lock)
> > +		spin_unlock_irqrestore(mux->lock, flags);
> > +
> > +	return 0;
> > +}
> > +
> > +static long clk_mux_round_rate(struct clk *clk, unsigned long rate)
> > +{
> > +	struct clk *parent = clk_get_parent(clk);
> > +
> > +	if (IS_ERR(parent))
> > +		return PTR_ERR(parent);
> > +
> > +	return clk_get_rate(parent);
> > +}
> > +
> > +static int clk_mux_set_rate(struct clk *clk, unsigned long desired)
> > +{
> > +	struct clk *parent = clk_get_parent(clk);
> > +
> > +	if (IS_ERR(parent))
> > +		return PTR_ERR(parent);
> > +
> > +	if (desired != clk_get_rate(parent))
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> Isn't not implementing set_rate good enough? Ditto for .round_rate.

Yes, I removed these.

> >  
> > +/**
> > + * clock multiplexer
> > + *
> > + * @clk		clock source
> > + * @reg		the register this multiplexer can be configured with
> > + * @shift	the shift to the start bit of this multiplexer
> > + * @width	the width in bits of this multiplexer
> > + * @num_clks	number of parent clocks
> > + * @lock	register lock
> > + * @clks	array of possible parents for this multiplexer. Can contain
> > + *		holes with NULL in it for invalid register settings
> NULL is a valid clk, isn't it?

You're right. I think for invalid mux settings we should ERR_PTR(-EINVAL)
or similar to the array.

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

* [PATCH 06/10] clk: Add support for a generic clock multiplexer
  2011-04-18 13:33     ` Sascha Hauer
@ 2011-04-18 13:54       ` Uwe Kleine-König
  2011-04-18 17:54       ` Stephen Boyd
  1 sibling, 0 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-18 13:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 18, 2011 at 03:33:53PM +0200, Sascha Hauer wrote:
> On Mon, Apr 18, 2011 at 03:15:27PM +0200, Uwe Kleine-K?nig wrote:
> > On Fri, Apr 15, 2011 at 09:08:11PM +0200, Sascha Hauer wrote:
> > > +
> > > +static int clk_mux_set_parent(struct clk *clk, struct clk *parent)
> > > +{
> > > +	struct clk_mux *mux = to_clk_mux(clk);
> > > +	u32 val;
> > > +	int i;
> > > +	unsigned long flags = 0;
> > = 0 isn't needed. (Or does gcc wail without it?)
> 
> At least my gcc is not smart engough for this. flags may be used unitialized.
Then please use

	unsigned long uninitialized_var(flags);

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 06/10] clk: Add support for a generic clock multiplexer
  2011-04-18 13:33     ` Sascha Hauer
  2011-04-18 13:54       ` Uwe Kleine-König
@ 2011-04-18 17:54       ` Stephen Boyd
  2011-04-18 18:34         ` Russell King - ARM Linux
  1 sibling, 1 reply; 165+ messages in thread
From: Stephen Boyd @ 2011-04-18 17:54 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/18/2011 06:33 AM, Sascha Hauer wrote:
>>>  
>>> +/**
>>> + * clock multiplexer
>>> + *
>>> + * @clk		clock source
>>> + * @reg		the register this multiplexer can be configured with
>>> + * @shift	the shift to the start bit of this multiplexer
>>> + * @width	the width in bits of this multiplexer
>>> + * @num_clks	number of parent clocks
>>> + * @lock	register lock
>>> + * @clks	array of possible parents for this multiplexer. Can contain
>>> + *		holes with NULL in it for invalid register settings
>> NULL is a valid clk, isn't it?
> You're right. I think for invalid mux settings we should ERR_PTR(-EINVAL)
> or similar to the array.

Note that if you're using clkdev you can't actually return a NULL clock
to the caller of clk_get() due to:

struct clk *clk_get_sys(const char *dev_id, const char *con_id)
{
        struct clk *clk;

        mutex_lock(&clocks_mutex);
        clk = clk_find(dev_id, con_id);
        if (clk && !__clk_get(clk))
                clk = NULL;
        mutex_unlock(&clocks_mutex);

        return clk ? clk : ERR_PTR(-ENOENT);
}


So all this talk about NULL being a valid clock returned to drivers is
kinda pointless unless the mach has a custom clk_get() implementation.
Perhaps we should force clkdev on users of the generic struct clk framework?

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

* [PATCH 06/10] clk: Add support for a generic clock multiplexer
  2011-04-18 17:54       ` Stephen Boyd
@ 2011-04-18 18:34         ` Russell King - ARM Linux
  2011-04-18 18:41           ` Russell King - ARM Linux
  0 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-18 18:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 18, 2011 at 10:54:49AM -0700, Stephen Boyd wrote:
> On 04/18/2011 06:33 AM, Sascha Hauer wrote:
> >>>  
> >>> +/**
> >>> + * clock multiplexer
> >>> + *
> >>> + * @clk		clock source
> >>> + * @reg		the register this multiplexer can be configured with
> >>> + * @shift	the shift to the start bit of this multiplexer
> >>> + * @width	the width in bits of this multiplexer
> >>> + * @num_clks	number of parent clocks
> >>> + * @lock	register lock
> >>> + * @clks	array of possible parents for this multiplexer. Can contain
> >>> + *		holes with NULL in it for invalid register settings
> >> NULL is a valid clk, isn't it?
> > You're right. I think for invalid mux settings we should ERR_PTR(-EINVAL)
> > or similar to the array.
> 
> Note that if you're using clkdev you can't actually return a NULL clock
> to the caller of clk_get() due to:
> 
> struct clk *clk_get_sys(const char *dev_id, const char *con_id)
> {
>         struct clk *clk;
> 
>         mutex_lock(&clocks_mutex);
>         clk = clk_find(dev_id, con_id);
>         if (clk && !__clk_get(clk))
>                 clk = NULL;
>         mutex_unlock(&clocks_mutex);
> 
>         return clk ? clk : ERR_PTR(-ENOENT);
> }
> 
> 
> So all this talk about NULL being a valid clock returned to drivers is
> kinda pointless unless the mach has a custom clk_get() implementation.

Oops, clk_get_sys() and clk_find() really should be fixed for this.  I'll
sort a patch for it.

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

* [PATCH 06/10] clk: Add support for a generic clock multiplexer
  2011-04-18 18:34         ` Russell King - ARM Linux
@ 2011-04-18 18:41           ` Russell King - ARM Linux
  2011-04-18 18:46             ` Stephen Boyd
  0 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-18 18:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 18, 2011 at 07:34:21PM +0100, Russell King - ARM Linux wrote:
> Oops, clk_get_sys() and clk_find() really should be fixed for this.  I'll
> sort a patch for it.

And here it is:

8<----
Subject: [PATCH] Fix clkdev return value for NULL clk case

clkdev may incorrectly cause a clkdev entry with a NULL clk to return
-ENOENT.  This is not the intention of this code; -ENOENT should only
be returned if the clock entry can not be found in the table.  Fix this.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 drivers/clk/clkdev.c |   19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0fc0a79..36a134f 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -32,10 +32,9 @@ static DEFINE_MUTEX(clocks_mutex);
  * Then we take the most specific entry - with the following
  * order of precedence: dev+con > dev only > con only.
  */
-static struct clk *clk_find(const char *dev_id, const char *con_id)
+static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
 {
-	struct clk_lookup *p;
-	struct clk *clk = NULL;
+	struct clk_lookup *p, *cl = NULL;
 	int match, best = 0;
 
 	list_for_each_entry(p, &clocks, node) {
@@ -52,27 +51,27 @@ static struct clk *clk_find(const char *dev_id, const char *con_id)
 		}
 
 		if (match > best) {
-			clk = p->clk;
+			cl = p;
 			if (match != 3)
 				best = match;
 			else
 				break;
 		}
 	}
-	return clk;
+	return cl;
 }
 
 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 {
-	struct clk *clk;
+	struct clk_lookup *cl;
 
 	mutex_lock(&clocks_mutex);
-	clk = clk_find(dev_id, con_id);
-	if (clk && !__clk_get(clk))
-		clk = NULL;
+	cl = clk_find(dev_id, con_id);
+	if (cl && !__clk_get(cl->clk))
+		cl = NULL;
 	mutex_unlock(&clocks_mutex);
 
-	return clk ? clk : ERR_PTR(-ENOENT);
+	return cl ? cl->clk : ERR_PTR(-ENOENT);
 }
 EXPORT_SYMBOL(clk_get_sys);
 

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

* [PATCH 06/10] clk: Add support for a generic clock multiplexer
  2011-04-18 18:41           ` Russell King - ARM Linux
@ 2011-04-18 18:46             ` Stephen Boyd
  0 siblings, 0 replies; 165+ messages in thread
From: Stephen Boyd @ 2011-04-18 18:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/18/2011 11:41 AM, Russell King - ARM Linux wrote:
> On Mon, Apr 18, 2011 at 07:34:21PM +0100, Russell King - ARM Linux wrote:
>> Oops, clk_get_sys() and clk_find() really should be fixed for this.  I'll
>> sort a patch for it.
> And here it is:
>
> 8<----
> Subject: [PATCH] Fix clkdev return value for NULL clk case
>
> clkdev may incorrectly cause a clkdev entry with a NULL clk to return
> -ENOENT.  This is not the intention of this code; -ENOENT should only
> be returned if the clock entry can not be found in the table.  Fix this.
>
> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

Thanks. Feel free to include a:

Reported-by: Stephen Boyd <sboyd@codeaurora.org>

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-15 19:08 ` [PATCH 05/10] clk: Add support for simple dividers Sascha Hauer
  2011-04-18  9:49   ` Uwe Kleine-König
@ 2011-04-18 22:40   ` Stephen Boyd
  2011-04-19  0:32     ` Jeremy Kerr
  2011-04-24 13:48   ` Richard Zhao
  2 siblings, 1 reply; 165+ messages in thread
From: Stephen Boyd @ 2011-04-18 22:40 UTC (permalink / raw)
  To: linux-arm-kernel

Just minor nitpicks.

On 04/15/2011 12:08 PM, Sascha Hauer wrote:
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> new file mode 100644
> index 0000000..2de94df
> --- /dev/null
> +++ b/drivers/clk/clk-divider.c
> @@ -0,0 +1,132 @@
> +/*
> + * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +#include <linux/module.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +
> +#define to_clk_divider(clk) (container_of(clk, struct clk_divider, clk))

Can you make this a static inline function with actual types? We get
slightly more type safety that way. Ditto for similar constructs in this
series.

> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index d014341..6f9771b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -180,6 +180,37 @@ unsigned long clk_parent_get_rate(struct clk *clk);
>  long clk_parent_round_rate(struct clk *clk, unsigned long rate);
>  int clk_parent_set_rate(struct clk *clk, unsigned long rate);
>  
> +/**
> + * clock divider
> + *
> + * @clk		clock source
> + * @reg		register containing the divider
> + * @shift	shift to the divider
> + * @width	width of the divider
> + * @lock	register lock
> + * @parent	parent clock
> + *
> + * This clock implements get_rate/set_rate/round_rate. prepare/unprepare and
> + * enable/disable are passed through to the parent.
> + *
> + * The divider is calculated as div = reg_val + 1
> + * or if CLK_DIVIDER_FLAG_ONE_BASED is set as div = reg_val
> + * (with reg_val == 0 considered invalid)
> + */

This isn't kernel-doc notation. See Documentation/kernel-doc-nano-HOWTO.txt

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-18 22:40   ` Stephen Boyd
@ 2011-04-19  0:32     ` Jeremy Kerr
  2011-04-19  5:41       ` Stephen Boyd
  0 siblings, 1 reply; 165+ messages in thread
From: Jeremy Kerr @ 2011-04-19  0:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Stephen,

> > +#define to_clk_divider(clk) (container_of(clk, struct clk_divider, clk))
> 
> Can you make this a static inline function with actual types? We get
> slightly more type safety that way.

Do we? The container_of macro requires that that it's first argument is
the same type as type->member, and returns a (type), so I don't see how
we're going to miss typing errors here.

However, with these macros, we need to use a parameter name that isn't
the same as the member name. Sascha: can you fix this? I'll update the
clk_fixed support.

Cheers,


Jeremy

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

* [PATCH 03/10] clk: Make NULL a valid clock again
  2011-04-15 19:08 ` [PATCH 03/10] clk: Make NULL a valid clock again Sascha Hauer
@ 2011-04-19  0:53   ` Jeremy Kerr
  2011-04-19  6:25     ` Sascha Hauer
  2011-04-20 12:53   ` Uwe Kleine-König
  1 sibling, 1 reply; 165+ messages in thread
From: Jeremy Kerr @ 2011-04-19  0:53 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sascha,

> NULL used to be a valid clock. This patch makes the common struct
> clk stuff work with this. Instead of crashing we return sane default
> values for this dummy clock, that is: can always be prepared, enabled,
> rate unkown and no set rate.

Although I'm not totally averse to this change, I've been trying to
avoid allowing NULL clocks - it seems to be a little 'messy' to allows
clocks that don't have any possible operations on them, and could hide
error cases where clock pointers have not been correctly initialised.

However, I understand that this may be required for flexibility between
machines, and in that case would make sense. Is that what you're
intending this for?

Cheers,


Jeremy

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-18 10:07     ` Sascha Hauer
@ 2011-04-19  2:45       ` Saravana Kannan
  2011-04-19  7:32         ` Uwe Kleine-König
  2011-04-28 15:14         ` Russell King - ARM Linux
  0 siblings, 2 replies; 165+ messages in thread
From: Saravana Kannan @ 2011-04-19  2:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/18/2011 03:07 AM, Sascha Hauer wrote:
> On Mon, Apr 18, 2011 at 11:49:09AM +0200, Uwe Kleine-K?nig wrote:
>> On Fri, Apr 15, 2011 at 09:08:10PM +0200, Sascha Hauer wrote:
>>> This patch adds support for the most common type of divider,
>>> which expects a register, width and shift values to desacribe
>>> the location of the divider. The divider can be zero based
>>> or one based (div = reg_val + 1 vs. div = reg_val).
>>>
>>> Signed-off-by: Sascha Hauer<s.hauer@pengutronix.de>
>>> Cc: Jeremy Kerr<jeremy.kerr@canonical.com>
>>> ---
>>>   drivers/clk/Kconfig       |    3 +
>>>   drivers/clk/Makefile      |    1 +
>>>   drivers/clk/clk-divider.c |  132 +++++++++++++++++++++++++++++++++++++++++++++
>>>   include/linux/clk.h       |   31 +++++++++++
>>>   4 files changed, 167 insertions(+), 0 deletions(-)
>>>   create mode 100644 drivers/clk/clk-divider.c
>>>
>>> +static int clk_divider_set_rate(struct clk *clk, unsigned long rate)
>>> +{
>>> +	unsigned long best_parent_rate;
>>> +	struct clk_divider *divider = to_clk_divider(clk);
>>> +	unsigned int div;
>>> +	int ret;
>>> +	unsigned long flags = 0;
>>> +	u32 val;
>>> +
>>> +	div = clk_divider_bestdiv(clk, rate,&best_parent_rate);
>>> +
>>> +	if (rate != best_parent_rate / div)
>>> +		return -EINVAL;
>> This is too harsh, isn't it. Or can you expect to only get values that
>> are returned by round_rate? Again you need DIV_ROUND_UP.
>
> AFAIK there are two different implementation types in the tree. Some
> implementations only allow to set to the exact rate round_rate returns
> while others round down in set_rate.
>
> Has this been specified what behaviour is expected?
>

This is something I have nagged Russell once or twice about and then 
sent out an email to the list for which there was very limited response. 
I think clk_round_rate() is too generic and not very useful.

We should really have something like:
clk_set_rate_range(min, ideal, max)

That way, we don't have to guess what's best for the consumer. The 
consumers knows exactly what range it can work with and what is ideal. 
Also, this simplifies the life of the device driver writer when the 
device is used in many different SoCs with different clock plans and 
different meanings of round rate (up vs. down vs. closest). As of today, 
to deal with the latter case, the device drivers will have to get the 
clock rate passed through platform data.

I'm really hoping there is enough attention to finally get the clock API 
cleaned up for better clarity.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-19  0:32     ` Jeremy Kerr
@ 2011-04-19  5:41       ` Stephen Boyd
  0 siblings, 0 replies; 165+ messages in thread
From: Stephen Boyd @ 2011-04-19  5:41 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/18/2011 5:32 PM, Jeremy Kerr wrote:
> Hi Stephen,
>
>>> +#define to_clk_divider(clk) (container_of(clk, struct clk_divider, clk))
>> Can you make this a static inline function with actual types? We get
>> slightly more type safety that way.
> Do we? The container_of macro requires that that it's first argument is
> the same type as type->member, and returns a (type), so I don't see how
> we're going to miss typing errors here.

Ah yes you're right. Should have looked further. I still like static
inline functions for these things but I don't see any reason why one is
better over the other.

Thanks,
Stephen

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

* [PATCH 03/10] clk: Make NULL a valid clock again
  2011-04-19  0:53   ` Jeremy Kerr
@ 2011-04-19  6:25     ` Sascha Hauer
  0 siblings, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-19  6:25 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Jeremy,

On Tue, Apr 19, 2011 at 08:53:40AM +0800, Jeremy Kerr wrote:
> Hi Sascha,
> 
> > NULL used to be a valid clock. This patch makes the common struct
> > clk stuff work with this. Instead of crashing we return sane default
> > values for this dummy clock, that is: can always be prepared, enabled,
> > rate unkown and no set rate.
> 
> Although I'm not totally averse to this change, I've been trying to
> avoid allowing NULL clocks - it seems to be a little 'messy' to allows
> clocks that don't have any possible operations on them, and could hide
> error cases where clock pointers have not been correctly initialised.
> 
> However, I understand that this may be required for flexibility between
> machines, and in that case would make sense. Is that what you're
> intending this for?

I intended to use NULL clocks but didn't do it then. The patch was
already created, so I posted it. I think We could equally well create a
dummy clock which can be used by all architectures. People (including
me) never really got used to NULL clocks and it's been a source of
confusion since they have been introduced.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-19  2:45       ` Saravana Kannan
@ 2011-04-19  7:32         ` Uwe Kleine-König
  2011-04-19  8:55           ` Saravana Kannan
  2011-04-28 15:14         ` Russell King - ARM Linux
  1 sibling, 1 reply; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-19  7:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Mon, Apr 18, 2011 at 07:45:53PM -0700, Saravana Kannan wrote:
> On 04/18/2011 03:07 AM, Sascha Hauer wrote:
> >On Mon, Apr 18, 2011 at 11:49:09AM +0200, Uwe Kleine-K?nig wrote:
> >>On Fri, Apr 15, 2011 at 09:08:10PM +0200, Sascha Hauer wrote:
> >AFAIK there are two different implementation types in the tree. Some
> >implementations only allow to set to the exact rate round_rate returns
> >while others round down in set_rate.
> >
> >Has this been specified what behaviour is expected?
> >
> 
> This is something I have nagged Russell once or twice about and then
> sent out an email to the list for which there was very limited
> response. I think clk_round_rate() is too generic and not very
> useful.
> 
> We should really have something like:
> clk_set_rate_range(min, ideal, max)
(Note this is orthogonal to the question if set_rate may barf on values
other than the return values of round_rate.)

clk_set_rate_range can even be implemented with clk_round_rate that is
just required to fulfill:

	clk_round_rate(clk, X) > 0 =>
	clk_set_rate(clk, clk_round_rate(clk, X)) == clk_round_rate(clk, X)
		and
	clk_round_rate(clk, clk_round_rate(clk, X)) == clk_round_rate(clk, X)

and

	X >= Y =>
	clk_round_rate(clk, X) >= clk_round_rate(clk, Y)

which every implementation should assert provided that X and Y are the
domain of clk_round_rate(clk, .)

Something like:

	long clk_round_rate_range(struct clk *clk, unsigned long minrate,
		unsigned long optrate, unsigned long maxrate)
	{
		unsigned long bot = minrate, best, cur, top = maxrate;
		unsigned long delta;
		long tmp;

		if (minrate > optrate || optrate > maxrate)
			return -EINVAL;

		if (maxrate > LONG_MAX)
			/* can anything be done here? */
			return -EINVAL;

		best = cur = clk_round_rate(clk, optrate);
		if (cur == optrate)
			return optrate;

		delta = optrate > best ? optrate - best : best - optrate;

		while (1) {
			if (cur > optrate) {
				if (delta > cur - optrate)
					best = cur;
				top = cur;
				cur = (bot + cur) / 2;
			} else if (cur < optrate) {
				if (delta > optrate - cur)
					best = cur;
				bot = cur;
				cur = (cur + top + 1) / 2;
			} else {
				WARN(1, "Your clk_round_rate implementation is broken (clk = %pS, [%lu, %lu, %lu]\n.",
					clk, minrate, optrate, maxrate);
				return -EINVAL;
			}

			tmp = clk_round_rate(clk, cur);
			if (tmp < 0)
				return tmp;
			cur = tmp;

			if (bot == top)
				break;
		}

		if (best < minrate || best > maxrate)
			return -EINVAL;

		return best;
	}

	int clk_set_rate_range(struct clk *clk, unsigned long minrate,
		unsigned long optrate, unsigned long maxrate)
	{
		long rate = clk_round_rate_range(clk, minrate,
				optrate, maxrate);

		if (rate < 0)
			return rate;

		clk_set_rate(clk, rate);
	}

Completely untestet so probably broken.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-19  7:32         ` Uwe Kleine-König
@ 2011-04-19  8:55           ` Saravana Kannan
  2011-04-19  9:31             ` Sascha Hauer
  0 siblings, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-04-19  8:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, April 19, 2011 12:32 am, Uwe Kleine-K?nig wrote:
> Hello,
>
> On Mon, Apr 18, 2011 at 07:45:53PM -0700, Saravana Kannan wrote:
>> On 04/18/2011 03:07 AM, Sascha Hauer wrote:
>> >On Mon, Apr 18, 2011 at 11:49:09AM +0200, Uwe Kleine-K?nig wrote:
>> >>On Fri, Apr 15, 2011 at 09:08:10PM +0200, Sascha Hauer wrote:
>> >AFAIK there are two different implementation types in the tree. Some
>> >implementations only allow to set to the exact rate round_rate returns
>> >while others round down in set_rate.
>> >
>> >Has this been specified what behaviour is expected?
>> >
>>
>> This is something I have nagged Russell once or twice about and then
>> sent out an email to the list for which there was very limited
>> response. I think clk_round_rate() is too generic and not very
>> useful.
>>
>> We should really have something like:
>> clk_set_rate_range(min, ideal, max)
> (Note this is orthogonal to the question if set_rate may barf on values
> other than the return values of round_rate.)
>
> clk_set_rate_range can even be implemented with clk_round_rate that is
> just required to fulfill:

I think it's more important that we try to find a new API that's better
than clk_round_rate(). We can worry about the specifics of the
implementation later.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-19  8:55           ` Saravana Kannan
@ 2011-04-19  9:31             ` Sascha Hauer
  2011-04-19 22:28               ` Saravana Kannan
  0 siblings, 1 reply; 165+ messages in thread
From: Sascha Hauer @ 2011-04-19  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 19, 2011 at 01:55:17AM -0700, Saravana Kannan wrote:
> On Tue, April 19, 2011 12:32 am, Uwe Kleine-K?nig wrote:
> > Hello,
> >
> > On Mon, Apr 18, 2011 at 07:45:53PM -0700, Saravana Kannan wrote:
> >> On 04/18/2011 03:07 AM, Sascha Hauer wrote:
> >> >On Mon, Apr 18, 2011 at 11:49:09AM +0200, Uwe Kleine-K?nig wrote:
> >> >>On Fri, Apr 15, 2011 at 09:08:10PM +0200, Sascha Hauer wrote:
> >> >AFAIK there are two different implementation types in the tree. Some
> >> >implementations only allow to set to the exact rate round_rate returns
> >> >while others round down in set_rate.
> >> >
> >> >Has this been specified what behaviour is expected?
> >> >
> >>
> >> This is something I have nagged Russell once or twice about and then
> >> sent out an email to the list for which there was very limited
> >> response. I think clk_round_rate() is too generic and not very
> >> useful.
> >>
> >> We should really have something like:
> >> clk_set_rate_range(min, ideal, max)
> > (Note this is orthogonal to the question if set_rate may barf on values
> > other than the return values of round_rate.)
> >
> > clk_set_rate_range can even be implemented with clk_round_rate that is
> > just required to fulfill:
> 
> I think it's more important that we try to find a new API that's better
> than clk_round_rate(). We can worry about the specifics of the
> implementation later.

You found it and Uwe found a way to implement this ontop of the old API,
that's a comfortable situation, isn't 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] 165+ messages in thread

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-15 19:08 ` [PATCH 04/10] clk: implement parent pass through functions Sascha Hauer
  2011-04-18  9:25   ` Uwe Kleine-König
@ 2011-04-19 17:20   ` Stephen Boyd
  2011-04-19 17:53     ` Sascha Hauer
  1 sibling, 1 reply; 165+ messages in thread
From: Stephen Boyd @ 2011-04-19 17:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/15/2011 12:08 PM, Sascha Hauer wrote:
> A common case for clocks is that certain operations are not implemented
> and shall be passed through to the parent. Add convenience functions
> for this purpose
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
>

I was hoping we could just build the parent handling into the core
instead of having every clk_ops->enable call the parent ops.

Something like: if the clk_ops doesn't have a get_parent,
clk_get_parent() would return NULL, and if the clk_ops doesn't have a
set_parent, clk_set_parent() would do nothing.

Then clk_enable()/clk_disable() would call clk_get_parent() and then
clk_enable() on that (whatever it is) before calling down into the
ops->enable() function. Of course this means NULL is now the "no parent"
value as opposed to ERR_PTR(-ENOSYS) but I'm willing to live with that
since it makes things a bit simpler when you only have to check for NULL
in the clk_enable()/clk_disable() path as opposed to NULL and IS_ERR.

I'm afraid this patch means every time the clk_ops wants to enable its
parent (which is almost always the case), it has to do so explicitly
when we really just want to concentrate on what enabling means for that
clock (namely setting some bits in some registers). Thoughts?

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-19 17:20   ` Stephen Boyd
@ 2011-04-19 17:53     ` Sascha Hauer
  2011-04-19 19:09       ` Uwe Kleine-König
  2011-04-29 10:20       ` [PATCH 04/10] clk: implement parent pass through functions Russell King - ARM Linux
  0 siblings, 2 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-19 17:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 19, 2011 at 10:20:28AM -0700, Stephen Boyd wrote:
> On 04/15/2011 12:08 PM, Sascha Hauer wrote:
> > A common case for clocks is that certain operations are not implemented
> > and shall be passed through to the parent. Add convenience functions
> > for this purpose
> >
> > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> >
> 
> I was hoping we could just build the parent handling into the core
> instead of having every clk_ops->enable call the parent ops.
> 
> Something like: if the clk_ops doesn't have a get_parent,
> clk_get_parent() would return NULL, and if the clk_ops doesn't have a
> set_parent, clk_set_parent() would do nothing.

That's the current behaviour (except that ERR_PTR(-ENOSYS) is returned
instead of NULL).

> 
> Then clk_enable()/clk_disable() would call clk_get_parent() and then
> clk_enable() on that (whatever it is) before calling down into the
> ops->enable() function. Of course this means NULL is now the "no parent"
> value as opposed to ERR_PTR(-ENOSYS) but I'm willing to live with that
> since it makes things a bit simpler when you only have to check for NULL
> in the clk_enable()/clk_disable() path as opposed to NULL and IS_ERR.
> 
> I'm afraid this patch means every time the clk_ops wants to enable its
> parent (which is almost always the case), it has to do so explicitly
> when we really just want to concentrate on what enabling means for that
> clock (namely setting some bits in some registers). Thoughts?

+1 for letting the core enable/disable and prepare/unprepare the parent
clocks. I scanned the different arm clock implementations and they all
do it, except the ones which do not implement parents at all.

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-19 17:53     ` Sascha Hauer
@ 2011-04-19 19:09       ` Uwe Kleine-König
  2011-04-19 20:58         ` Sascha Hauer
  2011-04-19 21:54         ` Thomas Gleixner
  2011-04-29 10:20       ` [PATCH 04/10] clk: implement parent pass through functions Russell King - ARM Linux
  1 sibling, 2 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-19 19:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Tue, Apr 19, 2011 at 07:53:18PM +0200, Sascha Hauer wrote:
> On Tue, Apr 19, 2011 at 10:20:28AM -0700, Stephen Boyd wrote:
> > On 04/15/2011 12:08 PM, Sascha Hauer wrote:
> > > A common case for clocks is that certain operations are not implemented
> > > and shall be passed through to the parent. Add convenience functions
> > > for this purpose
> > >
> > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> > > Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> > >
> > 
> > I was hoping we could just build the parent handling into the core
> > instead of having every clk_ops->enable call the parent ops.
> > 
> > Something like: if the clk_ops doesn't have a get_parent,
> > clk_get_parent() would return NULL, and if the clk_ops doesn't have a
> > set_parent, clk_set_parent() would do nothing.
> 
> That's the current behaviour (except that ERR_PTR(-ENOSYS) is returned
> instead of NULL).
> 
> > 
> > Then clk_enable()/clk_disable() would call clk_get_parent() and then
> > clk_enable() on that (whatever it is) before calling down into the
> > ops->enable() function. Of course this means NULL is now the "no parent"
> > value as opposed to ERR_PTR(-ENOSYS) but I'm willing to live with that
> > since it makes things a bit simpler when you only have to check for NULL
> > in the clk_enable()/clk_disable() path as opposed to NULL and IS_ERR.
> > 
> > I'm afraid this patch means every time the clk_ops wants to enable its
> > parent (which is almost always the case), it has to do so explicitly
> > when we really just want to concentrate on what enabling means for that
> > clock (namely setting some bits in some registers). Thoughts?
> 
> +1 for letting the core enable/disable and prepare/unprepare the parent
> clocks. I scanned the different arm clock implementations and they all
> do it, except the ones which do not implement parents at all.
Then the question is if all do handle parents in the same way. (i.e.
in enable do parent first, in disable do child first?)

If one layer of indirection is acceptable this can easily be
accomplished (unless I oversee something):

	struct clk_with_parent {
		struct clk clk;
		const struct clk_ops *ops;
		struct clk *parent;
	}

Then the callbacks in clk_with_parent.clk would handle the parent and
then call the respective callbacks in clk_with_parent.ops.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-19 19:09       ` Uwe Kleine-König
@ 2011-04-19 20:58         ` Sascha Hauer
  2011-04-19 21:54         ` Thomas Gleixner
  1 sibling, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-04-19 20:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 19, 2011 at 09:09:10PM +0200, Uwe Kleine-K?nig wrote:
> Hello,
> 
> > 
> > +1 for letting the core enable/disable and prepare/unprepare the parent
> > clocks. I scanned the different arm clock implementations and they all
> > do it, except the ones which do not implement parents at all.
> Then the question is if all do handle parents in the same way. (i.e.
> in enable do parent first, in disable do child first?)

Yes, they do.

> 
> If one layer of indirection is acceptable this can easily be
> accomplished (unless I oversee something):
> 
> 	struct clk_with_parent {
> 		struct clk clk;
> 		const struct clk_ops *ops;
> 		struct clk *parent;
> 	}
> 
> Then the callbacks in clk_with_parent.clk would handle the parent and
> then call the respective callbacks in clk_with_parent.ops.

I fail to see what you are trying to archieve. struct clk already has a ops
pointer, what's the purpose of the additional *ops here?
Other than that I prefer not to hardcode parent pointers. Often enough I
have looked at clock trees and wondered if the clock tree is in sync
with the hardware. When we read the mux values back from the hardware in
clk_get_parent the trees are in sync by definition (modulo refcounting
when you play with the registers somewhere else).

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-19 19:09       ` Uwe Kleine-König
  2011-04-19 20:58         ` Sascha Hauer
@ 2011-04-19 21:54         ` Thomas Gleixner
  2011-04-20  7:16           ` Uwe Kleine-König
  2011-04-20 14:07           ` [PATCH RFC] clk: add support for automatic parent handling Uwe Kleine-König
  1 sibling, 2 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-19 21:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 19 Apr 2011, Uwe Kleine-K?nig wrote:
> > +1 for letting the core enable/disable and prepare/unprepare the parent
> > clocks. I scanned the different arm clock implementations and they all
> > do it, except the ones which do not implement parents at all.
> Then the question is if all do handle parents in the same way. (i.e.
> in enable do parent first, in disable do child first?)

That's not a question at all. Anything which does it the other way
round is broken. Period.
 
> If one layer of indirection is acceptable this can easily be
> accomplished (unless I oversee something):
> 
> 	struct clk_with_parent {
> 		struct clk clk;
> 		const struct clk_ops *ops;
> 		struct clk *parent;
> 	}
> 
> Then the callbacks in clk_with_parent.clk would handle the parent and
> then call the respective callbacks in clk_with_parent.ops.

Why the heck do you want to do that? That's a complete and utter
failure. You invent indirections for no value at all which just
violate any sense of abstraction and layering.

clk_en/disable should just do (simplified):

clk_enable(clk)
{
	if (!clk)
	   return 0;

	ret = clk_enable(clk->parent);
	if (ret)
	   return ret;

	clk_refcnt++;

	if (!clk->enable) 
	   return 0;

   	ret = clk->enable();
	if (!ret)
	   return 0;

	clk_refcnt--;
	clk_disable(clk->parent);

	return ret;	
}

Now go figure how clk_disable should look like.

No clk should care about the parent at all, except for handing down
the pointer. And it should not even check for the pointer being NULL
or not. It does not matter at all, as long as clk_enable/disable
return sensible error codes.

Anything else is just overengineered clusterfuck for no value at all,
which makes error handling way more complex than it needs to be.

Thanks,

	tglx

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-19  9:31             ` Sascha Hauer
@ 2011-04-19 22:28               ` Saravana Kannan
  2011-04-20  6:36                 ` Sascha Hauer
  0 siblings, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-04-19 22:28 UTC (permalink / raw)
  To: linux-arm-kernel

Sascha Hauer <s.hauer@pengutronix.de> wrote:

>On Tue, Apr 19, 2011 at 01:55:17AM -0700, Saravana Kannan wrote:
>> On Tue, April 19, 2011 12:32 am, Uwe Kleine-K?nig wrote:
>> > Hello,
>> >
>> > On Mon, Apr 18, 2011 at 07:45:53PM -0700, Saravana Kannan wrote:
>> >> On 04/18/2011 03:07 AM, Sascha Hauer wrote:
>> >> >On Mon, Apr 18, 2011 at 11:49:09AM +0200, Uwe Kleine-K?nig wrote:
>> >> >>On Fri, Apr 15, 2011 at 09:08:10PM +0200, Sascha Hauer wrote:
>> >> >AFAIK there are two different implementation types in the tree.
>Some
>> >> >implementations only allow to set to the exact rate round_rate
>returns
>> >> >while others round down in set_rate.
>> >> >
>> >> >Has this been specified what behaviour is expected?
>> >> >
>> >>
>> >> This is something I have nagged Russell once or twice about and
>then
>> >> sent out an email to the list for which there was very limited
>> >> response. I think clk_round_rate() is too generic and not very
>> >> useful.
>> >>
>> >> We should really have something like:
>> >> clk_set_rate_range(min, ideal, max)
>> > (Note this is orthogonal to the question if set_rate may barf on
>values
>> > other than the return values of round_rate.)
>> >
>> > clk_set_rate_range can even be implemented with clk_round_rate that
>is
>> > just required to fulfill:
>> 
>> I think it's more important that we try to find a new API that's
>better
>> than clk_round_rate(). We can worry about the specifics of the
>> implementation later.
>
>You found it and Uwe found a way to implement this ontop of the old
>API,
>that's a comfortable situation, isn't it?

Well, do we all agree to this new API? I have no problem with Uwe's helper fn or his suggestion, if we all agree on the final API. I just didn't want him wasting his time when the API is not finalized.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-19 22:28               ` Saravana Kannan
@ 2011-04-20  6:36                 ` Sascha Hauer
  2011-04-20 21:45                   ` Saravana Kannan
  0 siblings, 1 reply; 165+ messages in thread
From: Sascha Hauer @ 2011-04-20  6:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 19, 2011 at 03:28:50PM -0700, Saravana Kannan wrote:
> Sascha Hauer <s.hauer@pengutronix.de> wrote:
> 
> >> >>
> >> >> We should really have something like:
> >> >> clk_set_rate_range(min, ideal, max)
> >> > (Note this is orthogonal to the question if set_rate may barf on
> >values
> >> > other than the return values of round_rate.)
> >> >
> >> > clk_set_rate_range can even be implemented with clk_round_rate that
> >is
> >> > just required to fulfill:
> >> 
> >> I think it's more important that we try to find a new API that's
> >better
> >> than clk_round_rate(). We can worry about the specifics of the
> >> implementation later.
> >
> >You found it and Uwe found a way to implement this ontop of the old
> >API,
> >that's a comfortable situation, isn't it?
> 
> Well, do we all agree to this new API? I have no problem with Uwe's
> helper fn or his suggestion, if we all agree on the final API. I just
> didn't want him wasting his time when the API is not finalized.

As Uwes suggestion does not change the internal clock API it's
relatively simple to try out. With this we moved to the
add-a-helper-function class of patches and are not in the
change-internal-and-external-API-with-hundreds-of-users
class anymore.

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-19 21:54         ` Thomas Gleixner
@ 2011-04-20  7:16           ` Uwe Kleine-König
  2011-04-20  8:34             ` Thomas Gleixner
  2011-04-20 14:07           ` [PATCH RFC] clk: add support for automatic parent handling Uwe Kleine-König
  1 sibling, 1 reply; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-20  7:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 19, 2011 at 11:54:21PM +0200, Thomas Gleixner wrote:
> On Tue, 19 Apr 2011, Uwe Kleine-K?nig wrote:
> > > +1 for letting the core enable/disable and prepare/unprepare the parent
> > > clocks. I scanned the different arm clock implementations and they all
> > > do it, except the ones which do not implement parents at all.
> > Then the question is if all do handle parents in the same way. (i.e.
> > in enable do parent first, in disable do child first?)
> 
> That's not a question at all. Anything which does it the other way
> round is broken. Period.
I havn't checked, but I remember Jeremy not wanting to handle parents in
the generic part because he saw some differences.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-20  7:16           ` Uwe Kleine-König
@ 2011-04-20  8:34             ` Thomas Gleixner
  0 siblings, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-20  8:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:

> On Tue, Apr 19, 2011 at 11:54:21PM +0200, Thomas Gleixner wrote:
> > On Tue, 19 Apr 2011, Uwe Kleine-K?nig wrote:
> > > > +1 for letting the core enable/disable and prepare/unprepare the parent
> > > > clocks. I scanned the different arm clock implementations and they all
> > > > do it, except the ones which do not implement parents at all.
> > > Then the question is if all do handle parents in the same way. (i.e.
> > > in enable do parent first, in disable do child first?)
> > 
> > That's not a question at all. Anything which does it the other way
> > round is broken. Period.
> I havn't checked, but I remember Jeremy not wanting to handle parents in
> the generic part because he saw some differences.

It does not matter whether you checked or not. And it does not matter
whether Jeremy found code which does it the other way round.

The only safe way is parent first on enable and child first on
disable. That's a matter of hardware and not a question of random Joe
hacker got it wrong and it happens to work.

Sure it works on a simple divider which is connected to the parent
clock, but think "child is a PLL".

So having a strict ordering enforced is the only sane way, unless you
can prove that a particular piece of hardware requires it the other
way round. And I doubt that you can find one.

So the framework should be coded for the sane case in the first
place. If the unlikely case of reverse ordering surfaces one day, then
it's not rocket science to deal with that with a flag in struct clk
which tells clk_enable/disable or prepare/unprepare to do it the other
way round.

Thanks,

	tglx

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

* [PATCH 03/10] clk: Make NULL a valid clock again
  2011-04-15 19:08 ` [PATCH 03/10] clk: Make NULL a valid clock again Sascha Hauer
  2011-04-19  0:53   ` Jeremy Kerr
@ 2011-04-20 12:53   ` Uwe Kleine-König
  1 sibling, 0 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-20 12:53 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:08:08PM +0200, Sascha Hauer wrote:
> NULL used to be a valid clock. This patch makes the common struct
> clk stuff work with this. Instead of crashing we return sane default
> values for this dummy clock, that is: can always be prepared, enabled,
> rate unkown and no set rate.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> ---
>  drivers/clk/clk.c |   27 +++++++++++++++++++++++++++
>  1 files changed, 27 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 0da0bb9..264c809 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -15,6 +15,9 @@ int clk_prepare(struct clk *clk)
>  {
>  	int ret = 0;
>  
> +	if (!clk)
> +		return 0;
> +
>  	mutex_lock(&clk->prepare_lock);
>  	if (clk->prepare_count == 0 && clk->ops->prepare)
>  		ret = clk->ops->prepare(clk);
> @@ -29,6 +32,9 @@ EXPORT_SYMBOL_GPL(clk_prepare);
>  
>  void clk_unprepare(struct clk *clk)
>  {
> +	if (!clk)
> +		return;
> +
>  	mutex_lock(&clk->prepare_lock);
>  
>  	WARN_ON(clk->prepare_count == 0);
> @@ -47,6 +53,9 @@ int clk_enable(struct clk *clk)
>  	unsigned long flags;
>  	int ret = 0;
>  
> +	if (!clk)
> +		return 0;
> +
>  	WARN_ON(clk->prepare_count == 0);
>  
>  	spin_lock_irqsave(&clk->enable_lock, flags);
> @@ -65,6 +74,9 @@ void clk_disable(struct clk *clk)
>  {
>  	unsigned long flags;
>  
> +	if (!clk)
> +		return;
> +
>  	spin_lock_irqsave(&clk->enable_lock, flags);
>  
>  	WARN_ON(clk->enable_count == 0);
> @@ -78,6 +90,9 @@ EXPORT_SYMBOL_GPL(clk_disable);
>  
>  unsigned long clk_get_rate(struct clk *clk)
>  {
> +	if (!clk)
> +		return 0;
> +
>  	if (clk->ops->get_rate)
>  		return clk->ops->get_rate(clk);
>  	return 0;
How about writing that as:

	if (clk && clk->ops->get_rate)
		return clk->ops->get_rate(clk);
	return 0;

? Ditto for some of the other functions.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-19 21:54         ` Thomas Gleixner
  2011-04-20  7:16           ` Uwe Kleine-König
@ 2011-04-20 14:07           ` Uwe Kleine-König
  2011-04-20 16:16             ` Thomas Gleixner
  2011-04-24  9:45             ` Richard Zhao
  1 sibling, 2 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-20 14:07 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
Hello,

only compile tested so far.

Best regards
Uwe

 drivers/clk/clk.c   |   43 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk.h |    8 ++++++++
 2 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 264c809..7627815 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -14,10 +14,23 @@
 int clk_prepare(struct clk *clk)
 {
 	int ret = 0;
+	struct clk *parent = ERR_PTR(-ENOSYS);
 
 	if (!clk)
 		return 0;
 
+	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
+		parent = clk_get_parent(clk);
+
+		if (!IS_ERR(parent)) {
+			ret = clk_prepare(parent);
+			if (ret)
+				return ret;
+		} else if (PTR_ERR(parent) != -ENOSYS)
+			/* -ENOSYS means no parent and is OK */
+			return PTR_ERR(parent);
+	}
+
 	mutex_lock(&clk->prepare_lock);
 	if (clk->prepare_count == 0 && clk->ops->prepare)
 		ret = clk->ops->prepare(clk);
@@ -26,6 +39,9 @@ int clk_prepare(struct clk *clk)
 		clk->prepare_count++;
 	mutex_unlock(&clk->prepare_lock);
 
+	if (ret && !IS_ERR(parent))
+		clk_unprepare(parent);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_prepare);
@@ -45,6 +61,12 @@ void clk_unprepare(struct clk *clk)
 	}
 
 	mutex_unlock(&clk->prepare_lock);
+
+	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
+		struct clk *parent = clk_get_parent(clk);
+		if (!IS_ERR(parent))
+			clk_unprepare(parent);
+	}
 }
 EXPORT_SYMBOL_GPL(clk_unprepare);
 
@@ -52,10 +74,22 @@ int clk_enable(struct clk *clk)
 {
 	unsigned long flags;
 	int ret = 0;
+	struct clk *parent = ERR_PTR(-ENOSYS);
 
 	if (!clk)
 		return 0;
 
+	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
+		parent = clk_get_parent(clk);
+		if (!IS_ERR(parent)) {
+			ret = clk_enable(parent);
+			if (ret)
+				return ret;
+		} else if (PTR_ERR(parent) != -ENOSYS)
+			/* -ENOSYS means no parent and is OK */
+			return PTR_ERR(parent);
+	}
+
 	WARN_ON(clk->prepare_count == 0);
 
 	spin_lock_irqsave(&clk->enable_lock, flags);
@@ -66,6 +100,9 @@ int clk_enable(struct clk *clk)
 		clk->enable_count++;
 	spin_unlock_irqrestore(&clk->enable_lock, flags);
 
+	if (ret && !IS_ERR(parent))
+		clk_disable(parent);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_enable);
@@ -85,6 +122,12 @@ void clk_disable(struct clk *clk)
 		clk->ops->disable(clk);
 
 	spin_unlock_irqrestore(&clk->enable_lock, flags);
+
+	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
+		struct clk *parent = clk_get_parent(clk);
+		if (!IS_ERR(parent))
+			clk_disable(parent);
+	}
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
diff --git a/include/linux/clk.h b/include/linux/clk.h
index d2f0db0..125e525 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -62,6 +62,11 @@ struct clk {
 	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
 }
 
+/* bit definitions for struct clk_ops.flags */
+#define CLK_OPS_GENERIC_PARENT	1	/* automatically handle parent in
+					   enable, disable, prepare and
+					   unprepare functions */
+
 /**
  * struct clk_ops -  Callback operations for clocks; these are to be provided
  * by the clock implementation, and will be called by drivers through the clk_*
@@ -91,6 +96,8 @@ struct clk {
  * @put:	Called by the core clock code when a devices driver releases a
  *		clock via clk_put(). Optional.
  *
+ * @flags:	see above for possible values.
+ *
  * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
  * implementations to split any work between atomic (enable) and sleepable
  * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
@@ -119,6 +126,7 @@ struct clk_ops {
 	int		(*set_rate)(struct clk *, unsigned long);
 	int		(*set_parent)(struct clk *, struct clk *);
 	struct clk *	(*get_parent)(struct clk *);
+	unsigned int	flags;
 };
 
 /**
-- 
1.7.4.1

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-20 14:07           ` [PATCH RFC] clk: add support for automatic parent handling Uwe Kleine-König
@ 2011-04-20 16:16             ` Thomas Gleixner
  2011-04-20 18:59               ` Uwe Kleine-König
  2011-04-24  9:45             ` Richard Zhao
  1 sibling, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-20 16:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:

Very useful changelog.

> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> ---
> Hello,
> 
> only compile tested so far.

You are not listening at all, right?
 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 264c809..7627815 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -14,10 +14,23 @@
>  int clk_prepare(struct clk *clk)
>  {
>  	int ret = 0;
> +	struct clk *parent = ERR_PTR(-ENOSYS);
>  
>  	if (!clk)
>  		return 0;
>  
> +	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {

Why the hell is this conditional? I told you that a proper abstraction
is for the sane cases which are the majority of the hardware and we
don't code for the buggy HW case unless we have evidence that it
exists. Once we have that evidence we can decide what to do - add a
flag or a separate function.

> +		parent = clk_get_parent(clk);
> +
> +		if (!IS_ERR(parent)) {
> +			ret = clk_prepare(parent);
> +			if (ret)
> +				return ret;
> +		} else if (PTR_ERR(parent) != -ENOSYS)
> +			/* -ENOSYS means no parent and is OK */
> +			return PTR_ERR(parent);
> +	}

And this whole mess should be written:

    ret = clk_prepare(clk->parent);
    if (ret)
		return ret;

Which returns 0 when there is no parent and it also returns 0 when
there is no prepare callback for the parent. Why the hell do we need
all this ERRPTR checking mess and all this conditional crap ?

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-20 16:16             ` Thomas Gleixner
@ 2011-04-20 18:59               ` Uwe Kleine-König
  2011-04-20 19:52                 ` Thomas Gleixner
  0 siblings, 1 reply; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-20 18:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 20, 2011 at 06:16:39PM +0200, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> 
> Very useful changelog.
IMHO OK for a RFC patch.

> > Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> > ---
> > Hello,
> > 
> > only compile tested so far.
> 
> You are not listening at all, right?
>  
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 264c809..7627815 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -14,10 +14,23 @@
> >  int clk_prepare(struct clk *clk)
> >  {
> >  	int ret = 0;
> > +	struct clk *parent = ERR_PTR(-ENOSYS);
> >  
> >  	if (!clk)
> >  		return 0;
> >  
> > +	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
> 
> Why the hell is this conditional? I told you that a proper abstraction
I made it conditional because the new behaviour is new and so minimizes
surprises. OK for me to drop this flag.

> is for the sane cases which are the majority of the hardware and we
> don't code for the buggy HW case unless we have evidence that it
> exists. Once we have that evidence we can decide what to do - add a
> flag or a separate function.
> 
> > +		parent = clk_get_parent(clk);
> > +
> > +		if (!IS_ERR(parent)) {
> > +			ret = clk_prepare(parent);
> > +			if (ret)
> > +				return ret;
> > +		} else if (PTR_ERR(parent) != -ENOSYS)
> > +			/* -ENOSYS means no parent and is OK */
> > +			return PTR_ERR(parent);
> > +	}
> 
> And this whole mess should be written:
> 
>     ret = clk_prepare(clk->parent);
>     if (ret)
> 		return ret;
> 
> Which returns 0 when there is no parent and it also returns 0 when
> there is no prepare callback for the parent. Why the hell do we need
> all this ERRPTR checking mess and all this conditional crap ?

struct clk has no parent member, there is only clk_get_parent(). If
there is no parent it returns ERR_PTR(-ENOSYS) and if you pass that to
clk_prepare it tries to dereference it. So either it must not be called
with an error pointer or clk_prepare et al. need adaption to handle
these error pointers. I choosed the former. Ah, or clk_get_parent must
be changed that it cannot fail and returns NULL to signal that there is
no parent.

I found some problems with my patch, so I will try if I can make you
more happy with a v2.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-20 18:59               ` Uwe Kleine-König
@ 2011-04-20 19:52                 ` Thomas Gleixner
  2011-04-21  6:58                     ` Saravana Kannan
                                     ` (3 more replies)
  0 siblings, 4 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-20 19:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> On Wed, Apr 20, 2011 at 06:16:39PM +0200, Thomas Gleixner wrote:
> > On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> > 
> > Very useful changelog.
> IMHO OK for a RFC patch.

Not at all.

> > 
> > And this whole mess should be written:
> > 
> >     ret = clk_prepare(clk->parent);
> >     if (ret)
> > 		return ret;
> > 
> > Which returns 0 when there is no parent and it also returns 0 when
> > there is no prepare callback for the parent. Why the hell do we need
> > all this ERRPTR checking mess and all this conditional crap ?
>
> struct clk has no parent member, there is only clk_get_parent(). If

Which is a complete failure to begin with. Why the heck do you need a
callback to figure that out?

Because someone claimed, that you need a callback to make it safe from
changing? Or what's the reason for this?

> there is no parent it returns ERR_PTR(-ENOSYS) and if you pass that
> to clk_prepare it tries to dereference it. So either it must not be
> called with an error pointer or clk_prepare et al. need adaption to
> handle

The whole clk struct is an utter failure.

It's simply the least common denominator of all clk madness in the
tree. Which results in a half documented data structure and a handful
helper functions of which most of them are exported, though the
functionality in them is less than the overhead of the EXPORT_SYMBOL.

That's not an abstraction and neither it's a framework. It's a half
arsed conglomorate of primitives w/o the minimal documentation how
those primitives should be used and why they are there in the first
place.

This is new code and it should be aimed to cleanup things not to
shuffle things around in a frenzy.

So what's wrong with that code:

1) struct clk is just a collection of function pointers and two locks

   It lacks:
   
   - a flag field for properties
   - a field for the parent
   - a field for the current clock rate
   - a field for the base register
   - a struct for the offsets of the most common registers relative to
     base

   optionally a set of common register accessor functions like I did
   for the generic irq chip.

2) The "framework" API is just a set of low level primitive helper
   functions

   It lacks:

   - proper refcounting. clk_get() / clk_put() should do that at the
     framework level.

   - the ability to propagate enable/disable/prepare/unprepare down
     through the parent tree

   - proper mechanisms to sanity check clk_set_parent(),
     clk_set_rate() et. al.

     This is not a implementation detail inside a specific clock. It's
     a problem which is common at least on the tree level:

                    rootclk
                 /          \
              clk1          clk2   
             /   \
           clk3  clk4
	   /
         clk5

    So now you want to change the rate of clk1. Can you do that?
    
    No, but where is the sanity check which prevents that ?
    
        In the clk1->set_rate() callback ?

	Great, that's the wrong place.

    So now you want to switch the parent of clk3 from clk1 to
    clk2. Can you do that?

    No, but where is the sanity check which prevents that ?

    	In the clk3->set_parent() callback ?

	Again, the wrong place.

    And these are not problems of a particular clk implementation,
    these are general problems and those want to be addressed in a
    real framework.

    It's debatable, whether you want to be able to change clocks which
    have active childs or not. If not the decision function is pretty
    simple. If yes, you need a list of child clks which you want to
    consult first before committing the change.

So unless you fix this stuff you should not even think about
converting anything to this "framework". That's just waste of time and
effort. Aside of declaring it stable and useful ....

The least thing which we need now are half baken "abstractions" which
just shuffle code around for no value.

Thanks,

	tglx

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-20  6:36                 ` Sascha Hauer
@ 2011-04-20 21:45                   ` Saravana Kannan
  2011-04-21  7:39                     ` Uwe Kleine-König
  0 siblings, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-04-20 21:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/19/2011 11:36 PM, Sascha Hauer wrote:
> On Tue, Apr 19, 2011 at 03:28:50PM -0700, Saravana Kannan wrote:
>> Sascha Hauer<s.hauer@pengutronix.de>  wrote:
>>
>>>>>>
>>>>>> We should really have something like:
>>>>>> clk_set_rate_range(min, ideal, max)
>>>>> (Note this is orthogonal to the question if set_rate may barf on
>>> values
>>>>> other than the return values of round_rate.)
>>>>>
>>>>> clk_set_rate_range can even be implemented with clk_round_rate that
>>> is
>>>>> just required to fulfill:
>>>>
>>>> I think it's more important that we try to find a new API that's
>>> better
>>>> than clk_round_rate(). We can worry about the specifics of the
>>>> implementation later.
>>>
>>> You found it and Uwe found a way to implement this ontop of the old
>>> API,
>>> that's a comfortable situation, isn't it?
>>
>> Well, do we all agree to this new API? I have no problem with Uwe's
>> helper fn or his suggestion, if we all agree on the final API. I just
>> didn't want him wasting his time when the API is not finalized.
>
> As Uwes suggestion does not change the internal clock API it's
> relatively simple to try out. With this we moved to the
> add-a-helper-function class of patches and are not in the
> change-internal-and-external-API-with-hundreds-of-users
> class anymore.

If clk_set_rate_range() is not made an external API, then it's pointless 
to even add it.

Also, you can make it an internal API (to be implemented by clock 
drivers) and still not need "hundreds of users to change". The generic 
code will use this helper function if the set_rate_range() API is not 
implemented by a specific clock/clock driver. If it's implemented by the 
specific clock, then that one will be used. That's not rocket science.

Let's stop discussion about whether Uwe's change is useful or not. I 
don't care. If you think it's great, then good for you both.

Or, may be I will start a separate thread if you don't like me using 
this thread to get an agreement on the API first. Just you and me 
agreeing is not enough.

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

* Re: [PATCH RFC] clk: add support for automatic parent handling
  2011-04-20 19:52                 ` Thomas Gleixner
  2011-04-21  6:58                     ` Saravana Kannan
@ 2011-04-21  6:58                     ` Saravana Kannan
  2011-04-21  7:42                   ` Sascha Hauer
  2011-04-29 10:30                   ` Russell King - ARM Linux
  3 siblings, 0 replies; 165+ messages in thread
From: Saravana Kannan @ 2011-04-21  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

Like most of what you had to say. Although, I think Jeremy did a pretty 
good job of trying to push things along in the right direction. So, I 
wouldn't call this an utter failure. I hope you aren't confusing 
Jeremy's patches with the additional patches that Sascha is adding on 
top. I haven't looked much at Sascha's patch series -- so I can't 
comment on them.

More comments follow.

On 04/20/2011 12:52 PM, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Uwe Kleine-König wrote:
>> On Wed, Apr 20, 2011 at 06:16:39PM +0200, Thomas Gleixner wrote:
>>> On Wed, 20 Apr 2011, Uwe Kleine-König wrote:
>>>
>>> Very useful changelog.
>> IMHO OK for a RFC patch.
>
> Not at all.
>
>>>
>>> And this whole mess should be written:
>>>
>>>      ret = clk_prepare(clk->parent);
>>>      if (ret)
>>> 		return ret;
>>>
>>> Which returns 0 when there is no parent and it also returns 0 when
>>> there is no prepare callback for the parent. Why the hell do we need
>>> all this ERRPTR checking mess and all this conditional crap ?
>>
>> struct clk has no parent member, there is only clk_get_parent(). If
>
> Which is a complete failure to begin with. Why the heck do you need a
> callback to figure that out?
>
> Because someone claimed, that you need a callback to make it safe from
> changing? Or what's the reason for this?
>
>> there is no parent it returns ERR_PTR(-ENOSYS) and if you pass that
>> to clk_prepare it tries to dereference it. So either it must not be
>> called with an error pointer or clk_prepare et al. need adaption to
>> handle
>
> The whole clk struct is an utter failure.
>
> It's simply the least common denominator of all clk madness in the
> tree. Which results in a half documented data structure and a handful
> helper functions of which most of them are exported, though the
> functionality in them is less than the overhead of the EXPORT_SYMBOL.
>
> That's not an abstraction and neither it's a framework. It's a half
> arsed conglomorate of primitives w/o the minimal documentation how
> those primitives should be used and why they are there in the first
> place.
>
> This is new code and it should be aimed to cleanup things not to
> shuffle things around in a frenzy.
>
> So what's wrong with that code:
>
> 1) struct clk is just a collection of function pointers and two locks
>
>     It lacks:
>
>     - a flag field for properties
Agree. I would very much like it.

>     - a field for the parent

Agree.

>     - a field for the current clock rate

Meh! Not a big deal. Some clocks don't have the concept of setting their 
rate since they share a parent with another unrelated clock (Ah, looks 
like you talk about with the tree diagram). So, it might be easier to 
have the rate inside each implementation if they need it. I shouldn't 
add too much code.

>     - a field for the base register

Definitely no. It's completely useless for clocks whose registers don't 
all line up with fixed offsets from the base register. Now I will have 
to put one register here and the rest of the registers in the internal data?

>     - a struct for the offsets of the most common registers relative to
>       base

Ok, you thought about rest of the registers. But, how can this fit in 
the common code? Each clock h/w implementation has totally different set 
of registers. Sometimes different even within the same SoC. This would 
be quite wasteful and doesn't even make sense to store at the top level. 
Also, storing offsets is a pain in the neck when the register space is 
not clean (happens more often than we would like :-().

>     optionally a set of common register accessor functions like I did
>     for the generic irq chip.

Again, I don't see the point in having this in the common code. May be 
I'm missing something?

IMO, a better option instead of the base register and the offsets would 
be an option to have a priv_data pointer. I forgot the exact use case, 
but we thought that would have been helpful when we tried to port the 
msm clock driver in our tree on top of Jeremy's patches.

> 2) The "framework" API is just a set of low level primitive helper
>     functions
>
>     It lacks:
>
>     - proper refcounting. clk_get() / clk_put() should do that at the
>       framework level.

This has nothing to do with the patches Jeremy made. clk_get()/_put() is 
in clkdev. Also, I'm not sure if clk_get()/put() needs refcounting. 
That's like asking kalloc/kfree to have refcounting.

>     - the ability to propagate enable/disable/prepare/unprepare down
>       through the parent tree

Agree. That would be nice. I think the main reason people were not 
pushing for it was to do things in manageable steps. It took a long time 
for people to agree on even the current framework Jeremy added.

>     - proper mechanisms to sanity check clk_set_parent(),
>       clk_set_rate() et. al.
>
>       This is not a implementation detail inside a specific clock. It's
>       a problem which is common at least on the tree level:
>
>                      rootclk
>                   /          \
>                clk1          clk2
>               /   \
>             clk3  clk4
> 	   /
>           clk5
>
>      So now you want to change the rate of clk1. Can you do that?
>
>      No, but where is the sanity check which prevents that ?
 >
>          In the clk1->set_rate() callback ?
>
> 	Great, that's the wrong place.

Ah! Nice to see that this bothers you too. This has been a point of 
contention with in our internal team too. I keep pushing back on 
requests to make child clock's set rate propagate up to the patent when 
the parent has two unrelated child clocks going to different devices.

IMO, the set rate should only work on the parent clock and if there 
really in a need to change the child clock rates, then the users of 
those child clocks will have to co-ordinate it amongst themselves. 
Although, our use case is a bit simpler in that most of the time the 
child clocks are direct branches (no dividers) of the parent.

To handle, more complex cases like these, I think a
clk_set_divider(div)
and/or
clk_set_frac_mult(numerator, denominator)

might be an API that we should add. If a child clock cares only about a 
ratio with the parent clock, clk_set_divider() is a much better API that 
clk_set_rate(). And we have real use cases of for these in MSM.

>      So now you want to switch the parent of clk3 from clk1 to
>      clk2. Can you do that?

At least in h/w I have seen so far, all the clocks that can really 
change parents fall under one of these categories:
1. A clock with a mux for input from several PLLs running at fixed rates 
(fixed at least after boot). So, these clocks can actually generate 
frequencies that they can guarantee won't change from underneath.

2. Clocks with are a mux from a bunch of external inputs that's 
completely end user/board defined.

For (1) the parent is really changed as part of "clk_set_rate()". For 
(2) I think we should just let set_parent() control the mux.

I'm not sure how realistic/common your example of switching parents for 
clk3 is. May be it is -- I would interested in what people have to say.

So, between clk_set_divider(), clk_set_parent() and clk_set_rate(), I 
think we should be able to cover most clock trees as long as we don't 
propagate clk_set_rate() to parents with more than one children. In 
those case, the children should just implement clk_set_divider() (or not 
even that if there is no divider) and not allow clk_set_rate().

>      No, but where is the sanity check which prevents that ?
>
>      	In the clk3->set_parent() callback ?
>
> 	Again, the wrong place.
>
>      And these are not problems of a particular clk implementation,
>      these are general problems and those want to be addressed in a
>      real framework.
>
>      It's debatable, whether you want to be able to change clocks which
>      have active childs or not. If not the decision function is pretty
>      simple. If yes, you need a list of child clks which you want to
>      consult first before committing the change.
>
> So unless you fix this stuff you should not even think about
> converting anything to this "framework". That's just waste of time and
> effort. Aside of declaring it stable and useful ....

I think you haven't seen all the repetition of refcounting and each 
mach's implementation of some variant of clock ops. The current patch 
set from Jeremy will certainly help cut down some of that. If we get the 
"enable parent before you enable child, etc" in now, I don't think there 
will be much churn when we try to add code to enforce the tree 
restrictions you mention above.

> The least thing which we need now are half baken "abstractions" which
> just shuffle code around for no value.

While a lot of your points are correct, I don't think the current 
patches from Jeremy are useless. May be I'm completely mistaken in 
assuming that you are referring to Jeremy's patches?

Btw, on a slight tangent, there is also the problem of clk_round_rate() 
not being sufficient when a driver is trying to work across different 
mach's. I think we need a clk_set_rate_range(min, ideal, max) but I can 
start a separate thread on that if you want. I talked about it a bit in 
another thread.

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

* Re: [PATCH RFC] clk: add support for automatic parent handling
@ 2011-04-21  6:58                     ` Saravana Kannan
  0 siblings, 0 replies; 165+ messages in thread
From: Saravana Kannan @ 2011-04-21  6:58 UTC (permalink / raw)
  To: Thomas Gleixner, Paul McKenney
  Cc: Uwe Kleine-König, linux-arm-kernel, Sascha Hauer,
	Stephen Boyd, Jeremy Kerr, kernel, linux-kernel, Ben Dooks,
	Linus Torvalds, Arnd Bergmann, Paul Mundt, linux-sh

Like most of what you had to say. Although, I think Jeremy did a pretty 
good job of trying to push things along in the right direction. So, I 
wouldn't call this an utter failure. I hope you aren't confusing 
Jeremy's patches with the additional patches that Sascha is adding on 
top. I haven't looked much at Sascha's patch series -- so I can't 
comment on them.

More comments follow.

On 04/20/2011 12:52 PM, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Uwe Kleine-König wrote:
>> On Wed, Apr 20, 2011 at 06:16:39PM +0200, Thomas Gleixner wrote:
>>> On Wed, 20 Apr 2011, Uwe Kleine-König wrote:
>>>
>>> Very useful changelog.
>> IMHO OK for a RFC patch.
>
> Not at all.
>
>>>
>>> And this whole mess should be written:
>>>
>>>      ret = clk_prepare(clk->parent);
>>>      if (ret)
>>> 		return ret;
>>>
>>> Which returns 0 when there is no parent and it also returns 0 when
>>> there is no prepare callback for the parent. Why the hell do we need
>>> all this ERRPTR checking mess and all this conditional crap ?
>>
>> struct clk has no parent member, there is only clk_get_parent(). If
>
> Which is a complete failure to begin with. Why the heck do you need a
> callback to figure that out?
>
> Because someone claimed, that you need a callback to make it safe from
> changing? Or what's the reason for this?
>
>> there is no parent it returns ERR_PTR(-ENOSYS) and if you pass that
>> to clk_prepare it tries to dereference it. So either it must not be
>> called with an error pointer or clk_prepare et al. need adaption to
>> handle
>
> The whole clk struct is an utter failure.
>
> It's simply the least common denominator of all clk madness in the
> tree. Which results in a half documented data structure and a handful
> helper functions of which most of them are exported, though the
> functionality in them is less than the overhead of the EXPORT_SYMBOL.
>
> That's not an abstraction and neither it's a framework. It's a half
> arsed conglomorate of primitives w/o the minimal documentation how
> those primitives should be used and why they are there in the first
> place.
>
> This is new code and it should be aimed to cleanup things not to
> shuffle things around in a frenzy.
>
> So what's wrong with that code:
>
> 1) struct clk is just a collection of function pointers and two locks
>
>     It lacks:
>
>     - a flag field for properties
Agree. I would very much like it.

>     - a field for the parent

Agree.

>     - a field for the current clock rate

Meh! Not a big deal. Some clocks don't have the concept of setting their 
rate since they share a parent with another unrelated clock (Ah, looks 
like you talk about with the tree diagram). So, it might be easier to 
have the rate inside each implementation if they need it. I shouldn't 
add too much code.

>     - a field for the base register

Definitely no. It's completely useless for clocks whose registers don't 
all line up with fixed offsets from the base register. Now I will have 
to put one register here and the rest of the registers in the internal data?

>     - a struct for the offsets of the most common registers relative to
>       base

Ok, you thought about rest of the registers. But, how can this fit in 
the common code? Each clock h/w implementation has totally different set 
of registers. Sometimes different even within the same SoC. This would 
be quite wasteful and doesn't even make sense to store at the top level. 
Also, storing offsets is a pain in the neck when the register space is 
not clean (happens more often than we would like :-().

>     optionally a set of common register accessor functions like I did
>     for the generic irq chip.

Again, I don't see the point in having this in the common code. May be 
I'm missing something?

IMO, a better option instead of the base register and the offsets would 
be an option to have a priv_data pointer. I forgot the exact use case, 
but we thought that would have been helpful when we tried to port the 
msm clock driver in our tree on top of Jeremy's patches.

> 2) The "framework" API is just a set of low level primitive helper
>     functions
>
>     It lacks:
>
>     - proper refcounting. clk_get() / clk_put() should do that at the
>       framework level.

This has nothing to do with the patches Jeremy made. clk_get()/_put() is 
in clkdev. Also, I'm not sure if clk_get()/put() needs refcounting. 
That's like asking kalloc/kfree to have refcounting.

>     - the ability to propagate enable/disable/prepare/unprepare down
>       through the parent tree

Agree. That would be nice. I think the main reason people were not 
pushing for it was to do things in manageable steps. It took a long time 
for people to agree on even the current framework Jeremy added.

>     - proper mechanisms to sanity check clk_set_parent(),
>       clk_set_rate() et. al.
>
>       This is not a implementation detail inside a specific clock. It's
>       a problem which is common at least on the tree level:
>
>                      rootclk
>                   /          \
>                clk1          clk2
>               /   \
>             clk3  clk4
> 	   /
>           clk5
>
>      So now you want to change the rate of clk1. Can you do that?
>
>      No, but where is the sanity check which prevents that ?
 >
>          In the clk1->set_rate() callback ?
>
> 	Great, that's the wrong place.

Ah! Nice to see that this bothers you too. This has been a point of 
contention with in our internal team too. I keep pushing back on 
requests to make child clock's set rate propagate up to the patent when 
the parent has two unrelated child clocks going to different devices.

IMO, the set rate should only work on the parent clock and if there 
really in a need to change the child clock rates, then the users of 
those child clocks will have to co-ordinate it amongst themselves. 
Although, our use case is a bit simpler in that most of the time the 
child clocks are direct branches (no dividers) of the parent.

To handle, more complex cases like these, I think a
clk_set_divider(div)
and/or
clk_set_frac_mult(numerator, denominator)

might be an API that we should add. If a child clock cares only about a 
ratio with the parent clock, clk_set_divider() is a much better API that 
clk_set_rate(). And we have real use cases of for these in MSM.

>      So now you want to switch the parent of clk3 from clk1 to
>      clk2. Can you do that?

At least in h/w I have seen so far, all the clocks that can really 
change parents fall under one of these categories:
1. A clock with a mux for input from several PLLs running at fixed rates 
(fixed at least after boot). So, these clocks can actually generate 
frequencies that they can guarantee won't change from underneath.

2. Clocks with are a mux from a bunch of external inputs that's 
completely end user/board defined.

For (1) the parent is really changed as part of "clk_set_rate()". For 
(2) I think we should just let set_parent() control the mux.

I'm not sure how realistic/common your example of switching parents for 
clk3 is. May be it is -- I would interested in what people have to say.

So, between clk_set_divider(), clk_set_parent() and clk_set_rate(), I 
think we should be able to cover most clock trees as long as we don't 
propagate clk_set_rate() to parents with more than one children. In 
those case, the children should just implement clk_set_divider() (or not 
even that if there is no divider) and not allow clk_set_rate().

>      No, but where is the sanity check which prevents that ?
>
>      	In the clk3->set_parent() callback ?
>
> 	Again, the wrong place.
>
>      And these are not problems of a particular clk implementation,
>      these are general problems and those want to be addressed in a
>      real framework.
>
>      It's debatable, whether you want to be able to change clocks which
>      have active childs or not. If not the decision function is pretty
>      simple. If yes, you need a list of child clks which you want to
>      consult first before committing the change.
>
> So unless you fix this stuff you should not even think about
> converting anything to this "framework". That's just waste of time and
> effort. Aside of declaring it stable and useful ....

I think you haven't seen all the repetition of refcounting and each 
mach's implementation of some variant of clock ops. The current patch 
set from Jeremy will certainly help cut down some of that. If we get the 
"enable parent before you enable child, etc" in now, I don't think there 
will be much churn when we try to add code to enforce the tree 
restrictions you mention above.

> The least thing which we need now are half baken "abstractions" which
> just shuffle code around for no value.

While a lot of your points are correct, I don't think the current 
patches from Jeremy are useless. May be I'm completely mistaken in 
assuming that you are referring to Jeremy's patches?

Btw, on a slight tangent, there is also the problem of clk_round_rate() 
not being sufficient when a driver is trying to work across different 
mach's. I think we need a clk_set_rate_range(min, ideal, max) but I can 
start a separate thread on that if you want. I talked about it a bit in 
another thread.

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

* [PATCH RFC] clk: add support for automatic parent handling
@ 2011-04-21  6:58                     ` Saravana Kannan
  0 siblings, 0 replies; 165+ messages in thread
From: Saravana Kannan @ 2011-04-21  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

Like most of what you had to say. Although, I think Jeremy did a pretty 
good job of trying to push things along in the right direction. So, I 
wouldn't call this an utter failure. I hope you aren't confusing 
Jeremy's patches with the additional patches that Sascha is adding on 
top. I haven't looked much at Sascha's patch series -- so I can't 
comment on them.

More comments follow.

On 04/20/2011 12:52 PM, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
>> On Wed, Apr 20, 2011 at 06:16:39PM +0200, Thomas Gleixner wrote:
>>> On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
>>>
>>> Very useful changelog.
>> IMHO OK for a RFC patch.
>
> Not at all.
>
>>>
>>> And this whole mess should be written:
>>>
>>>      ret = clk_prepare(clk->parent);
>>>      if (ret)
>>> 		return ret;
>>>
>>> Which returns 0 when there is no parent and it also returns 0 when
>>> there is no prepare callback for the parent. Why the hell do we need
>>> all this ERRPTR checking mess and all this conditional crap ?
>>
>> struct clk has no parent member, there is only clk_get_parent(). If
>
> Which is a complete failure to begin with. Why the heck do you need a
> callback to figure that out?
>
> Because someone claimed, that you need a callback to make it safe from
> changing? Or what's the reason for this?
>
>> there is no parent it returns ERR_PTR(-ENOSYS) and if you pass that
>> to clk_prepare it tries to dereference it. So either it must not be
>> called with an error pointer or clk_prepare et al. need adaption to
>> handle
>
> The whole clk struct is an utter failure.
>
> It's simply the least common denominator of all clk madness in the
> tree. Which results in a half documented data structure and a handful
> helper functions of which most of them are exported, though the
> functionality in them is less than the overhead of the EXPORT_SYMBOL.
>
> That's not an abstraction and neither it's a framework. It's a half
> arsed conglomorate of primitives w/o the minimal documentation how
> those primitives should be used and why they are there in the first
> place.
>
> This is new code and it should be aimed to cleanup things not to
> shuffle things around in a frenzy.
>
> So what's wrong with that code:
>
> 1) struct clk is just a collection of function pointers and two locks
>
>     It lacks:
>
>     - a flag field for properties
Agree. I would very much like it.

>     - a field for the parent

Agree.

>     - a field for the current clock rate

Meh! Not a big deal. Some clocks don't have the concept of setting their 
rate since they share a parent with another unrelated clock (Ah, looks 
like you talk about with the tree diagram). So, it might be easier to 
have the rate inside each implementation if they need it. I shouldn't 
add too much code.

>     - a field for the base register

Definitely no. It's completely useless for clocks whose registers don't 
all line up with fixed offsets from the base register. Now I will have 
to put one register here and the rest of the registers in the internal data?

>     - a struct for the offsets of the most common registers relative to
>       base

Ok, you thought about rest of the registers. But, how can this fit in 
the common code? Each clock h/w implementation has totally different set 
of registers. Sometimes different even within the same SoC. This would 
be quite wasteful and doesn't even make sense to store at the top level. 
Also, storing offsets is a pain in the neck when the register space is 
not clean (happens more often than we would like :-().

>     optionally a set of common register accessor functions like I did
>     for the generic irq chip.

Again, I don't see the point in having this in the common code. May be 
I'm missing something?

IMO, a better option instead of the base register and the offsets would 
be an option to have a priv_data pointer. I forgot the exact use case, 
but we thought that would have been helpful when we tried to port the 
msm clock driver in our tree on top of Jeremy's patches.

> 2) The "framework" API is just a set of low level primitive helper
>     functions
>
>     It lacks:
>
>     - proper refcounting. clk_get() / clk_put() should do that at the
>       framework level.

This has nothing to do with the patches Jeremy made. clk_get()/_put() is 
in clkdev. Also, I'm not sure if clk_get()/put() needs refcounting. 
That's like asking kalloc/kfree to have refcounting.

>     - the ability to propagate enable/disable/prepare/unprepare down
>       through the parent tree

Agree. That would be nice. I think the main reason people were not 
pushing for it was to do things in manageable steps. It took a long time 
for people to agree on even the current framework Jeremy added.

>     - proper mechanisms to sanity check clk_set_parent(),
>       clk_set_rate() et. al.
>
>       This is not a implementation detail inside a specific clock. It's
>       a problem which is common at least on the tree level:
>
>                      rootclk
>                   /          \
>                clk1          clk2
>               /   \
>             clk3  clk4
> 	   /
>           clk5
>
>      So now you want to change the rate of clk1. Can you do that?
>
>      No, but where is the sanity check which prevents that ?
 >
>          In the clk1->set_rate() callback ?
>
> 	Great, that's the wrong place.

Ah! Nice to see that this bothers you too. This has been a point of 
contention with in our internal team too. I keep pushing back on 
requests to make child clock's set rate propagate up to the patent when 
the parent has two unrelated child clocks going to different devices.

IMO, the set rate should only work on the parent clock and if there 
really in a need to change the child clock rates, then the users of 
those child clocks will have to co-ordinate it amongst themselves. 
Although, our use case is a bit simpler in that most of the time the 
child clocks are direct branches (no dividers) of the parent.

To handle, more complex cases like these, I think a
clk_set_divider(div)
and/or
clk_set_frac_mult(numerator, denominator)

might be an API that we should add. If a child clock cares only about a 
ratio with the parent clock, clk_set_divider() is a much better API that 
clk_set_rate(). And we have real use cases of for these in MSM.

>      So now you want to switch the parent of clk3 from clk1 to
>      clk2. Can you do that?

At least in h/w I have seen so far, all the clocks that can really 
change parents fall under one of these categories:
1. A clock with a mux for input from several PLLs running at fixed rates 
(fixed at least after boot). So, these clocks can actually generate 
frequencies that they can guarantee won't change from underneath.

2. Clocks with are a mux from a bunch of external inputs that's 
completely end user/board defined.

For (1) the parent is really changed as part of "clk_set_rate()". For 
(2) I think we should just let set_parent() control the mux.

I'm not sure how realistic/common your example of switching parents for 
clk3 is. May be it is -- I would interested in what people have to say.

So, between clk_set_divider(), clk_set_parent() and clk_set_rate(), I 
think we should be able to cover most clock trees as long as we don't 
propagate clk_set_rate() to parents with more than one children. In 
those case, the children should just implement clk_set_divider() (or not 
even that if there is no divider) and not allow clk_set_rate().

>      No, but where is the sanity check which prevents that ?
>
>      	In the clk3->set_parent() callback ?
>
> 	Again, the wrong place.
>
>      And these are not problems of a particular clk implementation,
>      these are general problems and those want to be addressed in a
>      real framework.
>
>      It's debatable, whether you want to be able to change clocks which
>      have active childs or not. If not the decision function is pretty
>      simple. If yes, you need a list of child clks which you want to
>      consult first before committing the change.
>
> So unless you fix this stuff you should not even think about
> converting anything to this "framework". That's just waste of time and
> effort. Aside of declaring it stable and useful ....

I think you haven't seen all the repetition of refcounting and each 
mach's implementation of some variant of clock ops. The current patch 
set from Jeremy will certainly help cut down some of that. If we get the 
"enable parent before you enable child, etc" in now, I don't think there 
will be much churn when we try to add code to enforce the tree 
restrictions you mention above.

> The least thing which we need now are half baken "abstractions" which
> just shuffle code around for no value.

While a lot of your points are correct, I don't think the current 
patches from Jeremy are useless. May be I'm completely mistaken in 
assuming that you are referring to Jeremy's patches?

Btw, on a slight tangent, there is also the problem of clk_round_rate() 
not being sufficient when a driver is trying to work across different 
mach's. I think we need a clk_set_rate_range(min, ideal, max) but I can 
start a separate thread on that if you want. I talked about it a bit in 
another thread.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-20 19:52                 ` Thomas Gleixner
  2011-04-21  6:58                     ` Saravana Kannan
@ 2011-04-21  7:22                   ` Uwe Kleine-König
  2011-04-21  9:12                     ` Thomas Gleixner
  2011-04-21 10:13                     ` Mark Brown
  2011-04-21  7:42                   ` Sascha Hauer
  2011-04-29 10:30                   ` Russell King - ARM Linux
  3 siblings, 2 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-21  7:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Thomas,

On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> > On Wed, Apr 20, 2011 at 06:16:39PM +0200, Thomas Gleixner wrote:
> > > And this whole mess should be written:
> > > 
> > >     ret = clk_prepare(clk->parent);
> > >     if (ret)
> > > 		return ret;
> > > 
> > > Which returns 0 when there is no parent and it also returns 0 when
> > > there is no prepare callback for the parent. Why the hell do we need
> > > all this ERRPTR checking mess and all this conditional crap ?
> >
> > struct clk has no parent member, there is only clk_get_parent(). If
> 
> Which is a complete failure to begin with. Why the heck do you need a
> callback to figure that out?
> 
> Because someone claimed, that you need a callback to make it safe from
> changing? Or what's the reason for this?
If there were a pointer tracking the parent you still needed to program
out the get_parent function anyhow to set the pointer initially. But I
agree that in other situations having a pointer is more comfortable and
saves ugly error handling e.g. in set_parent.

> > there is no parent it returns ERR_PTR(-ENOSYS) and if you pass that
> > to clk_prepare it tries to dereference it. So either it must not be
> > called with an error pointer or clk_prepare et al. need adaption to
> > handle
> 
> The whole clk struct is an utter failure.
> 
> It's simply the least common denominator of all clk madness in the
> tree. Which results in a half documented data structure and a handful
> helper functions of which most of them are exported, though the
> functionality in them is less than the overhead of the EXPORT_SYMBOL.
> 
> That's not an abstraction and neither it's a framework. It's a half
> arsed conglomorate of primitives w/o the minimal documentation how
> those primitives should be used and why they are there in the first
> place.
> 
> This is new code and it should be aimed to cleanup things not to
> shuffle things around in a frenzy.
> 
> So what's wrong with that code:
> 
> 1) struct clk is just a collection of function pointers and two locks
> 
>    It lacks:
>    
>    - a flag field for properties
Up to now there are no properties to distinguish. When the first comes
up such a field is easily added, no?

>    - a field for the parent
I can agree here, see above.

>    - a field for the current clock rate
Then you need a mechanism to notify the children if the rate or parent
of a clock changes. I assume you won't allow that for a clock that has
more than one (enabled) consumer. Knowing only very few platforms I
don't know if that is something you can forbid.

>    - a field for the base register
This is not needed for all clocks (at least not a say void __iomem *). I
think it's fine here to leave that to the platforms as it is now.

>    - a struct for the offsets of the most common registers relative to
>      base
I'm not sure I understand you right here. If this is about not
duplicating data/code for similar clocks, this works (IMHO) fine with
the current approach (ie. sharing the ops pointer).

>    optionally a set of common register accessor functions like I did
>    for the generic irq chip.
Agreed, this can (and should) come when the base API is fixed.

> 2) The "framework" API is just a set of low level primitive helper
>    functions
> 
>    It lacks:
> 
>    - proper refcounting. clk_get() / clk_put() should do that at the
>      framework level.
For most clocks it's not important if they are referenced somewhere.
What should be done with that reference count at the framework level?
The only thing I currently can come up with now is to module_get an
optional owner. I'm not convinced this is worth to include in the
framework. Still it should be possible to do, and it is.
 
>    - the ability to propagate enable/disable/prepare/unprepare down
>      through the parent tree
Ack, I'm working on that.

>    - proper mechanisms to sanity check clk_set_parent(),
>      clk_set_rate() et. al.
> 
>      This is not a implementation detail inside a specific clock. It's
>      a problem which is common at least on the tree level:
> 
>                     rootclk
>                  /          \
>               clk1          clk2   
>              /   \
>            clk3  clk4
>           /
>          clk5
> 
>     So now you want to change the rate of clk1. Can you do that?
>     
>     No, but where is the sanity check which prevents that ?
I assume your ascii art should imply that clk3 and clk4 are enabled?
What is the policy you suggest?
This was discussed at some point[1] with the result that the user of
set_rate should be aware of the clk tree and the changes it introduces
for now and that some policy could still be added later.  Ditto for
set_parent. 
It's easy enough to implement such a policy on top of Jeremy's patches.
I'm not able to see already now all the requirements of all users of the
clk-API. So I agree with you that it probably isn't (yet) the perfect
framework, but I think it's a good base to see these requirements.

>         In the clk1->set_rate() callback ?
> 
> 	Great, that's the wrong place.
> 
>     So now you want to switch the parent of clk3 from clk1 to
>     clk2. Can you do that?
> 
>     No, but where is the sanity check which prevents that ?
> 
>     	In the clk3->set_parent() callback ?
> 
> 	Again, the wrong place.
> 
>     And these are not problems of a particular clk implementation,
>     these are general problems and those want to be addressed in a
>     real framework.
> 
>     It's debatable, whether you want to be able to change clocks which
>     have active childs or not. If not the decision function is pretty
>     simple. If yes, you need a list of child clks which you want to
>     consult first before committing the change.
> 
> So unless you fix this stuff you should not even think about
> converting anything to this "framework". That's just waste of time and
> effort. Aside of declaring it stable and useful ....
With stable I didn't intend to say something about the quality (though I
still think it's a good thing), but that I won't rewrite the commits
such that others can base their work on top of them.
Before your mail nobody spoke up against these patches and some people
see a value in them and want to convert their platform to it. So
providing a branch seems sensible to me.
I don't say that this common struct clk is perfect already now and I
expect it to change here and there. It allows to consolidate some code
and so is a good thing. I think nobody disagrees that when having
converted most or all platforms to it we're not done. It's just the
first step. Maybe one of the next is to add a "class" of clocks that
looks similar to this:

	struct clk_generic {
		struct clk clk;
		unsigned long rate;
		struct clk *parent;
		void __iomem *iobase;

		sometype enable_regoffset;
		size_t enable_shift;

		struct clk **possible_parents;
		size_t num_possible_parents;
		sometype parent_regoffset;
		size_t parent_shift;
	};

and that could be used for a big part of the needed clocks.

Best regards
Uwe

[1] see for example
    http://thread.gmane.org/gmane.linux.ports.sh.devel/9755/focus=1100223
    and the replies to it.

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-20 21:45                   ` Saravana Kannan
@ 2011-04-21  7:39                     ` Uwe Kleine-König
  0 siblings, 0 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-21  7:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 20, 2011 at 02:45:39PM -0700, Saravana Kannan wrote:
> On 04/19/2011 11:36 PM, Sascha Hauer wrote:
> >On Tue, Apr 19, 2011 at 03:28:50PM -0700, Saravana Kannan wrote:
> >>Sascha Hauer<s.hauer@pengutronix.de>  wrote:
> >>
> >>>>>>
> >>>>>>We should really have something like:
> >>>>>>clk_set_rate_range(min, ideal, max)
> >>>>>(Note this is orthogonal to the question if set_rate may barf on
> >>>values
> >>>>>other than the return values of round_rate.)
> >>>>>
> >>>>>clk_set_rate_range can even be implemented with clk_round_rate that
> >>>is
> >>>>>just required to fulfill:
> >>>>
> >>>>I think it's more important that we try to find a new API that's
> >>>better
> >>>>than clk_round_rate(). We can worry about the specifics of the
> >>>>implementation later.
> >>>
> >>>You found it and Uwe found a way to implement this ontop of the old
> >>>API,
> >>>that's a comfortable situation, isn't it?
> >>
> >>Well, do we all agree to this new API? I have no problem with Uwe's
> >>helper fn or his suggestion, if we all agree on the final API. I just
> >>didn't want him wasting his time when the API is not finalized.
> >
> >As Uwes suggestion does not change the internal clock API it's
> >relatively simple to try out. With this we moved to the
> >add-a-helper-function class of patches and are not in the
> >change-internal-and-external-API-with-hundreds-of-users
> >class anymore.
> 
> If clk_set_rate_range() is not made an external API, then it's
> pointless to even add it.
Correct, if it's there every driver should be able to use it.
 
> Also, you can make it an internal API (to be implemented by clock
> drivers) and still not need "hundreds of users to change". The
> generic code will use this helper function if the set_rate_range()
> API is not implemented by a specific clock/clock driver. If it's
> implemented by the specific clock, then that one will be used.
> That's not rocket science.
It's discussable if it's worth to add it to the internal API or if my
suggestion works for everybody. I think the best path to choose here is:
When this functionallity is needed add a global and generic function
(like my suggestion). If this proves to behave bad for a certain clk
a mechanism to override it per clk can still be added later.

> Let's stop discussion about whether Uwe's change is useful or not. I
> don't care. If you think it's great, then good for you both.
Right, it only makes sense to think about adding such a function when
the first user pops up.
 
Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-20 19:52                 ` Thomas Gleixner
  2011-04-21  6:58                     ` Saravana Kannan
  2011-04-21  7:22                   ` Uwe Kleine-König
@ 2011-04-21  7:42                   ` Sascha Hauer
  2011-04-21  9:21                     ` Thomas Gleixner
  2011-04-29 10:30                   ` Russell King - ARM Linux
  3 siblings, 1 reply; 165+ messages in thread
From: Sascha Hauer @ 2011-04-21  7:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> > On Wed, Apr 20, 2011 at 06:16:39PM +0200, Thomas Gleixner wrote:
> > > On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> > > 
> > > Very useful changelog.
> > IMHO OK for a RFC patch.
> 
> Not at all.
> 
> > > 
> > > And this whole mess should be written:
> > > 
> > >     ret = clk_prepare(clk->parent);
> > >     if (ret)
> > > 		return ret;
> > > 
> > > Which returns 0 when there is no parent and it also returns 0 when
> > > there is no prepare callback for the parent. Why the hell do we need
> > > all this ERRPTR checking mess and all this conditional crap ?
> >
> > struct clk has no parent member, there is only clk_get_parent(). If
> 
> Which is a complete failure to begin with. Why the heck do you need a
> callback to figure that out?
> 
> Because someone claimed, that you need a callback to make it safe from
> changing? Or what's the reason for this?
> 
> > there is no parent it returns ERR_PTR(-ENOSYS) and if you pass that
> > to clk_prepare it tries to dereference it. So either it must not be
> > called with an error pointer or clk_prepare et al. need adaption to
> > handle
> 
> The whole clk struct is an utter failure.
> 
> It's simply the least common denominator of all clk madness in the
> tree. Which results in a half documented data structure and a handful
> helper functions of which most of them are exported, though the
> functionality in them is less than the overhead of the EXPORT_SYMBOL.
> 
> That's not an abstraction and neither it's a framework. It's a half
> arsed conglomorate of primitives w/o the minimal documentation how
> those primitives should be used and why they are there in the first
> place.
> 
> This is new code and it should be aimed to cleanup things not to
> shuffle things around in a frenzy.
> 
> So what's wrong with that code:
> 
> 1) struct clk is just a collection of function pointers and two locks
> 
>    It lacks:
>    
>    - a flag field for properties

>    - a field for the parent
>    - a field for the current clock rate

Currently there is no possibility to bring the clock tree in sync with
the hardware. clocks are not registered at all, they are just there. So
there is no instance who could iterate over the tree in order to bring
it in sync. Unless we create that (which I would like) there is no point
in adding rate and parent fields.
Hm, thinking about this maybe we could add a CLK_IN_SYNC field which
is initially cleared and gets set once the get_parent()/get_rate()
callback has been called for a clock.

>    - a field for the base register
>    - a struct for the offsets of the most common registers relative to
>      base

What's wrong with embedding struct clk into a more specific clock and
access it with container_of()? It must be done anyway once a field is
missing in struct clk, or we end up with a lot of fields in struct clk
which are used in only few types of clocks.

> 
> The least thing which we need now are half baken "abstractions" which
> just shuffle code around for no value.

While I agree with several things you say even the half baken
abstractions help to bring the problems into the light. What we have now
is that all these problems are hidden in SoC specific abstractions which
all have their own problems and bugs.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21  7:22                   ` Uwe Kleine-König
@ 2011-04-21  9:12                     ` Thomas Gleixner
  2011-04-21 10:31                       ` Mark Brown
  2011-04-29 10:37                       ` Russell King - ARM Linux
  2011-04-21 10:13                     ` Mark Brown
  1 sibling, 2 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21  9:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 21 Apr 2011, Uwe Kleine-K?nig wrote:
> > Which is a complete failure to begin with. Why the heck do you need a
> > callback to figure that out?
> > 
> > Because someone claimed, that you need a callback to make it safe from
> > changing? Or what's the reason for this?
> If there were a pointer tracking the parent you still needed to program
> out the get_parent function anyhow to set the pointer initially. But I
> agree that in other situations having a pointer is more comfortable and
> saves ugly error handling e.g. in set_parent.

That's nonsense. Why do you want a get_parent() function at all?
parent is set up when the clock is established in the clock tree. And
that's not done by some random driver. That's a property of the clock.

> >    It lacks:
> >    
> >    - a flag field for properties
> Up to now there are no properties to distinguish. When the first comes
> up such a field is easily added, no?

Crap. FIXED_CLOCK_RATE is the first thing which comes to my mind
 
> >    - a field for the parent
> I can agree here, see above.
> 
> >    - a field for the current clock rate
> Then you need a mechanism to notify the children if the rate or parent
> of a clock changes. I assume you won't allow that for a clock that has
> more than one (enabled) consumer. 

Here we go. That's why I say that this code is not a framework at
all. It's a random conglomorate of random functions with no
functionality at all.

> Knowing only very few platforms I
> don't know if that is something you can forbid.
 
Did you ever take the time to look over the various clk
implementations and try to see the patterens there? Obviously not, so
what are you arguing about?

> >    - a field for the base register
> This is not needed for all clocks (at least not a say void __iomem *). I
> think it's fine here to leave that to the platforms as it is now.

Crap. All clocks which are configurable in some way or can be
enabled/disabled need access register(s) so you need a base address.

> >    - a struct for the offsets of the most common registers relative to
> >      base
> I'm not sure I understand you right here. If this is about not
> duplicating data/code for similar clocks, this works (IMHO) fine with
> the current approach (ie. sharing the ops pointer).

Right and have tons of duplicated 

      struct myclock {
      	     struct clk;
	     void *base;
	     unsigned long enable_reg;
	     unsigned long enable_reg_cache;
     };

all over the place. Brilliant.
 
> >    optionally a set of common register accessor functions like I did
> >    for the generic irq chip.
> Agreed, this can (and should) come when the base API is fixed.

Base API ?
 
> > 2) The "framework" API is just a set of low level primitive helper
> >    functions
> > 
> >    It lacks:
> > 
> >    - proper refcounting. clk_get() / clk_put() should do that at the
> >      framework level.
> For most clocks it's not important if they are referenced somewhere.
> What should be done with that reference count at the framework level?
> The only thing I currently can come up with now is to module_get an
> optional owner. I'm not convinced this is worth to include in the
> framework. Still it should be possible to do, and it is.

For most clocks it's not important to be protected by a spinlock
either, for many clocks even the prepare mutex is not needed.

The whole point of frameworks is to figure out common patterns and
implement them in a common place. That includes code which is not
needed for many of the users of the code. See all the other
infrastructure stuff: clocksources, clockevents, genirq. Strictly most
of arch/* could do with half of the functionality, but that's not an
argument to implement only half of it and keep the rest somewhere in
the arch/ driver/ implementation.

> >    - proper mechanisms to sanity check clk_set_parent(),
> >      clk_set_rate() et. al.
> > 
> >      This is not a implementation detail inside a specific clock. It's
> >      a problem which is common at least on the tree level:
> > 
> >                     rootclk
> >                  /          \
> >               clk1          clk2   
> >              /   \
> >            clk3  clk4
> >           /
> >          clk5
> > 
> >     So now you want to change the rate of clk1. Can you do that?
> >     
> >     No, but where is the sanity check which prevents that ?
> I assume your ascii art should imply that clk3 and clk4 are enabled?
> What is the policy you suggest?
> This was discussed at some point[1] with the result that the user of
> set_rate should be aware of the clk tree and the changes it introduces
> for now and that some policy could still be added later.  Ditto for
> set_parent. 

Crap. We add a new framework now and we better think twice before
starting to grow any user at all.

> It's easy enough to implement such a policy on top of Jeremy's patches.
> I'm not able to see already now all the requirements of all users of the
> clk-API. So I agree with you that it probably isn't (yet) the perfect
> framework, but I think it's a good base to see these requirements.

Stop calling this a framework and stop telling me that it's easy to
implement stuff on top of it.

> > So unless you fix this stuff you should not even think about
> > converting anything to this "framework". That's just waste of time and
> > effort. Aside of declaring it stable and useful ....
> With stable I didn't intend to say something about the quality (though I
> still think it's a good thing), but that I won't rewrite the commits
> such that others can base their work on top of them.

Stop that bullshit already. We don't add stuff which has questionable
quality and questionable functionality.

> Before your mail nobody spoke up against these patches and some people
> see a value in them and want to convert their platform to it. So

Yes, because most involved people have the same narrow mindset as you
and all you could agree on was the least common denominator of non
functionality. People who have taste and see the big picture gave up
on that. But that does not mean that it's good and something which
should go near the tree or be provided for anyone to convert his
platform to it.

> providing a branch seems sensible to me.

Provide as much branches as you see fit. They wont go near anything.

> I don't say that this common struct clk is perfect already now and I
> expect it to change here and there. It allows to consolidate some code
> and so is a good thing. I think nobody disagrees that when having
> converted most or all platforms to it we're not done. It's just the
> first step. Maybe one of the next is to add a "class" of clocks that
> looks similar to this:

Wrong. We make a sensible functionality first and then convert bulk
instead of doing it over and over again.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21  7:42                   ` Sascha Hauer
@ 2011-04-21  9:21                     ` Thomas Gleixner
  2011-04-21 11:50                       ` Mark Brown
  2011-04-21 12:06                       ` Sascha Hauer
  0 siblings, 2 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21  9:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 21 Apr 2011, Sascha Hauer wrote:
> On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:
> >    - a field for the parent
> >    - a field for the current clock rate
> 
> Currently there is no possibility to bring the clock tree in sync with
> the hardware. clocks are not registered at all, they are just there. So
> there is no instance who could iterate over the tree in order to bring
> it in sync. Unless we create that (which I would like) there is no point
> in adding rate and parent fields.

And that's where the problem starts. What's the point of that current
conglomorate of function pointers and half baken helper wrappers if we
don't have answers for how to populate the clk tree, how to simplify
stuff w/o the need of tons of callbacks which have to be implemented
all over the place ?

> Hm, thinking about this maybe we could add a CLK_IN_SYNC field which
> is initially cleared and gets set once the get_parent()/get_rate()
> callback has been called for a clock.
> 
> >    - a field for the base register
> >    - a struct for the offsets of the most common registers relative to
> >      base
> 
> What's wrong with embedding struct clk into a more specific clock and
> access it with container_of()? It must be done anyway once a field is
> missing in struct clk, or we end up with a lot of fields in struct clk
> which are used in only few types of clocks.

As I explained already, that's the whole purpose of frameworks. See
clockevents, clocksource, genirq. Lots of stuff is only used by a very
small subset, but it's better to have that in common code than growing
warts at all ends.

> > 
> > The least thing which we need now are half baken "abstractions" which
> > just shuffle code around for no value.
> 
> While I agree with several things you say even the half baken
> abstractions help to bring the problems into the light. What we have now
> is that all these problems are hidden in SoC specific abstractions which
> all have their own problems and bugs.

And sadly enough the proposed solution keeps 90% of that crap where it
is. So it's not a real improvement, just shuffling code around.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21  7:22                   ` Uwe Kleine-König
  2011-04-21  9:12                     ` Thomas Gleixner
@ 2011-04-21 10:13                     ` Mark Brown
  2011-04-21 11:39                       ` Tony Lindgren
  1 sibling, 1 reply; 165+ messages in thread
From: Mark Brown @ 2011-04-21 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 09:22:59AM +0200, Uwe Kleine-K?nig wrote:
> On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:

> >    - a field for the current clock rate

> Then you need a mechanism to notify the children if the rate or parent
> of a clock changes. I assume you won't allow that for a clock that has
> more than one (enabled) consumer. Knowing only very few platforms I
> don't know if that is something you can forbid.

I suspect you need it - cpufreq style scaling of the core clocks (which
many SoCs can do) involves pretty much the entire clock tree, though
obviously the idea is that the effects get hidden at the edges.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21  9:12                     ` Thomas Gleixner
@ 2011-04-21 10:31                       ` Mark Brown
  2011-04-21 11:42                         ` Tony Lindgren
  2011-04-21 14:29                         ` Thomas Gleixner
  2011-04-29 10:37                       ` Russell King - ARM Linux
  1 sibling, 2 replies; 165+ messages in thread
From: Mark Brown @ 2011-04-21 10:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 11:12:36AM +0200, Thomas Gleixner wrote:
> On Thu, 21 Apr 2011, Uwe Kleine-K?nig wrote:

> > If there were a pointer tracking the parent you still needed to program
> > out the get_parent function anyhow to set the pointer initially. But I
> > agree that in other situations having a pointer is more comfortable and
> > saves ugly error handling e.g. in set_parent.

> That's nonsense. Why do you want a get_parent() function at all?
> parent is set up when the clock is established in the clock tree. And
> that's not done by some random driver. That's a property of the clock.

That's not universal - right now the drivers can and do know about this
on some platforms.  In some cases there will be requirements beyond the
clock rate which mean that the driver will need to be able to tell the
framework that, for example, it needs one clock to be in the same clock
domain as another.

> > >    - a field for the base register

> > This is not needed for all clocks (at least not a say void __iomem *). I
> > think it's fine here to leave that to the platforms as it is now.

> Crap. All clocks which are configurable in some way or can be
> enabled/disabled need access register(s) so you need a base address.

That's not reliably the case, some systems have some of the clock tree
(esepcialy the core parts of the tree) controlled by a system management
unit which isn't memory mapped and it's common for I2C or SPI connected
chips to be involved to some extent too.  One advantage we should be
able to get from this framework is that it will be much easier to have
standard drivers for off-SoC chips that could be shared.

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

* Re: [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21  6:58                     ` Saravana Kannan
  (?)
@ 2011-04-21 10:33                       ` Thomas Gleixner
  -1 siblings, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21 10:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 20 Apr 2011, Saravana Kannan wrote:
> On 04/20/2011 12:52 PM, Thomas Gleixner wrote:
> > So what's wrong with that code:
> > 
> > 1) struct clk is just a collection of function pointers and two locks
> > 
> >     It lacks:
> > 
> >     - a flag field for properties
> Agree. I would very much like it.
> 
> >     - a field for the parent
> 
> Agree.
> 
> >     - a field for the current clock rate
> 
> Meh! Not a big deal. Some clocks don't have the concept of setting their rate
> since they share a parent with another unrelated clock (Ah, looks like you
> talk about with the tree diagram). So, it might be easier to have the rate
> inside each implementation if they need it. I shouldn't add too much code.

No. Each clock has a rate, even if it's fixed and there is no point in
calling down the tree to figure that out.
 
> >     - a field for the base register
> 
> Definitely no. It's completely useless for clocks whose registers don't all
> line up with fixed offsets from the base register. Now I will have to put one
> register here and the rest of the registers in the internal data?
>
> >     - a struct for the offsets of the most common registers relative to
> >       base
> 
> Ok, you thought about rest of the registers. But, how can this fit in the
> common code? Each clock h/w implementation has totally different set of
> registers. Sometimes different even within the same SoC. This would be quite
> wasteful and doesn't even make sense to store at the top level. Also, storing
> offsets is a pain in the neck when the register space is not clean (happens
> more often than we would like :-().

Depends, there is a lot of sane hardware out there (not necessarily in
the ARM SoC world). We can do with a pointer if the need arises.
 
> >     optionally a set of common register accessor functions like I did
> >     for the generic irq chip.
> 
> Again, I don't see the point in having this in the common code. May be I'm
> missing something?

See my RFC patch of a generic irq chip implementation and how much
duplicated five line inline functions they removed.
 
> IMO, a better option instead of the base register and the offsets would be an
> option to have a priv_data pointer. I forgot the exact use case, but we
> thought that would have been helpful when we tried to port the msm clock
> driver in our tree on top of Jeremy's patches.

It works either way, but we should try to comeup with a sensible
common base struct for sane hardware.
 
> > 2) The "framework" API is just a set of low level primitive helper
> >     functions
> > 
> >     It lacks:
> > 
> >     - proper refcounting. clk_get() / clk_put() should do that at the
> >       framework level.
> 
> This has nothing to do with the patches Jeremy made. clk_get()/_put() is in
> clkdev. Also, I'm not sure if clk_get()/put() needs refcounting. That's like
> asking kalloc/kfree to have refcounting.

Ok. I missed the clkdev part.
 
> >     - the ability to propagate enable/disable/prepare/unprepare down
> >       through the parent tree
> 
> Agree. That would be nice. I think the main reason people were not pushing for
> it was to do things in manageable steps. It took a long time for people to
> agree on even the current framework Jeremy added.

Sad enough. But I'm not happy about that in any way. I know where it
ends if you try to please everyone and agree on everything.

> >     - proper mechanisms to sanity check clk_set_parent(),
> >       clk_set_rate() et. al.
> > 
> >       This is not a implementation detail inside a specific clock. It's
> >       a problem which is common at least on the tree level:
> > 
> >                      rootclk
> >                   /          \
> >                clk1          clk2
> >               /   \
> >             clk3  clk4
> > 	   /
> >           clk5
> > 
> >      So now you want to change the rate of clk1. Can you do that?
> > 
> >      No, but where is the sanity check which prevents that ?
> >
> >          In the clk1->set_rate() callback ?
> > 
> > 	Great, that's the wrong place.
> 
> Ah! Nice to see that this bothers you too. This has been a point of contention
> with in our internal team too. I keep pushing back on requests to make child
> clock's set rate propagate up to the patent when the parent has two unrelated
> child clocks going to different devices.
> 
> IMO, the set rate should only work on the parent clock and if there really in
> a need to change the child clock rates, then the users of those child clocks
> will have to co-ordinate it amongst themselves. Although, our use case is a
> bit simpler in that most of the time the child clocks are direct branches (no
> dividers) of the parent.

Still most of this should be handled in the common code. It's not a
unique problem to a single hardware implementation. It's just a given
problem due to the tree nature. And the current code completely lacks
a representation of that and therefor all needs to be done at the
implementation detail level.
 
> I'm not sure how realistic/common your example of switching parents for clk3
> is. May be it is -- I would interested in what people have to say.

I just used it to illustrate what common code should handle.
 
> So, between clk_set_divider(), clk_set_parent() and clk_set_rate(), I think we
> should be able to cover most clock trees as long as we don't propagate
> clk_set_rate() to parents with more than one children. In those case, the
> children should just implement clk_set_divider() (or not even that if there is
> no divider) and not allow clk_set_rate().

The problem starts exactly at the point where you have all that
propagation decision stuff in the chip implementation.

clk_set_rate(clk, rate)
{
	u64 parent_rate = 0;

        if (clk->users > 1)
	      	 return -EBUSY;

	if (!clk->set_rate)
	   	 return rate = clk->rate ? 0 : -EINVAL;

	ret = clk->set_rate(rate, &div, &parent_rate);
	if (!ret)
		return 0;

	if (ret != NEED_PARENT_CHANGE)
	   	return ret;

	if (WARN_ON(!clk->parent))
		return -EINVAL;

        ret = clk_set_rate(clk->parent, parent_rate);
        return ret ? ret : clk->set_rate(rate, NULL);
}

Something along that will cover the tree traversal and remove the
propagation from the chip implementations. 

> > So unless you fix this stuff you should not even think about
> > converting anything to this "framework". That's just waste of time and
> > effort. Aside of declaring it stable and useful ....
> 
> I think you haven't seen all the repetition of refcounting and each mach's
> implementation of some variant of clock ops. The current patch set from Jeremy

Yes, I have looked through the maze as I went through all irq stuff
recently. Jeremys stuff is a start, but I think we should start with
something a bit more complete than that minimal set. I know the pain
when you start with a minimal set and try to force people into
cleaning up their stuff over and over. :(

And we can identify stuff already, so it should be added now.

> will certainly help cut down some of that. If we get the "enable parent before
> you enable child, etc" in now, I don't think there will be much churn when we
> try to add code to enforce the tree restrictions you mention above.

Yes, that's needs to be done before we start churning the tree.
 
> > The least thing which we need now are half baken "abstractions" which
> > just shuffle code around for no value.
> 
> While a lot of your points are correct, I don't think the current patches from
> Jeremy are useless. May be I'm completely mistaken in assuming that you are
> referring to Jeremy's patches?

I'm not saying they are useless, but they need to be more complete
before we start converting code to it.
 
> Btw, on a slight tangent, there is also the problem of clk_round_rate() not
> being sufficient when a driver is trying to work across different mach's. I
> think we need a clk_set_rate_range(min, ideal, max) but I can start a separate
> thread on that if you want. I talked about it a bit in another thread.

Yes, but that's one step after the minimal set :)

Thanks,

	tglx

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

* Re: [PATCH RFC] clk: add support for automatic parent handling
@ 2011-04-21 10:33                       ` Thomas Gleixner
  0 siblings, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21 10:33 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: Paul McKenney, Uwe Kleine-König, linux-arm-kernel,
	Sascha Hauer, Stephen Boyd, Jeremy Kerr, kernel, linux-kernel,
	Ben Dooks, Linus Torvalds, Arnd Bergmann, Paul Mundt, linux-sh

On Wed, 20 Apr 2011, Saravana Kannan wrote:
> On 04/20/2011 12:52 PM, Thomas Gleixner wrote:
> > So what's wrong with that code:
> > 
> > 1) struct clk is just a collection of function pointers and two locks
> > 
> >     It lacks:
> > 
> >     - a flag field for properties
> Agree. I would very much like it.
> 
> >     - a field for the parent
> 
> Agree.
> 
> >     - a field for the current clock rate
> 
> Meh! Not a big deal. Some clocks don't have the concept of setting their rate
> since they share a parent with another unrelated clock (Ah, looks like you
> talk about with the tree diagram). So, it might be easier to have the rate
> inside each implementation if they need it. I shouldn't add too much code.

No. Each clock has a rate, even if it's fixed and there is no point in
calling down the tree to figure that out.
 
> >     - a field for the base register
> 
> Definitely no. It's completely useless for clocks whose registers don't all
> line up with fixed offsets from the base register. Now I will have to put one
> register here and the rest of the registers in the internal data?
>
> >     - a struct for the offsets of the most common registers relative to
> >       base
> 
> Ok, you thought about rest of the registers. But, how can this fit in the
> common code? Each clock h/w implementation has totally different set of
> registers. Sometimes different even within the same SoC. This would be quite
> wasteful and doesn't even make sense to store at the top level. Also, storing
> offsets is a pain in the neck when the register space is not clean (happens
> more often than we would like :-().

Depends, there is a lot of sane hardware out there (not necessarily in
the ARM SoC world). We can do with a pointer if the need arises.
 
> >     optionally a set of common register accessor functions like I did
> >     for the generic irq chip.
> 
> Again, I don't see the point in having this in the common code. May be I'm
> missing something?

See my RFC patch of a generic irq chip implementation and how much
duplicated five line inline functions they removed.
 
> IMO, a better option instead of the base register and the offsets would be an
> option to have a priv_data pointer. I forgot the exact use case, but we
> thought that would have been helpful when we tried to port the msm clock
> driver in our tree on top of Jeremy's patches.

It works either way, but we should try to comeup with a sensible
common base struct for sane hardware.
 
> > 2) The "framework" API is just a set of low level primitive helper
> >     functions
> > 
> >     It lacks:
> > 
> >     - proper refcounting. clk_get() / clk_put() should do that at the
> >       framework level.
> 
> This has nothing to do with the patches Jeremy made. clk_get()/_put() is in
> clkdev. Also, I'm not sure if clk_get()/put() needs refcounting. That's like
> asking kalloc/kfree to have refcounting.

Ok. I missed the clkdev part.
 
> >     - the ability to propagate enable/disable/prepare/unprepare down
> >       through the parent tree
> 
> Agree. That would be nice. I think the main reason people were not pushing for
> it was to do things in manageable steps. It took a long time for people to
> agree on even the current framework Jeremy added.

Sad enough. But I'm not happy about that in any way. I know where it
ends if you try to please everyone and agree on everything.

> >     - proper mechanisms to sanity check clk_set_parent(),
> >       clk_set_rate() et. al.
> > 
> >       This is not a implementation detail inside a specific clock. It's
> >       a problem which is common at least on the tree level:
> > 
> >                      rootclk
> >                   /          \
> >                clk1          clk2
> >               /   \
> >             clk3  clk4
> > 	   /
> >           clk5
> > 
> >      So now you want to change the rate of clk1. Can you do that?
> > 
> >      No, but where is the sanity check which prevents that ?
> >
> >          In the clk1->set_rate() callback ?
> > 
> > 	Great, that's the wrong place.
> 
> Ah! Nice to see that this bothers you too. This has been a point of contention
> with in our internal team too. I keep pushing back on requests to make child
> clock's set rate propagate up to the patent when the parent has two unrelated
> child clocks going to different devices.
> 
> IMO, the set rate should only work on the parent clock and if there really in
> a need to change the child clock rates, then the users of those child clocks
> will have to co-ordinate it amongst themselves. Although, our use case is a
> bit simpler in that most of the time the child clocks are direct branches (no
> dividers) of the parent.

Still most of this should be handled in the common code. It's not a
unique problem to a single hardware implementation. It's just a given
problem due to the tree nature. And the current code completely lacks
a representation of that and therefor all needs to be done at the
implementation detail level.
 
> I'm not sure how realistic/common your example of switching parents for clk3
> is. May be it is -- I would interested in what people have to say.

I just used it to illustrate what common code should handle.
 
> So, between clk_set_divider(), clk_set_parent() and clk_set_rate(), I think we
> should be able to cover most clock trees as long as we don't propagate
> clk_set_rate() to parents with more than one children. In those case, the
> children should just implement clk_set_divider() (or not even that if there is
> no divider) and not allow clk_set_rate().

The problem starts exactly at the point where you have all that
propagation decision stuff in the chip implementation.

clk_set_rate(clk, rate)
{
	u64 parent_rate = 0;

        if (clk->users > 1)
	      	 return -EBUSY;

	if (!clk->set_rate)
	   	 return rate == clk->rate ? 0 : -EINVAL;

	ret = clk->set_rate(rate, &div, &parent_rate);
	if (!ret)
		return 0;

	if (ret != NEED_PARENT_CHANGE)
	   	return ret;

	if (WARN_ON(!clk->parent))
		return -EINVAL;

        ret = clk_set_rate(clk->parent, parent_rate);
        return ret ? ret : clk->set_rate(rate, NULL);
}

Something along that will cover the tree traversal and remove the
propagation from the chip implementations. 

> > So unless you fix this stuff you should not even think about
> > converting anything to this "framework". That's just waste of time and
> > effort. Aside of declaring it stable and useful ....
> 
> I think you haven't seen all the repetition of refcounting and each mach's
> implementation of some variant of clock ops. The current patch set from Jeremy

Yes, I have looked through the maze as I went through all irq stuff
recently. Jeremys stuff is a start, but I think we should start with
something a bit more complete than that minimal set. I know the pain
when you start with a minimal set and try to force people into
cleaning up their stuff over and over. :(

And we can identify stuff already, so it should be added now.

> will certainly help cut down some of that. If we get the "enable parent before
> you enable child, etc" in now, I don't think there will be much churn when we
> try to add code to enforce the tree restrictions you mention above.

Yes, that's needs to be done before we start churning the tree.
 
> > The least thing which we need now are half baken "abstractions" which
> > just shuffle code around for no value.
> 
> While a lot of your points are correct, I don't think the current patches from
> Jeremy are useless. May be I'm completely mistaken in assuming that you are
> referring to Jeremy's patches?

I'm not saying they are useless, but they need to be more complete
before we start converting code to it.
 
> Btw, on a slight tangent, there is also the problem of clk_round_rate() not
> being sufficient when a driver is trying to work across different mach's. I
> think we need a clk_set_rate_range(min, ideal, max) but I can start a separate
> thread on that if you want. I talked about it a bit in another thread.

Yes, but that's one step after the minimal set :)

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
@ 2011-04-21 10:33                       ` Thomas Gleixner
  0 siblings, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21 10:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 20 Apr 2011, Saravana Kannan wrote:
> On 04/20/2011 12:52 PM, Thomas Gleixner wrote:
> > So what's wrong with that code:
> > 
> > 1) struct clk is just a collection of function pointers and two locks
> > 
> >     It lacks:
> > 
> >     - a flag field for properties
> Agree. I would very much like it.
> 
> >     - a field for the parent
> 
> Agree.
> 
> >     - a field for the current clock rate
> 
> Meh! Not a big deal. Some clocks don't have the concept of setting their rate
> since they share a parent with another unrelated clock (Ah, looks like you
> talk about with the tree diagram). So, it might be easier to have the rate
> inside each implementation if they need it. I shouldn't add too much code.

No. Each clock has a rate, even if it's fixed and there is no point in
calling down the tree to figure that out.
 
> >     - a field for the base register
> 
> Definitely no. It's completely useless for clocks whose registers don't all
> line up with fixed offsets from the base register. Now I will have to put one
> register here and the rest of the registers in the internal data?
>
> >     - a struct for the offsets of the most common registers relative to
> >       base
> 
> Ok, you thought about rest of the registers. But, how can this fit in the
> common code? Each clock h/w implementation has totally different set of
> registers. Sometimes different even within the same SoC. This would be quite
> wasteful and doesn't even make sense to store at the top level. Also, storing
> offsets is a pain in the neck when the register space is not clean (happens
> more often than we would like :-().

Depends, there is a lot of sane hardware out there (not necessarily in
the ARM SoC world). We can do with a pointer if the need arises.
 
> >     optionally a set of common register accessor functions like I did
> >     for the generic irq chip.
> 
> Again, I don't see the point in having this in the common code. May be I'm
> missing something?

See my RFC patch of a generic irq chip implementation and how much
duplicated five line inline functions they removed.
 
> IMO, a better option instead of the base register and the offsets would be an
> option to have a priv_data pointer. I forgot the exact use case, but we
> thought that would have been helpful when we tried to port the msm clock
> driver in our tree on top of Jeremy's patches.

It works either way, but we should try to comeup with a sensible
common base struct for sane hardware.
 
> > 2) The "framework" API is just a set of low level primitive helper
> >     functions
> > 
> >     It lacks:
> > 
> >     - proper refcounting. clk_get() / clk_put() should do that at the
> >       framework level.
> 
> This has nothing to do with the patches Jeremy made. clk_get()/_put() is in
> clkdev. Also, I'm not sure if clk_get()/put() needs refcounting. That's like
> asking kalloc/kfree to have refcounting.

Ok. I missed the clkdev part.
 
> >     - the ability to propagate enable/disable/prepare/unprepare down
> >       through the parent tree
> 
> Agree. That would be nice. I think the main reason people were not pushing for
> it was to do things in manageable steps. It took a long time for people to
> agree on even the current framework Jeremy added.

Sad enough. But I'm not happy about that in any way. I know where it
ends if you try to please everyone and agree on everything.

> >     - proper mechanisms to sanity check clk_set_parent(),
> >       clk_set_rate() et. al.
> > 
> >       This is not a implementation detail inside a specific clock. It's
> >       a problem which is common at least on the tree level:
> > 
> >                      rootclk
> >                   /          \
> >                clk1          clk2
> >               /   \
> >             clk3  clk4
> > 	   /
> >           clk5
> > 
> >      So now you want to change the rate of clk1. Can you do that?
> > 
> >      No, but where is the sanity check which prevents that ?
> >
> >          In the clk1->set_rate() callback ?
> > 
> > 	Great, that's the wrong place.
> 
> Ah! Nice to see that this bothers you too. This has been a point of contention
> with in our internal team too. I keep pushing back on requests to make child
> clock's set rate propagate up to the patent when the parent has two unrelated
> child clocks going to different devices.
> 
> IMO, the set rate should only work on the parent clock and if there really in
> a need to change the child clock rates, then the users of those child clocks
> will have to co-ordinate it amongst themselves. Although, our use case is a
> bit simpler in that most of the time the child clocks are direct branches (no
> dividers) of the parent.

Still most of this should be handled in the common code. It's not a
unique problem to a single hardware implementation. It's just a given
problem due to the tree nature. And the current code completely lacks
a representation of that and therefor all needs to be done at the
implementation detail level.
 
> I'm not sure how realistic/common your example of switching parents for clk3
> is. May be it is -- I would interested in what people have to say.

I just used it to illustrate what common code should handle.
 
> So, between clk_set_divider(), clk_set_parent() and clk_set_rate(), I think we
> should be able to cover most clock trees as long as we don't propagate
> clk_set_rate() to parents with more than one children. In those case, the
> children should just implement clk_set_divider() (or not even that if there is
> no divider) and not allow clk_set_rate().

The problem starts exactly at the point where you have all that
propagation decision stuff in the chip implementation.

clk_set_rate(clk, rate)
{
	u64 parent_rate = 0;

        if (clk->users > 1)
	      	 return -EBUSY;

	if (!clk->set_rate)
	   	 return rate == clk->rate ? 0 : -EINVAL;

	ret = clk->set_rate(rate, &div, &parent_rate);
	if (!ret)
		return 0;

	if (ret != NEED_PARENT_CHANGE)
	   	return ret;

	if (WARN_ON(!clk->parent))
		return -EINVAL;

        ret = clk_set_rate(clk->parent, parent_rate);
        return ret ? ret : clk->set_rate(rate, NULL);
}

Something along that will cover the tree traversal and remove the
propagation from the chip implementations. 

> > So unless you fix this stuff you should not even think about
> > converting anything to this "framework". That's just waste of time and
> > effort. Aside of declaring it stable and useful ....
> 
> I think you haven't seen all the repetition of refcounting and each mach's
> implementation of some variant of clock ops. The current patch set from Jeremy

Yes, I have looked through the maze as I went through all irq stuff
recently. Jeremys stuff is a start, but I think we should start with
something a bit more complete than that minimal set. I know the pain
when you start with a minimal set and try to force people into
cleaning up their stuff over and over. :(

And we can identify stuff already, so it should be added now.

> will certainly help cut down some of that. If we get the "enable parent before
> you enable child, etc" in now, I don't think there will be much churn when we
> try to add code to enforce the tree restrictions you mention above.

Yes, that's needs to be done before we start churning the tree.
 
> > The least thing which we need now are half baken "abstractions" which
> > just shuffle code around for no value.
> 
> While a lot of your points are correct, I don't think the current patches from
> Jeremy are useless. May be I'm completely mistaken in assuming that you are
> referring to Jeremy's patches?

I'm not saying they are useless, but they need to be more complete
before we start converting code to it.
 
> Btw, on a slight tangent, there is also the problem of clk_round_rate() not
> being sufficient when a driver is trying to work across different mach's. I
> think we need a clk_set_rate_range(min, ideal, max) but I can start a separate
> thread on that if you want. I talked about it a bit in another thread.

Yes, but that's one step after the minimal set :)

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 10:13                     ` Mark Brown
@ 2011-04-21 11:39                       ` Tony Lindgren
  0 siblings, 0 replies; 165+ messages in thread
From: Tony Lindgren @ 2011-04-21 11:39 UTC (permalink / raw)
  To: linux-arm-kernel

* Mark Brown <broonie@opensource.wolfsonmicro.com> [110421 03:11]:
> On Thu, Apr 21, 2011 at 09:22:59AM +0200, Uwe Kleine-K?nig wrote:
> > On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:
> 
> > >    - a field for the current clock rate
> 
> > Then you need a mechanism to notify the children if the rate or parent
> > of a clock changes. I assume you won't allow that for a clock that has
> > more than one (enabled) consumer. Knowing only very few platforms I
> > don't know if that is something you can forbid.
> 
> I suspect you need it - cpufreq style scaling of the core clocks (which
> many SoCs can do) involves pretty much the entire clock tree, though
> obviously the idea is that the effects get hidden at the edges.

That's correct, scaling of the whole clock tree is needed for
cpufreq and DVFS. An example is scaling of the L3 bus on omaps.

Tony

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 10:31                       ` Mark Brown
@ 2011-04-21 11:42                         ` Tony Lindgren
  2011-04-21 14:52                           ` Thomas Gleixner
  2011-04-21 14:29                         ` Thomas Gleixner
  1 sibling, 1 reply; 165+ messages in thread
From: Tony Lindgren @ 2011-04-21 11:42 UTC (permalink / raw)
  To: linux-arm-kernel

* Mark Brown <broonie@opensource.wolfsonmicro.com> [110421 03:29]:
> On Thu, Apr 21, 2011 at 11:12:36AM +0200, Thomas Gleixner wrote:
> > On Thu, 21 Apr 2011, Uwe Kleine-K?nig wrote:
> 
> > > If there were a pointer tracking the parent you still needed to program
> > > out the get_parent function anyhow to set the pointer initially. But I
> > > agree that in other situations having a pointer is more comfortable and
> > > saves ugly error handling e.g. in set_parent.
> 
> > That's nonsense. Why do you want a get_parent() function at all?
> > parent is set up when the clock is established in the clock tree. And
> > that's not done by some random driver. That's a property of the clock.
> 
> That's not universal - right now the drivers can and do know about this
> on some platforms.  In some cases there will be requirements beyond the
> clock rate which mean that the driver will need to be able to tell the
> framework that, for example, it needs one clock to be in the same clock
> domain as another.

Also there can be multiple parent clocks. An example are the timers on
omaps where the parent clock can be either the 32KiHz clock or external
source clock. ?his may need to be reprogrammed dynamically in some cases
for advanced idle modes as one of the parent clocks may be shut down.

Tony

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21  9:21                     ` Thomas Gleixner
@ 2011-04-21 11:50                       ` Mark Brown
  2011-04-21 12:20                         ` Thomas Gleixner
  2011-04-21 12:06                       ` Sascha Hauer
  1 sibling, 1 reply; 165+ messages in thread
From: Mark Brown @ 2011-04-21 11:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 11:21:53AM +0200, Thomas Gleixner wrote:
> On Thu, 21 Apr 2011, Sascha Hauer wrote:
> > On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:

> > >    - a field for the base register
> > >    - a struct for the offsets of the most common registers relative to
> > >      base

> > What's wrong with embedding struct clk into a more specific clock and
> > access it with container_of()? It must be done anyway once a field is
> > missing in struct clk, or we end up with a lot of fields in struct clk
> > which are used in only few types of clocks.

> As I explained already, that's the whole purpose of frameworks. See
> clockevents, clocksource, genirq. Lots of stuff is only used by a very
> small subset, but it's better to have that in common code than growing
> warts at all ends.

There's nothing intrinsic about the concept of a clock which means that
it needs to be memory mapped or have a particular set of registers for
us to work with.  This sounds like something that ought to be factored
out but it's not obvious to me that it should be part of the core struct.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21  9:21                     ` Thomas Gleixner
  2011-04-21 11:50                       ` Mark Brown
@ 2011-04-21 12:06                       ` Sascha Hauer
  2011-04-21 15:38                         ` Thomas Gleixner
  1 sibling, 1 reply; 165+ messages in thread
From: Sascha Hauer @ 2011-04-21 12:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 11:21:53AM +0200, Thomas Gleixner wrote:
> On Thu, 21 Apr 2011, Sascha Hauer wrote:
> > On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:
> > >    - a field for the parent
> > >    - a field for the current clock rate
> > 
> > Currently there is no possibility to bring the clock tree in sync with
> > the hardware. clocks are not registered at all, they are just there. So
> > there is no instance who could iterate over the tree in order to bring
> > it in sync. Unless we create that (which I would like) there is no point
> > in adding rate and parent fields.
> 
> And that's where the problem starts. What's the point of that current
> conglomorate of function pointers and half baken helper wrappers if we
> don't have answers for how to populate the clk tree, how to simplify
> stuff w/o the need of tons of callbacks which have to be implemented
> all over the place ?
> 
> > Hm, thinking about this maybe we could add a CLK_IN_SYNC field which
> > is initially cleared and gets set once the get_parent()/get_rate()
> > callback has been called for a clock.
> > 
> > >    - a field for the base register
> > >    - a struct for the offsets of the most common registers relative to
> > >      base
> > 
> > What's wrong with embedding struct clk into a more specific clock and
> > access it with container_of()? It must be done anyway once a field is
> > missing in struct clk, or we end up with a lot of fields in struct clk
> > which are used in only few types of clocks.
> 
> As I explained already, that's the whole purpose of frameworks. See
> clockevents, clocksource, genirq. Lots of stuff is only used by a very
> small subset, but it's better to have that in common code than growing
> warts at all ends.
> 
> > > 
> > > The least thing which we need now are half baken "abstractions" which
> > > just shuffle code around for no value.
> > 
> > While I agree with several things you say even the half baken
> > abstractions help to bring the problems into the light. What we have now
> > is that all these problems are hidden in SoC specific abstractions which
> > all have their own problems and bugs.
> 
> And sadly enough the proposed solution keeps 90% of that crap where it
> is. So it's not a real improvement, just shuffling code around.

That's why I tried to sort out some common patterns (divider, gates,
muxes) and put them into drivers/clk for other people to use it. It's
enough to build a whole clock tree out of it (except plls and special
stuff). All things you mentioned which are missing in the common clock
stuff can be added without touching the i.MX specific parts. You want
the framework (once it actually is one) to handle the parents? just move
the parent handling out of drivers/clk/clk-[divider|mux|gate].c to
drivers/clk/clk.c. Refcounting shall be fixed? do so in
drivers/clk/clkdev.c.

I didn't say that the patches I posted shall be moved upstream as-is. I
only wanted to show how a clock tree can look like when we sort out
common patterns.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 11:50                       ` Mark Brown
@ 2011-04-21 12:20                         ` Thomas Gleixner
  2011-04-21 12:35                           ` Mark Brown
  2011-04-29 10:49                           ` Russell King - ARM Linux
  0 siblings, 2 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21 12:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 21 Apr 2011, Mark Brown wrote:
> On Thu, Apr 21, 2011 at 11:21:53AM +0200, Thomas Gleixner wrote:
> > On Thu, 21 Apr 2011, Sascha Hauer wrote:
> > > On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:
> 
> > > >    - a field for the base register
> > > >    - a struct for the offsets of the most common registers relative to
> > > >      base
> 
> > > What's wrong with embedding struct clk into a more specific clock and
> > > access it with container_of()? It must be done anyway once a field is
> > > missing in struct clk, or we end up with a lot of fields in struct clk
> > > which are used in only few types of clocks.
> 
> > As I explained already, that's the whole purpose of frameworks. See
> > clockevents, clocksource, genirq. Lots of stuff is only used by a very
> > small subset, but it's better to have that in common code than growing
> > warts at all ends.
> 
> There's nothing intrinsic about the concept of a clock which means that
> it needs to be memory mapped or have a particular set of registers for
> us to work with.  This sounds like something that ought to be factored
> out but it's not obvious to me that it should be part of the core struct.

Care to look over the various implementations and find out that a lot
of them look like:

static int _clk_enable(struct clk *clk)
{
        unsigned int reg;

        reg = __raw_readl(clk->enable_reg);
        reg |= 1 << clk->enable_shift;
        __raw_writel(reg, clk->enable_reg);

        return 0;
}

Just in about 100 variations of the theme. Which is basically the same
as we have in irq chip implementations. And I showed how much of these
things can be factored out when done right. And even if a particular
clock does not implement enable/disable calls, then having
regs.enable_reg around is not a problem.

That's not a requirement for the first step, but I want to see people
thinking about it instead of mindlessly converting their clocks to the
generic clock structure and the generic handling functions. And I'd
rather see people coming and say: We see that the following thing
would be cute:

      clk_regs {
      	       struct spin_lock *reg_lock;
      	       void *base;
	       union {
	       	       void *enable_reg;
	       	       unsigned long enable_offset;
	       };
	       ....
	       u32 enable_cache;
      };

Because that's what we implement via container_of now. And we can add
such stuff which is obvious right away.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 12:20                         ` Thomas Gleixner
@ 2011-04-21 12:35                           ` Mark Brown
  2011-04-25  2:03                             ` Richard Zhao
  2011-04-29 10:49                           ` Russell King - ARM Linux
  1 sibling, 1 reply; 165+ messages in thread
From: Mark Brown @ 2011-04-21 12:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 02:20:22PM +0200, Thomas Gleixner wrote:
> On Thu, 21 Apr 2011, Mark Brown wrote:

> > There's nothing intrinsic about the concept of a clock which means that
> > it needs to be memory mapped or have a particular set of registers for
> > us to work with.  This sounds like something that ought to be factored
> > out but it's not obvious to me that it should be part of the core struct.

> Care to look over the various implementations and find out that a lot
> of them look like:

Please bear in mind that due to the fact that we've currently got one
clock implementation per subarchitecture anything off-SoC has some
serious barriers to implementation in kernel.  For the system management
units you'd be looking at very new systems, this is a new development.

> Just in about 100 variations of the theme. Which is basically the same
> as we have in irq chip implementations. And I showed how much of these
> things can be factored out when done right. And even if a particular
> clock does not implement enable/disable calls, then having
> regs.enable_reg around is not a problem.

This is why I said "This sounds like something that ought to be factored
out but it's not obvious to me that it should be part of the core
struct" above - I agree strongly that we should have a generic memory
mapped implementation which factors out all the redundant code you'd get
for these clocks.

> Because that's what we implement via container_of now. And we can add
> such stuff which is obvious right away.

That's exactly the sort of thing I'm suggesting.  You were asking for
this to be part of struct clk itself, embedding the struct clk in a
struct mm_clk (or whatever) and having standard ops for the mm_clk a
much better abstraction.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 10:31                       ` Mark Brown
  2011-04-21 11:42                         ` Tony Lindgren
@ 2011-04-21 14:29                         ` Thomas Gleixner
  1 sibling, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21 14:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 21 Apr 2011, Mark Brown wrote:
> That's not reliably the case, some systems have some of the clock tree
> (esepcialy the core parts of the tree) controlled by a system management
> unit which isn't memory mapped and it's common for I2C or SPI connected
> chips to be involved to some extent too.  One advantage we should be
> able to get from this framework is that it will be much easier to have
> standard drivers for off-SoC chips that could be shared.

Fair enough.
 

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 11:42                         ` Tony Lindgren
@ 2011-04-21 14:52                           ` Thomas Gleixner
  2011-04-22  7:09                             ` Tony Lindgren
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21 14:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 21 Apr 2011, Tony Lindgren wrote:

> * Mark Brown <broonie@opensource.wolfsonmicro.com> [110421 03:29]:
> > On Thu, Apr 21, 2011 at 11:12:36AM +0200, Thomas Gleixner wrote:
> > > On Thu, 21 Apr 2011, Uwe Kleine-K?nig wrote:
> > 
> > > > If there were a pointer tracking the parent you still needed to program
> > > > out the get_parent function anyhow to set the pointer initially. But I
> > > > agree that in other situations having a pointer is more comfortable and
> > > > saves ugly error handling e.g. in set_parent.
> > 
> > > That's nonsense. Why do you want a get_parent() function at all?
> > > parent is set up when the clock is established in the clock tree. And
> > > that's not done by some random driver. That's a property of the clock.
> > 
> > That's not universal - right now the drivers can and do know about this
> > on some platforms.  In some cases there will be requirements beyond the
> > clock rate which mean that the driver will need to be able to tell the
> > framework that, for example, it needs one clock to be in the same clock
> > domain as another.
> 
> Also there can be multiple parent clocks. An example are the timers on
> omaps where the parent clock can be either the 32KiHz clock or external
> source clock. ?his may need to be reprogrammed dynamically in some cases
> for advanced idle modes as one of the parent clocks may be shut down.

If you need to propagate from bottom up, then you need a list of
childs in struct clk. Right ?

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 12:06                       ` Sascha Hauer
@ 2011-04-21 15:38                         ` Thomas Gleixner
  2011-04-22  0:23                           ` Colin Cross
  2011-04-22  4:54                           ` Saravana Kannan
  0 siblings, 2 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21 15:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 21 Apr 2011, Sascha Hauer wrote:
> On Thu, Apr 21, 2011 at 11:21:53AM +0200, Thomas Gleixner wrote:
> That's why I tried to sort out some common patterns (divider, gates,
> muxes) and put them into drivers/clk for other people to use it. It's
> enough to build a whole clock tree out of it (except plls and special
> stuff). All things you mentioned which are missing in the common clock
> stuff can be added without touching the i.MX specific parts. You want
> the framework (once it actually is one) to handle the parents? just move
> the parent handling out of drivers/clk/clk-[divider|mux|gate].c to
> drivers/clk/clk.c. Refcounting shall be fixed? do so in
> drivers/clk/clkdev.c.

The point is that we want to do stuff like that now - BEFORE anyone
starts using struct clk and the helper functions.

> I didn't say that the patches I posted shall be moved upstream as-is. I
> only wanted to show how a clock tree can look like when we sort out
> common patterns.

We really want to get some sensible functionality for starting.

So what I can see now from the discussion is that we should at least
add the following fields to struct clk:

       unsigned long  flags;
       unsigned long   rate;
       struct clk     *parent;
       unsigned int   users;

Add the parent propagation to the clk_enable disable prepare unprepare
functions.

And we should add right away:

       struct hlist_head childs;
       struct hlist_node node;

Plus infrastructure to register clocks with the parent. Advanced
things like bottom up propagation of clock rate changes is something
we can do later, but we really want to make proper registration a
required change for users of the new stuff.

That brings in another question and this really needs to be answered
now: Locking

I'm pushing hard on this because I know that retrofitting proper
locking schemes is going to be a nightmare.

You already have a lock nesting problem when you do parent
propagation. With your code you do the parent propagation in the child
callback under the prepare_mutex or the enable_lock.

This is going to end up in lockdep being quite unhappy unless you want
tons of different lock classes for this stuff. i.e.

     clk_prepare(clk2)
	mutex_lock(clk2->mutex);
	   clk->prepare(clk);
		clk_prepare(clk1)
		    mutex_lock(clk1->mutex);	

And you _CANNOT_ call clk1->prepare() from your clk2 prepare function
as it would forgo the serialization and the prepare refcounting. And
this kind of scheme is going to be even more problematic if you do
bottom up propagation because you will run into lock inversion.

I seriously doubt that the fine grained per clock locking is going to
work out at all.

How do you protect changes to the tree hierarchy against a traversal
of a concurrent clk->prepare... propagation? Not at all, because you
CANNOT. And you cannot use RCU for this either.

So what's the point of the per clk locks? I can't see one at all.

All those callbacks are not high frequency called functions, so if you
want to make this a true framework which deals with tons of
interesting stuff like propagation, reparenting and rate changes from
bottom up then there is only one way to do that: global serialization.

There is no way around that. Everything else is going to be the
locking hell and racy all over the place.

Thanks,

	tglx

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

* Re: [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 10:33                       ` Thomas Gleixner
  (?)
@ 2011-04-21 19:22                         ` torbenh
  -1 siblings, 0 replies; 165+ messages in thread
From: torbenh @ 2011-04-21 19:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 12:33:49PM +0200, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Saravana Kannan wrote:
> > On 04/20/2011 12:52 PM, Thomas Gleixner wrote:
> > > 2) The "framework" API is just a set of low level primitive helper
> > >     functions
> > > 
> > >     It lacks:
> > > 
> > >     - proper refcounting. clk_get() / clk_put() should do that at the
> > >       framework level.
> > 
> > This has nothing to do with the patches Jeremy made. clk_get()/_put() is in
> > clkdev. Also, I'm not sure if clk_get()/put() needs refcounting. That's like
> > asking kalloc/kfree to have refcounting.
> 
> Ok. I missed the clkdev part.

well... just look at this:

-> git grep __clk_get
arch/arm/mach-bcmring/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-davinci/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/mach-ep93xx/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-integrator/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/mach-lpc32xx/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-mmp/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-msm/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk) { return 1; }
arch/arm/mach-mxs/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-nomadik/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-nuc93x/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-pnx4008/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-pxa/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-realview/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-shmobile/clock.c:int __clk_get(struct clk *clk)
arch/arm/mach-shmobile/clock.c:EXPORT_SYMBOL(__clk_get);
arch/arm/mach-shmobile/include/mach/clkdev.h:int __clk_get(struct clk *clk);
arch/arm/mach-tegra/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/mach-u300/clock.c:int __clk_get(struct clk *clk)
arch/arm/mach-u300/clock.c:EXPORT_SYMBOL(__clk_get);
arch/arm/mach-u300/include/mach/clkdev.h:int __clk_get(struct clk *clk);
arch/arm/mach-ux500/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-versatile/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-vexpress/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-w90x900/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-mxc/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-omap/include/plat/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/plat-spear/include/plat/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-stmp3xxx/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-tcc/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/sh/include/asm/clkdev.h:#define __clk_get(clk) ({ 1; })
drivers/clk/clkdev.c:   if (clk && !__clk_get(clk))




-- 
torben Hohn

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

* Re: [PATCH RFC] clk: add support for automatic parent handling
@ 2011-04-21 19:22                         ` torbenh
  0 siblings, 0 replies; 165+ messages in thread
From: torbenh @ 2011-04-21 19:22 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Saravana Kannan, Paul McKenney, Uwe Kleine-König,
	linux-arm-kernel, Sascha Hauer, Stephen Boyd, Jeremy Kerr,
	kernel, linux-kernel, Ben Dooks, Linus Torvalds, Arnd Bergmann,
	Paul Mundt, linux-sh

On Thu, Apr 21, 2011 at 12:33:49PM +0200, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Saravana Kannan wrote:
> > On 04/20/2011 12:52 PM, Thomas Gleixner wrote:
> > > 2) The "framework" API is just a set of low level primitive helper
> > >     functions
> > > 
> > >     It lacks:
> > > 
> > >     - proper refcounting. clk_get() / clk_put() should do that at the
> > >       framework level.
> > 
> > This has nothing to do with the patches Jeremy made. clk_get()/_put() is in
> > clkdev. Also, I'm not sure if clk_get()/put() needs refcounting. That's like
> > asking kalloc/kfree to have refcounting.
> 
> Ok. I missed the clkdev part.

well... just look at this:

-> git grep __clk_get
arch/arm/mach-bcmring/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-davinci/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/mach-ep93xx/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-integrator/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/mach-lpc32xx/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-mmp/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-msm/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk) { return 1; }
arch/arm/mach-mxs/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-nomadik/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-nuc93x/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-pnx4008/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-pxa/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-realview/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-shmobile/clock.c:int __clk_get(struct clk *clk)
arch/arm/mach-shmobile/clock.c:EXPORT_SYMBOL(__clk_get);
arch/arm/mach-shmobile/include/mach/clkdev.h:int __clk_get(struct clk *clk);
arch/arm/mach-tegra/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/mach-u300/clock.c:int __clk_get(struct clk *clk)
arch/arm/mach-u300/clock.c:EXPORT_SYMBOL(__clk_get);
arch/arm/mach-u300/include/mach/clkdev.h:int __clk_get(struct clk *clk);
arch/arm/mach-ux500/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-versatile/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-vexpress/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-w90x900/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-mxc/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-omap/include/plat/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/plat-spear/include/plat/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-stmp3xxx/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-tcc/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/sh/include/asm/clkdev.h:#define __clk_get(clk) ({ 1; })
drivers/clk/clkdev.c:   if (clk && !__clk_get(clk))




-- 
torben Hohn

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

* [PATCH RFC] clk: add support for automatic parent handling
@ 2011-04-21 19:22                         ` torbenh
  0 siblings, 0 replies; 165+ messages in thread
From: torbenh @ 2011-04-21 19:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 12:33:49PM +0200, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Saravana Kannan wrote:
> > On 04/20/2011 12:52 PM, Thomas Gleixner wrote:
> > > 2) The "framework" API is just a set of low level primitive helper
> > >     functions
> > > 
> > >     It lacks:
> > > 
> > >     - proper refcounting. clk_get() / clk_put() should do that at the
> > >       framework level.
> > 
> > This has nothing to do with the patches Jeremy made. clk_get()/_put() is in
> > clkdev. Also, I'm not sure if clk_get()/put() needs refcounting. That's like
> > asking kalloc/kfree to have refcounting.
> 
> Ok. I missed the clkdev part.

well... just look at this:

-> git grep __clk_get
arch/arm/mach-bcmring/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-davinci/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/mach-ep93xx/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-integrator/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/mach-lpc32xx/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-mmp/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-msm/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk) { return 1; }
arch/arm/mach-mxs/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-nomadik/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-nuc93x/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-pnx4008/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-pxa/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-realview/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-shmobile/clock.c:int __clk_get(struct clk *clk)
arch/arm/mach-shmobile/clock.c:EXPORT_SYMBOL(__clk_get);
arch/arm/mach-shmobile/include/mach/clkdev.h:int __clk_get(struct clk *clk);
arch/arm/mach-tegra/include/mach/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/mach-u300/clock.c:int __clk_get(struct clk *clk)
arch/arm/mach-u300/clock.c:EXPORT_SYMBOL(__clk_get);
arch/arm/mach-u300/include/mach/clkdev.h:int __clk_get(struct clk *clk);
arch/arm/mach-ux500/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-versatile/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-vexpress/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/mach-w90x900/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-mxc/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-omap/include/plat/clkdev.h:static inline int __clk_get(struct clk *clk)
arch/arm/plat-spear/include/plat/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-stmp3xxx/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/arm/plat-tcc/include/mach/clkdev.h:#define __clk_get(clk) ({ 1; })
arch/sh/include/asm/clkdev.h:#define __clk_get(clk) ({ 1; })
drivers/clk/clkdev.c:   if (clk && !__clk_get(clk))




-- 
torben Hohn

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

* [PATCH 01/10] Add a common struct clk
  2011-04-15 19:08 ` [PATCH 01/10] Add a common struct clk Sascha Hauer
@ 2011-04-21 19:48   ` Thomas Gleixner
  2011-04-22  0:28     ` Richard Zhao
                       ` (2 more replies)
  2011-04-30  8:06   ` Linus Walleij
  2011-05-01 20:33   ` Rob Herring
  2 siblings, 3 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-21 19:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 15 Apr 2011, Sascha Hauer wrote:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>
> + * @get:	Called by the core clock code when a device driver acquires a
> + *		clock via clk_get(). Optional.
> + *
> + * @put:	Called by the core clock code when a devices driver releases a
> + *		clock via clk_put(). Optional.

These callbacks are completely pointless. There are only two non empty
implementations in tree:

One does a try_module_get(clk->owner), which should be done in generic
code. The other does special clock enabling magic which wants to go to
clk->prepare().

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 15:38                         ` Thomas Gleixner
@ 2011-04-22  0:23                           ` Colin Cross
  2011-04-22  9:51                             ` Thomas Gleixner
  2011-04-22  4:54                           ` Saravana Kannan
  1 sibling, 1 reply; 165+ messages in thread
From: Colin Cross @ 2011-04-22  0:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 8:38 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> That brings in another question and this really needs to be answered
> now: Locking
>
> I'm pushing hard on this because I know that retrofitting proper
> locking schemes is going to be a nightmare.
>
> You already have a lock nesting problem when you do parent
> propagation. With your code you do the parent propagation in the child
> callback under the prepare_mutex or the enable_lock.
>
> This is going to end up in lockdep being quite unhappy unless you want
> tons of different lock classes for this stuff. i.e.
>
> ? ? clk_prepare(clk2)
> ? ? ? ?mutex_lock(clk2->mutex);
> ? ? ? ? ? clk->prepare(clk);
> ? ? ? ? ? ? ? ?clk_prepare(clk1)
> ? ? ? ? ? ? ? ? ? ?mutex_lock(clk1->mutex);
>
> And you _CANNOT_ call clk1->prepare() from your clk2 prepare function
> as it would forgo the serialization and the prepare refcounting. And
> this kind of scheme is going to be even more problematic if you do
> bottom up propagation because you will run into lock inversion.
>
> I seriously doubt that the fine grained per clock locking is going to
> work out at all.
>
> How do you protect changes to the tree hierarchy against a traversal
> of a concurrent clk->prepare... propagation? Not at all, because you
> CANNOT. And you cannot use RCU for this either.
>
> So what's the point of the per clk locks? I can't see one at all.
>
> All those callbacks are not high frequency called functions, so if you
> want to make this a true framework which deals with tons of
> interesting stuff like propagation, reparenting and rate changes from
> bottom up then there is only one way to do that: global serialization.
>
> There is no way around that. Everything else is going to be the
> locking hell and racy all over the place.

Per clock locks are useful if you have some very slow clocks and some
very fast clocks.  PLLs may take 20 ms to lock, and preventing any
other call to clk_prepare for that long could be problematic.  The
problem was worse before the clk_enable/clk_prepare split, maybe it's
not necessary at all any more.

For Tegra, I solved my clock locking problems by (almost) always
locking from child to parent, the normal case for
clk_enable/clk_prepare.  In general, you only need to lock parent and
then child if you store the rate of the child in the child's clk
struct and need to update it when the parent changes, or when
traversing the tree for debugging output.  I solved the first problem
by storing the relation between the child and the parent in the child
struct and locking from child to parent on clk_get_rate calls to
calculate the rate, and the second by using a trylock loop over the
list of clocks (see arch/arm/mach-tegra/clock.c).

Now that clk_prepare and clk_enable are split, the long-held locks
(for plls, maybe dvfs?) are separated from the short-held locks for
clk_enable/clk_disable, and the cost of global serialization is much
more acceptable.

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

* [PATCH 01/10] Add a common struct clk
  2011-04-21 19:48   ` Thomas Gleixner
@ 2011-04-22  0:28     ` Richard Zhao
  2011-04-22  9:23       ` Thomas Gleixner
  2011-04-22  4:57     ` Saravana Kannan
  2011-04-29 10:09     ` Russell King - ARM Linux
  2 siblings, 1 reply; 165+ messages in thread
From: Richard Zhao @ 2011-04-22  0:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Thomas,

On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > + * @get:	Called by the core clock code when a device driver acquires a
> > + *		clock via clk_get(). Optional.
> > + *
> > + * @put:	Called by the core clock code when a devices driver releases a
> > + *		clock via clk_put(). Optional.
> 
> These callbacks are completely pointless. There are only two non empty
> implementations in tree:
> 
> One does a try_module_get(clk->owner), which should be done in generic
> code. The other does special clock enabling magic which wants to go to
> clk->prepare().
You forget mach-u300 __clk_get. It updates some registers.
The ops get/put let arch clock driver have a chance to do special things at the
time when a user begins to use the clock.

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

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 15:38                         ` Thomas Gleixner
  2011-04-22  0:23                           ` Colin Cross
@ 2011-04-22  4:54                           ` Saravana Kannan
  2011-04-22  9:06                             ` Thomas Gleixner
  1 sibling, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-04-22  4:54 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/21/2011 08:38 AM, Thomas Gleixner wrote:
> On Thu, 21 Apr 2011, Sascha Hauer wrote:
>> On Thu, Apr 21, 2011 at 11:21:53AM +0200, Thomas Gleixner wrote:
>> That's why I tried to sort out some common patterns (divider, gates,
>> muxes) and put them into drivers/clk for other people to use it. It's
>> enough to build a whole clock tree out of it (except plls and special
>> stuff). All things you mentioned which are missing in the common clock
>> stuff can be added without touching the i.MX specific parts. You want
>> the framework (once it actually is one) to handle the parents? just move
>> the parent handling out of drivers/clk/clk-[divider|mux|gate].c to
>> drivers/clk/clk.c. Refcounting shall be fixed? do so in
>> drivers/clk/clkdev.c.
>
> The point is that we want to do stuff like that now - BEFORE anyone
> starts using struct clk and the helper functions.
>
>> I didn't say that the patches I posted shall be moved upstream as-is. I
>> only wanted to show how a clock tree can look like when we sort out
>> common patterns.
>
> We really want to get some sensible functionality for starting.
>
> So what I can see now from the discussion is that we should at least
> add the following fields to struct clk:
>
>         unsigned long  flags;
>         unsigned long   rate;
>         struct clk     *parent;
>         unsigned int   users;
>
> Add the parent propagation to the clk_enable disable prepare unprepare
> functions.
>
> And we should add right away:
>
>         struct hlist_head childs;
>         struct hlist_node node;
>
> Plus infrastructure to register clocks with the parent. Advanced
> things like bottom up propagation of clock rate changes is something
> we can do later, but we really want to make proper registration a
> required change for users of the new stuff.
>
> That brings in another question and this really needs to be answered
> now: Locking
>
> I'm pushing hard on this because I know that retrofitting proper
> locking schemes is going to be a nightmare.
>
> You already have a lock nesting problem when you do parent
> propagation. With your code you do the parent propagation in the child
> callback under the prepare_mutex or the enable_lock.
>
> This is going to end up in lockdep being quite unhappy unless you want
> tons of different lock classes for this stuff. i.e.
>
>       clk_prepare(clk2)
> 	mutex_lock(clk2->mutex);
> 	   clk->prepare(clk);
> 		clk_prepare(clk1)
> 		    mutex_lock(clk1->mutex);	
>
> And you _CANNOT_ call clk1->prepare() from your clk2 prepare function
> as it would forgo the serialization and the prepare refcounting. And
> this kind of scheme is going to be even more problematic if you do
> bottom up propagation because you will run into lock inversion.
>
> I seriously doubt that the fine grained per clock locking is going to
> work out at all.
>
> How do you protect changes to the tree hierarchy against a traversal
> of a concurrent clk->prepare... propagation? Not at all, because you
> CANNOT. And you cannot use RCU for this either.
>
> So what's the point of the per clk locks? I can't see one at all.
>
> All those callbacks are not high frequency called functions, so if you
> want to make this a true framework which deals with tons of
> interesting stuff like propagation, reparenting and rate changes from
> bottom up then there is only one way to do that: global serialization.
>
> There is no way around that. Everything else is going to be the
> locking hell and racy all over the place.

We (MSM guys) had to go thru this thought process when we did some 
internal reorg of the clock code. Per clock locks prevent us from 
slowing down clock manipulation of some fast clocks when there is 
another call going on to manipulate slow clocks. There are some clocks 
that are not controlled by writing to registers directly and they are 
extremely slow compared to the usual set of clocks.

One thing we did to handle the locking issue was to have a lock per 
"class" of clocks. For example, we had one lock for clocks controlled by 
writing to registers, one lock for voting clocks that just do 
aggregation and one lock for these extremely slow clocks. Since each 
class of clocks are generally implemented in their own file, having one 
lock per class was just a matter of declaring a static-global lock 
inside the file and grabbing it before you do any transaction.

For example, there are some clocks that need to disable all the children 
before changing their rate. So, what happens if someone calls 
clk_enable() on the child when the parent is going thru a set rate 
process. Since both these will grab the same "fast clocks lock", we 
don't have any problems.

(Just read Colin's email)

As Colin said in his email, a global lock is less of an issue with the 
clk_prepare/unprepare() APIs now in place. But even among 
prepare/unprepare or enable/disable, some clocks might take much longer 
than others. For example, prepare for a clock might just need enabling a 
PLL, but for another clock it might need enabling a PLL and increasing 
some voltage. If the voltage control is going to go thru I2C, then it's 
going to be pretty bad for the other clock doing the prepare.

I think if we have the parent/child relationship captured in the generic 
framework, we might be able to get away with per clock locking if we 
always make sure we grab the locks in a top-down or bottom-up fashion. 
We could even throw in some flags if we know that a clock will have a 
stable parent (one that doesn't change rates or need to lock children) 
to reduce how deep we have to traverse the tree.

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

* [PATCH 01/10] Add a common struct clk
  2011-04-21 19:48   ` Thomas Gleixner
  2011-04-22  0:28     ` Richard Zhao
@ 2011-04-22  4:57     ` Saravana Kannan
  2011-04-22  9:13       ` Thomas Gleixner
  2011-04-29 10:09     ` Russell King - ARM Linux
  2 siblings, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-04-22  4:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/21/2011 12:48 PM, Thomas Gleixner wrote:
> On Fri, 15 Apr 2011, Sascha Hauer wrote:
>> From: Jeremy Kerr<jeremy.kerr@canonical.com>
>> + * @get:	Called by the core clock code when a device driver acquires a
>> + *		clock via clk_get(). Optional.
>> + *
>> + * @put:	Called by the core clock code when a devices driver releases a
>> + *		clock via clk_put(). Optional.
>
> These callbacks are completely pointless. There are only two non empty
> implementations in tree:
>
> One does a try_module_get(clk->owner), which should be done in generic
> code. The other does special clock enabling magic which wants to go to
> clk->prepare().

Aren't you kinda contradicting yourself? In the other thread you say 
that when we implement a generic framework, you will have to implement 
more than what a specific arch would need. This seems to be exactly one 
of those cases. What's wrong with it?

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 14:52                           ` Thomas Gleixner
@ 2011-04-22  7:09                             ` Tony Lindgren
  2011-04-22  8:22                               ` Thomas Gleixner
  0 siblings, 1 reply; 165+ messages in thread
From: Tony Lindgren @ 2011-04-22  7:09 UTC (permalink / raw)
  To: linux-arm-kernel

* Thomas Gleixner <tglx@linutronix.de> [110421 07:49]:
> On Thu, 21 Apr 2011, Tony Lindgren wrote:
> 
> > * Mark Brown <broonie@opensource.wolfsonmicro.com> [110421 03:29]:
> > > On Thu, Apr 21, 2011 at 11:12:36AM +0200, Thomas Gleixner wrote:
> > > > On Thu, 21 Apr 2011, Uwe Kleine-K?nig wrote:
> > > 
> > > > > If there were a pointer tracking the parent you still needed to program
> > > > > out the get_parent function anyhow to set the pointer initially. But I
> > > > > agree that in other situations having a pointer is more comfortable and
> > > > > saves ugly error handling e.g. in set_parent.
> > > 
> > > > That's nonsense. Why do you want a get_parent() function at all?
> > > > parent is set up when the clock is established in the clock tree. And
> > > > that's not done by some random driver. That's a property of the clock.
> > > 
> > > That's not universal - right now the drivers can and do know about this
> > > on some platforms.  In some cases there will be requirements beyond the
> > > clock rate which mean that the driver will need to be able to tell the
> > > framework that, for example, it needs one clock to be in the same clock
> > > domain as another.
> > 
> > Also there can be multiple parent clocks. An example are the timers on
> > omaps where the parent clock can be either the 32KiHz clock or external
> > source clock. ?his may need to be reprogrammed dynamically in some cases
> > for advanced idle modes as one of the parent clocks may be shut down.
> 
> If you need to propagate from bottom up, then you need a list of
> childs in struct clk. Right ?

Yes we need to be able to reprogram all children if the parent clock needs
to be reprogrammed for cpufreq/DVFS.

Also a child may need to change the parent clock like I wrote above.
However, it might be possible to deal with this by registering the same
child for both parents and handle that directly in the driver for the
special cases if that simplifies things.

In some clk_set_rate cases for a child the parent clock may need to be
reprogrammed to provide the desired rate. I don't know how common this
is, and this may be doable by requesting both parent and child in the
driver if that simplifies things.

Would be good to hear Paul's comments on this, as he probably knows best
what's really needed so I've added him to Cc.

Regards,

Tony

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-22  7:09                             ` Tony Lindgren
@ 2011-04-22  8:22                               ` Thomas Gleixner
  0 siblings, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-22  8:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 22 Apr 2011, Tony Lindgren wrote:
> * Thomas Gleixner <tglx@linutronix.de> [110421 07:49]:
> > On Thu, 21 Apr 2011, Tony Lindgren wrote:
> > > Also there can be multiple parent clocks. An example are the timers on
> > > omaps where the parent clock can be either the 32KiHz clock or external
> > > source clock. ?his may need to be reprogrammed dynamically in some cases
> > > for advanced idle modes as one of the parent clocks may be shut down.
> > 
> > If you need to propagate from bottom up, then you need a list of
> > childs in struct clk. Right ?
> 
> Yes we need to be able to reprogram all children if the parent clock needs
> to be reprogrammed for cpufreq/DVFS.

Bottom up propagation is not rocket science. :)

> Also a child may need to change the parent clock like I wrote above.
> However, it might be possible to deal with this by registering the same
> child for both parents and handle that directly in the driver for the
> special cases if that simplifies things.
> 
> In some clk_set_rate cases for a child the parent clock may need to be
> reprogrammed to provide the desired rate. I don't know how common this
> is, and this may be doable by requesting both parent and child in the
> driver if that simplifies things.

I don't think so. That should be done in a library function which
traverses the tree an validates whether this can be done or
not. Though that's an orthogonal problem and not necessary for the
primary set of functionality as long as we have the proper bottom up
propagation and validation mechanisms in place.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-22  4:54                           ` Saravana Kannan
@ 2011-04-22  9:06                             ` Thomas Gleixner
  0 siblings, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-22  9:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 21 Apr 2011, Saravana Kannan wrote:
> On 04/21/2011 08:38 AM, Thomas Gleixner wrote:
> > I seriously doubt that the fine grained per clock locking is going to
> > work out at all.
> 
> One thing we did to handle the locking issue was to have a lock per "class" of
> clocks. For example, we had one lock for clocks controlled by writing to
> registers, one lock for voting clocks that just do aggregation and one lock
> for these extremely slow clocks. Since each class of clocks are generally
> implemented in their own file, having one lock per class was just a matter of
> declaring a static-global lock inside the file and grabbing it before you do
> any transaction.

So you are talking about clock trees which are completely independent
of each other where you can never have any relationship between them?
 
> As Colin said in his email, a global lock is less of an issue with the
> clk_prepare/unprepare() APIs now in place. But even among prepare/unprepare or
> enable/disable, some clocks might take much longer than others. For example,
> prepare for a clock might just need enabling a PLL, but for another clock it
> might need enabling a PLL and increasing some voltage. If the voltage control
> is going to go thru I2C, then it's going to be pretty bad for the other clock
> doing the prepare.

Right, but that's pretty unavoidable if you need to do proper
propagation. And really we need to be able to traverse the tree in
both directions.

> I think if we have the parent/child relationship captured in the generic
> framework, we might be able to get away with per clock locking if we always
> make sure we grab the locks in a top-down or bottom-up fashion. We could even

You _CANNOT_ make sure that you traverse only in one direction and with
clocks which can be associated to different parents its going to be
even worse as you can create arbitrary lock orders that way.

> throw in some flags if we know that a clock will have a stable parent (one
> that doesn't change rates or need to lock children) to reduce how deep we have
> to traverse the tree.

Yes, we can be clever about how deep we traverse, but that's an
optimization and not a design decision. But we won't go to a point,
where we make locking conditional on a flag. That's broken by
definition.

We can add support for completely independent clock trees and make the
"global" locking per tree, but that's as far as it will go. Everything
else will result in a total nightmare. See the locking horror in
kernel/rtmutex.c:rt_mutex_adjust_prio_chain(). We'd end up with a way
worse mess for protecting eg. parent changes or complex rate
propagations.

We still have a mutex and a spinlock and either of them guarentees
that the parent child relation ship is not changing during a
traversal. So the fast path operations enable/disable require only the
spinlock and everything else (parent changes and rate settings) need
to be protected by the mutex simply because we can't do that with
spinlocks held and interrupts disabled.

Thanks,

	tglx

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

* [PATCH 01/10] Add a common struct clk
  2011-04-22  4:57     ` Saravana Kannan
@ 2011-04-22  9:13       ` Thomas Gleixner
  0 siblings, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-22  9:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 21 Apr 2011, Saravana Kannan wrote:

> On 04/21/2011 12:48 PM, Thomas Gleixner wrote:
> > On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > > From: Jeremy Kerr<jeremy.kerr@canonical.com>
> > > + * @get:	Called by the core clock code when a device driver acquires a
> > > + *		clock via clk_get(). Optional.
> > > + *
> > > + * @put:	Called by the core clock code when a devices driver releases a
> > > + *		clock via clk_put(). Optional.
> > 
> > These callbacks are completely pointless. There are only two non empty
> > implementations in tree:
> > 
> > One does a try_module_get(clk->owner), which should be done in generic
> > code. The other does special clock enabling magic which wants to go to
> > clk->prepare().
> 
> Aren't you kinda contradicting yourself? In the other thread you say that when
> we implement a generic framework, you will have to implement more than what a
> specific arch would need. This seems to be exactly one of those cases. What's
> wrong with it?

Errm, that's why the try_module_get() goes into generic code. Simply
because we can have loadable clock modules and we want proper module
refcounts on them.

The clock enabling magic in mach-u300/ is setting up some registers,
which can be done in the clk->prepare() callback as well. So there is
no point for having an extra step and an extra indirection.

So how am I contradicting myself? By moving useful stuff to the core
and moving hardware specific code to a different callback where it
actually belongs?

And yes a framework will always have more functionality than most
users need, but that's not an excuse to implement arbitrary and
pointless crap.

Thanks,

	tglx

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

* [PATCH 01/10] Add a common struct clk
  2011-04-22  0:28     ` Richard Zhao
@ 2011-04-22  9:23       ` Thomas Gleixner
  2011-04-23 14:08         ` Richard Zhao
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-22  9:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 22 Apr 2011, Richard Zhao wrote:
> Hi Thomas,
> 
> On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> > On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > > + * @get:	Called by the core clock code when a device driver acquires a
> > > + *		clock via clk_get(). Optional.
> > > + *
> > > + * @put:	Called by the core clock code when a devices driver releases a
> > > + *		clock via clk_put(). Optional.
> > 
> > These callbacks are completely pointless. There are only two non empty
> > implementations in tree:
> > 
> > One does a try_module_get(clk->owner), which should be done in generic
> > code. The other does special clock enabling magic which wants to go to
> > clk->prepare().
> You forget mach-u300 __clk_get. It updates some registers.
> The ops get/put let arch clock driver have a chance to do special things at the
> time when a user begins to use the clock.

No I did not forget. It's exactly the code which wants to go into
clk->prepare. Which you have to call _before_ doing anything with the
clock, so there is no need for an extra callback.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-22  0:23                           ` Colin Cross
@ 2011-04-22  9:51                             ` Thomas Gleixner
  2011-04-22 16:14                               ` Thomas Gleixner
  2011-04-22 16:39                               ` Colin Cross
  0 siblings, 2 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-22  9:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 21 Apr 2011, Colin Cross wrote:
> On Thu, Apr 21, 2011 at 8:38 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> > There is no way around that. Everything else is going to be the
> > locking hell and racy all over the place.
> 
> Per clock locks are useful if you have some very slow clocks and some
> very fast clocks.  PLLs may take 20 ms to lock, and preventing any
> other call to clk_prepare for that long could be problematic.  The
> problem was worse before the clk_enable/clk_prepare split, maybe it's
> not necessary at all any more.
> 
> For Tegra, I solved my clock locking problems by (almost) always
> locking from child to parent, the normal case for
> clk_enable/clk_prepare. In general, you only need to lock parent and
> then child if you store the rate of the child in the child's clk
> struct and need to update it when the parent changes, or when
> traversing the tree for debugging output.  I solved the first problem
> by storing the relation between the child and the parent in the child
> struct and locking from child to parent on clk_get_rate calls to
> calculate the rate, and the second by using a trylock loop over the
> list of clocks (see arch/arm/mach-tegra/clock.c).

Yes, and that's exaclty what we don't want to have. You still need a
global lock for doing the full tree acquisition and the only advantage
which is left is that you can do parallel prepare/unprepare and
everything else (parent settings, rate propagations) will need to do
the locking dance.

And the bad thing about your approach is that it requires a full tree
lock acquisition all the time, while the real operation might be just
affecting 3 clocks out of 50. To avoid that you'd need to do the
trylock dance over the child list.

I doubt it's worth the trouble, really.

> Now that clk_prepare and clk_enable are split, the long-held locks
> (for plls, maybe dvfs?) are separated from the short-held locks for
> clk_enable/clk_disable, and the cost of global serialization is much
> more acceptable.

Right. And that's how we start. Simple. If it turns out to be a real
issue, then we can revisit the fine grained locking approach, but I
really want to avoid it as far as possible.

Another thing I'm pondering is to provide the ability to maintain
separate clk trees. So you can have individual domains which have
their per clk tree locking. Would that make sense ?

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-22  9:51                             ` Thomas Gleixner
@ 2011-04-22 16:14                               ` Thomas Gleixner
  2011-04-22 16:39                               ` Colin Cross
  1 sibling, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-22 16:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 22 Apr 2011, Thomas Gleixner wrote:
> On Thu, 21 Apr 2011, Colin Cross wrote:
> 
> Yes, and that's exaclty what we don't want to have. You still need a
> global lock for doing the full tree acquisition and the only advantage
> which is left is that you can do parallel prepare/unprepare and
> everything else (parent settings, rate propagations) will need to do
> the locking dance.

And worse with the prepare/unprepare separation you need to do the
lock dance twice in some cases. Once for the mutex and once for the
spinlock. Not really a intriguing idea.

Thanks,

	tglx

 

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-22  9:51                             ` Thomas Gleixner
  2011-04-22 16:14                               ` Thomas Gleixner
@ 2011-04-22 16:39                               ` Colin Cross
  2011-04-22 16:57                                 ` Thomas Gleixner
  1 sibling, 1 reply; 165+ messages in thread
From: Colin Cross @ 2011-04-22 16:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 22, 2011 at 2:51 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> Another thing I'm pondering is to provide the ability to maintain
> separate clk trees. So you can have individual domains which have
> their per clk tree locking. Would that make sense ?

Clock trees are likely to be linked somewhere - an external clock chip
that drives the main clock input on the SoC, or an SoC clock output
that drives a chip with an internal clock tree.  Domains would have to
be dynamically managed to ensure two clocks from different clock chips
that become linked are moved under the same clock lock.  Probably
easier to keep a global lock.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-22 16:39                               ` Colin Cross
@ 2011-04-22 16:57                                 ` Thomas Gleixner
  2011-04-22 22:26                                   ` Saravana Kannan
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-22 16:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 22 Apr 2011, Colin Cross wrote:

> On Fri, Apr 22, 2011 at 2:51 AM, Thomas Gleixner <tglx@linutronix.de> wrote:
> > Another thing I'm pondering is to provide the ability to maintain
> > separate clk trees. So you can have individual domains which have
> > their per clk tree locking. Would that make sense ?
> 
> Clock trees are likely to be linked somewhere - an external clock chip
> that drives the main clock input on the SoC, or an SoC clock output
> that drives a chip with an internal clock tree.  Domains would have to
> be dynamically managed to ensure two clocks from different clock chips
> that become linked are moved under the same clock lock.  Probably
> easier to keep a global lock.

Ok. It's easy enough to split later if the need arises.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-22 16:57                                 ` Thomas Gleixner
@ 2011-04-22 22:26                                   ` Saravana Kannan
  2011-04-22 22:55                                     ` Thomas Gleixner
  0 siblings, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-04-22 22:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/22/2011 09:57 AM, Thomas Gleixner wrote:
> On Fri, 22 Apr 2011, Colin Cross wrote:
>
>> On Fri, Apr 22, 2011 at 2:51 AM, Thomas Gleixner<tglx@linutronix.de>  wrote:
>>> Another thing I'm pondering is to provide the ability to maintain
>>> separate clk trees. So you can have individual domains which have
>>> their per clk tree locking. Would that make sense ?
>>
>> Clock trees are likely to be linked somewhere - an external clock chip
>> that drives the main clock input on the SoC, or an SoC clock output
>> that drives a chip with an internal clock tree.  Domains would have to
>> be dynamically managed to ensure two clocks from different clock chips
>> that become linked are moved under the same clock lock.  Probably
>> easier to keep a global lock.
>
> Ok. It's easy enough to split later if the need arises.

MSM certainly has the need for having independent clock trees. I would 
like support for this to be in from the start otherwise it's going to 
really screw clocks in one of the trees.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-22 22:26                                   ` Saravana Kannan
@ 2011-04-22 22:55                                     ` Thomas Gleixner
  2011-04-23  0:48                                       ` Saravana Kannan
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-22 22:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 22 Apr 2011, Saravana Kannan wrote:

> On 04/22/2011 09:57 AM, Thomas Gleixner wrote:
> > On Fri, 22 Apr 2011, Colin Cross wrote:
> > 
> > > On Fri, Apr 22, 2011 at 2:51 AM, Thomas Gleixner<tglx@linutronix.de>
> > > wrote:
> > > > Another thing I'm pondering is to provide the ability to maintain
> > > > separate clk trees. So you can have individual domains which have
> > > > their per clk tree locking. Would that make sense ?
> > > 
> > > Clock trees are likely to be linked somewhere - an external clock chip
> > > that drives the main clock input on the SoC, or an SoC clock output
> > > that drives a chip with an internal clock tree.  Domains would have to
> > > be dynamically managed to ensure two clocks from different clock chips
> > > that become linked are moved under the same clock lock.  Probably
> > > easier to keep a global lock.
> > 
> > Ok. It's easy enough to split later if the need arises.
> 
> MSM certainly has the need for having independent clock trees. I would like
> support for this to be in from the start otherwise it's going to really screw
> clocks in one of the trees.

Are they completely independent or do you need a global
synchronization mechanism between those clock trees as well ?

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-22 22:55                                     ` Thomas Gleixner
@ 2011-04-23  0:48                                       ` Saravana Kannan
  2011-04-23 23:34                                         ` Benjamin Herrenschmidt
  0 siblings, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-04-23  0:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/22/2011 03:55 PM, Thomas Gleixner wrote:
> On Fri, 22 Apr 2011, Saravana Kannan wrote:
>
>> On 04/22/2011 09:57 AM, Thomas Gleixner wrote:
>>> On Fri, 22 Apr 2011, Colin Cross wrote:
>>>
>>>> On Fri, Apr 22, 2011 at 2:51 AM, Thomas Gleixner<tglx@linutronix.de>
>>>> wrote:
>>>>> Another thing I'm pondering is to provide the ability to maintain
>>>>> separate clk trees. So you can have individual domains which have
>>>>> their per clk tree locking. Would that make sense ?
>>>>
>>>> Clock trees are likely to be linked somewhere - an external clock chip
>>>> that drives the main clock input on the SoC, or an SoC clock output
>>>> that drives a chip with an internal clock tree.  Domains would have to
>>>> be dynamically managed to ensure two clocks from different clock chips
>>>> that become linked are moved under the same clock lock.  Probably
>>>> easier to keep a global lock.
>>>
>>> Ok. It's easy enough to split later if the need arises.
>>
>> MSM certainly has the need for having independent clock trees. I would like
>> support for this to be in from the start otherwise it's going to really screw
>> clocks in one of the trees.
>
> Are they completely independent or do you need a global
> synchronization mechanism between those clock trees as well ?
>
> Thanks,
>
> 	tglx

They are completely independent. No synchronization is needed between 
these clock trees. It's basically a bunch of clocks controlled by 
another processor that has it's own set of PLLs, etc.

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

* [PATCH 01/10] Add a common struct clk
  2011-04-22  9:23       ` Thomas Gleixner
@ 2011-04-23 14:08         ` Richard Zhao
  2011-04-23 15:30           ` Thomas Gleixner
  0 siblings, 1 reply; 165+ messages in thread
From: Richard Zhao @ 2011-04-23 14:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 22, 2011 at 11:23:49AM +0200, Thomas Gleixner wrote:
> On Fri, 22 Apr 2011, Richard Zhao wrote:
> > Hi Thomas,
> > 
> > On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> > > On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > > > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > > > + * @get:	Called by the core clock code when a device driver acquires a
> > > > + *		clock via clk_get(). Optional.
> > > > + *
> > > > + * @put:	Called by the core clock code when a devices driver releases a
> > > > + *		clock via clk_put(). Optional.
> > > 
> > > These callbacks are completely pointless. There are only two non empty
> > > implementations in tree:
> > > 
> > > One does a try_module_get(clk->owner), which should be done in generic
> > > code. The other does special clock enabling magic which wants to go to
> > > clk->prepare().
> > You forget mach-u300 __clk_get. It updates some registers.
> > The ops get/put let arch clock driver have a chance to do special things at the
> > time when a user begins to use the clock.
> 
> No I did not forget. It's exactly the code which wants to go into
> clk->prepare. Which you have to call _before_ doing anything with the
> clock, so there is no need for an extra callback.
No. clk_prepare only have to be called before clk_enable, but not have to for
other operations, set_rate/set_parent etc.

Thanks
Richard
> 
> Thanks,
> 
> 	tglx

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

* [PATCH 01/10] Add a common struct clk
  2011-04-23 14:08         ` Richard Zhao
@ 2011-04-23 15:30           ` Thomas Gleixner
  2011-04-24  2:54             ` Richard Zhao
  2011-04-24  7:20             ` Linus Walleij
  0 siblings, 2 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-23 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 23 Apr 2011, Richard Zhao wrote:
> On Fri, Apr 22, 2011 at 11:23:49AM +0200, Thomas Gleixner wrote:
> > On Fri, 22 Apr 2011, Richard Zhao wrote:
> > > Hi Thomas,
> > > 
> > > On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> > > > On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > > > > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > > > > + * @get:	Called by the core clock code when a device driver acquires a
> > > > > + *		clock via clk_get(). Optional.
> > > > > + *
> > > > > + * @put:	Called by the core clock code when a devices driver releases a
> > > > > + *		clock via clk_put(). Optional.
> > > > 
> > > > These callbacks are completely pointless. There are only two non empty
> > > > implementations in tree:
> > > > 
> > > > One does a try_module_get(clk->owner), which should be done in generic
> > > > code. The other does special clock enabling magic which wants to go to
> > > > clk->prepare().
> > > You forget mach-u300 __clk_get. It updates some registers.
> > > The ops get/put let arch clock driver have a chance to do special things at the
> > > time when a user begins to use the clock.
> > 
> > No I did not forget. It's exactly the code which wants to go into
> > clk->prepare. Which you have to call _before_ doing anything with the
> > clock, so there is no need for an extra callback.
> No. clk_prepare only have to be called before clk_enable, but not have to for
> other operations, set_rate/set_parent etc.

And why do you need those registers set before you actually
prepare/enable the clock? Just to set the rate register? You can store
that information and set it on prepare. Before prepare/enable the
value of the rate register is totally irrelevant.

The point of anything whats named get and put in the kernel is to
obtain or drop a reference to an object.

Putting arbitrary initialization into such functions is a really bad
hack.

And looking at that u300 code, it's borken:

    user1: clk_get("MCLK");
    	   clk_set_rate(.....);

    user2: clk_get("MCLK");

The second clk_get() call will overwrite what ?

The fact that you decided to put that into the absolutely wrong
function is not an argument for keeping those callbacks.

The only real usecase for __clk_get() is the
try_module_get()/module_put() code which will become part of the
generic code. It does exaclty what get and put are meant for: dealing
with refcounts.

Thanks,

	tglx

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

* Re: [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 10:33                       ` Thomas Gleixner
  (?)
@ 2011-04-23 23:26                         ` Benjamin Herrenschmidt
  -1 siblings, 0 replies; 165+ messages in thread
From: Benjamin Herrenschmidt @ 2011-04-23 23:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-04-21 at 12:33 +0200, Thomas Gleixner wrote:
> 
> Depends, there is a lot of sane hardware out there (not necessarily in
> the ARM SoC world). We can do with a pointer if the need arises.
>  
> > >     optionally a set of common register accessor functions like I did
> > >     for the generic irq chip.
> > 
> > Again, I don't see the point in having this in the common code. May be I'm
> > missing something?
> 
> See my RFC patch of a generic irq chip implementation and how much
> duplicated five line inline functions they removed.
>  
> > IMO, a better option instead of the base register and the offsets would be an
> > option to have a priv_data pointer. I forgot the exact use case, but we
> > thought that would have been helpful when we tried to port the msm clock
> > driver in our tree on top of Jeremy's patches.
> 
> It works either way, but we should try to comeup with a sensible
> common base struct for sane hardware. 

Doesn't have to be in the base struct tho. I think a better approach is
to keep the base struct reasonably API-only, and have an
"implementation" subclass called something like simple_clk for example,
that carries those few fields common to most MMIO based implementation
and which can be created with existing "helper" code for the most common
ones.

Ben.



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

* Re: [PATCH RFC] clk: add support for automatic parent handling
@ 2011-04-23 23:26                         ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 165+ messages in thread
From: Benjamin Herrenschmidt @ 2011-04-23 23:26 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Saravana Kannan, Paul McKenney, Uwe Kleine-König,
	linux-arm-kernel, Sascha Hauer, Stephen Boyd, Jeremy Kerr,
	kernel, linux-kernel, Ben Dooks, Linus Torvalds, Arnd Bergmann,
	Paul Mundt, linux-sh

On Thu, 2011-04-21 at 12:33 +0200, Thomas Gleixner wrote:
> 
> Depends, there is a lot of sane hardware out there (not necessarily in
> the ARM SoC world). We can do with a pointer if the need arises.
>  
> > >     optionally a set of common register accessor functions like I did
> > >     for the generic irq chip.
> > 
> > Again, I don't see the point in having this in the common code. May be I'm
> > missing something?
> 
> See my RFC patch of a generic irq chip implementation and how much
> duplicated five line inline functions they removed.
>  
> > IMO, a better option instead of the base register and the offsets would be an
> > option to have a priv_data pointer. I forgot the exact use case, but we
> > thought that would have been helpful when we tried to port the msm clock
> > driver in our tree on top of Jeremy's patches.
> 
> It works either way, but we should try to comeup with a sensible
> common base struct for sane hardware. 

Doesn't have to be in the base struct tho. I think a better approach is
to keep the base struct reasonably API-only, and have an
"implementation" subclass called something like simple_clk for example,
that carries those few fields common to most MMIO based implementation
and which can be created with existing "helper" code for the most common
ones.

Ben.



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

* [PATCH RFC] clk: add support for automatic parent handling
@ 2011-04-23 23:26                         ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 165+ messages in thread
From: Benjamin Herrenschmidt @ 2011-04-23 23:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2011-04-21 at 12:33 +0200, Thomas Gleixner wrote:
> 
> Depends, there is a lot of sane hardware out there (not necessarily in
> the ARM SoC world). We can do with a pointer if the need arises.
>  
> > >     optionally a set of common register accessor functions like I did
> > >     for the generic irq chip.
> > 
> > Again, I don't see the point in having this in the common code. May be I'm
> > missing something?
> 
> See my RFC patch of a generic irq chip implementation and how much
> duplicated five line inline functions they removed.
>  
> > IMO, a better option instead of the base register and the offsets would be an
> > option to have a priv_data pointer. I forgot the exact use case, but we
> > thought that would have been helpful when we tried to port the msm clock
> > driver in our tree on top of Jeremy's patches.
> 
> It works either way, but we should try to comeup with a sensible
> common base struct for sane hardware. 

Doesn't have to be in the base struct tho. I think a better approach is
to keep the base struct reasonably API-only, and have an
"implementation" subclass called something like simple_clk for example,
that carries those few fields common to most MMIO based implementation
and which can be created with existing "helper" code for the most common
ones.

Ben.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-23  0:48                                       ` Saravana Kannan
@ 2011-04-23 23:34                                         ` Benjamin Herrenschmidt
  0 siblings, 0 replies; 165+ messages in thread
From: Benjamin Herrenschmidt @ 2011-04-23 23:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2011-04-22 at 17:48 -0700, Saravana Kannan wrote:
> 
> They are completely independent. No synchronization is needed between 
> these clock trees. It's basically a bunch of clocks controlled by 
> another processor that has it's own set of PLLs, etc. 

In fact the common struct clk work that Jeremy picked up from initial
patches I did for powerpc was intended for just that ... ie by moving
the implementation out to have the clock "provider" being the one
creating the clock objects.

There's many other similar cases, ie, you can have a multifunction
device (wifi + bt + mmc reader for example) which has its own internal
clock network and might want to use struct clk to handle clocks between
those parts.

None of that should sit in the arch or platform code.

In fact, with the device-tree, you could completely represent the
binding between those objects without involving any platform code, that
was the original intend and I hope that ARM eventually gets there.

Cheers,
Ben.

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

* [PATCH 01/10] Add a common struct clk
  2011-04-23 15:30           ` Thomas Gleixner
@ 2011-04-24  2:54             ` Richard Zhao
  2011-04-24  7:20             ` Linus Walleij
  1 sibling, 0 replies; 165+ messages in thread
From: Richard Zhao @ 2011-04-24  2:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Apr 23, 2011 at 05:30:37PM +0200, Thomas Gleixner wrote:
> On Sat, 23 Apr 2011, Richard Zhao wrote:
> > On Fri, Apr 22, 2011 at 11:23:49AM +0200, Thomas Gleixner wrote:
> > > On Fri, 22 Apr 2011, Richard Zhao wrote:
> > > > Hi Thomas,
> > > > 
> > > > On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> > > > > On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > > > > > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > > > > > + * @get:	Called by the core clock code when a device driver acquires a
> > > > > > + *		clock via clk_get(). Optional.
> > > > > > + *
> > > > > > + * @put:	Called by the core clock code when a devices driver releases a
> > > > > > + *		clock via clk_put(). Optional.
> > > > > 
> > > > > These callbacks are completely pointless. There are only two non empty
> > > > > implementations in tree:
> > > > > 
> > > > > One does a try_module_get(clk->owner), which should be done in generic
> > > > > code. The other does special clock enabling magic which wants to go to
> > > > > clk->prepare().
> > > > You forget mach-u300 __clk_get. It updates some registers.
> > > > The ops get/put let arch clock driver have a chance to do special things at the
> > > > time when a user begins to use the clock.
> > > 
> > > No I did not forget. It's exactly the code which wants to go into
> > > clk->prepare. Which you have to call _before_ doing anything with the
> > > clock, so there is no need for an extra callback.
> > No. clk_prepare only have to be called before clk_enable, but not have to for
> > other operations, set_rate/set_parent etc.
> 
> And why do you need those registers set before you actually
> prepare/enable the clock? Just to set the rate register? You can store
> that information and set it on prepare. Before prepare/enable the
> value of the rate register is totally irrelevant.
Generally, the divider and enable registers can be set seperately.
> 
> The point of anything whats named get and put in the kernel is to
> obtain or drop a reference to an object.
> 
> Putting arbitrary initialization into such functions is a really bad
> hack.
> 
> And looking at that u300 code, it's borken:
> 
>     user1: clk_get("MCLK");
>     	   clk_set_rate(.....);
> 
>     user2: clk_get("MCLK");
> 
> The second clk_get() call will overwrite what ?
> 
> The fact that you decided to put that into the absolutely wrong
> function is not an argument for keeping those callbacks.
Better ask u300 maintainer whether the _clk_get/put stuff may be moved to other
functions. If yes, I agree to remove get/put from ops.
> 
> The only real usecase for __clk_get() is the
> try_module_get()/module_put() code which will become part of the
> generic code. It does exaclty what get and put are meant for: dealing
> with refcounts.
It might be usefull for loadable clock module. But do we already have such use
case? Even clock module is loadable, it'll never unloaded unless clock hw module
support hot plug.

Thanks
Richard
> 
> Thanks,
> 
> 	tglx

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

* [PATCH 01/10] Add a common struct clk
  2011-04-23 15:30           ` Thomas Gleixner
  2011-04-24  2:54             ` Richard Zhao
@ 2011-04-24  7:20             ` Linus Walleij
  2011-04-24  9:55               ` Richard Zhao
  1 sibling, 1 reply; 165+ messages in thread
From: Linus Walleij @ 2011-04-24  7:20 UTC (permalink / raw)
  To: linux-arm-kernel

2011/4/23 Thomas Gleixner <tglx@linutronix.de>:
> On Sat, 23 Apr 2011, Richard Zhao wrote:
>> On Fri, Apr 22, 2011 at 11:23:49AM +0200, Thomas Gleixner wrote:
>> > On Fri, 22 Apr 2011, Richard Zhao wrote:
>> > > > One does a try_module_get(clk->owner), which should be done in generic
>> > > > code. The other does special clock enabling magic which wants to go to
>> > > > clk->prepare().
>> > > >
>> > > You forget mach-u300 __clk_get. It updates some registers.
>> > > The ops get/put let arch clock driver have a chance to do special things at the
>> > > time when a user begins to use the clock.
>> >
>> > No I did not forget. It's exactly the code which wants to go into
>> > clk->prepare. Which you have to call _before_ doing anything with the
>> > clock, so there is no need for an extra callback.
>>
>> No. clk_prepare only have to be called before clk_enable, but not have to for
>> other operations, set_rate/set_parent etc.
>
> And why do you need those registers set before you actually
> prepare/enable the clock? Just to set the rate register? You can store
> that information and set it on prepare. Before prepare/enable the
> value of the rate register is totally irrelevant.
>
> The point of anything whats named get and put in the kernel is to
> obtain or drop a reference to an object.
>
> Putting arbitrary initialization into such functions is a really bad
> hack.
>
> And looking at that u300 code, it's borken:
>
> ? ?user1: clk_get("MCLK");
> ? ? ? ? ? clk_set_rate(.....);
>
> ? ?user2: clk_get("MCLK");
>
> The second clk_get() call will overwrite what ?

Heh yeah that is the case, and this code can just as well live in the
->prepare() function.

The clock that goes to "MCLK" and "MSPRO" is utilizing a common
clock divider, which sounds backwards, but in practice this is because
it's and MMC or Memory Stick Pro block clock, and you cannot pinmux
in both in the ASIC, they are connected to the same pins and either
function need its own support electronics. So naturally only one of
them is ever active at the same time.

This should be *properly* reflected by creating the pin/padmux
framework and have the clock prepare() call hook back into that,
so that when you try to activate say "mclk" you need to mux in these
pins and if the mspro is muxed in at that time you return -ENODEV
and the clock code bails out.

We should just move it to prepare() and I'll fix it up if need be.

Linus Walleij

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-20 14:07           ` [PATCH RFC] clk: add support for automatic parent handling Uwe Kleine-König
  2011-04-20 16:16             ` Thomas Gleixner
@ 2011-04-24  9:45             ` Richard Zhao
  2011-04-24 20:14               ` Uwe Kleine-König
  1 sibling, 1 reply; 165+ messages in thread
From: Richard Zhao @ 2011-04-24  9:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,
On Wed, Apr 20, 2011 at 04:07:37PM +0200, Uwe Kleine-K?nig wrote:
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> ---
> Hello,
> 
> only compile tested so far.
> 
> Best regards
> Uwe
> 
>  drivers/clk/clk.c   |   43 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h |    8 ++++++++
>  2 files changed, 51 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 264c809..7627815 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -14,10 +14,23 @@
>  int clk_prepare(struct clk *clk)
>  {
>  	int ret = 0;
> +	struct clk *parent = ERR_PTR(-ENOSYS);
>  
>  	if (!clk)
>  		return 0;
>  
> +	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
> +		parent = clk_get_parent(clk);
> +
> +		if (!IS_ERR(parent)) {
> +			ret = clk_prepare(parent);
> +			if (ret)
> +				return ret;
> +		} else if (PTR_ERR(parent) != -ENOSYS)
> +			/* -ENOSYS means no parent and is OK */
> +			return PTR_ERR(parent);
> +	}
Is this supposed to be in prepare_lock? If prepare_count > 1, we need do nothing.
Other parent operations need to be in lock protect too.

Thanks
Richard
> +
>  	mutex_lock(&clk->prepare_lock);
>  	if (clk->prepare_count == 0 && clk->ops->prepare)
>  		ret = clk->ops->prepare(clk);
> @@ -26,6 +39,9 @@ int clk_prepare(struct clk *clk)
>  		clk->prepare_count++;
>  	mutex_unlock(&clk->prepare_lock);
>  
> +	if (ret && !IS_ERR(parent))
> +		clk_unprepare(parent);
> +
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(clk_prepare);
> @@ -45,6 +61,12 @@ void clk_unprepare(struct clk *clk)
>  	}
>  
>  	mutex_unlock(&clk->prepare_lock);
> +
> +	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
> +		struct clk *parent = clk_get_parent(clk);
> +		if (!IS_ERR(parent))
> +			clk_unprepare(parent);
> +	}
>  }
>  EXPORT_SYMBOL_GPL(clk_unprepare);
>  
> @@ -52,10 +74,22 @@ int clk_enable(struct clk *clk)
>  {
>  	unsigned long flags;
>  	int ret = 0;
> +	struct clk *parent = ERR_PTR(-ENOSYS);
>  
>  	if (!clk)
>  		return 0;
>  
> +	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
> +		parent = clk_get_parent(clk);
> +		if (!IS_ERR(parent)) {
> +			ret = clk_enable(parent);
> +			if (ret)
> +				return ret;
> +		} else if (PTR_ERR(parent) != -ENOSYS)
> +			/* -ENOSYS means no parent and is OK */
> +			return PTR_ERR(parent);
> +	}
> +
>  	WARN_ON(clk->prepare_count == 0);
>  
>  	spin_lock_irqsave(&clk->enable_lock, flags);
> @@ -66,6 +100,9 @@ int clk_enable(struct clk *clk)
>  		clk->enable_count++;
>  	spin_unlock_irqrestore(&clk->enable_lock, flags);
>  
> +	if (ret && !IS_ERR(parent))
> +		clk_disable(parent);
> +
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(clk_enable);
> @@ -85,6 +122,12 @@ void clk_disable(struct clk *clk)
>  		clk->ops->disable(clk);
>  
>  	spin_unlock_irqrestore(&clk->enable_lock, flags);
> +
> +	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
> +		struct clk *parent = clk_get_parent(clk);
> +		if (!IS_ERR(parent))
> +			clk_disable(parent);
> +	}
>  }
>  EXPORT_SYMBOL_GPL(clk_disable);
>  
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index d2f0db0..125e525 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -62,6 +62,11 @@ struct clk {
>  	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
>  }
>  
> +/* bit definitions for struct clk_ops.flags */
> +#define CLK_OPS_GENERIC_PARENT	1	/* automatically handle parent in
> +					   enable, disable, prepare and
> +					   unprepare functions */
> +
>  /**
>   * struct clk_ops -  Callback operations for clocks; these are to be provided
>   * by the clock implementation, and will be called by drivers through the clk_*
> @@ -91,6 +96,8 @@ struct clk {
>   * @put:	Called by the core clock code when a devices driver releases a
>   *		clock via clk_put(). Optional.
>   *
> + * @flags:	see above for possible values.
> + *
>   * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
>   * implementations to split any work between atomic (enable) and sleepable
>   * (prepare) contexts.  If a clock requires sleeping code to be turned on, this
> @@ -119,6 +126,7 @@ struct clk_ops {
>  	int		(*set_rate)(struct clk *, unsigned long);
>  	int		(*set_parent)(struct clk *, struct clk *);
>  	struct clk *	(*get_parent)(struct clk *);
> +	unsigned int	flags;
>  };
>  
>  /**
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 01/10] Add a common struct clk
  2011-04-24  7:20             ` Linus Walleij
@ 2011-04-24  9:55               ` Richard Zhao
  0 siblings, 0 replies; 165+ messages in thread
From: Richard Zhao @ 2011-04-24  9:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Apr 24, 2011 at 09:20:30AM +0200, Linus Walleij wrote:
> 2011/4/23 Thomas Gleixner <tglx@linutronix.de>:
> > On Sat, 23 Apr 2011, Richard Zhao wrote:
> >> On Fri, Apr 22, 2011 at 11:23:49AM +0200, Thomas Gleixner wrote:
> >> > On Fri, 22 Apr 2011, Richard Zhao wrote:
> >> > > > One does a try_module_get(clk->owner), which should be done in generic
> >> > > > code. The other does special clock enabling magic which wants to go to
> >> > > > clk->prepare().
> >> > > >
> >> > > You forget mach-u300 __clk_get. It updates some registers.
> >> > > The ops get/put let arch clock driver have a chance to do special things at the
> >> > > time when a user begins to use the clock.
> >> >
> >> > No I did not forget. It's exactly the code which wants to go into
> >> > clk->prepare. Which you have to call _before_ doing anything with the
> >> > clock, so there is no need for an extra callback.
> >>
> >> No. clk_prepare only have to be called before clk_enable, but not have to for
> >> other operations, set_rate/set_parent etc.
> >
> > And why do you need those registers set before you actually
> > prepare/enable the clock? Just to set the rate register? You can store
> > that information and set it on prepare. Before prepare/enable the
> > value of the rate register is totally irrelevant.
> >
> > The point of anything whats named get and put in the kernel is to
> > obtain or drop a reference to an object.
> >
> > Putting arbitrary initialization into such functions is a really bad
> > hack.
> >
> > And looking at that u300 code, it's borken:
> >
> > ? ?user1: clk_get("MCLK");
> > ? ? ? ? ? clk_set_rate(.....);
> >
> > ? ?user2: clk_get("MCLK");
> >
> > The second clk_get() call will overwrite what ?
> 
> Heh yeah that is the case, and this code can just as well live in the
> ->prepare() function.
> 
> The clock that goes to "MCLK" and "MSPRO" is utilizing a common
> clock divider, which sounds backwards, but in practice this is because
> it's and MMC or Memory Stick Pro block clock, and you cannot pinmux
> in both in the ASIC, they are connected to the same pins and either
> function need its own support electronics. So naturally only one of
> them is ever active at the same time.
> 
> This should be *properly* reflected by creating the pin/padmux
> framework and have the clock prepare() call hook back into that,
> so that when you try to activate say "mclk" you need to mux in these
> pins and if the mspro is muxed in at that time you return -ENODEV
> and the clock code bails out.
> 
> We should just move it to prepare() and I'll fix it up if need be.
Great, so we don't need __clk_get/put. The only purpose of clk_get is
to return pointer of clk.

Thanks
Richard
> 
> Linus Walleij

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-15 19:08 ` [PATCH 05/10] clk: Add support for simple dividers Sascha Hauer
  2011-04-18  9:49   ` Uwe Kleine-König
  2011-04-18 22:40   ` Stephen Boyd
@ 2011-04-24 13:48   ` Richard Zhao
  2011-04-25 18:51     ` Sascha Hauer
  2 siblings, 1 reply; 165+ messages in thread
From: Richard Zhao @ 2011-04-24 13:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 15, 2011 at 09:08:10PM +0200, Sascha Hauer wrote:
> This patch adds support for the most common type of divider,
> which expects a register, width and shift values to desacribe
> the location of the divider. The divider can be zero based
> or one based (div = reg_val + 1 vs. div = reg_val).
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
> ---
>  drivers/clk/Kconfig       |    3 +
>  drivers/clk/Makefile      |    1 +
>  drivers/clk/clk-divider.c |  132 +++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/clk.h       |   31 +++++++++++
>  4 files changed, 167 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/clk/clk-divider.c
> 
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 6e3ae54..76bb4c9 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -5,3 +5,6 @@ config CLKDEV_LOOKUP
>  
>  config USE_COMMON_STRUCT_CLK
>  	bool
> +
> +config USE_COMMON_CLK_DIVIDER
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index a1a06d3..723d884 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,3 +1,4 @@
>  
>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>  obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> +obj-$(CONFIG_USE_COMMON_CLK_DIVIDER) += clk-divider.o
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> new file mode 100644
> index 0000000..2de94df
> --- /dev/null
> +++ b/drivers/clk/clk-divider.c
> @@ -0,0 +1,132 @@
> +/*
> + * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +#include <linux/module.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +
> +#define to_clk_divider(clk) (container_of(clk, struct clk_divider, clk))
> +
> +static unsigned long clk_divider_get_rate(struct clk *clk)
> +{
> +	struct clk_divider *divider = to_clk_divider(clk);
> +	unsigned long rate = clk_get_rate(divider->parent);
> +	unsigned int div;
> +
> +	div = readl(divider->reg) >> divider->shift;
> +	div &= (1 << divider->width) - 1;
> +
> +	if (!(divider->flags & CLK_DIVIDER_FLAG_ONE_BASED))
> +		div++;
> +
> +	return rate / div;
> +}
> +
> +static int clk_divider_bestdiv(struct clk *clk, unsigned long rate,
> +		unsigned long *best_parent_rate)
> +{
> +	struct clk_divider *divider = to_clk_divider(clk);
> +	int i, bestdiv = 0;
> +	unsigned long parent_rate, best = 0, now, maxdiv;
> +
> +	maxdiv = (1 << divider->width);
> +
> +	if (divider->flags & CLK_DIVIDER_FLAG_ONE_BASED)
> +		maxdiv--;
> +
> +	/*
> +	 * 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++) {
> +		parent_rate = clk_round_rate(divider->parent, (rate + 1) * i);
> +		now = parent_rate / i;
> +
> +		if (now <= rate && now >= best) {
> +			bestdiv = i;
> +			best = now;
> +		}
> +	}
> +
> +	if (!bestdiv) {
> +		bestdiv = (1 << divider->width);
> +		parent_rate = clk_round_rate(divider->parent, 1);
> +	} else {
> +		parent_rate = best * bestdiv;
> +	}
> +
> +	if (best_parent_rate)
> +		*best_parent_rate = parent_rate;
> +
> +	return bestdiv;
> +}
> +
> +static long clk_divider_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	unsigned long best_parent_rate;
> +	int div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
> +
> +	return best_parent_rate / div;
> +}
> +
> +static int clk_divider_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	unsigned long best_parent_rate;
> +	struct clk_divider *divider = to_clk_divider(clk);
> +	unsigned int div;
> +	int ret;
> +	unsigned long flags = 0;
> +	u32 val;
> +
> +	div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
> +
> +	if (rate != best_parent_rate / div)
> +		return -EINVAL;
> +
> +	ret = clk_set_rate(divider->parent, best_parent_rate);
why do you set parent rate? It may impact hte parent's other children.

Thanks
Richard
> +	if (ret)
> +		return ret;
> +
> +	if (divider->lock)
> +		spin_lock_irqsave(divider->lock, flags);
> +
> +	if (!(divider->flags & CLK_DIVIDER_FLAG_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;
> +}
> +
> +static struct clk *clk_divider_get_parent(struct clk *clk)
> +{
> +	struct clk_divider *divider = to_clk_divider(clk);
> +
> +	return divider->parent;
> +}
> +
> +struct clk_ops clk_divider_ops = {
> +	.prepare = clk_parent_prepare,
> +	.unprepare = clk_parent_unprepare,
> +	.enable = clk_parent_enable,
> +	.disable = clk_parent_disable,
> +	.get_rate = clk_divider_get_rate,
> +	.round_rate = clk_divider_round_rate,
> +	.set_rate = clk_divider_set_rate,
> +	.get_parent = clk_divider_get_parent,
> +};
> +EXPORT_SYMBOL_GPL(clk_divider_ops);
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index d014341..6f9771b 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -180,6 +180,37 @@ unsigned long clk_parent_get_rate(struct clk *clk);
>  long clk_parent_round_rate(struct clk *clk, unsigned long rate);
>  int clk_parent_set_rate(struct clk *clk, unsigned long rate);
>  
> +/**
> + * clock divider
> + *
> + * @clk		clock source
> + * @reg		register containing the divider
> + * @shift	shift to the divider
> + * @width	width of the divider
> + * @lock	register lock
> + * @parent	parent clock
> + *
> + * This clock implements get_rate/set_rate/round_rate. prepare/unprepare and
> + * enable/disable are passed through to the parent.
> + *
> + * The divider is calculated as div = reg_val + 1
> + * or if CLK_DIVIDER_FLAG_ONE_BASED is set as div = reg_val
> + * (with reg_val == 0 considered invalid)
> + */
> +struct clk_divider {
> +	struct clk	clk;
> +	void __iomem	*reg;
> +	unsigned char	shift;
> +	unsigned char	width;
> +	unsigned int	div;
> +	struct clk	*parent;
> +	spinlock_t	*lock;
> +#define CLK_DIVIDER_FLAG_ONE_BASED	(1 << 0)
> +	unsigned int	flags;
> +};
> +
> +extern struct clk_ops clk_divider_ops;
> +
>  #else /* !CONFIG_USE_COMMON_STRUCT_CLK */
>  
>  /*
> -- 
> 1.7.4.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-24  9:45             ` Richard Zhao
@ 2011-04-24 20:14               ` Uwe Kleine-König
  0 siblings, 0 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-04-24 20:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Apr 24, 2011 at 05:45:57PM +0800, Richard Zhao wrote:
> Hi Uwe,
> On Wed, Apr 20, 2011 at 04:07:37PM +0200, Uwe Kleine-K?nig wrote:
> > Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
> > ---
> > Hello,
> > 
> > only compile tested so far.
> > 
> > Best regards
> > Uwe
> > 
> >  drivers/clk/clk.c   |   43 +++++++++++++++++++++++++++++++++++++++++++
> >  include/linux/clk.h |    8 ++++++++
> >  2 files changed, 51 insertions(+), 0 deletions(-)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index 264c809..7627815 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -14,10 +14,23 @@
> >  int clk_prepare(struct clk *clk)
> >  {
> >  	int ret = 0;
> > +	struct clk *parent = ERR_PTR(-ENOSYS);
> >  
> >  	if (!clk)
> >  		return 0;
> >  
> > +	if (clk->ops->flags & CLK_OPS_GENERIC_PARENT) {
> > +		parent = clk_get_parent(clk);
> > +
> > +		if (!IS_ERR(parent)) {
> > +			ret = clk_prepare(parent);
> > +			if (ret)
> > +				return ret;
> > +		} else if (PTR_ERR(parent) != -ENOSYS)
> > +			/* -ENOSYS means no parent and is OK */
> > +			return PTR_ERR(parent);
> > +	}
> Is this supposed to be in prepare_lock? If prepare_count > 1, we need do nothing.
> Other parent operations need to be in lock protect too.
Yeah, I noticed that myself, too. Also it would be nice to handle the
set_parent callback.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 12:35                           ` Mark Brown
@ 2011-04-25  2:03                             ` Richard Zhao
  2011-04-25 10:57                               ` Mark Brown
  0 siblings, 1 reply; 165+ messages in thread
From: Richard Zhao @ 2011-04-25  2:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 01:35:42PM +0100, Mark Brown wrote:
> On Thu, Apr 21, 2011 at 02:20:22PM +0200, Thomas Gleixner wrote:
> > On Thu, 21 Apr 2011, Mark Brown wrote:
> 
> > > There's nothing intrinsic about the concept of a clock which means that
> > > it needs to be memory mapped or have a particular set of registers for
> > > us to work with.  This sounds like something that ought to be factored
> > > out but it's not obvious to me that it should be part of the core struct.
> 
> > Care to look over the various implementations and find out that a lot
> > of them look like:
> 
> Please bear in mind that due to the fact that we've currently got one
> clock implementation per subarchitecture anything off-SoC has some
> serious barriers to implementation in kernel.  For the system management
> units you'd be looking at very new systems, this is a new development.
How many arch have off-soc clocks? Where's the source? 
At least for arm, nearly all is memory mapped clock registers. clk is free
to override, we just need abstract the most common things.

Thanks
Richard
> 
> > Just in about 100 variations of the theme. Which is basically the same
> > as we have in irq chip implementations. And I showed how much of these
> > things can be factored out when done right. And even if a particular
> > clock does not implement enable/disable calls, then having
> > regs.enable_reg around is not a problem.
> 
> This is why I said "This sounds like something that ought to be factored
> out but it's not obvious to me that it should be part of the core
> struct" above - I agree strongly that we should have a generic memory
> mapped implementation which factors out all the redundant code you'd get
> for these clocks.
> 
> > Because that's what we implement via container_of now. And we can add
> > such stuff which is obvious right away.
> 
> That's exactly the sort of thing I'm suggesting.  You were asking for
> this to be part of struct clk itself, embedding the struct clk in a
> struct mm_clk (or whatever) and having standard ops for the mm_clk a
> much better abstraction.
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-25  2:03                             ` Richard Zhao
@ 2011-04-25 10:57                               ` Mark Brown
  2011-04-25 14:41                                 ` Richard Zhao
  0 siblings, 1 reply; 165+ messages in thread
From: Mark Brown @ 2011-04-25 10:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 25, 2011 at 10:03:49AM +0800, Richard Zhao wrote:
> On Thu, Apr 21, 2011 at 01:35:42PM +0100, Mark Brown wrote:

> > Please bear in mind that due to the fact that we've currently got one
> > clock implementation per subarchitecture anything off-SoC has some
> > serious barriers to implementation in kernel.  For the system management
> > units you'd be looking at very new systems, this is a new development.

> How many arch have off-soc clocks? Where's the source? 
> At least for arm, nearly all is memory mapped clock registers. clk is free
> to override, we just need abstract the most common things.

Even for many ARMs it's common for the clock tree to be rooted in the
PMIC (since it will always be on), and of course the full system clock
tree will not just include the CPU but also any other digital components
in the system.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-25 10:57                               ` Mark Brown
@ 2011-04-25 14:41                                 ` Richard Zhao
  2011-04-25 14:44                                   ` Mark Brown
  0 siblings, 1 reply; 165+ messages in thread
From: Richard Zhao @ 2011-04-25 14:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 25, 2011 at 11:57:45AM +0100, Mark Brown wrote:
> On Mon, Apr 25, 2011 at 10:03:49AM +0800, Richard Zhao wrote:
> > On Thu, Apr 21, 2011 at 01:35:42PM +0100, Mark Brown wrote:
> 
> > > Please bear in mind that due to the fact that we've currently got one
> > > clock implementation per subarchitecture anything off-SoC has some
> > > serious barriers to implementation in kernel.  For the system management
> > > units you'd be looking at very new systems, this is a new development.
> 
> > How many arch have off-soc clocks? Where's the source? 
> > At least for arm, nearly all is memory mapped clock registers. clk is free
> > to override, we just need abstract the most common things.
> 
> Even for many ARMs it's common for the clock tree to be rooted in the
> PMIC (since it will always be on), and of course the full system clock
> tree will not just include the CPU but also any other digital components
> in the system.
Yes, I see pmic or other on-board osc may be clock source. I just didn't realize
anyone will put them to clk. 

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

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-25 14:41                                 ` Richard Zhao
@ 2011-04-25 14:44                                   ` Mark Brown
  0 siblings, 0 replies; 165+ messages in thread
From: Mark Brown @ 2011-04-25 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 25, 2011 at 10:41:32PM +0800, Richard Zhao wrote:
> On Mon, Apr 25, 2011 at 11:57:45AM +0100, Mark Brown wrote:

> > Even for many ARMs it's common for the clock tree to be rooted in the
> > PMIC (since it will always be on), and of course the full system clock
> > tree will not just include the CPU but also any other digital components
> > in the system.

> Yes, I see pmic or other on-board osc may be clock source. I just didn't realize
> anyone will put them to clk. 

My point here is that right now nobody does anything like that unless
they really have to in part because this then makes the driver for the
off-SoC chip get tied in to the chip clock structure.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-24 13:48   ` Richard Zhao
@ 2011-04-25 18:51     ` Sascha Hauer
  2011-04-26  1:54       ` Richard Zhao
  0 siblings, 1 reply; 165+ messages in thread
From: Sascha Hauer @ 2011-04-25 18:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Apr 24, 2011 at 09:48:33PM +0800, Richard Zhao wrote:
> > +
> > +	div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
> > +
> > +	if (rate != best_parent_rate / div)
> > +		return -EINVAL;
> > +
> > +	ret = clk_set_rate(divider->parent, best_parent_rate);
> why do you set parent rate? It may impact hte parent's other children.
>

In a newer version I already created a barrier flag for not setting the
parents rate. Setting the parents rate is needed for for example
cascaded dividers. Otherwise this could be much simpler.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-25 18:51     ` Sascha Hauer
@ 2011-04-26  1:54       ` Richard Zhao
  0 siblings, 0 replies; 165+ messages in thread
From: Richard Zhao @ 2011-04-26  1:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 25, 2011 at 08:51:13PM +0200, Sascha Hauer wrote:
> On Sun, Apr 24, 2011 at 09:48:33PM +0800, Richard Zhao wrote:
> > > +
> > > +	div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
> > > +
> > > +	if (rate != best_parent_rate / div)
> > > +		return -EINVAL;
> > > +
> > > +	ret = clk_set_rate(divider->parent, best_parent_rate);
> > why do you set parent rate? It may impact hte parent's other children.
> >
> 
> In a newer version I already created a barrier flag for not setting the
> parents rate. Setting the parents rate is needed for for example
> cascaded dividers. Otherwise this could be much simpler.
And do you find a way to let clock actual parents indepent on reset or uboot
register settings. If we can register clk, maybe:
if (clk->ops.hw_get_parent)
	clk->parent = clk->ops->hw_get_parent;

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

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-19  2:45       ` Saravana Kannan
  2011-04-19  7:32         ` Uwe Kleine-König
@ 2011-04-28 15:14         ` Russell King - ARM Linux
  2011-05-03  3:37           ` Saravana Kannan
  1 sibling, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-28 15:14 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 18, 2011 at 07:45:53PM -0700, Saravana Kannan wrote:
> On 04/18/2011 03:07 AM, Sascha Hauer wrote:
>> AFAIK there are two different implementation types in the tree. Some
>> implementations only allow to set to the exact rate round_rate returns
>> while others round down in set_rate.
>>
>> Has this been specified what behaviour is expected?
>>
>
> This is something I have nagged Russell once or twice about and then  
> sent out an email to the list for which there was very limited response.  
> I think clk_round_rate() is too generic and not very useful.

As I've always said, clk_round_rate() returns the rate which you will
get if you ask clk_set_rate() to set the same rate.  It's not ment to
be "tell me the clock rate which I'd like to then pass to clk_set_rate(),
oh that's not good enough, so lets tweak it a bit and try again".

For example, take a video driver.  The user passes in the pixel clock as
a picosecond argument.  This gets converted to Hz.  We can then use
clk_round_rate() to find out what clock rate we _actually_ end up with
when we set that rate using clk_set_rate(), and return that rate (again
as ps) back to the user before we alter anything.  The user can then
make a decision whether they want to actually set it.

Having some sort of range stuff doesn't help you there because you're
not supplied a range from userspace.  You're just asked to set a 39752ps
clock rate.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-18  9:49   ` Uwe Kleine-König
  2011-04-18 10:07     ` Sascha Hauer
@ 2011-04-28 15:22     ` Russell King - ARM Linux
  2011-05-02  7:58       ` Sascha Hauer
  1 sibling, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-28 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 18, 2011 at 11:49:09AM +0200, Uwe Kleine-K?nig wrote:
> > +static int clk_divider_set_rate(struct clk *clk, unsigned long rate)
> > +{
> > +	unsigned long best_parent_rate;
> > +	struct clk_divider *divider = to_clk_divider(clk);
> > +	unsigned int div;
> > +	int ret;
> > +	unsigned long flags = 0;
> > +	u32 val;
> > +
> > +	div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
> > +
> > +	if (rate != best_parent_rate / div)
> > +		return -EINVAL;
> This is too harsh, isn't it. Or can you expect to only get values that
> are returned by round_rate? Again you need DIV_ROUND_UP.

It is too harsh, and I've wished many a time that people would implement
clk_set_rate() and clk_round_rate() as:

long clk_round_rate(struct clk *clk, unsigned long rate)
{
	err = calculate_clock_paramters(clk, params, rate);
	if (err < 0)
		return err;
	return calculate_clock_rate(clk, params);
}

int clk_set_rate(struct clk *clk, unsigned long rate)
{
	err = calculate_clock_parameters(clk, params, rate);
	if (err < 0)
		return err;
	set_clock_parameters(clk, params);
	clk->rate = calculate_clock_rate(clk, params);
	return 0;
}

IOW, clk_round_rate() does what clk_set_rate() does but does _not_ set
the hardware rate itself.

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

* [PATCH 01/10] Add a common struct clk
  2011-04-21 19:48   ` Thomas Gleixner
  2011-04-22  0:28     ` Richard Zhao
  2011-04-22  4:57     ` Saravana Kannan
@ 2011-04-29 10:09     ` Russell King - ARM Linux
  2011-04-29 10:45       ` Thomas Gleixner
  2 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 10:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > + * @get:	Called by the core clock code when a device driver acquires a
> > + *		clock via clk_get(). Optional.
> > + *
> > + * @put:	Called by the core clock code when a devices driver releases a
> > + *		clock via clk_put(). Optional.
> 
> These callbacks are completely pointless. There are only two non empty
> implementations in tree:
> 
> One does a try_module_get(clk->owner), which should be done in generic
> code. The other does special clock enabling magic which wants to go to
> clk->prepare().

I disagree.  Most clocks don't live in a module - there's only one
platform which does at present.  To force every clock to have an owner
field is rediculous.  We already know that the OMAP tree represents a
significant amount of data, and for every additional unnecessary word,
it gobbles up another 4K of data space.

If we go down the route of separating clock stuff into bite-size pieces,
OMAP is going to end up with yet more struct clks, which is going to add
to the bloat even more.

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

* [PATCH 04/10] clk: implement parent pass through functions
  2011-04-19 17:53     ` Sascha Hauer
  2011-04-19 19:09       ` Uwe Kleine-König
@ 2011-04-29 10:20       ` Russell King - ARM Linux
  1 sibling, 0 replies; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 10:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Apr 19, 2011 at 07:53:18PM +0200, Sascha Hauer wrote:
> That's the current behaviour (except that ERR_PTR(-ENOSYS) is returned
> instead of NULL).

I think you're getting confused about clk being NULL.  Let's take a
step backwards shall we?

A NULL clk has no pointers to anything useful.  It gets treated by the
clk_* functions as a no-op.  So, if clk_get_parent() returns NULL, then
internally within the clk code, we know that it's going to be reated as
a no-op clock.  If it's a no-op clock then there is no parent.

The next point is - should clk_get_parent() return NULL?  It can do
as that's a valid return from clk_get() which is not an error case.
Any driver asking for the parent clock should treat it no different
from a non-NULL value:

/**
 * clk_get_parent - get the parent clock source for this clock
 * @clk: clock source
 *
 * Returns struct clk corresponding to parent clock source, or
 * valid IS_ERR() condition containing errno.
 */
struct clk *clk_get_parent(struct clk *clk);

However, internally within the clk API we can make the assumption that
a NULL return value means "no clk" because the clk internals is on the
clock implementation side of the API dividing line and can deal with
this knowledge.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-20 19:52                 ` Thomas Gleixner
                                     ` (2 preceding siblings ...)
  2011-04-21  7:42                   ` Sascha Hauer
@ 2011-04-29 10:30                   ` Russell King - ARM Linux
  2011-04-29 10:51                     ` Thomas Gleixner
  3 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 10:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:
> On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> > struct clk has no parent member, there is only clk_get_parent(). If
> 
> Which is a complete failure to begin with. Why the heck do you need a
> callback to figure that out?

Thomas, you're wrong.  You're looking at things far too simply, because
all you can see is a tree of clocks.

When you have MUXes, a clock can have one of many parents.  So a single
clk->parent doesn't hack it.  That's one reason why clk_get_parent()
exists, so that MUXes can return the appropriate parent for the current
MUX setting.

You may wish to store the current setting in clk->parent, but I'd argue
that's a recipe for things going wrong when the MUX settings differ from
the cached clk->parent value.  Instead, having clk_get_parent()s
implementation return the _current_ parent and let MUXes do the right
thing depending on hardware is much easier and more reliably correct.

So I don't agree with you on some of these points.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21  9:12                     ` Thomas Gleixner
  2011-04-21 10:31                       ` Mark Brown
@ 2011-04-29 10:37                       ` Russell King - ARM Linux
  2011-04-29 11:01                         ` Thomas Gleixner
  1 sibling, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 10:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 11:12:36AM +0200, Thomas Gleixner wrote:
> On Thu, 21 Apr 2011, Uwe Kleine-K?nig wrote:
> > > Which is a complete failure to begin with. Why the heck do you need a
> > > callback to figure that out?
> > > 
> > > Because someone claimed, that you need a callback to make it safe from
> > > changing? Or what's the reason for this?
> > If there were a pointer tracking the parent you still needed to program
> > out the get_parent function anyhow to set the pointer initially. But I
> > agree that in other situations having a pointer is more comfortable and
> > saves ugly error handling e.g. in set_parent.
> 
> That's nonsense. Why do you want a get_parent() function at all?
> parent is set up when the clock is established in the clock tree. And
> that's not done by some random driver. That's a property of the clock.

It's *not* a fixed property of the clock.  It's a runtime property.

If you change the rate of a clock, you may need to change its parent.
If you change the operating point of the device, (eg, sleep mode where
the main system PLL gets turned off) you may need to change its parent
to a slower clock to ensure wakeup timers continue to run but at a lower
resolution.

Sure the API doesn't handle the runtime cases at all well, but that's
not a reason to enforce a fixed tree structure on something which isn't
a fixed tree structure.

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

* [PATCH 01/10] Add a common struct clk
  2011-04-29 10:09     ` Russell King - ARM Linux
@ 2011-04-29 10:45       ` Thomas Gleixner
  2011-04-29 10:58         ` Tony Lindgren
  2011-04-29 11:01         ` Russell King - ARM Linux
  0 siblings, 2 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> > On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > > + * @get:	Called by the core clock code when a device driver acquires a
> > > + *		clock via clk_get(). Optional.
> > > + *
> > > + * @put:	Called by the core clock code when a devices driver releases a
> > > + *		clock via clk_put(). Optional.
> > 
> > These callbacks are completely pointless. There are only two non empty
> > implementations in tree:
> > 
> > One does a try_module_get(clk->owner), which should be done in generic
> > code. The other does special clock enabling magic which wants to go to
> > clk->prepare().
> 
> I disagree.  Most clocks don't live in a module - there's only one
> platform which does at present.  To force every clock to have an owner
> field is rediculous.  We already know that the OMAP tree represents a

So we trade an owner field (which can be NULL) versus two function
pointers in the clk_ops struct, which are of course subject to be
abused for all kind of crap which does not belong there at all.

> significant amount of data, and for every additional unnecessary word,
> it gobbles up another 4K of data space.

What are we talking about?

arch/arm/mach-omap2/clock2420_data.c:117
arch/arm/mach-omap2/clock2430_data.c:126
arch/arm/mach-omap2/clock3xxx_data.c:235
arch/arm/mach-omap2/clock44xx_data.c:228

So even if we could build a common kernel for all these omaps, then
adding owner to struct clk will consume ~2800 bytes.

> If we go down the route of separating clock stuff into bite-size pieces,
> OMAP is going to end up with yet more struct clks, which is going to add
> to the bloat even more.

Make it 8k then and it's still not any significant number.

Abstractions and I mean abstractions which encapsulate common
functionality have always a tradeoff in larger data size. And one
lesson I learned the hard way is that if you make abstractions and
frameworks by design permissive, then you end up with tons of extra
private code because people prefer to hack their "special needs" into
their private code instead of talking to the people who maintain the
core code where it could be solved in a generalized way.

Yes, we want to avoid unneccesary data size growth, but at the same
time we have to make it as hard as it gets for users of an
abstraction/framework to tinker around the core code as they see
fit. Otherwise you wont get any consolidation and reduction of over
and over copied and modified code doing basically the same thing.

If I can trade 2800 bytes of data vs. 280 lines of duplicated code and
a can of worms opened by interfaces which are an invitation for abuse,
then I chose the 2800 bytes any time.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-21 12:20                         ` Thomas Gleixner
  2011-04-21 12:35                           ` Mark Brown
@ 2011-04-29 10:49                           ` Russell King - ARM Linux
  2011-04-29 11:11                             ` Thomas Gleixner
  1 sibling, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 10:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 21, 2011 at 02:20:22PM +0200, Thomas Gleixner wrote:
> Care to look over the various implementations and find out that a lot
> of them look like:
> 
> static int _clk_enable(struct clk *clk)
> {
>         unsigned int reg;
> 
>         reg = __raw_readl(clk->enable_reg);
>         reg |= 1 << clk->enable_shift;
>         __raw_writel(reg, clk->enable_reg);
> 
>         return 0;
> }
> 
> Just in about 100 variations of the theme. Which is basically the same
> as we have in irq chip implementations. And I showed how much of these
> things can be factored out when done right. And even if a particular
> clock does not implement enable/disable calls, then having
> regs.enable_reg around is not a problem.

And you haven't noticed that with how things stand with what Jeremy's
proposed, we _can_ abstract this kind of stuff.

Having read a number of your messages, I think you don't like it because
you haven't been involved in creating it - I don't think there's anything
much more specific than that to your protestations about it.

We _can_ (and I hope we do) factor out the 100 "clock gate" implementations
into one instance - and I believe we can do that with Jeremy's proposal.

For those clocks which have an clock gate and a clock mux, we can create
two clk structures, one being the clock gate container and one being the
clock mux container, even if they're accessing the same register.

Shoving the enable crap into the core framework enforces that every clock
has an gate attached to it, which is soo far departed from reality I've
got to ask what universe you're living in.

Finally, go look at the OMAP clock structure where they stuff everything
into one struct clk:

struct clk {
        struct list_head        node;
        const struct clkops     *ops;
        const char              *name;
        struct clk              *parent;
        struct list_head        children;
        struct list_head        sibling;        /* node for children */
        unsigned long           rate;
        void __iomem            *enable_reg;
        unsigned long           (*recalc)(struct clk *);
        int                     (*set_rate)(struct clk *, unsigned long);
        long                    (*round_rate)(struct clk *, unsigned long);
        void                    (*init)(struct clk *);
        u8                      enable_bit;
        s8                      usecount;
        u8                      fixed_div;
        u8                      flags;
#ifdef CONFIG_ARCH_OMAP2PLUS
        void __iomem            *clksel_reg;
        u32                     clksel_mask;
        const struct clksel     *clksel;
        struct dpll_data        *dpll_data;
        const char              *clkdm_name;
        struct clockdomain      *clkdm;
#else
        u8                      rate_offset;
        u8                      src_offset;
#endif
#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
        struct dentry           *dent;  /* For visible tree hierarchy */
#endif
};

If you start saying "a clock struct should contain enable bit, register
address" then you're well on the path to creating a horrid mess like the
above.  And this is something we _must_ avoid.

So, Jeremy's done the right thing and created a base struct clk which
is very much like a kobject, along with a set of methods to operate on
it.  Around that can be built things like fixed rate clocks, MUXes,
gates, PLLs, and everything else which is required with minimal expense
- and all provided by core clk code.  And we avoid crappy bloated
structures like the thing above.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 10:30                   ` Russell King - ARM Linux
@ 2011-04-29 10:51                     ` Thomas Gleixner
  2011-04-29 10:56                       ` Russell King - ARM Linux
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 10:51 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:

> On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:
> > On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> > > struct clk has no parent member, there is only clk_get_parent(). If
> > 
> > Which is a complete failure to begin with. Why the heck do you need a
> > callback to figure that out?
> 
> Thomas, you're wrong.  You're looking at things far too simply, because
> all you can see is a tree of clocks.

And that's what it is. Even if the clock can have sevaral possible
parents, then there is only one active parent at a time. It's still a
tree.
 
> When you have MUXes, a clock can have one of many parents.  So a single
> clk->parent doesn't hack it.  That's one reason why clk_get_parent()
> exists, so that MUXes can return the appropriate parent for the current
> MUX setting.

That's only ever needed when you register a clk with the framework to
decode the current setting from the hardware.
 
> You may wish to store the current setting in clk->parent, but I'd argue
> that's a recipe for things going wrong when the MUX settings differ from
> the cached clk->parent value.  Instead, having clk_get_parent()s
> implementation return the _current_ parent and let MUXes do the right
> thing depending on hardware is much easier and more reliably correct.

If something changes the clk parent in the hardware without going
through common framework functions, which take care of updating
clk->parent in the proper way, then the implementer got it wrong
badly. That's the same thing as if you change the clock rate of your
timekeeping clock behind the timekeeping core and then complain about
timekeeping going awry.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 10:51                     ` Thomas Gleixner
@ 2011-04-29 10:56                       ` Russell King - ARM Linux
  0 siblings, 0 replies; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2011 at 12:51:44PM +0200, Thomas Gleixner wrote:
> On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> 
> > On Wed, Apr 20, 2011 at 09:52:15PM +0200, Thomas Gleixner wrote:
> > > On Wed, 20 Apr 2011, Uwe Kleine-K?nig wrote:
> > > > struct clk has no parent member, there is only clk_get_parent(). If
> > > 
> > > Which is a complete failure to begin with. Why the heck do you need a
> > > callback to figure that out?
> > 
> > Thomas, you're wrong.  You're looking at things far too simply, because
> > all you can see is a tree of clocks.
> 
> And that's what it is. Even if the clock can have sevaral possible
> parents, then there is only one active parent at a time. It's still a
> tree.
>  
> > When you have MUXes, a clock can have one of many parents.  So a single
> > clk->parent doesn't hack it.  That's one reason why clk_get_parent()
> > exists, so that MUXes can return the appropriate parent for the current
> > MUX setting.
> 
> That's only ever needed when you register a clk with the framework to
> decode the current setting from the hardware.
>  
> > You may wish to store the current setting in clk->parent, but I'd argue
> > that's a recipe for things going wrong when the MUX settings differ from
> > the cached clk->parent value.  Instead, having clk_get_parent()s
> > implementation return the _current_ parent and let MUXes do the right
> > thing depending on hardware is much easier and more reliably correct.
> 
> If something changes the clk parent in the hardware without going
> through common framework functions, which take care of updating
> clk->parent in the proper way, then the implementer got it wrong
> badly. That's the same thing as if you change the clock rate of your
> timekeeping clock behind the timekeeping core and then complain about
> timekeeping going awry.

No, the question is whether you cache the parent clock in a pointer,
or use an abstraction to obtain the parent clock.  It's merely an
implementation detail and is not as big a problem as you've been
trying to make it out to be.

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

* [PATCH 01/10] Add a common struct clk
  2011-04-29 10:45       ` Thomas Gleixner
@ 2011-04-29 10:58         ` Tony Lindgren
  2011-04-29 11:01         ` Russell King - ARM Linux
  1 sibling, 0 replies; 165+ messages in thread
From: Tony Lindgren @ 2011-04-29 10:58 UTC (permalink / raw)
  To: linux-arm-kernel

* Thomas Gleixner <tglx@linutronix.de> [110429 03:42]:
> On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> 
> > On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> > > On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > > > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > > > + * @get:	Called by the core clock code when a device driver acquires a
> > > > + *		clock via clk_get(). Optional.
> > > > + *
> > > > + * @put:	Called by the core clock code when a devices driver releases a
> > > > + *		clock via clk_put(). Optional.
> > > 
> > > These callbacks are completely pointless. There are only two non empty
> > > implementations in tree:
> > > 
> > > One does a try_module_get(clk->owner), which should be done in generic
> > > code. The other does special clock enabling magic which wants to go to
> > > clk->prepare().
> > 
> > I disagree.  Most clocks don't live in a module - there's only one
> > platform which does at present.  To force every clock to have an owner
> > field is rediculous.  We already know that the OMAP tree represents a
> 
> So we trade an owner field (which can be NULL) versus two function
> pointers in the clk_ops struct, which are of course subject to be
> abused for all kind of crap which does not belong there at all.
> 
> > significant amount of data, and for every additional unnecessary word,
> > it gobbles up another 4K of data space.
> 
> What are we talking about?
> 
> arch/arm/mach-omap2/clock2420_data.c:117
> arch/arm/mach-omap2/clock2430_data.c:126
> arch/arm/mach-omap2/clock3xxx_data.c:235
> arch/arm/mach-omap2/clock44xx_data.c:228
> 
> So even if we could build a common kernel for all these omaps, then
> adding owner to struct clk will consume ~2800 bytes.

Just to correct something, we are already building a common kernel
for all these, see omap2plus_defconfig.

For the size, device tree will shrink down that data where only
only one set of clock data is passed to the kernel. So I don't
think the size is such a big issue.

Regards,

Tony

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

* [PATCH 01/10] Add a common struct clk
  2011-04-29 10:45       ` Thomas Gleixner
  2011-04-29 10:58         ` Tony Lindgren
@ 2011-04-29 11:01         ` Russell King - ARM Linux
  2011-04-30 18:30           ` Pavel Machek
  1 sibling, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2011 at 12:45:00PM +0200, Thomas Gleixner wrote:
> On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> 
> > On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> > > On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > > > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > > > + * @get:	Called by the core clock code when a device driver acquires a
> > > > + *		clock via clk_get(). Optional.
> > > > + *
> > > > + * @put:	Called by the core clock code when a devices driver releases a
> > > > + *		clock via clk_put(). Optional.
> > > 
> > > These callbacks are completely pointless. There are only two non empty
> > > implementations in tree:
> > > 
> > > One does a try_module_get(clk->owner), which should be done in generic
> > > code. The other does special clock enabling magic which wants to go to
> > > clk->prepare().
> > 
> > I disagree.  Most clocks don't live in a module - there's only one
> > platform which does at present.  To force every clock to have an owner
> > field is rediculous.  We already know that the OMAP tree represents a
> 
> So we trade an owner field (which can be NULL) versus two function
> pointers in the clk_ops struct, which are of course subject to be
> abused for all kind of crap which does not belong there at all.

And the current __clk_get/__clk_put stuff has been abused to hell and
back hasn't it with just three implementations.  While I agree with your
sentiment, lets agree to address that _if_ it becomes a problem.  At
the moment, we have _enough_ problems to deal with, we don't need to
invent new ones which really don't matter at this stage.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 10:37                       ` Russell King - ARM Linux
@ 2011-04-29 11:01                         ` Thomas Gleixner
  2011-04-29 11:06                           ` Russell King - ARM Linux
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 11:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:

> On Thu, Apr 21, 2011 at 11:12:36AM +0200, Thomas Gleixner wrote:
> > On Thu, 21 Apr 2011, Uwe Kleine-K?nig wrote:
> > > > Which is a complete failure to begin with. Why the heck do you need a
> > > > callback to figure that out?
> > > > 
> > > > Because someone claimed, that you need a callback to make it safe from
> > > > changing? Or what's the reason for this?
> > > If there were a pointer tracking the parent you still needed to program
> > > out the get_parent function anyhow to set the pointer initially. But I
> > > agree that in other situations having a pointer is more comfortable and
> > > saves ugly error handling e.g. in set_parent.
> > 
> > That's nonsense. Why do you want a get_parent() function at all?
> > parent is set up when the clock is established in the clock tree. And
> > that's not done by some random driver. That's a property of the clock.
> 
> It's *not* a fixed property of the clock.  It's a runtime property.

I know that stuff can change and needs to be changed runtime. But this
has to be done at the framework level and not at some random place in
some random clk->ops->fn() implementation.
 
> If you change the rate of a clock, you may need to change its parent.

If you have a proper description of properties like possible parents,
then you can figure out at the framework level that you need to change
the parent in order to get the requested rate. It's not a SoC specific
problem, it's a problem which can be described pretty well for the
most common cases.

> If you change the operating point of the device, (eg, sleep mode where
> the main system PLL gets turned off) you may need to change its parent
> to a slower clock to ensure wakeup timers continue to run but at a lower
> resolution.

Again. That's a problem to be solved at the framework level. If the
sleep code decides to shut down the main pll then the framework can
walk the tree and figure out which clocks need to be moved to a
different parent, as long as the affected clocks are marked "keep me
always alive" or whatever property is chosen to make such decisions.
 
> Sure the API doesn't handle the runtime cases at all well, but that's
> not a reason to enforce a fixed tree structure on something which isn't
> a fixed tree structure.

I don't want to enforce a fixed tree structure. I want proper tree
handling - which includes runtime changes to the tree - at the
framework level and not encoded in 10 different bogus ways in every
other SoC implementation.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 11:01                         ` Thomas Gleixner
@ 2011-04-29 11:06                           ` Russell King - ARM Linux
  2011-04-29 12:13                             ` Thomas Gleixner
  0 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 11:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2011 at 01:01:58PM +0200, Thomas Gleixner wrote:
> On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> 
> > On Thu, Apr 21, 2011 at 11:12:36AM +0200, Thomas Gleixner wrote:
> > > On Thu, 21 Apr 2011, Uwe Kleine-K?nig wrote:
> > > > > Which is a complete failure to begin with. Why the heck do you need a
> > > > > callback to figure that out?
> > > > > 
> > > > > Because someone claimed, that you need a callback to make it safe from
> > > > > changing? Or what's the reason for this?
> > > > If there were a pointer tracking the parent you still needed to program
> > > > out the get_parent function anyhow to set the pointer initially. But I
> > > > agree that in other situations having a pointer is more comfortable and
> > > > saves ugly error handling e.g. in set_parent.
> > > 
> > > That's nonsense. Why do you want a get_parent() function at all?
> > > parent is set up when the clock is established in the clock tree. And
> > > that's not done by some random driver. That's a property of the clock.
> > 
> > It's *not* a fixed property of the clock.  It's a runtime property.
> 
> I know that stuff can change and needs to be changed runtime. But this
> has to be done at the framework level and not at some random place in
> some random clk->ops->fn() implementation.

Look, how do you _not_ do it at the clk->ops->fn() level when you have
clocks which are pure muxes, and so are selected by a bitfield in a
register vs other clocks which are muxes _and_ dividers combined which
can't be separated.  Do you _really_ want to teach the core clock
framework about every type of platform quirk like that?

That's the direction you're heading for by demanding that the core clk
code does all this kind of crap.  Crap in the core clock code, rather
than a set of compartmentalized clock implementations for fixed rate
clocks, muxes, dividers, dividers with muxes, plls, etc.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 10:49                           ` Russell King - ARM Linux
@ 2011-04-29 11:11                             ` Thomas Gleixner
  2011-04-29 11:38                               ` Russell King - ARM Linux
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 11:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> On Thu, Apr 21, 2011 at 02:20:22PM +0200, Thomas Gleixner wrote:
> > Just in about 100 variations of the theme. Which is basically the same
> > as we have in irq chip implementations. And I showed how much of these
> > things can be factored out when done right. And even if a particular
> > clock does not implement enable/disable calls, then having
> > regs.enable_reg around is not a problem.
> 
> And you haven't noticed that with how things stand with what Jeremy's
> proposed, we _can_ abstract this kind of stuff.
> 
> Having read a number of your messages, I think you don't like it because
> you haven't been involved in creating it - I don't think there's anything
> much more specific than that to your protestations about it.
> 
> We _can_ (and I hope we do) factor out the 100 "clock gate" implementations
> into one instance - and I believe we can do that with Jeremy's proposal.
> 
> For those clocks which have an clock gate and a clock mux, we can create
> two clk structures, one being the clock gate container and one being the
> clock mux container, even if they're accessing the same register.
> 
> Shoving the enable crap into the core framework enforces that every clock
> has an gate attached to it, which is soo far departed from reality I've
> got to ask what universe you're living in.

Not at all. If a clk has clk->ops->enable() == NULL then you still
need to do proper refcounting and descending down the parent tree to
make sure, that the parent clocks are enabled.
 
> };
> 
> If you start saying "a clock struct should contain enable bit, register
> address" then you're well on the path to creating a horrid mess like the
> above.  And this is something we _must_ avoid.

I already have dumped that idea in course of the discussion and yes,
we can implement something as a container like I did for the generic
irq chip.
 
> So, Jeremy's done the right thing and created a base struct clk which
> is very much like a kobject, along with a set of methods to operate on
> it.  Around that can be built things like fixed rate clocks, MUXes,
> gates, PLLs, and everything else which is required with minimal expense
> - and all provided by core clk code.  And we avoid crappy bloated
> structures like the thing above.

I tend to disagree. Yes, he created the minimal common level for a
struct clk and the ops around it. But does that change anything about
the status quo of duplicated functions walking the tree, duplicated
functions to validate and round clock rates? The whole approach will
keep the whole code mess in the SoCs the same as it is now and just
enforce a common data structure and a dozen wrapper "API" functions
around it.

So omap will simply have their bloat in a struct omap_clk() and every
other SoC will do the same. The duplicated code, the locking mess
etc. will all remain in totally incompatible ways. So what's the win?

I looked at a few new SoC trees and guess what comes along ? Another
few copies of existing clock implementations hacked into submission so
the thing works on that new hardware.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 11:11                             ` Thomas Gleixner
@ 2011-04-29 11:38                               ` Russell King - ARM Linux
  2011-04-29 12:19                                 ` Thomas Gleixner
  0 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 11:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2011 at 01:11:25PM +0200, Thomas Gleixner wrote:
> I tend to disagree. Yes, he created the minimal common level for a
> struct clk and the ops around it. But does that change anything about
> the status quo of duplicated functions walking the tree, duplicated
> functions to validate and round clock rates? The whole approach will
> keep the whole code mess in the SoCs the same as it is now and just
> enforce a common data structure and a dozen wrapper "API" functions
> around it.
> 
> So omap will simply have their bloat in a struct omap_clk() and every
> other SoC will do the same. The duplicated code, the locking mess
> etc. will all remain in totally incompatible ways. So what's the win?

I disagree.  With a 'divider+mux' clk, OMAP can move those clocks
over.  With a 'pll' clk, OMAP can move the PLL stuff over.  With a
simple enable/disable clk, OMAP can move those over.  That's a
significant portion of the OMAP clk mess converted over to smaller,
much more well defined, self contained clk structures.

I don't see any reason with this why OMAP - or anyone else - should
have their own platform_clk structure if we have the necessary building
blocks, and provided there is sufficient review to ensure that those
building blocks which are found to be lacking get fixed along the way.

As for the locking mess, that's what happens when you try to generalize
stuff and end up with a finer locking scheme.  The more locks you have,
the more complex the locking rules become, and the more problems you
encounter with potential deadlocks.  And it seems that lockdep also
starts to struggle too (as it operates on classes of locks not actual
locks.)

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 11:06                           ` Russell King - ARM Linux
@ 2011-04-29 12:13                             ` Thomas Gleixner
  2011-04-29 13:26                               ` Russell King - ARM Linux
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 12:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> On Fri, Apr 29, 2011 at 01:01:58PM +0200, Thomas Gleixner wrote:
> > On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> > 
> > > On Thu, Apr 21, 2011 at 11:12:36AM +0200, Thomas Gleixner wrote:
> > > > On Thu, 21 Apr 2011, Uwe Kleine-K?nig wrote:
> > > > > > Which is a complete failure to begin with. Why the heck do you need a
> > > > > > callback to figure that out?
> > > > > > 
> > > > > > Because someone claimed, that you need a callback to make it safe from
> > > > > > changing? Or what's the reason for this?
> > > > > If there were a pointer tracking the parent you still needed to program
> > > > > out the get_parent function anyhow to set the pointer initially. But I
> > > > > agree that in other situations having a pointer is more comfortable and
> > > > > saves ugly error handling e.g. in set_parent.
> > > > 
> > > > That's nonsense. Why do you want a get_parent() function at all?
> > > > parent is set up when the clock is established in the clock tree. And
> > > > that's not done by some random driver. That's a property of the clock.
> > > 
> > > It's *not* a fixed property of the clock.  It's a runtime property.
> > 
> > I know that stuff can change and needs to be changed runtime. But this
> > has to be done at the framework level and not at some random place in
> > some random clk->ops->fn() implementation.
> 
> Look, how do you _not_ do it at the clk->ops->fn() level when you have
> clocks which are pure muxes, and so are selected by a bitfield in a
> register vs other clocks which are muxes _and_ dividers combined which
> can't be separated.  Do you _really_ want to teach the core clock
> framework about every type of platform quirk like that?

Not at all. The core code should merily handle the tree structure
correctly and some common other functions, nothing else. 
 
> That's the direction you're heading for by demanding that the core clk
> code does all this kind of crap.  Crap in the core clock code, rather
> than a set of compartmentalized clock implementations for fixed rate
> clocks, muxes, dividers, dividers with muxes, plls, etc.

You need that anyway. The core code does not want to know about those
ugly details and there is no need to know it.

So lets look at an example:

[Root clock A]-
      	      |
      	      - [Selector] -- [Divisor] -- [ Gate ]
              |
[Root clock B]-

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 11:38                               ` Russell King - ARM Linux
@ 2011-04-29 12:19                                 ` Thomas Gleixner
  2011-04-29 13:27                                   ` Russell King - ARM Linux
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 12:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> On Fri, Apr 29, 2011 at 01:11:25PM +0200, Thomas Gleixner wrote:
> > I tend to disagree. Yes, he created the minimal common level for a
> > struct clk and the ops around it. But does that change anything about
> > the status quo of duplicated functions walking the tree, duplicated
> > functions to validate and round clock rates? The whole approach will
> > keep the whole code mess in the SoCs the same as it is now and just
> > enforce a common data structure and a dozen wrapper "API" functions
> > around it.
> > 
> > So omap will simply have their bloat in a struct omap_clk() and every
> > other SoC will do the same. The duplicated code, the locking mess
> > etc. will all remain in totally incompatible ways. So what's the win?
> 
> I disagree.  With a 'divider+mux' clk, OMAP can move those clocks
> over.  With a 'pll' clk, OMAP can move the PLL stuff over.  With a
> simple enable/disable clk, OMAP can move those over.  That's a
> significant portion of the OMAP clk mess converted over to smaller,
> much more well defined, self contained clk structures.
> 
> I don't see any reason with this why OMAP - or anyone else - should
> have their own platform_clk structure if we have the necessary building
> blocks, and provided there is sufficient review to ensure that those
> building blocks which are found to be lacking get fixed along the way.

Agreed. But that's an orthogonal problem to the proper handling of the
tree walks, propagation of rates, enable, prepare etc. and common
validation functions.
 
> As for the locking mess, that's what happens when you try to generalize
> stuff and end up with a finer locking scheme.  The more locks you have,
> the more complex the locking rules become, and the more problems you
> encounter with potential deadlocks.  And it seems that lockdep also
> starts to struggle too (as it operates on classes of locks not actual
> locks.)

The per clk locking is not going to work ever except you want to have
the trylock dance if you need to propagate changes up the tree and
down the tree. So yes, we need per tree locking and I can see the need
for the mutex and the spinlock to protect the tree, but you really
want to have the logic dealing with those locks and how they both
protect the tree in common code and not in some random place.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 12:13                             ` Thomas Gleixner
@ 2011-04-29 13:26                               ` Russell King - ARM Linux
  2011-04-29 15:31                                 ` Thomas Gleixner
                                                   ` (2 more replies)
  0 siblings, 3 replies; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 13:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2011 at 02:13:06PM +0200, Thomas Gleixner wrote:
> This are all well defined semantical problems and should be solved in
> common code rather than having different buggy implementations in each
> SoC clock "framework".

Why are you associating functional elements in drivers/clk with the
SoC clock framework?

I think that's the root cause of this misunderstanding, and until you
start realising that these building blocks are not part of the SoC
implementation, we're going to continue arguing about this.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 12:19                                 ` Thomas Gleixner
@ 2011-04-29 13:27                                   ` Russell King - ARM Linux
  2011-04-29 15:47                                     ` Thomas Gleixner
  0 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 13:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2011 at 02:19:25PM +0200, Thomas Gleixner wrote:
> The per clk locking is not going to work ever except you want to have
> the trylock dance if you need to propagate changes up the tree and
> down the tree. So yes, we need per tree locking and I can see the need
> for the mutex and the spinlock to protect the tree, but you really
> want to have the logic dealing with those locks and how they both
> protect the tree in common code and not in some random place.

rotfl.  "per tree locking".  That's farsical when you have muxes which
select between different distinct trees.  That _surely_ is the path to
locking mayhem, because the child clocks can have their lock changed
beneath them as the mux changes its parent.

I still think you're in a different universe.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 13:26                               ` Russell King - ARM Linux
@ 2011-04-29 15:31                                 ` Thomas Gleixner
  2011-04-29 22:07                                   ` Russell King - ARM Linux
  2011-04-30 14:27                                 ` torbenh
  2011-05-03  2:44                                 ` Saravana Kannan
  2 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:

> On Fri, Apr 29, 2011 at 02:13:06PM +0200, Thomas Gleixner wrote:
> > This are all well defined semantical problems and should be solved in
> > common code rather than having different buggy implementations in each
> > SoC clock "framework".
> 
> Why are you associating functional elements in drivers/clk with the
> SoC clock framework?
> 
> I think that's the root cause of this misunderstanding, and until you
> start realising that these building blocks are not part of the SoC
> implementation, we're going to continue arguing about this.

I'm realizing that those building blocks are separate abstractions for
the various incarnations of clk functionalities, which are just
configured per SoC.

I'm not confusing anything. I'm just looking at the status quo in the
first place. And the status quo is that every SoC has it's own
"framework".

So now you propose two things to consolidate that:

1) A common struct clk and a handful wrapper functions

2) A set of abstraction blocks which represent the various clk
   incarnations (divisors, muxes, plls etc)

And my point is that this is not going to work out really well.

There is no consolidated handling of the tree itself. The per clk
locking does what? Serialize the prepare/enable functions for a single
clock. Now, tree traversal to make sure that the parent clocks are
enabled/prepared etc as well need to take the locks nested. That works
nicely in descending down the parent chain.

Though when you need to propagate changes up the chain (e.g. rate
changes) then you need to take the locks in reverse order with trylock
and back down to the place where you started when a trylock
fails. Otherwise you run into deadlocks. With the split locks you do
that for the mutex chain first and then for the spinlock one. It's
doable, but is it worth the trouble?

If it is worth the trouble, then where are you going to implement
this?

The proposed "API" pushes the walk logic into the clkops->fn()
callbacks. Into every single one.

This is simply wrong. That's like having each filesystem providing
it's own directory traversal mechanism.

You don't want to have that logic in each callback. That's tree
management which needs to be done one level above. And it does not
matter which locking scheme you are using - global or per clk.

Lets look at a simple example (locking omitted)

clk_enable(clk) {
	if (clk->enable_count == 0) {
  	   res = clk->ops->enable(clk);
	   if (res)
	      return res;
        }
	enable_count++;
	return 0;
};   

So in each enable op you have:

*_enable(clk)
{
	res = clk_enable(clk_get_parent(clk));
	if (res)
		return res;

	res = hw_magic_enable(clk);
	if (res)
		clk_disable(clk_get_parent(clk));
	return res;
}

Instead of having at the core level:

clk_enable(clk)
{
	if (clk->enable_count == 0) {
		res = clk_enable(clk_get_parent(clk));
		if (res)
			return res;

		res = clk->ops->enable(clk);
		if (res) {
			clk_disable(clk_get_parent(clk));
			return res;
		}
	}
	clk->enable_count++;
	return 0;
}

And in each *_enable op:

*_enable(clk)
{
	return hw_magic_enable(clk);
}

Now add the locking mess (whatever variant) to that whole thing and
then tell me which solution is the proper one.

It gets worse when you look at the proposed clk_set_parent() wrapper:

clk_set_parent(clk)
{
	if (!clk->ops->set_parent)
		return -ENOSYS;

	return clk->ops->set_parent(clk);
}

So this does no locking at all for a simple reason. Because if you
change the parent then you need to lock the clocks in the upwards
direction with full trylock dance. And you have to do that because
otherwise a clk_enable/disable/prepare/unprepare call on a leaf clk
might follow down a chain which is changing under it.

So you want to do that in every possible set_parent() callback? Same
for set_rate() implementations which need to disable and/or adjust the
clocks tree upwards before they can change the rate at the bottom.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 13:27                                   ` Russell King - ARM Linux
@ 2011-04-29 15:47                                     ` Thomas Gleixner
  0 siblings, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 15:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:

> On Fri, Apr 29, 2011 at 02:19:25PM +0200, Thomas Gleixner wrote:
> > The per clk locking is not going to work ever except you want to have
> > the trylock dance if you need to propagate changes up the tree and
> > down the tree. So yes, we need per tree locking and I can see the need
> > for the mutex and the spinlock to protect the tree, but you really
> > want to have the logic dealing with those locks and how they both
> > protect the tree in common code and not in some random place.
> 
> rotfl.  "per tree locking".  That's farsical when you have muxes which
> select between different distinct trees.  That _surely_ is the path to
> locking mayhem, because the child clocks can have their lock changed
> beneath them as the mux changes its parent.
> 
> I still think you're in a different universe.

No, we just seem to talk past each other a lot.

So what you are referring to is the situation where you have different
root clocks and consider them as a separate tree. There are two
possible solutions to that:

1) Global locking

2) Per root clock tree locking:

   That can be done, when the handling is at the clk_FN() API level.

   clk_set_parent(clk, parent)
   {
	lock_trees(clk, parent);
	
	handle_parent_switch();

	unlock_trees(clk, parent); 
   }

   That's not a mayhem, as (un)lock_trees() can easily take care of
   the lock ordering issues.

   It's going to be a mayhem if you have lock pointers and lock
   functions outside of the core code and let random clk
   implementations fiddle with it.

That's why I'm arguing for moving the tree handling and tree traversal
functions one level above the building block abstractions.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 15:31                                 ` Thomas Gleixner
@ 2011-04-29 22:07                                   ` Russell King - ARM Linux
  2011-04-29 22:16                                     ` Thomas Gleixner
  0 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 22:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2011 at 05:31:44PM +0200, Thomas Gleixner wrote:
> Lets look at a simple example (locking omitted)
> 
> clk_enable(clk) {
> 	if (clk->enable_count == 0) {
>   	   res = clk->ops->enable(clk);
> 	   if (res)
> 	      return res;
>         }
> 	enable_count++;
> 	return 0;
> };   
> 
> So in each enable op you have:
> 
> *_enable(clk)
> {
> 	res = clk_enable(clk_get_parent(clk));
> 	if (res)
> 		return res;
> 
> 	res = hw_magic_enable(clk);
> 	if (res)
> 		clk_disable(clk_get_parent(clk));
> 	return res;
> }
> 
> Instead of having at the core level:
> 
> clk_enable(clk)
> {
> 	if (clk->enable_count == 0) {
> 		res = clk_enable(clk_get_parent(clk));
> 		if (res)
> 			return res;
> 
> 		res = clk->ops->enable(clk);
> 		if (res) {
> 			clk_disable(clk_get_parent(clk));
> 			return res;
> 		}
> 	}
> 	clk->enable_count++;
> 	return 0;
> }

I'm going to give up discussing this with you - you have no desire to
even understand what I'm saying.  I don't see any point continuing this
discussion any further.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 22:07                                   ` Russell King - ARM Linux
@ 2011-04-29 22:16                                     ` Thomas Gleixner
  2011-04-29 22:19                                       ` Russell King - ARM Linux
  0 siblings, 1 reply; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 22:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> On Fri, Apr 29, 2011 at 05:31:44PM +0200, Thomas Gleixner wrote:
> > }
> 
> I'm going to give up discussing this with you - you have no desire to
> even understand what I'm saying.  I don't see any point continuing this
> discussion any further.

Right, I have no interest in understanding what you want to do. 

At the same time I have yet to see any reasonable answer to basic
questions how the locking and the very basic tree traversal rules are
going to be.

All I got so far is that I'm living in the wrong universe and that I'm
neither able nor willing to understand the reasoning behind your grand
master plan. Pretty constructive.

Thanks,

	tglx

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 22:16                                     ` Thomas Gleixner
@ 2011-04-29 22:19                                       ` Russell King - ARM Linux
  2011-04-29 22:47                                         ` Thomas Gleixner
  0 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-29 22:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Apr 30, 2011 at 12:16:52AM +0200, Thomas Gleixner wrote:
> On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> > On Fri, Apr 29, 2011 at 05:31:44PM +0200, Thomas Gleixner wrote:
> > > }
> > 
> > I'm going to give up discussing this with you - you have no desire to
> > even understand what I'm saying.  I don't see any point continuing this
> > discussion any further.
> 
> Right, I have no interest in understanding what you want to do. 

And that's your basic problem.  You don't even want to try and understand
these arguments.  So its pointless continuing the discussion.

Thanks for confirming that I've been wasting my time over the last couple
of days.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 22:19                                       ` Russell King - ARM Linux
@ 2011-04-29 22:47                                         ` Thomas Gleixner
  0 siblings, 0 replies; 165+ messages in thread
From: Thomas Gleixner @ 2011-04-29 22:47 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> On Sat, Apr 30, 2011 at 12:16:52AM +0200, Thomas Gleixner wrote:
> > On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> > > On Fri, Apr 29, 2011 at 05:31:44PM +0200, Thomas Gleixner wrote:
> > > > }
> > > 
> > > I'm going to give up discussing this with you - you have no desire to
> > > even understand what I'm saying.  I don't see any point continuing this
> > > discussion any further.
> > 
> > Right, I have no interest in understanding what you want to do. 
> 
> And that's your basic problem.  You don't even want to try and understand
> these arguments.  So its pointless continuing the discussion.

I see. We are at the point where selective quoting is the solution to
the problem. And yes, it's my fault that I forgot to put the <SARCASM>
tags around that sentence.

> Thanks for confirming that I've been wasting my time over the last couple
> of days.

If you insist on moving a technical discussion to a personal
mudslinging level, then we really can stop right here.

Thanks,

	tglx

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

* [PATCH 01/10] Add a common struct clk
  2011-04-15 19:08 ` [PATCH 01/10] Add a common struct clk Sascha Hauer
  2011-04-21 19:48   ` Thomas Gleixner
@ 2011-04-30  8:06   ` Linus Walleij
  2011-04-30  9:01     ` Russell King - ARM Linux
  2011-05-01 20:33   ` Rob Herring
  2 siblings, 1 reply; 165+ messages in thread
From: Linus Walleij @ 2011-04-30  8:06 UTC (permalink / raw)
  To: linux-arm-kernel

2011/4/15 Sascha Hauer <s.hauer@pengutronix.de>:
> From: Jeremy Kerr <jeremy.kerr@canonical.com>

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

Sorry for this late comment, maybe already adressed:

> +int clk_enable(struct clk *clk)
> +{
> + ? ? ? unsigned long flags;
> + ? ? ? int ret = 0;
> +
> + ? ? ? WARN_ON(clk->prepare_count == 0);
> +
> + ? ? ? spin_lock_irqsave(&clk->enable_lock, flags);
> + ? ? ? if (clk->enable_count == 0 && clk->ops->enable)
> + ? ? ? ? ? ? ? ret = clk->ops->enable(clk);

Here the spinlock is held requiring the clock implementation to
be non-sleeping, something that has been discussed at no end,
without addressing that eternal debate, please just drop the
spinlock during the ->enable() call, what is it protecting during
that time anyway...

> +
> + ? ? ? if (!ret)
> + ? ? ? ? ? ? ? clk->enable_count++;
> + ? ? ? spin_unlock_irqrestore(&clk->enable_lock, flags);
> +
> + ? ? ? return ret;
> +}
> +EXPORT_SYMBOL_GPL(clk_enable);
> +
> +void clk_disable(struct clk *clk)
> +{
> + ? ? ? unsigned long flags;
> +
> + ? ? ? spin_lock_irqsave(&clk->enable_lock, flags);
> +
> + ? ? ? WARN_ON(clk->enable_count == 0);
> +
> + ? ? ? if (!--clk->enable_count == 0 && clk->ops->disable)
> + ? ? ? ? ? ? ? clk->ops->disable(clk);

Same here.

> +
> + ? ? ? spin_unlock_irqrestore(&clk->enable_lock, flags);
> +}
> +EXPORT_SYMBOL_GPL(clk_disable);

Apart from that I need to add that I really like the spirit this patch.

Yours,
Linus Walleij

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

* [PATCH 01/10] Add a common struct clk
  2011-04-30  8:06   ` Linus Walleij
@ 2011-04-30  9:01     ` Russell King - ARM Linux
  2011-04-30 16:30       ` Linus Walleij
  0 siblings, 1 reply; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-04-30  9:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Apr 30, 2011 at 10:06:18AM +0200, Linus Walleij wrote:
> 2011/4/15 Sascha Hauer <s.hauer@pengutronix.de>:
> > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> 
> > We currently have ~21 definitions of struct clk in the ARM architecture,
> > each defined on a per-platform basis. This makes it difficult to define
> > platform- (or architecture-) independent clock sources without making
> > assumptions about struct clk, and impossible to compile two
> > platforms with different struct clks into a single image.
> 
> Sorry for this late comment, maybe already adressed:
> 
> > +int clk_enable(struct clk *clk)
> > +{
> > + ? ? ? unsigned long flags;
> > + ? ? ? int ret = 0;
> > +
> > + ? ? ? WARN_ON(clk->prepare_count == 0);
> > +
> > + ? ? ? spin_lock_irqsave(&clk->enable_lock, flags);
> > + ? ? ? if (clk->enable_count == 0 && clk->ops->enable)
> > + ? ? ? ? ? ? ? ret = clk->ops->enable(clk);
> 
> Here the spinlock is held requiring the clock implementation to
> be non-sleeping, something that has been discussed at no end,
> without addressing that eternal debate, please just drop the
> spinlock during the ->enable() call, what is it protecting during
> that time anyway...

clk->enable_count and two concurrent enables passing each other (eg,
while one enable is in progress, another enable may pass it unless
the spinlock is held.)

That's not going to change; we decided that the enable call shall be
non-sleeping for everything.  That's why we introduced the prepare
call for the sleeping part of the problem.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 13:26                               ` Russell King - ARM Linux
  2011-04-29 15:31                                 ` Thomas Gleixner
@ 2011-04-30 14:27                                 ` torbenh
  2011-05-03  6:35                                   ` Colin Cross
  2011-05-03  2:44                                 ` Saravana Kannan
  2 siblings, 1 reply; 165+ messages in thread
From: torbenh @ 2011-04-30 14:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Apr 29, 2011 at 02:26:13PM +0100, Russell King - ARM Linux wrote:
> On Fri, Apr 29, 2011 at 02:13:06PM +0200, Thomas Gleixner wrote:
> > This are all well defined semantical problems and should be solved in
> > common code rather than having different buggy implementations in each
> > SoC clock "framework".
> 
> Why are you associating functional elements in drivers/clk with the
> SoC clock framework?

i think i pretty much understand what thomas is after. but i have
problems understanding, what you want here.

until this point, it looks like you only want the driver/clk to
model the clock endpoints inside the devices. A device itself shouldnt
be caring for clock parents or anything. its only concern is that a
clock pin is fed with the right frequency, or off...

> 
> I think that's the root cause of this misunderstanding, and until you
> start realising that these building blocks are not part of the SoC
> implementation, we're going to continue arguing about this.

what you say now, pretty much sounds like what thomas wants.
these building blocks would be objects derived from the clock baseclass,
which thomas is trying to define. he doesnt seem to be concerned about
the second more special layer yet.

i am quite puzzled, what exactly your fighting over :S


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

-- 
torben Hohn

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

* [PATCH 01/10] Add a common struct clk
  2011-04-30  9:01     ` Russell King - ARM Linux
@ 2011-04-30 16:30       ` Linus Walleij
  0 siblings, 0 replies; 165+ messages in thread
From: Linus Walleij @ 2011-04-30 16:30 UTC (permalink / raw)
  To: linux-arm-kernel

2011/4/30 Russell King - ARM Linux <linux@arm.linux.org.uk>:

> we decided that the enable call shall be
> non-sleeping for everything. ?That's why we introduced the prepare
> call for the sleeping part of the problem.

Ah, that makes perfect sense. Let's go ahead with this.

Yours,
Linus Walleij

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

* [PATCH 01/10] Add a common struct clk
  2011-04-29 11:01         ` Russell King - ARM Linux
@ 2011-04-30 18:30           ` Pavel Machek
  0 siblings, 0 replies; 165+ messages in thread
From: Pavel Machek @ 2011-04-30 18:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri 2011-04-29 12:01:15, Russell King - ARM Linux wrote:
> On Fri, Apr 29, 2011 at 12:45:00PM +0200, Thomas Gleixner wrote:
> > On Fri, 29 Apr 2011, Russell King - ARM Linux wrote:
> > 
> > > On Thu, Apr 21, 2011 at 09:48:28PM +0200, Thomas Gleixner wrote:
> > > > On Fri, 15 Apr 2011, Sascha Hauer wrote:
> > > > > From: Jeremy Kerr <jeremy.kerr@canonical.com>
> > > > > + * @get:	Called by the core clock code when a device driver acquires a
> > > > > + *		clock via clk_get(). Optional.
> > > > > + *
> > > > > + * @put:	Called by the core clock code when a devices driver releases a
> > > > > + *		clock via clk_put(). Optional.
> > > > 
> > > > These callbacks are completely pointless. There are only two non empty
> > > > implementations in tree:
> > > > 
> > > > One does a try_module_get(clk->owner), which should be done in generic
> > > > code. The other does special clock enabling magic which wants to go to
> > > > clk->prepare().
> > > 
> > > I disagree.  Most clocks don't live in a module - there's only one
> > > platform which does at present.  To force every clock to have an owner
> > > field is rediculous.  We already know that the OMAP tree represents a
> > 
> > So we trade an owner field (which can be NULL) versus two function
> > pointers in the clk_ops struct, which are of course subject to be
> > abused for all kind of crap which does not belong there at all.
> 
> And the current __clk_get/__clk_put stuff has been abused to hell and
> back hasn't it with just three implementations.  While I agree with your
> sentiment, lets agree to address that _if_ it becomes a problem.  At
> the moment, we have _enough_ problems to deal with, we don't need to
> invent new ones which really don't matter at this stage.

So lets.. add the pointer and see if 4K lost is a problem for
someone...?

It should be 'nice abstractions first, optimalizations later'...
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* [PATCH 01/10] Add a common struct clk
  2011-04-15 19:08 ` [PATCH 01/10] Add a common struct clk Sascha Hauer
  2011-04-21 19:48   ` Thomas Gleixner
  2011-04-30  8:06   ` Linus Walleij
@ 2011-05-01 20:33   ` Rob Herring
  2011-05-02  1:09     ` Jeremy Kerr
  2 siblings, 1 reply; 165+ messages in thread
From: Rob Herring @ 2011-05-01 20:33 UTC (permalink / raw)
  To: linux-arm-kernel

Jeremy,

On 04/15/2011 02:08 PM, Sascha Hauer wrote:
> From: Jeremy Kerr<jeremy.kerr@canonical.com>
>
> We currently have ~21 definitions of struct clk in the ARM architecture,
> each defined on a per-platform basis. This makes it difficult to define
> platform- (or architecture-) independent clock sources without making
> assumptions about struct clk, and impossible to compile two
> platforms with different struct clks into a single image.
>
> This change is an effort to unify struct clk where possible, by defining
> a common struct clk, containing a set of clock operations. Different
> clock implementations can set their own operations, and have a standard
> interface for generic code. The callback interface is exposed to the
> kernel proper, while the clock implementations only need to be seen by
> the platform internals.
>
> This allows us to share clock code among platforms, and makes it
> possible to dynamically create clock devices in platform-independent
> code.
>
> Platforms can enable the generic struct clock through
> CONFIG_USE_COMMON_STRUCT_CLK. In this case, the clock infrastructure
> consists of a common struct clk:
>
> struct clk {
> 	const struct clk_ops	*ops;
> 	unsigned int		enable_count;
> 	unsigned int		prepare_count;
> 	spinlock_t		enable_lock;
> 	struct mutex		prepare_lock;
> };
>
> And a set of clock operations (defined per type of clock):
>
> struct clk_ops {
> 	int             (*enable)(struct clk *);
> 	void            (*disable)(struct clk *);
> 	unsigned long   (*get_rate)(struct clk *);
> 	[...]
> };
>
> To define a hardware-specific clock, machine code can "subclass" the
> struct clock into a new struct (adding any device-specific data), and
> provide a set of operations:
>
> struct clk_foo {
> 	struct clk	clk;
> 	void __iomem	*some_register;
> };
>
> struct clk_ops clk_foo_ops = {
> 	.get_rate = clk_foo_get_rate,
> };
>
> The common clock definitions are based on a development patch from Ben
> Herrenschmidt<benh@kernel.crashing.org>.
>
> Signed-off-by: Jeremy Kerr<jeremy.kerr@canonical.com>
> Signed-off-by: Uwe Kleine-K?nig<u.kleine-koenig@pengutronix.de>
> ---
>   drivers/clk/Kconfig  |    3 +
>   drivers/clk/Makefile |    1 +
>   drivers/clk/clk.c    |  132 ++++++++++++++++++++++++++++++++++++++++
>   drivers/clk/clkdev.c |    7 ++
>   include/linux/clk.h  |  164 +++++++++++++++++++++++++++++++++++++++++++++++---
>   5 files changed, 298 insertions(+), 9 deletions(-)
>   create mode 100644 drivers/clk/clk.c
>
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index 4168c88..6e3ae54 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -2,3 +2,6 @@
>   config CLKDEV_LOOKUP
>   	bool
>   	select HAVE_CLK
> +
> +config USE_COMMON_STRUCT_CLK
> +	bool
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 07613fa..a1a06d3 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -1,2 +1,3 @@
>
>   obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
> +obj-$(CONFIG_USE_COMMON_STRUCT_CLK) += clk.o
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> new file mode 100644
> index 0000000..0bc9c6f
> --- /dev/null
> +++ b/drivers/clk/clk.c
> @@ -0,0 +1,132 @@
> +/*
> + * Copyright (C) 2010-2011 Canonical Ltd<jeremy.kerr@canonical.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * Standard functionality for the common clock API.
> + */
> +
> +#include<linux/clk.h>
> +#include<linux/module.h>
> +
> +int clk_prepare(struct clk *clk)
> +{
> +	int ret = 0;
> +

Shouldn't all these functions have some clk pointer checks:

	if (IS_ERR_OR_NULL(clk))
		return -EINVAL;


Rob

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

* [PATCH 01/10] Add a common struct clk
  2011-05-01 20:33   ` Rob Herring
@ 2011-05-02  1:09     ` Jeremy Kerr
  2011-05-02  3:09       ` Rob Herring
  0 siblings, 1 reply; 165+ messages in thread
From: Jeremy Kerr @ 2011-05-02  1:09 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Rob,

> > +int clk_prepare(struct clk *clk)
> > +{
> > +	int ret = 0;
> > +
> 
> Shouldn't all these functions have some clk pointer checks:
> 
> 	if (IS_ERR_OR_NULL(clk))
> 		return -EINVAL;
> 

No, I'd prefer not to. The driver code should be responsible for passing
a valid pointer here, by doing this check once (where the clock is
initially acquired through clk_get), rather than the core code doing it
on each function call.

Cheers,


Jeremy

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

* [PATCH 01/10] Add a common struct clk
  2011-05-02  1:09     ` Jeremy Kerr
@ 2011-05-02  3:09       ` Rob Herring
  2011-05-02  3:40         ` Jeremy Kerr
  0 siblings, 1 reply; 165+ messages in thread
From: Rob Herring @ 2011-05-02  3:09 UTC (permalink / raw)
  To: linux-arm-kernel

Jeremy,

On 05/01/2011 08:09 PM, Jeremy Kerr wrote:
> Hi Rob,
>
>>> +int clk_prepare(struct clk *clk)
>>> +{
>>> +	int ret = 0;
>>> +
>>
>> Shouldn't all these functions have some clk pointer checks:
>>
>> 	if (IS_ERR_OR_NULL(clk))
>> 		return -EINVAL;
>>
>
> No, I'd prefer not to. The driver code should be responsible for passing
> a valid pointer here, by doing this check once (where the clock is
> initially acquired through clk_get), rather than the core code doing it
> on each function call.

I think you will find many examples in the kernel where that is not done 
by drivers. It is also common that the same driver is used on platforms 
with and without clock support. Adding NULL ptr checks around every clk 
api function makes for ugly and duplicated code.

Every implementation of clk_enable that I looked at does this check in 
their implementation. I looked at omap, imx, spear, and samsung. Seems 
like we should try to minimize breakage from switching to common struct clk.

Rob

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

* [PATCH 01/10] Add a common struct clk
  2011-05-02  3:09       ` Rob Herring
@ 2011-05-02  3:40         ` Jeremy Kerr
  2011-05-02 16:30           ` Rob Herring
  2011-05-02 16:55           ` David Brown
  0 siblings, 2 replies; 165+ messages in thread
From: Jeremy Kerr @ 2011-05-02  3:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Rob,

> I think you will find many examples in the kernel where that is not done 
> by drivers.

Drivers should be checking the return value of clk_get - if they don't,
it's a bug. This is the logical place to check, rather than before all
clock API calls.

For cases where there is no clock provided for the device (but is a
valid clock on some machines), the platform code should return a no-op
clock from the clk_get call. This 'noop clock' would be a good contender
for inclusion into the kernel-wide infrastructure, like clk_fixed.

Cheers,


Jeremy

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-28 15:22     ` Russell King - ARM Linux
@ 2011-05-02  7:58       ` Sascha Hauer
  0 siblings, 0 replies; 165+ messages in thread
From: Sascha Hauer @ 2011-05-02  7:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 28, 2011 at 04:22:17PM +0100, Russell King - ARM Linux wrote:
> On Mon, Apr 18, 2011 at 11:49:09AM +0200, Uwe Kleine-K?nig wrote:
> > > +static int clk_divider_set_rate(struct clk *clk, unsigned long rate)
> > > +{
> > > +	unsigned long best_parent_rate;
> > > +	struct clk_divider *divider = to_clk_divider(clk);
> > > +	unsigned int div;
> > > +	int ret;
> > > +	unsigned long flags = 0;
> > > +	u32 val;
> > > +
> > > +	div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
> > > +
> > > +	if (rate != best_parent_rate / div)
> > > +		return -EINVAL;
> > This is too harsh, isn't it. Or can you expect to only get values that
> > are returned by round_rate? Again you need DIV_ROUND_UP.
> 
> It is too harsh, and I've wished many a time that people would implement
> clk_set_rate() and clk_round_rate() as:
> 
> long clk_round_rate(struct clk *clk, unsigned long rate)
> {
> 	err = calculate_clock_paramters(clk, params, rate);
> 	if (err < 0)
> 		return err;
> 	return calculate_clock_rate(clk, params);
> }
> 
> int clk_set_rate(struct clk *clk, unsigned long rate)
> {
> 	err = calculate_clock_parameters(clk, params, rate);
> 	if (err < 0)
> 		return err;
> 	set_clock_parameters(clk, params);
> 	clk->rate = calculate_clock_rate(clk, params);
> 	return 0;
> }
> 
> IOW, clk_round_rate() does what clk_set_rate() does but does _not_ set
> the hardware rate itself.

Ok. It's easier to implement anyway since rounding errors do not have
such a bad impact.

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

* [PATCH 01/10] Add a common struct clk
  2011-05-02  3:40         ` Jeremy Kerr
@ 2011-05-02 16:30           ` Rob Herring
  2011-05-02 22:36             ` Russell King - ARM Linux
  2011-05-02 16:55           ` David Brown
  1 sibling, 1 reply; 165+ messages in thread
From: Rob Herring @ 2011-05-02 16:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/01/2011 10:40 PM, Jeremy Kerr wrote:
> Hi Rob,
>
>> I think you will find many examples in the kernel where that is not done
>> by drivers.
>
> Drivers should be checking the return value of clk_get - if they don't,
> it's a bug. This is the logical place to check, rather than before all
> clock API calls.

Maybe so, but it's common practice. Why not allow it, but add a warning? 
Or allow NULL, but not an error value.

> For cases where there is no clock provided for the device (but is a
> valid clock on some machines), the platform code should return a no-op
> clock from the clk_get call. This 'noop clock' would be a good contender
> for inclusion into the kernel-wide infrastructure, like clk_fixed.
>

There could be cases where the driver wants to know if there is no 
clock. A cpufreq driver for example would be pointless to register if no 
clock is available. Making the every platform clk_get code have to 
handle the 2 cases would require the platform code to know what the 
driver wants. Also, it would require at least some platform clock code 
to enable a new platform if you have existing drivers with both cases.

You could do something like this:

clk = clk_get(mydev, NULL);
if (IS_ERR(clk))
	clk = noop_clk;

Or add a variation of clk_get like clk_get_or_fail where clk_get returns 
noop clk and clk_get_or_fail returns nothing if the clock is not found.

Rob

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

* [PATCH 01/10] Add a common struct clk
  2011-05-02  3:40         ` Jeremy Kerr
  2011-05-02 16:30           ` Rob Herring
@ 2011-05-02 16:55           ` David Brown
  2011-05-02 17:31             ` Stephen Boyd
  1 sibling, 1 reply; 165+ messages in thread
From: David Brown @ 2011-05-02 16:55 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, May 01 2011, Jeremy Kerr wrote:

> Hi Rob,
>
>> I think you will find many examples in the kernel where that is not done 
>> by drivers.
>
> Drivers should be checking the return value of clk_get - if they don't,
> it's a bug. This is the logical place to check, rather than before all
> clock API calls.
>
> For cases where there is no clock provided for the device (but is a
> valid clock on some machines), the platform code should return a no-op
> clock from the clk_get call. This 'noop clock' would be a good contender
> for inclusion into the kernel-wide infrastructure, like clk_fixed.

Having a general fixed clock is a good idea.  There seem to be several
'dummy' clocks under various subarchs, and Stephen Boyd posted one for
MSM on March 24.

Most of the MSM drivers check the clk_get and fail to probe the driver
if the clock is unavailable.

David

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

* [PATCH 01/10] Add a common struct clk
  2011-05-02 16:55           ` David Brown
@ 2011-05-02 17:31             ` Stephen Boyd
  0 siblings, 0 replies; 165+ messages in thread
From: Stephen Boyd @ 2011-05-02 17:31 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/02/2011 09:55 AM, David Brown wrote:
> On Sun, May 01 2011, Jeremy Kerr wrote:
>
>> Hi Rob,
>>
>>> I think you will find many examples in the kernel where that is not done 
>>> by drivers.
>> Drivers should be checking the return value of clk_get - if they don't,
>> it's a bug. This is the logical place to check, rather than before all
>> clock API calls.
>>
>> For cases where there is no clock provided for the device (but is a
>> valid clock on some machines), the platform code should return a no-op
>> clock from the clk_get call. This 'noop clock' would be a good contender
>> for inclusion into the kernel-wide infrastructure, like clk_fixed.
> Having a general fixed clock is a good idea.  There seem to be several
> 'dummy' clocks under various subarchs, and Stephen Boyd posted one for
> MSM on March 24.
>
> Most of the MSM drivers check the clk_get and fail to probe the driver
> if the clock is unavailable.

Actually I would like to build the dummy clock into the core and just
have the dummy clock be a NULL pointer. I didn't do this in the MSM code
because clkdev wasn't properly handling the NULL clock case. That has
since been fixed by Russell elsewhere in this thread.

Subject: Re: [PATCH 06/10] clk: Add support for a generic clock multiplexer
Message-ID: <20110418184138.GE25671@n2100.arm.linux.org.uk>
http://lkml.kernel.org/n/20110418184138.GE25671 at n2100.arm.linux.org.uk


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

* [PATCH 01/10] Add a common struct clk
  2011-05-02 16:30           ` Rob Herring
@ 2011-05-02 22:36             ` Russell King - ARM Linux
  2011-05-03  0:22               ` Saravana Kannan
  2011-05-04 23:35               ` Paul Walmsley
  0 siblings, 2 replies; 165+ messages in thread
From: Russell King - ARM Linux @ 2011-05-02 22:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, May 02, 2011 at 11:30:10AM -0500, Rob Herring wrote:
> On 05/01/2011 10:40 PM, Jeremy Kerr wrote:
>> Hi Rob,
>>
>>> I think you will find many examples in the kernel where that is not done
>>> by drivers.
>>
>> Drivers should be checking the return value of clk_get - if they don't,
>> it's a bug. This is the logical place to check, rather than before all
>> clock API calls.
>
> Maybe so, but it's common practice. Why not allow it, but add a warning?  
> Or allow NULL, but not an error value.

If drivers don't check the return value of clk_get() then they'll suffer
kernel oopses.  What's to say that if the driver doesn't check the return
value from clk_get() that they'll bother checking the return value from
any of the other clk_* API functions.  Nothing.

So, checking for ERR values inside the clk_* functions is silly, and just
means that buggy drivers continue with undiscovered bugs because they
happen not to fail.

>> For cases where there is no clock provided for the device (but is a
>> valid clock on some machines), the platform code should return a no-op
>> clock from the clk_get call. This 'noop clock' would be a good contender
>> for inclusion into the kernel-wide infrastructure, like clk_fixed.
>
> There could be cases where the driver wants to know if there is no  
> clock.

How exactly would a driver know that the clock it has is a no-op clock
with it being a pointer to some random data structure?  A better question
would be in the case of a cpufreq driver, how would such a driver know
that it's pointless trying to set the rate on a fixed rate clock?

There's soo many combinations here where you can say "if a clock has
property X, then maybe the driver doesn't want to do Y".  So, instead
of trying to cover all the possibilities, take a step back and look at
the bigger picture.

1. in a cpufreq driver, if it gets a clock, one would hope that the
clock it has been provided with is adjustable - in other words,
clk_set_rate() stands a chance of succeeding.  If it fails, then it
has the wrong clock.

2. if the clock it has does not support adjustments in this way, then
there is a bug in the data involved in selecting that clock, and that's
what's at fault.  You find this out when you try to change its rate
via clk_set_rate() which should fail.

3. (to head off something that I can see being proposed) no, I don't
think we need a system of properties.

A cpufreq driver which obtains clks should be no different from any
other driver.  It should get a clk via clk_get(), and report errors if
that fails.  If clk_set_rate() fails, then it should report that error
too.  There's really nothing "special" here.

This does bring us to an interesting question though: should clk_set_rate()
succeed or fail with a NULL clk?  There is no clock to control, so my
feeling is that it should fail, just like clk_get_rate() should return
zero because the rate is meaningless.  There is no rate to get and no
rate to set.

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

* [PATCH 01/10] Add a common struct clk
  2011-05-02 22:36             ` Russell King - ARM Linux
@ 2011-05-03  0:22               ` Saravana Kannan
  2011-05-04  6:40                 ` Sascha Hauer
  2011-05-04 23:35               ` Paul Walmsley
  1 sibling, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-05-03  0:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/02/2011 03:36 PM, Russell King - ARM Linux wrote:
> On Mon, May 02, 2011 at 11:30:10AM -0500, Rob Herring wrote:
>> On 05/01/2011 10:40 PM, Jeremy Kerr wrote:
>>> Hi Rob,
>>>
>>>> I think you will find many examples in the kernel where that is not done
>>>> by drivers.
>>>
>>> Drivers should be checking the return value of clk_get - if they don't,
>>> it's a bug. This is the logical place to check, rather than before all
>>> clock API calls.
>>
>> Maybe so, but it's common practice. Why not allow it, but add a warning?
>> Or allow NULL, but not an error value.
>
> If drivers don't check the return value of clk_get() then they'll suffer
> kernel oopses.  What's to say that if the driver doesn't check the return
> value from clk_get() that they'll bother checking the return value from
> any of the other clk_* API functions.  Nothing.
>
> So, checking for ERR values inside the clk_* functions is silly, and just
> means that buggy drivers continue with undiscovered bugs because they
> happen not to fail.
>
>>> For cases where there is no clock provided for the device (but is a
>>> valid clock on some machines), the platform code should return a no-op
>>> clock from the clk_get call. This 'noop clock' would be a good contender
>>> for inclusion into the kernel-wide infrastructure, like clk_fixed.
>>
>> There could be cases where the driver wants to know if there is no
>> clock.
>
> How exactly would a driver know that the clock it has is a no-op clock
> with it being a pointer to some random data structure?  A better question
> would be in the case of a cpufreq driver, how would such a driver know
> that it's pointless trying to set the rate on a fixed rate clock?
>
> There's soo many combinations here where you can say "if a clock has
> property X, then maybe the driver doesn't want to do Y".  So, instead
> of trying to cover all the possibilities, take a step back and look at
> the bigger picture.
>
> 1. in a cpufreq driver, if it gets a clock, one would hope that the
> clock it has been provided with is adjustable - in other words,
> clk_set_rate() stands a chance of succeeding.  If it fails, then it
> has the wrong clock.
>
> 2. if the clock it has does not support adjustments in this way, then
> there is a bug in the data involved in selecting that clock, and that's
> what's at fault.  You find this out when you try to change its rate
> via clk_set_rate() which should fail.
>
> 3. (to head off something that I can see being proposed) no, I don't
> think we need a system of properties.
>
> A cpufreq driver which obtains clks should be no different from any
> other driver.  It should get a clk via clk_get(), and report errors if
> that fails.  If clk_set_rate() fails, then it should report that error
> too.  There's really nothing "special" here.
>
> This does bring us to an interesting question though: should clk_set_rate()
> succeed or fail with a NULL clk?  There is no clock to control, so my
> feeling is that it should fail, just like clk_get_rate() should return
> zero because the rate is meaningless.  There is no rate to get and no
> rate to set.

I think having NULL clocks return success on set_rate() would be more 
useful. The most common use case for NULL clocks is when a clocks is 
present in some soc/arch/mach but is not present in another. Instead of 
having the consumers having an "if" around every clk_* calls on that 
clk, they would get a NULL clk. If NULL clk starts failing for 
clk_set_rate(), I think the point of a NULL clk will get defeated.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-29 13:26                               ` Russell King - ARM Linux
  2011-04-29 15:31                                 ` Thomas Gleixner
  2011-04-30 14:27                                 ` torbenh
@ 2011-05-03  2:44                                 ` Saravana Kannan
  2011-05-03  2:46                                   ` Saravana Kannan
  2 siblings, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-05-03  2:44 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/29/2011 06:26 AM, Russell King - ARM Linux wrote:
> On Fri, Apr 29, 2011 at 02:13:06PM +0200, Thomas Gleixner wrote:
>> This are all well defined semantical problems and should be solved in
>> common code rather than having different buggy implementations in each
>> SoC clock "framework".
>
> Why are you associating functional elements in drivers/clk with the
> SoC clock framework?
>
> I think that's the root cause of this misunderstanding, and until you
> start realising that these building blocks are not part of the SoC
> implementation, we're going to continue arguing about this.

Ok, the discussion went down hill real quick after this point. So, I 
will start from here.

I will try and propose what I think might be a reasonable compromise 
based on what I have seen so far.

I think Thomas mostly cares about having the tree handling done at the 
core code level. Russell's main point seems to be that the parent can 
change for reasons other than "clk_set_parent()" and hence we can have 
the core code manage all of the parent handling.

The parent of a clock can really change for only two reasons (based on 
my experience with clocks -- in no way extensive, but not insignificant 
either):
* clk_set_rate() -- where the set rate code takes care of selecting the 
right parent for a given rate.
* clk_set_parent() -- where the "clk" is just a mux of a random bunch of 
inputs and we just allow the caller to pick the mux input. The clock 
framework might not even know what the rate/characteristic (jitter, duty 
cycle, etc) of the input are since some of them could come from an 
external source that's board specific.

A simple compromise might be to have the generic/base clk structure have 
a "parent" field. Then the generic clk_set_parent() and clk_set_rate() 
would grab the clock's mutex (currently named prepare_lock) before 
calling the clk->ops->set_rate/set_parent. I already suggested grabbing 
this mutex when Jeremy's patches were being review, but it was put off 
for later/Soc specific code (forgot what the decision was). That's why 
we see a might_sleep() in his clk_set_rate().

With the above suggestion, the Soc specific code can change the parent 
all it wants and the core code can still do the tree handling in 
clk_prepare/clk_unprepare (they already grab the mutex).

Although this might not be what each side wants, I think this is a 
reasonable compromise.

Thomas/Russell, Does it sound acceptable to both of you?

We can go to the per-clock vs. per-tree locking after we can agree on 
this. My current opinion (can change easily) is that while per-tree 
locking might be nice, it might be hard/ugly to capture it in the data 
structures. Per-clock locking will allow the soc-specific code which has 
a better idea of the tree to do per-tree locking internally while 
allowing the core code to handle propagating enable/disable up the tree.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-05-03  2:44                                 ` Saravana Kannan
@ 2011-05-03  2:46                                   ` Saravana Kannan
  0 siblings, 0 replies; 165+ messages in thread
From: Saravana Kannan @ 2011-05-03  2:46 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/02/2011 07:44 PM, Saravana Kannan wrote:
> I think Thomas mostly cares about having the tree handling done at the
> core code level. Russell's main point seems to be that the parent can
> change for reasons other than "clk_set_parent()" and hence we can have
> the core code manage all of the parent handling.

Typo. Meant to say:
and hence we can't have the core code manage all of the parent handling.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-04-28 15:14         ` Russell King - ARM Linux
@ 2011-05-03  3:37           ` Saravana Kannan
  2011-05-03  7:12             ` Uwe Kleine-König
  0 siblings, 1 reply; 165+ messages in thread
From: Saravana Kannan @ 2011-05-03  3:37 UTC (permalink / raw)
  To: linux-arm-kernel

On 04/28/2011 08:14 AM, Russell King - ARM Linux wrote:
> On Mon, Apr 18, 2011 at 07:45:53PM -0700, Saravana Kannan wrote:
>> On 04/18/2011 03:07 AM, Sascha Hauer wrote:
>>> AFAIK there are two different implementation types in the tree. Some
>>> implementations only allow to set to the exact rate round_rate returns
>>> while others round down in set_rate.
>>>
>>> Has this been specified what behaviour is expected?
>>>
>>
>> This is something I have nagged Russell once or twice about and then
>> sent out an email to the list for which there was very limited response.
>> I think clk_round_rate() is too generic and not very useful.
>
> As I've always said, clk_round_rate() returns the rate which you will
> get if you ask clk_set_rate() to set the same rate.  It's not ment to
> be "tell me the clock rate which I'd like to then pass to clk_set_rate(),
> oh that's not good enough, so lets tweak it a bit and try again".

Yes, I understood the purpose of clk_round_rate() from the previous 
discussion we had.

> For example, take a video driver.  The user passes in the pixel clock as
> a picosecond argument.  This gets converted to Hz.  We can then use
> clk_round_rate() to find out what clock rate we _actually_ end up with
> when we set that rate using clk_set_rate(), and return that rate (again
> as ps) back to the user before we alter anything.  The user can then
> make a decision whether they want to actually set it.

Sure clk_round_rate() might be sufficient for this case.

> Having some sort of range stuff doesn't help you there because you're
> not supplied a range from userspace.  You're just asked to set a 39752ps
> clock rate.

But this not the problem I'm trying to solve though. There are several 
devices that have a freq operating range in their spec sheet and they 
can't operate outside of that range. As of today, when the 
device/drivers are used in multiple soc/arch, they are solving that 
issue either by using clk_round_rate() in a way that you didn't intend 
(to search for a freq that will work for them) or by passing in the 
clock freq through platform data.

I think a better way to solve this problem is to have a 
clk_set_rate_range() and hence suggesting it. This would also help 
reduce the no. of lines/data passed in board files which I think helps 
clean up ARM code.

Btw, one of the use cases this would help is actually related to display 
too. It's some clock that's fed to the display panel (I don't think it's 
the pixel clock) which has a 96 MHz - 103 MHz operating range.

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-04-30 14:27                                 ` torbenh
@ 2011-05-03  6:35                                   ` Colin Cross
  2011-05-05  8:35                                     ` torbenh
  0 siblings, 1 reply; 165+ messages in thread
From: Colin Cross @ 2011-05-03  6:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Apr 30, 2011 at 7:27 AM, torbenh <torbenh@gmx.de> wrote:
> On Fri, Apr 29, 2011 at 02:26:13PM +0100, Russell King - ARM Linux wrote:
>> On Fri, Apr 29, 2011 at 02:13:06PM +0200, Thomas Gleixner wrote:
>> > This are all well defined semantical problems and should be solved in
>> > common code rather than having different buggy implementations in each
>> > SoC clock "framework".
>>
>> Why are you associating functional elements in drivers/clk with the
>> SoC clock framework?
>
> i think i pretty much understand what thomas is after. but i have
> problems understanding, what you want here.
>
> until this point, it looks like you only want the driver/clk to
> model the clock endpoints inside the devices. A device itself shouldnt
> be caring for clock parents or anything. its only concern is that a
> clock pin is fed with the right frequency, or off...
>
>>
>> I think that's the root cause of this misunderstanding, and until you
>> start realising that these building blocks are not part of the SoC
>> implementation, we're going to continue arguing about this.
>
> what you say now, pretty much sounds like what thomas wants.
> these building blocks would be objects derived from the clock baseclass,
> which thomas is trying to define. he doesnt seem to be concerned about
> the second more special layer yet.
>
> i am quite puzzled, what exactly your fighting over :S

Thomas wants a core framework that handles the clock tree, with each
clock being the implementation of just the clock.  Russell thinks this
is impossible, and wants to stop at implementing building blocks for
the standard clock types, and let each SoC put them into a tree.

I don't think anybody can argue that a shared clock tree framework, if
it was possible to do well, would be a benefit.  But there are a few
problems that make abstracting the differences between SoCs very hard
at that level.

After implementing the Tegra clock tree at least 10 times to solve
different problems, there are two very hard problems to solve.

First is locking.  Per-clock locking is hard because it requires
choosing up front which way locking will go, usually locking the
child, then locking the parent, then enabling the parent, and enabling
the child.  Any operation flow that requires traversing the tree from
the parent to the child, for example changing the rate of the parent,
causes lock inversion.  Global locking is easy, but can be wasteful on
platforms that have some very slow clocks (think external i2c clocks),
and some very fast clocks (internal register writes).  This is
mitigated by the separation of clk_prepare and clk_enable locking -
clk_enable can never sleep, so it can't be blocked for long.  Locking
at the root node of the tree would be nice, but most SoCs don't have a
root node - they have a fast root clock and a slow root clock, and can
switch the all or most of clock tree over to the slow clock in some
modes.

The second problem is rate changing.  Different platforms require
wildly different strategies for changing clock rates.  On Tegra,
clk_set_rate will never change the parent, because we can generally
set up the parent clocks to the correct frequencies for all the
devices, and then device drivers can change their dividers to get the
rate they need.  The few cases where the parent needs to change
(cpufreq and display pclk), the driver manually calls clk_set_parent.
On other platforms, it is common to need to change the parent to get
the necessary rate.

Automatically selecting parents in a generic way is impossible.  If
one DEV1 calls clk_set_rate and clk_enable, and the core framework
responds by setting pll A to frequency X, and setting the parent of
DEV1 to A, what happens when DEV2 calls clk_set_rate to a frequency
that can only be satisfied by setting pll A to frequency Y?  DEV1
can't be switched to another pll, because it is already enabled, and
some platforms can't support glitchlessly changing a mux, even if the
frequency doesn't change.

I still think a common implementation of the clock tree framework
would be useful, even if not all platforms can use it.  Allow the
platforms that can to use it, providing only clock data, and maybe a
few clock implementations if the building blocks are not sufficient,
and allow those that can't to implement their own versions of the
clk_* functions on top of the clock building blocks.  Tegra already
has a fairly generic implementation of a clock tree in
arch/arm/mach-tegra/clock.c, moving it to the common clk struct and
sharing it with other platforms wouldn't be any extra code, even if no
other platforms could use it.  And I bet at least OMAP could use it,
from what I've seen.

Per-tree locking is a solvable problem, as long as a tree was
considered as an ordered graph - two root nodes that feed into the
same clocks would be considered part of the same tree.  The core
framework could look at all possible parents of a clock to determine
what clock trees were truly independent, which would result in a
single global lock on most platforms, but multiple locks on platforms
that really had independent clock trees.  Dynamically added clocks
would cause problems with this solution.

I think automatic clock parent and rate setting would need to be
delegated to a platform-specific layer, and I'm not sure how.  Maybe
allow platforms to override the set_rate ops in the clock tree
building blocks, or a new op that can determine the new tree
structure, and call the old set_rate op to set the registers.

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

* [PATCH 05/10] clk: Add support for simple dividers
  2011-05-03  3:37           ` Saravana Kannan
@ 2011-05-03  7:12             ` Uwe Kleine-König
  0 siblings, 0 replies; 165+ messages in thread
From: Uwe Kleine-König @ 2011-05-03  7:12 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

On Mon, May 02, 2011 at 08:37:06PM -0700, Saravana Kannan wrote:
> I think a better way to solve this problem is to have a
> clk_set_rate_range() and hence suggesting it. This would also help
> reduce the no. of lines/data passed in board files which I think
> helps clean up ARM code.
Just an implementation detail: clk_round_rate_range would be enough.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 01/10] Add a common struct clk
  2011-05-03  0:22               ` Saravana Kannan
@ 2011-05-04  6:40                 ` Sascha Hauer
  2011-05-04 18:33                   ` Saravana Kannan
  0 siblings, 1 reply; 165+ messages in thread
From: Sascha Hauer @ 2011-05-04  6:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, May 02, 2011 at 05:22:01PM -0700, Saravana Kannan wrote:
> >This does bring us to an interesting question though: should clk_set_rate()
> >succeed or fail with a NULL clk?  There is no clock to control, so my
> >feeling is that it should fail, just like clk_get_rate() should return
> >zero because the rate is meaningless.  There is no rate to get and no
> >rate to set.
> 
> I think having NULL clocks return success on set_rate() would be
> more useful. The most common use case for NULL clocks is when a
> clocks is present in some soc/arch/mach but is not present in
> another. Instead of having the consumers having an "if" around every
> clk_* calls on that clk, they would get a NULL clk. If NULL clk
> starts failing for clk_set_rate(), I think the point of a NULL clk
> will get defeated.

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

* [PATCH 01/10] Add a common struct clk
  2011-05-04  6:40                 ` Sascha Hauer
@ 2011-05-04 18:33                   ` Saravana Kannan
  0 siblings, 0 replies; 165+ messages in thread
From: Saravana Kannan @ 2011-05-04 18:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/03/2011 11:40 PM, Sascha Hauer wrote:
> On Mon, May 02, 2011 at 05:22:01PM -0700, Saravana Kannan wrote:
>>> This does bring us to an interesting question though: should clk_set_rate()
>>> succeed or fail with a NULL clk?  There is no clock to control, so my
>>> feeling is that it should fail, just like clk_get_rate() should return
>>> zero because the rate is meaningless.  There is no rate to get and no
>>> rate to set.
>>
>> I think having NULL clocks return success on set_rate() would be
>> more useful. The most common use case for NULL clocks is when a
>> clocks is present in some soc/arch/mach but is not present in
>> another. Instead of having the consumers having an "if" around every
>> clk_* calls on that clk, they would get a NULL clk. If NULL clk
>> starts failing for clk_set_rate(), I think the point of a NULL clk
>> will get defeated.
>
>  From my experience when a clock is present on one SoC but not on another
> the actual rate does not matter, only enabling/disabling the clock for
> register accesses is important. When a driver sets a rate on a clock it
> does it on purpose and if this clock is not even present on other SoCs
> it looks like a bug or at least a very special case for me. So I think
> clk_set_rate for a NULL clock should fail.

Good point.

> Other than that it's not a good behaviour when clk_get_rate() returns
> 0 for clock which rate has been successfully set to another rate using
> clk_set_rate().

It's a NULL clock, so it hopefully shouldn't matter.

I think you have convinced my about set_rate() returning error is not 
catastrophic. But if it doesn't hurt to return success, I think we 
should go ahead and do that in case someone cares about it?

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

* [PATCH 01/10] Add a common struct clk
  2011-05-02 22:36             ` Russell King - ARM Linux
  2011-05-03  0:22               ` Saravana Kannan
@ 2011-05-04 23:35               ` Paul Walmsley
  2011-05-10 20:06                 ` Saravana Kannan
  1 sibling, 1 reply; 165+ messages in thread
From: Paul Walmsley @ 2011-05-04 23:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi

On Mon, 2 May 2011, Russell King - ARM Linux wrote:

> This does bring us to an interesting question though: should clk_set_rate()
> succeed or fail with a NULL clk?  There is no clock to control, so my
> feeling is that it should fail, just like clk_get_rate() should return
> zero because the rate is meaningless.  There is no rate to get and no
> rate to set.

Returning an error would be my preference when a NULL or bogus clock 
pointer is passed to any clk_* operation, especially since those 
operations will need to dereference the clock pointer.


- Paul

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

* [PATCH RFC] clk: add support for automatic parent handling
  2011-05-03  6:35                                   ` Colin Cross
@ 2011-05-05  8:35                                     ` torbenh
  0 siblings, 0 replies; 165+ messages in thread
From: torbenh @ 2011-05-05  8:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, May 02, 2011 at 11:35:25PM -0700, Colin Cross wrote:
> On Sat, Apr 30, 2011 at 7:27 AM, torbenh <torbenh@gmx.de> wrote:
> > On Fri, Apr 29, 2011 at 02:26:13PM +0100, Russell King - ARM Linux wrote:
> >> On Fri, Apr 29, 2011 at 02:13:06PM +0200, Thomas Gleixner wrote:
> >> > This are all well defined semantical problems and should be solved in
> >> > common code rather than having different buggy implementations in each
> >> > SoC clock "framework".
> >>
> >> Why are you associating functional elements in drivers/clk with the
> >> SoC clock framework?
> >
> > i think i pretty much understand what thomas is after. but i have
> > problems understanding, what you want here.
> >
> > until this point, it looks like you only want the driver/clk to
> > model the clock endpoints inside the devices. A device itself shouldnt
> > be caring for clock parents or anything. its only concern is that a
> > clock pin is fed with the right frequency, or off...
> >
> >>
> >> I think that's the root cause of this misunderstanding, and until you
> >> start realising that these building blocks are not part of the SoC
> >> implementation, we're going to continue arguing about this.
> >
> > what you say now, pretty much sounds like what thomas wants.
> > these building blocks would be objects derived from the clock baseclass,
> > which thomas is trying to define. he doesnt seem to be concerned about
> > the second more special layer yet.
> >
> > i am quite puzzled, what exactly your fighting over :S
> 
> Thomas wants a core framework that handles the clock tree, with each
> clock being the implementation of just the clock.  Russell thinks this
> is impossible, and wants to stop at implementing building blocks for
> the standard clock types, and let each SoC put them into a tree.

Thomas wants the clocks to reference a clock_chip.
(much like genirq... you have irq_desc and and irq_chip)
so there is still one component which has the "big picture"
and can implement crazy platform rules, if necessary.
> 
> I don't think anybody can argue that a shared clock tree framework, if
> it was possible to do well, would be a benefit.  But there are a few
> problems that make abstracting the differences between SoCs very hard
> at that level.
> 
> After implementing the Tegra clock tree at least 10 times to solve
> different problems, there are two very hard problems to solve.
> 
> First is locking.  Per-clock locking is hard because it requires
> choosing up front which way locking will go, usually locking the
> child, then locking the parent, then enabling the parent, and enabling
> the child.  Any operation flow that requires traversing the tree from
> the parent to the child, for example changing the rate of the parent,
> causes lock inversion.  Global locking is easy, but can be wasteful on
> platforms that have some very slow clocks (think external i2c clocks),
> and some very fast clocks (internal register writes).  This is
> mitigated by the separation of clk_prepare and clk_enable locking -
> clk_enable can never sleep, so it can't be blocked for long.  Locking
> at the root node of the tree would be nice, but most SoCs don't have a
> root node - they have a fast root clock and a slow root clock, and can
> switch the all or most of clock tree over to the slow clock in some
> modes.

yeah. one of the big reasons, why the generic code should do the
locking. 
> 
> The second problem is rate changing.  Different platforms require
> wildly different strategies for changing clock rates.  On Tegra,
> clk_set_rate will never change the parent, because we can generally
> set up the parent clocks to the correct frequencies for all the
> devices, and then device drivers can change their dividers to get the
> rate they need.  The few cases where the parent needs to change
> (cpufreq and display pclk), the driver manually calls clk_set_parent.
> On other platforms, it is common to need to change the parent to get
> the necessary rate.
> 
> Automatically selecting parents in a generic way is impossible.  If
> one DEV1 calls clk_set_rate and clk_enable, and the core framework
> responds by setting pll A to frequency X, and setting the parent of
> DEV1 to A, what happens when DEV2 calls clk_set_rate to a frequency
> that can only be satisfied by setting pll A to frequency Y?  DEV1
> can't be switched to another pll, because it is already enabled, and
> some platforms can't support glitchlessly changing a mux, even if the
> frequency doesn't change.

in the case where we cant change a parent clock, the generic code could
just fail to set_rate. then delegate the problem to the clk_chip which
can resolve the problem.
the locking would be tricky, but it is solvable.
but its still somthing we only want implemented once.

so how does changing a mux, which glitches, work now ?
do the child clocked devices need to be turned off/notified when this
happens ?

> 
> I still think a common implementation of the clock tree framework
> would be useful, even if not all platforms can use it.  Allow the
> platforms that can to use it, providing only clock data, and maybe a
> few clock implementations if the building blocks are not sufficient,
> and allow those that can't to implement their own versions of the
> clk_* functions on top of the clock building blocks.  Tegra already
> has a fairly generic implementation of a clock tree in
> arch/arm/mach-tegra/clock.c, moving it to the common clk struct and
> sharing it with other platforms wouldn't be any extra code, even if no
> other platforms could use it.  And I bet at least OMAP could use it,
> from what I've seen.
> 
> Per-tree locking is a solvable problem, as long as a tree was
> considered as an ordered graph - two root nodes that feed into the
> same clocks would be considered part of the same tree.  The core
> framework could look at all possible parents of a clock to determine
> what clock trees were truly independent, which would result in a
> single global lock on most platforms, but multiple locks on platforms
> that really had independent clock trees.  Dynamically added clocks
> would cause problems with this solution.
> 
> I think automatic clock parent and rate setting would need to be
> delegated to a platform-specific layer, and I'm not sure how.  Maybe
> allow platforms to override the set_rate ops in the clock tree
> building blocks, or a new op that can determine the new tree
> structure, and call the old set_rate op to set the registers.

yeah, getting these constraints solved automatically is pretty
expensive. some heuristics are probably indicated here.

-- 
torben Hohn

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

* [PATCH 01/10] Add a common struct clk
  2011-05-04 23:35               ` Paul Walmsley
@ 2011-05-10 20:06                 ` Saravana Kannan
  0 siblings, 0 replies; 165+ messages in thread
From: Saravana Kannan @ 2011-05-10 20:06 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/04/2011 04:35 PM, Paul Walmsley wrote:
> Hi
>
> On Mon, 2 May 2011, Russell King - ARM Linux wrote:
>
>> This does bring us to an interesting question though: should clk_set_rate()
>> succeed or fail with a NULL clk?  There is no clock to control, so my
>> feeling is that it should fail, just like clk_get_rate() should return
>> zero because the rate is meaningless.  There is no rate to get and no
>> rate to set.
>
> Returning an error would be my preference when a NULL or bogus clock
> pointer is passed to any clk_* operation, especially since those
> operations will need to dereference the clock pointer.

Wouldn't returning an error for all clk_* ops for a NULL clock make it 
meaningless? It would be the same as -ENOENT in that case.

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

end of thread, other threads:[~2011-05-10 20:06 UTC | newest]

Thread overview: 165+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-15 19:08 [RFC] sanitizing crazy clock data files Sascha Hauer
2011-04-15 19:08 ` [PATCH 01/10] Add a common struct clk Sascha Hauer
2011-04-21 19:48   ` Thomas Gleixner
2011-04-22  0:28     ` Richard Zhao
2011-04-22  9:23       ` Thomas Gleixner
2011-04-23 14:08         ` Richard Zhao
2011-04-23 15:30           ` Thomas Gleixner
2011-04-24  2:54             ` Richard Zhao
2011-04-24  7:20             ` Linus Walleij
2011-04-24  9:55               ` Richard Zhao
2011-04-22  4:57     ` Saravana Kannan
2011-04-22  9:13       ` Thomas Gleixner
2011-04-29 10:09     ` Russell King - ARM Linux
2011-04-29 10:45       ` Thomas Gleixner
2011-04-29 10:58         ` Tony Lindgren
2011-04-29 11:01         ` Russell King - ARM Linux
2011-04-30 18:30           ` Pavel Machek
2011-04-30  8:06   ` Linus Walleij
2011-04-30  9:01     ` Russell King - ARM Linux
2011-04-30 16:30       ` Linus Walleij
2011-05-01 20:33   ` Rob Herring
2011-05-02  1:09     ` Jeremy Kerr
2011-05-02  3:09       ` Rob Herring
2011-05-02  3:40         ` Jeremy Kerr
2011-05-02 16:30           ` Rob Herring
2011-05-02 22:36             ` Russell King - ARM Linux
2011-05-03  0:22               ` Saravana Kannan
2011-05-04  6:40                 ` Sascha Hauer
2011-05-04 18:33                   ` Saravana Kannan
2011-05-04 23:35               ` Paul Walmsley
2011-05-10 20:06                 ` Saravana Kannan
2011-05-02 16:55           ` David Brown
2011-05-02 17:31             ` Stephen Boyd
2011-04-15 19:08 ` [PATCH 02/10] clk: Generic support for fixed-rate clocks Sascha Hauer
2011-04-15 19:08 ` [PATCH 03/10] clk: Make NULL a valid clock again Sascha Hauer
2011-04-19  0:53   ` Jeremy Kerr
2011-04-19  6:25     ` Sascha Hauer
2011-04-20 12:53   ` Uwe Kleine-König
2011-04-15 19:08 ` [PATCH 04/10] clk: implement parent pass through functions Sascha Hauer
2011-04-18  9:25   ` Uwe Kleine-König
2011-04-18  9:48     ` Sascha Hauer
2011-04-19 17:20   ` Stephen Boyd
2011-04-19 17:53     ` Sascha Hauer
2011-04-19 19:09       ` Uwe Kleine-König
2011-04-19 20:58         ` Sascha Hauer
2011-04-19 21:54         ` Thomas Gleixner
2011-04-20  7:16           ` Uwe Kleine-König
2011-04-20  8:34             ` Thomas Gleixner
2011-04-20 14:07           ` [PATCH RFC] clk: add support for automatic parent handling Uwe Kleine-König
2011-04-20 16:16             ` Thomas Gleixner
2011-04-20 18:59               ` Uwe Kleine-König
2011-04-20 19:52                 ` Thomas Gleixner
2011-04-21  6:58                   ` Saravana Kannan
2011-04-21  6:58                     ` Saravana Kannan
2011-04-21  6:58                     ` Saravana Kannan
2011-04-21 10:33                     ` Thomas Gleixner
2011-04-21 10:33                       ` Thomas Gleixner
2011-04-21 10:33                       ` Thomas Gleixner
2011-04-21 19:22                       ` torbenh
2011-04-21 19:22                         ` torbenh
2011-04-21 19:22                         ` torbenh
2011-04-23 23:26                       ` Benjamin Herrenschmidt
2011-04-23 23:26                         ` Benjamin Herrenschmidt
2011-04-23 23:26                         ` Benjamin Herrenschmidt
2011-04-21  7:22                   ` Uwe Kleine-König
2011-04-21  9:12                     ` Thomas Gleixner
2011-04-21 10:31                       ` Mark Brown
2011-04-21 11:42                         ` Tony Lindgren
2011-04-21 14:52                           ` Thomas Gleixner
2011-04-22  7:09                             ` Tony Lindgren
2011-04-22  8:22                               ` Thomas Gleixner
2011-04-21 14:29                         ` Thomas Gleixner
2011-04-29 10:37                       ` Russell King - ARM Linux
2011-04-29 11:01                         ` Thomas Gleixner
2011-04-29 11:06                           ` Russell King - ARM Linux
2011-04-29 12:13                             ` Thomas Gleixner
2011-04-29 13:26                               ` Russell King - ARM Linux
2011-04-29 15:31                                 ` Thomas Gleixner
2011-04-29 22:07                                   ` Russell King - ARM Linux
2011-04-29 22:16                                     ` Thomas Gleixner
2011-04-29 22:19                                       ` Russell King - ARM Linux
2011-04-29 22:47                                         ` Thomas Gleixner
2011-04-30 14:27                                 ` torbenh
2011-05-03  6:35                                   ` Colin Cross
2011-05-05  8:35                                     ` torbenh
2011-05-03  2:44                                 ` Saravana Kannan
2011-05-03  2:46                                   ` Saravana Kannan
2011-04-21 10:13                     ` Mark Brown
2011-04-21 11:39                       ` Tony Lindgren
2011-04-21  7:42                   ` Sascha Hauer
2011-04-21  9:21                     ` Thomas Gleixner
2011-04-21 11:50                       ` Mark Brown
2011-04-21 12:20                         ` Thomas Gleixner
2011-04-21 12:35                           ` Mark Brown
2011-04-25  2:03                             ` Richard Zhao
2011-04-25 10:57                               ` Mark Brown
2011-04-25 14:41                                 ` Richard Zhao
2011-04-25 14:44                                   ` Mark Brown
2011-04-29 10:49                           ` Russell King - ARM Linux
2011-04-29 11:11                             ` Thomas Gleixner
2011-04-29 11:38                               ` Russell King - ARM Linux
2011-04-29 12:19                                 ` Thomas Gleixner
2011-04-29 13:27                                   ` Russell King - ARM Linux
2011-04-29 15:47                                     ` Thomas Gleixner
2011-04-21 12:06                       ` Sascha Hauer
2011-04-21 15:38                         ` Thomas Gleixner
2011-04-22  0:23                           ` Colin Cross
2011-04-22  9:51                             ` Thomas Gleixner
2011-04-22 16:14                               ` Thomas Gleixner
2011-04-22 16:39                               ` Colin Cross
2011-04-22 16:57                                 ` Thomas Gleixner
2011-04-22 22:26                                   ` Saravana Kannan
2011-04-22 22:55                                     ` Thomas Gleixner
2011-04-23  0:48                                       ` Saravana Kannan
2011-04-23 23:34                                         ` Benjamin Herrenschmidt
2011-04-22  4:54                           ` Saravana Kannan
2011-04-22  9:06                             ` Thomas Gleixner
2011-04-29 10:30                   ` Russell King - ARM Linux
2011-04-29 10:51                     ` Thomas Gleixner
2011-04-29 10:56                       ` Russell King - ARM Linux
2011-04-24  9:45             ` Richard Zhao
2011-04-24 20:14               ` Uwe Kleine-König
2011-04-29 10:20       ` [PATCH 04/10] clk: implement parent pass through functions Russell King - ARM Linux
2011-04-15 19:08 ` [PATCH 05/10] clk: Add support for simple dividers Sascha Hauer
2011-04-18  9:49   ` Uwe Kleine-König
2011-04-18 10:07     ` Sascha Hauer
2011-04-19  2:45       ` Saravana Kannan
2011-04-19  7:32         ` Uwe Kleine-König
2011-04-19  8:55           ` Saravana Kannan
2011-04-19  9:31             ` Sascha Hauer
2011-04-19 22:28               ` Saravana Kannan
2011-04-20  6:36                 ` Sascha Hauer
2011-04-20 21:45                   ` Saravana Kannan
2011-04-21  7:39                     ` Uwe Kleine-König
2011-04-28 15:14         ` Russell King - ARM Linux
2011-05-03  3:37           ` Saravana Kannan
2011-05-03  7:12             ` Uwe Kleine-König
2011-04-28 15:22     ` Russell King - ARM Linux
2011-05-02  7:58       ` Sascha Hauer
2011-04-18 22:40   ` Stephen Boyd
2011-04-19  0:32     ` Jeremy Kerr
2011-04-19  5:41       ` Stephen Boyd
2011-04-24 13:48   ` Richard Zhao
2011-04-25 18:51     ` Sascha Hauer
2011-04-26  1:54       ` Richard Zhao
2011-04-15 19:08 ` [PATCH 06/10] clk: Add support for a generic clock multiplexer Sascha Hauer
2011-04-18 13:15   ` Uwe Kleine-König
2011-04-18 13:33     ` Sascha Hauer
2011-04-18 13:54       ` Uwe Kleine-König
2011-04-18 17:54       ` Stephen Boyd
2011-04-18 18:34         ` Russell King - ARM Linux
2011-04-18 18:41           ` Russell King - ARM Linux
2011-04-18 18:46             ` Stephen Boyd
2011-04-15 19:08 ` [PATCH 07/10] ARM i.MX: Support for clock building blocks Sascha Hauer
2011-04-15 19:08 ` [PATCH 08/10] ARM i.MX: Add generic support for pllv2 Sascha Hauer
2011-04-15 19:08 ` [PATCH 09/10] ARM i.MX51/53: reimplement clock support Sascha Hauer
2011-04-15 19:08 ` [PATCH 10/10] ARM i.MX51/53: remove old " Sascha Hauer
2011-04-15 19:36 ` [RFC] sanitizing crazy clock data files Russell King - ARM Linux
2011-04-15 20:12   ` Sascha Hauer
2011-04-15 20:25     ` Russell King - ARM Linux
2011-04-15 20:28       ` Russell King - ARM Linux
2011-04-15 20:49         ` Uwe Kleine-König
2011-04-18  4:07     ` Shawn Guo
2011-04-15 20:45 ` Uwe Kleine-König
2011-04-18  7:42 ` Sascha Hauer

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