linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 0/8] Per-user clock constraints
@ 2014-08-18 15:30 Tomeu Vizoso
  2014-08-18 15:30 ` [PATCH v7 1/8] clk: Add temporary mapping to the existing API Tomeu Vizoso
                   ` (8 more replies)
  0 siblings, 9 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-18 15:30 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Warren, Thierry Reding, Tomasz Figa, Peter De Schrijver,
	rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
	Tomeu Vizoso

Hi,

in this v7 of the patchset I have only rebased on top of 3.17rc1, with no other
changes. I have had to do a fair amount of fixing due to the rebase, more
details below. Follows the original cover letter blurb:

I'm retaking Rabin's patches [0] for splitting the clk API in two: one API for
clk consumers and another for providers. The consumer API uses a clk structure
that just keeps track of the consumer and has a reference to the actual
clk_core struct, which is used internally.

I have kept a patch from Rabin that aims to aid in debugging nested
enable/disable calls, though my personal aim is to allow more than one consumer
to influence the final, effective frequency rate. For now this is limited to
setting floor and ceiling constraints, with the short-term aim of allowing
devfreq and thermal drivers to set floor and ceiling frequencies on the memory
clock, respectively.

For those functions in the consumer clk API that were called from providers, I
have added variants to clk-provider.h that are the same only that accept a
clk_core instead. These functions are prefixed with clk_provider_.

Patch 1/8 just adds a bunch of defines with the goal of having all the renames
in their own commit while preserving git-bisectability, with patch 5/8
containing the rename itself as generated by the Coccinelle script in [1].
Patches 2/8 and 3/8 remove an instance of a clock consumer using what is
currently provider-only API. Patch 4/8 is needed because
sound/soc/mxs/mxs-saif.c calls both the consumer and the provider API. The
actual implementation of the API split comes in patch 6/8. I will be happy to
organize the refactoring differently if anybody has a better idea.

Patch 7/8 warns when there's an unbalanced usage of the enable and disable
APIs, and patch 8/8 adds the API for setting floor and ceiling frequencies, per
consumer.

[0] http://thread.gmane.org/gmane.linux.kernel/1402006
[1] http://cgit.collabora.com/git/user/tomeu/linux.git/commit/?id=da9c7e34d9

Thanks,

Tomeu

Sebastian Hesselbarth (1):
  clk: provide public clk_is_enabled function

Tomeu Vizoso (7):
  clk: Add temporary mapping to the existing API
  cpufreq: kirkwood: Remove use of the clk provider API
  ASoC: mxs-saif: fix mixed use of public and provider clk API
  clk: Move all drivers to use internal API
  clk: use struct clk only for external API
  clk: per-user clock accounting for debug
  clk: Add floor and ceiling constraints to clock rates

[detailed diffstat omitted for brevity sake]

 256 files changed, 2267 insertions(+), 1732 deletions(-)

-- 
1.9.3


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

* [PATCH v7 1/8] clk: Add temporary mapping to the existing API
  2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
@ 2014-08-18 15:30 ` Tomeu Vizoso
       [not found]   ` <20140820145006.5251.30923@quantum>
  2014-08-18 15:30 ` [PATCH v7 2/8] clk: provide public clk_is_enabled function Tomeu Vizoso
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-18 15:30 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Warren, Thierry Reding, Tomasz Figa, Peter De Schrijver,
	rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
	Tomeu Vizoso

To preserve git-bisectability, add aliases from the future provider API to the
existing public API.

Also includes clk-provider.h and clk-dev.h in a few places so the right
functions are defined.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

---
v7: * Add mappings for clk_notifier_[un]register
    * Add more clk-provider.h includes to clk implementations

v4: * Add more clk-provider.h includes to clk implementations
    * Add mapping for clk_provider_round_rate
---
 arch/arm/mach-omap2/display.c                 |  1 +
 arch/arm/mach-omap2/omap_device.c             |  1 +
 arch/arm/mach-shmobile/clock.c                |  1 +
 arch/arm/plat-orion/common.c                  |  1 +
 drivers/clk/berlin/bg2.c                      |  1 +
 drivers/clk/berlin/bg2q.c                     |  1 +
 drivers/clk/clk-conf.c                        |  1 +
 drivers/clk/clkdev.c                          |  1 +
 drivers/media/platform/exynos4-is/media-dev.c |  1 +
 include/linux/clk-provider.h                  | 25 +++++++++++++++++++++++++
 include/linux/clk/zynq.h                      |  1 +
 11 files changed, 35 insertions(+)

diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index bf852d7..0f9e479 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -21,6 +21,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/of.h>
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 01ef59d..fbe8cf0 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -32,6 +32,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/notifier.h>
diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
index 806f940..ed415dc 100644
--- a/arch/arm/mach-shmobile/clock.c
+++ b/arch/arm/mach-shmobile/clock.c
@@ -24,6 +24,7 @@
 
 #ifdef CONFIG_COMMON_CLK
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include "clock.h"
 
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 3ec6e8e..961b593 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -15,6 +15,7 @@
 #include <linux/serial_8250.h>
 #include <linux/ata_platform.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/mv643xx_i2c.h>
diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c
index 515fb13..4c81e09 100644
--- a/drivers/clk/berlin/bg2.c
+++ b/drivers/clk/berlin/bg2.c
@@ -19,6 +19,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/clkdev.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c
index 21784e4..748da9b 100644
--- a/drivers/clk/berlin/bg2q.c
+++ b/drivers/clk/berlin/bg2q.c
@@ -19,6 +19,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/clkdev.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index aad4796..d36a7b3 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clkdev.h>
 #include <linux/clk-provider.h>
 #include <linux/clk/clk-conf.h>
 #include <linux/device.h>
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index da4bda8..c751d0c 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
+#include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
 
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index 344718d..2620c48 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -13,6 +13,7 @@
 #include <linux/bug.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/clkdev.h>
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 411dd7e..a1a7bb7 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -16,6 +16,31 @@
 
 #ifdef CONFIG_COMMON_CLK
 
+/* Temporarily map the to-be-added API to the old API, just so stuff compiles */
+#define clk_core			clk
+
+#define __clk_create_clk
+
+#define clk_provider_get			clk_get
+#define clk_provider_get_sys			clk_get_sys
+#define devm_clk_provider_get			devm_clk_get
+#define of_clk_provider_get			of_clk_get
+#define of_clk_provider_get_by_name		of_clk_get_by_name
+
+#define clk_provider_set_rate			clk_set_rate
+#define clk_provider_get_rate			clk_get_rate
+#define clk_provider_round_rate			clk_round_rate
+#define clk_provider_set_parent			clk_set_parent
+#define clk_provider_get_parent			clk_get_parent
+#define clk_provider_prepare			clk_prepare
+#define clk_provider_unprepare			clk_unprepare
+#define clk_provider_enable			clk_enable
+#define clk_provider_disable			clk_disable
+#define clk_provider_prepare_enable		clk_prepare_enable
+#define clk_provider_disable_unprepare		clk_unprepare
+#define clk_provider_notifier_register		clk_notifier_register
+#define clk_provider_notifier_unregister	clk_notifier_unregister
+
 /*
  * flags used across common struct clk.  these flags should only affect the
  * top-level framework.  custom flags for dealing with hardware specifics
diff --git a/include/linux/clk/zynq.h b/include/linux/clk/zynq.h
index 7a5633b..a990a59 100644
--- a/include/linux/clk/zynq.h
+++ b/include/linux/clk/zynq.h
@@ -21,6 +21,7 @@
 #define __LINUX_CLK_ZYNQ_H_
 
 #include <linux/spinlock.h>
+#include <linux/clk-provider.h>
 
 void zynq_clock_init(void);
 
-- 
1.9.3


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

* [PATCH v7 2/8] clk: provide public clk_is_enabled function
  2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
  2014-08-18 15:30 ` [PATCH v7 1/8] clk: Add temporary mapping to the existing API Tomeu Vizoso
@ 2014-08-18 15:30 ` Tomeu Vizoso
  2014-08-18 15:30 ` [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API Tomeu Vizoso
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-18 15:30 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Warren, Thierry Reding, Tomasz Figa, Peter De Schrijver,
	rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
	Sebastian Hesselbarth, Tomeu Vizoso

From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

To determine if a clk has been previously enabled, provide a public
clk_is_enabled function. This is especially helpful to check the state
of clk-gate without actually changing the state of the gate.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
 drivers/clk/clk.c   | 18 ++++++++++++++++++
 include/linux/clk.h | 13 +++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b76fa69..bf46d27 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -953,6 +953,24 @@ int clk_enable(struct clk *clk)
 EXPORT_SYMBOL_GPL(clk_enable);
 
 /**
+ * clk_is_enabled - return the enabled state of a clk
+ * @clk: the clk whose enabled state gets returned
+ *
+ * Returns true if the clock is enabled, false otherwise.
+ */
+bool clk_is_enabled(struct clk *clk)
+{
+	bool is_en;
+
+	clk_prepare_lock();
+	is_en = __clk_is_enabled(clk);
+	clk_prepare_unlock();
+
+	return is_en;
+}
+EXPORT_SYMBOL_GPL(clk_is_enabled);
+
+/**
  * __clk_round_rate - round the given rate for a clk
  * @clk: round the rate of this clock
  * @rate: the rate which is to be rounded
diff --git a/include/linux/clk.h b/include/linux/clk.h
index fb5e097..2cd8d3c 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -218,6 +218,14 @@ int clk_enable(struct clk *clk);
 void clk_disable(struct clk *clk);
 
 /**
+ * clk_is_enabled - return the enabled state of a clk
+ * @clk: the clk whose enabled state gets returned
+ *
+ * Returns true if the clock is enabled, false otherwise.
+ */
+bool clk_is_enabled(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.
  * @clk: clock source
@@ -330,6 +338,11 @@ static inline int clk_enable(struct clk *clk)
 
 static inline void clk_disable(struct clk *clk) {}
 
+static inline bool clk_is_enabled(struct clk *clk)
+{
+	return false;
+}
+
 static inline unsigned long clk_get_rate(struct clk *clk)
 {
 	return 0;
-- 
1.9.3


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

* [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
  2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
  2014-08-18 15:30 ` [PATCH v7 1/8] clk: Add temporary mapping to the existing API Tomeu Vizoso
  2014-08-18 15:30 ` [PATCH v7 2/8] clk: provide public clk_is_enabled function Tomeu Vizoso
@ 2014-08-18 15:30 ` Tomeu Vizoso
       [not found]   ` <20140820225513.5251.284@quantum>
  2014-08-18 15:30 ` [PATCH v7 4/8] ASoC: mxs-saif: fix mixed use of public and provider clk API Tomeu Vizoso
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-18 15:30 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Warren, Thierry Reding, Tomasz Figa, Peter De Schrijver,
	rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
	Tomeu Vizoso

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
 drivers/cpufreq/kirkwood-cpufreq.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index 37a4806..f3d087f 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -12,7 +12,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/clk.h>
-#include <linux/clk-provider.h>
 #include <linux/cpufreq.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
@@ -50,7 +49,7 @@ static struct cpufreq_frequency_table kirkwood_freq_table[] = {
 
 static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
 {
-	if (__clk_is_enabled(priv.powersave_clk))
+	if (clk_is_enabled(priv.powersave_clk))
 		return kirkwood_freq_table[1].frequency;
 	return kirkwood_freq_table[0].frequency;
 }
-- 
1.9.3


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

* [PATCH v7 4/8] ASoC: mxs-saif: fix mixed use of public and provider clk API
  2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
                   ` (2 preceding siblings ...)
  2014-08-18 15:30 ` [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API Tomeu Vizoso
@ 2014-08-18 15:30 ` Tomeu Vizoso
  2014-08-18 15:30 ` [PATCH v7 6/8] clk: use struct clk only for external API Tomeu Vizoso
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-18 15:30 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Warren, Thierry Reding, Tomasz Figa, Peter De Schrijver,
	rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
	Tomeu Vizoso

In preparation to changing the clk provider API to use struct clk_core instead
of struct clk.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Acked-by: Mark Brown <broonie@linaro.org>
---
 sound/soc/mxs/mxs-saif.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
index 231d7e7..a24367d 100644
--- a/sound/soc/mxs/mxs-saif.c
+++ b/sound/soc/mxs/mxs-saif.c
@@ -682,11 +682,11 @@ static int mxs_saif_mclk_init(struct platform_device *pdev)
 {
 	struct mxs_saif *saif = platform_get_drvdata(pdev);
 	struct device_node *np = pdev->dev.of_node;
-	struct clk *clk;
+	struct clk_core *clk;
 	int ret;
 
 	clk = clk_register_divider(&pdev->dev, "mxs_saif_mclk",
-				   __clk_get_name(saif->clk), 0,
+				   clk_get_name(saif->clk), 0,
 				   saif->base + SAIF_CTRL,
 				   BP_SAIF_CTRL_BITCLK_MULT_RATE, 3,
 				   0, NULL);
-- 
1.9.3


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

* [PATCH v7 6/8] clk: use struct clk only for external API
  2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
                   ` (3 preceding siblings ...)
  2014-08-18 15:30 ` [PATCH v7 4/8] ASoC: mxs-saif: fix mixed use of public and provider clk API Tomeu Vizoso
@ 2014-08-18 15:30 ` Tomeu Vizoso
  2014-08-18 15:30 ` [PATCH v7 7/8] clk: per-user clock accounting for debug Tomeu Vizoso
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-18 15:30 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Warren, Thierry Reding, Tomasz Figa, Peter De Schrijver,
	rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
	Tomeu Vizoso

In order to provide per-user accounting, this separates the struct clk
used in the common clock framework into two structures 'struct clk_core'
and 'struct clk'. struct clk_core will be used for internal
manipulation and struct clk will be used in the clock API
implementation.

In this patch, struct clk is simply renamed to struct clk_core and a new
struct clk is implemented which simply wraps it. In the next patch, the
new struct clk will be used to implement per-user clock enable
accounting.

Based on previous work by Rabin Vincent <rabin@rab.in>.

NOTE: with this patch, clk_get_parent() behaves like clk_get(), i.e. it
needs to be matched with a clk_put().  Otherwise, memory will leak.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

---

v7: * convert clk_is_enabled to clk_core
    * add clk_provider_notifier_[un]register

v4: * export clk_to_clk_core so mach-msm can use it for clk_reset
    * add clk_provider_round_rate, for mach-imx
    * fix build with !CONFIG_COMMON_CLK
    * keep handling NULL struct clk gracefully as before

v3: * Allocate and release the per-user struct clk
    * Have clk_core_to_clk return any error it's passed, so calls to it can be chained
    * Add provider API for enable and disable
    * Remove clk_free_clk for now
    * Have clk_to_clk_core be an inline function to benefit of type-checking
    * Have devres wrap the clk struct instead of clk_core
    * Rename clk_core_to_clk to __clk_create_clk to make more clear that it allocates
---
 arch/arm/mach-msm/clock.c    |   2 +-
 drivers/clk/clk-devres.c     |  31 ++
 drivers/clk/clk.c            | 674 ++++++++++++++++++++++++++-----------------
 drivers/clk/clk.h            |   6 +
 drivers/clk/clkdev.c         | 125 ++++++--
 include/linux/clk-private.h  |  38 +--
 include/linux/clk-provider.h | 162 ++++++-----
 include/linux/clk.h          |  32 +-
 include/linux/clkdev.h       |  24 +-
 9 files changed, 707 insertions(+), 387 deletions(-)

diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 35ea02b5..1de0b5a 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -21,7 +21,7 @@
 
 int clk_reset(struct clk *clk, enum clk_reset_action action)
 {
-	struct clk_hw *hw = __clk_get_hw(clk);
+	struct clk_hw *hw = __clk_get_hw(clk_to_clk_core(clk));
 	struct msm_clk *m = to_msm_clk(hw);
 	return m->reset(hw, action);
 }
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 8f57154..79cd4d3 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -5,10 +5,14 @@
  */
 
 #include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/device.h>
 #include <linux/export.h>
 #include <linux/gfp.h>
 
+#include "clk.h"
+
 static void devm_clk_release(struct device *dev, void *res)
 {
 	clk_put(*(struct clk **)res);
@@ -34,6 +38,33 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL(devm_clk_get);
 
+#if defined(CONFIG_COMMON_CLK)
+static void devm_clk_core_release(struct device *dev, void *res)
+{
+	__clk_put(*(struct clk_core **)res);
+}
+
+struct clk_core *devm_clk_provider_get(struct device *dev, const char *id)
+{
+	struct clk_core **ptr, *clk;
+
+	ptr = devres_alloc(devm_clk_core_release, sizeof(*ptr), GFP_KERNEL);
+	if (!ptr)
+		return ERR_PTR(-ENOMEM);
+
+	clk = clk_provider_get(dev, id);
+	if (!IS_ERR(clk)) {
+		*ptr = clk;
+		devres_add(dev, ptr);
+	} else {
+		devres_free(ptr);
+	}
+
+	return clk;
+}
+EXPORT_SYMBOL(devm_clk_provider_get);
+#endif
+
 static int devm_clk_match(struct device *dev, void *res, void *data)
 {
 	struct clk **c = res;
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bf46d27..a2d0ee5 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -37,6 +37,8 @@ static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
+static long __clk_get_accuracy_internal(struct clk_core *clk);
+
 /***           locking             ***/
 static void clk_prepare_lock(void)
 {
@@ -112,7 +114,7 @@ static struct hlist_head *orphan_list[] = {
 	NULL,
 };
 
-static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c, int level)
 {
 	if (!c)
 		return;
@@ -120,14 +122,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
 	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",
 		   level * 3 + 1, "",
 		   30 - level * 3, c->name,
-		   c->enable_count, c->prepare_count, clk_get_rate(c),
-		   clk_get_accuracy(c));
+		   c->enable_count, c->prepare_count, clk_provider_get_rate(c),
+		   __clk_get_accuracy_internal(c));
 }
 
-static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
 				     int level)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	if (!c)
 		return;
@@ -140,7 +142,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
 
 static int clk_summary_show(struct seq_file *s, void *data)
 {
-	struct clk *c;
+	struct clk_core *c;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
 	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy\n");
@@ -170,7 +172,7 @@ static const struct file_operations clk_summary_fops = {
 	.release	= single_release,
 };
 
-static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
 {
 	if (!c)
 		return;
@@ -178,13 +180,13 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
 	seq_printf(s, "\"%s\": { ", c->name);
 	seq_printf(s, "\"enable_count\": %d,", c->enable_count);
 	seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
-	seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
-	seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));
+	seq_printf(s, "\"rate\": %lu", clk_provider_get_rate(c));
+	seq_printf(s, "\"accuracy\": %lu", __clk_get_accuracy_internal(c));
 }
 
-static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	if (!c)
 		return;
@@ -201,7 +203,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
 
 static int clk_dump(struct seq_file *s, void *data)
 {
-	struct clk *c;
+	struct clk_core *c;
 	bool first_node = true;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
@@ -238,7 +240,7 @@ static const struct file_operations clk_dump_fops = {
 };
 
 /* caller must hold prepare_lock */
-static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
 {
 	struct dentry *d;
 	int ret = -ENOMEM;
@@ -301,9 +303,9 @@ out:
 }
 
 /* caller must hold prepare_lock */
-static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_subtree(struct clk_core *clk, struct dentry *pdentry)
 {
-	struct clk *child;
+	struct clk_core *child;
 	int ret = -EINVAL;;
 
 	if (!clk || !pdentry)
@@ -333,7 +335,7 @@ out:
  * Caller must hold prepare_lock.  Only clk_init calls this function (so
  * far) so this is taken care.
  */
-static int clk_debug_register(struct clk *clk)
+static int clk_debug_register(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -356,12 +358,12 @@ out:
  *
  * Caller must hold prepare_lock.
  */
-static void clk_debug_unregister(struct clk *clk)
+static void clk_debug_unregister(struct clk_core *clk)
 {
 	debugfs_remove_recursive(clk->dentry);
 }
 
-struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
+struct dentry *clk_debugfs_add_file(struct clk_core *clk, char *name, umode_t mode,
 				void *data, const struct file_operations *fops)
 {
 	struct dentry *d = NULL;
@@ -387,7 +389,7 @@ EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
  */
 static int __init clk_debug_init(void)
 {
-	struct clk *clk;
+	struct clk_core *clk;
 	struct dentry *d;
 
 	rootdir = debugfs_create_dir("clk", NULL);
@@ -431,19 +433,19 @@ static int __init clk_debug_init(void)
 }
 late_initcall(clk_debug_init);
 #else
-static inline int clk_debug_register(struct clk *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
+static inline int clk_debug_register(struct clk_core *clk) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *clk, struct clk_core *new_parent)
 {
 }
-static inline void clk_debug_unregister(struct clk *clk)
+static inline void clk_debug_unregister(struct clk_core *clk)
 {
 }
 #endif
 
 /* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *clk)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	if (!clk)
 		return;
@@ -466,9 +468,9 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
 }
 
 /* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk *clk)
+static void clk_disable_unused_subtree(struct clk_core *clk)
 {
-	struct clk *child;
+	struct clk_core *child;
 	unsigned long flags;
 
 	if (!clk)
@@ -514,7 +516,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
 
 static int clk_disable_unused(void)
 {
-	struct clk *clk;
+	struct clk_core *clk;
 
 	if (clk_ignore_unused) {
 		pr_warn("clk: Not disabling unused clocks\n");
@@ -541,33 +543,50 @@ static int clk_disable_unused(void)
 }
 late_initcall_sync(clk_disable_unused);
 
+struct clk *__clk_create_clk(struct clk_core *clk_core)
+{
+	struct clk *clk;
+
+	/* This is to allow this function to be chained to others */
+	if (!clk_core || IS_ERR(clk_core))
+		return (struct clk *) clk_core;
+
+	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+	if (!clk)
+		return ERR_PTR(-ENOMEM);
+
+	clk->core = clk_core;
+
+	return clk;
+}
+
 /***    helper functions   ***/
 
-const char *__clk_get_name(struct clk *clk)
+const char *__clk_get_name(struct clk_core *clk)
 {
 	return !clk ? NULL : clk->name;
 }
 EXPORT_SYMBOL_GPL(__clk_get_name);
 
-struct clk_hw *__clk_get_hw(struct clk *clk)
+struct clk_hw *__clk_get_hw(struct clk_core *clk)
 {
 	return !clk ? NULL : clk->hw;
 }
 EXPORT_SYMBOL_GPL(__clk_get_hw);
 
-u8 __clk_get_num_parents(struct clk *clk)
+u8 __clk_get_num_parents(struct clk_core *clk)
 {
 	return !clk ? 0 : clk->num_parents;
 }
 EXPORT_SYMBOL_GPL(__clk_get_num_parents);
 
-struct clk *__clk_get_parent(struct clk *clk)
+struct clk_core *__clk_get_parent(struct clk_core *clk)
 {
 	return !clk ? NULL : clk->parent;
 }
 EXPORT_SYMBOL_GPL(__clk_get_parent);
 
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+struct clk_core *clk_get_parent_by_index(struct clk_core *clk, u8 index)
 {
 	if (!clk || index >= clk->num_parents)
 		return NULL;
@@ -581,17 +600,17 @@ struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
 }
 EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
 
-unsigned int __clk_get_enable_count(struct clk *clk)
+unsigned int __clk_get_enable_count(struct clk_core *clk)
 {
 	return !clk ? 0 : clk->enable_count;
 }
 
-unsigned int __clk_get_prepare_count(struct clk *clk)
+unsigned int __clk_get_prepare_count(struct clk_core *clk)
 {
 	return !clk ? 0 : clk->prepare_count;
 }
 
-unsigned long __clk_get_rate(struct clk *clk)
+unsigned long __clk_get_rate(struct clk_core *clk)
 {
 	unsigned long ret;
 
@@ -613,7 +632,7 @@ out:
 }
 EXPORT_SYMBOL_GPL(__clk_get_rate);
 
-unsigned long __clk_get_accuracy(struct clk *clk)
+unsigned long __clk_get_accuracy(struct clk_core *clk)
 {
 	if (!clk)
 		return 0;
@@ -621,13 +640,13 @@ unsigned long __clk_get_accuracy(struct clk *clk)
 	return clk->accuracy;
 }
 
-unsigned long __clk_get_flags(struct clk *clk)
+unsigned long __clk_get_flags(struct clk_core *clk)
 {
 	return !clk ? 0 : clk->flags;
 }
 EXPORT_SYMBOL_GPL(__clk_get_flags);
 
-bool __clk_is_prepared(struct clk *clk)
+bool __clk_is_prepared(struct clk_core *clk)
 {
 	int ret;
 
@@ -648,7 +667,7 @@ out:
 	return !!ret;
 }
 
-bool __clk_is_enabled(struct clk *clk)
+bool __clk_is_enabled(struct clk_core *clk)
 {
 	int ret;
 
@@ -670,10 +689,10 @@ out:
 }
 EXPORT_SYMBOL_GPL(__clk_is_enabled);
 
-static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
+static struct clk_core *__clk_lookup_subtree(const char *name, struct clk_core *clk)
 {
-	struct clk *child;
-	struct clk *ret;
+	struct clk_core *child;
+	struct clk_core *ret;
 
 	if (!strcmp(clk->name, name))
 		return clk;
@@ -687,10 +706,10 @@ static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
 	return NULL;
 }
 
-struct clk *__clk_lookup(const char *name)
+struct clk_core *__clk_lookup(const char *name)
 {
-	struct clk *root_clk;
-	struct clk *ret;
+	struct clk_core *root_clk;
+	struct clk_core *ret;
 
 	if (!name)
 		return NULL;
@@ -719,9 +738,9 @@ struct clk *__clk_lookup(const char *name)
  */
 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 			      unsigned long *best_parent_rate,
-			      struct clk **best_parent_p)
+			      struct clk_core **best_parent_p)
 {
-	struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+	struct clk_core *clk = hw->clk, *parent, *best_parent = NULL;
 	int i, num_parents;
 	unsigned long parent_rate, best = 0;
 
@@ -764,7 +783,7 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
 
 /***        clk api        ***/
 
-void __clk_unprepare(struct clk *clk)
+void __clk_unprepare(struct clk_core *clk)
 {
 	if (!clk)
 		return;
@@ -783,9 +802,20 @@ void __clk_unprepare(struct clk *clk)
 	__clk_unprepare(clk->parent);
 }
 
+void clk_provider_unprepare(struct clk_core *clk)
+{
+	if (IS_ERR_OR_NULL(clk))
+		return;
+
+	clk_prepare_lock();
+	__clk_unprepare(clk);
+	clk_prepare_unlock();
+}
+EXPORT_SYMBOL_GPL(clk_provider_unprepare);
+
 /**
  * clk_unprepare - undo preparation of a clock source
- * @clk: the clk being unprepared
+ * @clk_user: the clk being unprepared
  *
  * clk_unprepare may sleep, which differentiates it from clk_disable.  In a
  * simple case, clk_unprepare can be used instead of clk_disable to gate a clk
@@ -794,18 +824,16 @@ void __clk_unprepare(struct clk *clk)
  * part.  It is this reason that clk_unprepare and clk_disable are not mutually
  * exclusive.  In fact clk_disable must be called before clk_unprepare.
  */
-void clk_unprepare(struct clk *clk)
+void clk_unprepare(struct clk *clk_user)
 {
-	if (IS_ERR_OR_NULL(clk))
+	if (IS_ERR_OR_NULL(clk_user))
 		return;
 
-	clk_prepare_lock();
-	__clk_unprepare(clk);
-	clk_prepare_unlock();
+	clk_provider_unprepare(clk_to_clk_core(clk_user));
 }
 EXPORT_SYMBOL_GPL(clk_unprepare);
 
-int __clk_prepare(struct clk *clk)
+int __clk_prepare(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -831,9 +859,21 @@ int __clk_prepare(struct clk *clk)
 	return 0;
 }
 
+int clk_provider_prepare(struct clk_core *clk)
+{
+	int ret;
+
+	clk_prepare_lock();
+	ret = __clk_prepare(clk);
+	clk_prepare_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_provider_prepare);
+
 /**
  * clk_prepare - prepare a clock source
- * @clk: the clk being prepared
+ * @clk_user: the clk being prepared
  *
  * clk_prepare may sleep, which differentiates it from clk_enable.  In a simple
  * case, clk_prepare can be used instead of clk_enable to ungate a clk if the
@@ -843,19 +883,16 @@ int __clk_prepare(struct clk *clk)
  * exclusive.  In fact clk_prepare must be called before clk_enable.
  * Returns 0 on success, -EERROR otherwise.
  */
-int clk_prepare(struct clk *clk)
+int clk_prepare(struct clk *clk_user)
 {
-	int ret;
-
-	clk_prepare_lock();
-	ret = __clk_prepare(clk);
-	clk_prepare_unlock();
+	if (!clk_user)
+		return 0;
 
-	return ret;
+	return clk_provider_prepare(clk_to_clk_core(clk_user));
 }
 EXPORT_SYMBOL_GPL(clk_prepare);
 
-static void __clk_disable(struct clk *clk)
+static void __clk_disable(struct clk_core *clk)
 {
 	if (!clk)
 		return;
@@ -872,9 +909,22 @@ static void __clk_disable(struct clk *clk)
 	__clk_disable(clk->parent);
 }
 
+void clk_provider_disable(struct clk_core *clk)
+{
+	unsigned long flags;
+
+	if (IS_ERR_OR_NULL(clk))
+		return;
+
+	flags = clk_enable_lock();
+	__clk_disable(clk);
+	clk_enable_unlock(flags);
+}
+EXPORT_SYMBOL_GPL(clk_provider_disable);
+
 /**
  * clk_disable - gate a clock
- * @clk: the clk being gated
+ * @clk_user: the clk being gated
  *
  * clk_disable must not sleep, which differentiates it from clk_unprepare.  In
  * a simple case, clk_disable can be used instead of clk_unprepare to gate a
@@ -884,20 +934,16 @@ static void __clk_disable(struct clk *clk)
  * this reason that clk_unprepare and clk_disable are not mutually exclusive.
  * In fact clk_disable must be called before clk_unprepare.
  */
-void clk_disable(struct clk *clk)
+void clk_disable(struct clk *clk_user)
 {
-	unsigned long flags;
-
-	if (IS_ERR_OR_NULL(clk))
+	if (IS_ERR_OR_NULL(clk_user))
 		return;
 
-	flags = clk_enable_lock();
-	__clk_disable(clk);
-	clk_enable_unlock(flags);
+	clk_provider_disable(clk_to_clk_core(clk_user));
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
-static int __clk_enable(struct clk *clk)
+static int __clk_enable(struct clk_core *clk)
 {
 	int ret = 0;
 
@@ -926,9 +972,22 @@ static int __clk_enable(struct clk *clk)
 	return 0;
 }
 
+int clk_provider_enable(struct clk_core *clk)
+{
+	unsigned long flags;
+	int ret;
+
+	flags = clk_enable_lock();
+	ret = __clk_enable(clk);
+	clk_enable_unlock(flags);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_provider_enable);
+
 /**
  * clk_enable - ungate a clock
- * @clk: the clk being ungated
+ * @clk_user: the clk being ungated
  *
  * clk_enable must not sleep, which differentiates it from clk_prepare.  In a
  * simple case, clk_enable can be used instead of clk_prepare to ungate a clk
@@ -939,16 +998,12 @@ static int __clk_enable(struct clk *clk)
  * must be called before clk_enable.  Returns 0 on success, -EERROR
  * otherwise.
  */
-int clk_enable(struct clk *clk)
+int clk_enable(struct clk *clk_user)
 {
-	unsigned long flags;
-	int ret;
-
-	flags = clk_enable_lock();
-	ret = __clk_enable(clk);
-	clk_enable_unlock(flags);
+	if (!clk_user)
+		return 0;
 
-	return ret;
+	return clk_provider_enable(clk_to_clk_core(clk_user));
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
@@ -958,10 +1013,13 @@ EXPORT_SYMBOL_GPL(clk_enable);
  *
  * Returns true if the clock is enabled, false otherwise.
  */
-bool clk_is_enabled(struct clk *clk)
+bool clk_is_enabled(struct clk *clk_user)
 {
+	struct clk_core *clk;
 	bool is_en;
 
+	clk = clk_to_clk_core(clk_user);
+
 	clk_prepare_lock();
 	is_en = __clk_is_enabled(clk);
 	clk_prepare_unlock();
@@ -977,10 +1035,10 @@ EXPORT_SYMBOL_GPL(clk_is_enabled);
  *
  * Caller must hold prepare_lock.  Useful for clk_ops such as .set_rate
  */
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+unsigned long __clk_round_rate(struct clk_core *clk, unsigned long rate)
 {
 	unsigned long parent_rate = 0;
-	struct clk *parent;
+	struct clk_core *parent;
 
 	if (!clk)
 		return 0;
@@ -1001,42 +1059,51 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
 }
 EXPORT_SYMBOL_GPL(__clk_round_rate);
 
+long clk_provider_round_rate(struct clk_core *clk, unsigned long rate)
+{
+	unsigned long ret;
+
+	clk_prepare_lock();
+	ret = __clk_round_rate(clk, rate);
+	clk_prepare_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(clk_provider_round_rate);
+
 /**
  * clk_round_rate - round the given rate for a clk
- * @clk: the clk for which we are rounding a rate
+ * @clk_user: the clk for which we are rounding a rate
  * @rate: the rate which is to be rounded
  *
  * Takes in a rate as input and rounds it to a rate that the clk can actually
  * use which is then returned.  If clk doesn't support round_rate operation
  * then the parent rate is returned.
  */
-long clk_round_rate(struct clk *clk, unsigned long rate)
+long clk_round_rate(struct clk *clk_user, unsigned long rate)
 {
-	unsigned long ret;
-
-	clk_prepare_lock();
-	ret = __clk_round_rate(clk, rate);
-	clk_prepare_unlock();
+	if (!clk_user)
+		return 0;
 
-	return ret;
+	return clk_provider_round_rate(clk_to_clk_core(clk_user), rate);
 }
 EXPORT_SYMBOL_GPL(clk_round_rate);
 
 /**
  * __clk_notify - call clk notifier chain
- * @clk: struct clk * that is changing rate
+ * @clk: struct clk_core * that is changing rate
  * @msg: clk notifier type (see include/linux/clk.h)
  * @old_rate: old clk rate
  * @new_rate: new clk rate
  *
  * Triggers a notifier call chain on the clk rate-change notification
- * for 'clk'.  Passes a pointer to the struct clk and the previous
+ * for 'clk'.  Passes a pointer to the struct clk_core and the previous
  * and current rates to the notifier callback.  Intended to be called by
  * internal clock code only.  Returns NOTIFY_DONE from the last driver
  * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
  * a driver returns that.
  */
-static int __clk_notify(struct clk *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *clk, unsigned long msg,
 		unsigned long old_rate, unsigned long new_rate)
 {
 	struct clk_notifier *cn;
@@ -1069,10 +1136,10 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
  *
  * Caller must hold prepare_lock.
  */
-static void __clk_recalc_accuracies(struct clk *clk)
+static void __clk_recalc_accuracies(struct clk_core *clk)
 {
 	unsigned long parent_accuracy = 0;
-	struct clk *child;
+	struct clk_core *child;
 
 	if (clk->parent)
 		parent_accuracy = clk->parent->accuracy;
@@ -1087,16 +1154,7 @@ static void __clk_recalc_accuracies(struct clk *clk)
 		__clk_recalc_accuracies(child);
 }
 
-/**
- * clk_get_accuracy - return the accuracy of clk
- * @clk: the clk whose accuracy is being returned
- *
- * Simply returns the cached accuracy of the clk, unless
- * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be
- * issued.
- * If clk is NULL then returns 0.
- */
-long clk_get_accuracy(struct clk *clk)
+static long __clk_get_accuracy_internal(struct clk_core *clk)
 {
 	unsigned long accuracy;
 
@@ -1109,9 +1167,23 @@ long clk_get_accuracy(struct clk *clk)
 
 	return accuracy;
 }
+
+/**
+ * clk_get_accuracy - return the accuracy of clk
+ * @clk_user: the clk whose accuracy is being returned
+ *
+ * Simply returns the cached accuracy of the clk, unless
+ * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be
+ * issued.
+ * If clk is NULL then returns 0.
+ */
+long clk_get_accuracy(struct clk *clk_user)
+{
+	return __clk_get_accuracy_internal(clk_to_clk_core(clk_user));
+}
 EXPORT_SYMBOL_GPL(clk_get_accuracy);
 
-static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
+static unsigned long clk_recalc(struct clk_core *clk, unsigned long parent_rate)
 {
 	if (clk->ops->recalc_rate)
 		return clk->ops->recalc_rate(clk->hw, parent_rate);
@@ -1132,11 +1204,11 @@ static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
  *
  * Caller must hold prepare_lock.
  */
-static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
 {
 	unsigned long old_rate;
 	unsigned long parent_rate = 0;
-	struct clk *child;
+	struct clk_core *child;
 
 	old_rate = clk->rate;
 
@@ -1156,15 +1228,7 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
 		__clk_recalc_rates(child, msg);
 }
 
-/**
- * clk_get_rate - return the rate of clk
- * @clk: the clk whose rate is being returned
- *
- * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
- * is set, which means a recalc_rate will be issued.
- * If clk is NULL then returns 0.
- */
-unsigned long clk_get_rate(struct clk *clk)
+unsigned long clk_provider_get_rate(struct clk_core *clk)
 {
 	unsigned long rate;
 
@@ -1178,15 +1242,32 @@ unsigned long clk_get_rate(struct clk *clk)
 
 	return rate;
 }
+EXPORT_SYMBOL_GPL(clk_provider_get_rate);
+
+/**
+ * clk_get_rate - return the rate of clk
+ * @clk_user: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
+ * is set, which means a recalc_rate will be issued.
+ * If clk is NULL then returns 0.
+ */
+unsigned long clk_get_rate(struct clk *clk_user)
+{
+	if (!clk_user)
+		return 0;
+
+	return clk_provider_get_rate(clk_to_clk_core(clk_user));
+}
 EXPORT_SYMBOL_GPL(clk_get_rate);
 
-static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
+static int clk_fetch_parent_index(struct clk_core *clk, struct clk_core *parent)
 {
 	int i;
 
 	if (!clk->parents) {
 		clk->parents = kcalloc(clk->num_parents,
-					sizeof(struct clk *), GFP_KERNEL);
+					sizeof(struct clk_core *), GFP_KERNEL);
 		if (!clk->parents)
 			return -ENOMEM;
 	}
@@ -1212,7 +1293,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
 	return -EINVAL;
 }
 
-static void clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
 {
 	hlist_del(&clk->child_node);
 
@@ -1229,10 +1310,10 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent)
 	clk->parent = new_parent;
 }
 
-static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
+static struct clk_core *__clk_set_parent_before(struct clk_core *clk, struct clk_core *parent)
 {
 	unsigned long flags;
-	struct clk *old_parent = clk->parent;
+	struct clk_core *old_parent = clk->parent;
 
 	/*
 	 * Migrate prepare state between parents and prevent race with
@@ -1253,8 +1334,8 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
 	 */
 	if (clk->prepare_count) {
 		__clk_prepare(parent);
-		clk_enable(parent);
-		clk_enable(clk);
+		clk_provider_enable(parent);
+		clk_provider_enable(clk);
 	}
 
 	/* update the clk tree topology */
@@ -1265,25 +1346,25 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
 	return old_parent;
 }
 
-static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
-		struct clk *old_parent)
+static void __clk_set_parent_after(struct clk_core *clk, struct clk_core *parent,
+		struct clk_core *old_parent)
 {
 	/*
 	 * Finish the migration of prepare state and undo the changes done
 	 * for preventing a race with clk_enable().
 	 */
 	if (clk->prepare_count) {
-		clk_disable(clk);
-		clk_disable(old_parent);
+		clk_provider_disable(clk);
+		clk_provider_disable(old_parent);
 		__clk_unprepare(old_parent);
 	}
 }
 
-static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
+static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent, u8 p_index)
 {
 	unsigned long flags;
 	int ret = 0;
-	struct clk *old_parent;
+	struct clk_core *old_parent;
 
 	old_parent = __clk_set_parent_before(clk, parent);
 
@@ -1297,8 +1378,8 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
 		clk_enable_unlock(flags);
 
 		if (clk->prepare_count) {
-			clk_disable(clk);
-			clk_disable(parent);
+			clk_provider_disable(clk);
+			clk_provider_disable(parent);
 			__clk_unprepare(parent);
 		}
 		return ret;
@@ -1325,9 +1406,9 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
  *
  * Caller must hold prepare_lock.
  */
-static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
+static int __clk_speculate_rates(struct clk_core *clk, unsigned long parent_rate)
 {
-	struct clk *child;
+	struct clk_core *child;
 	unsigned long new_rate;
 	int ret = NOTIFY_DONE;
 
@@ -1353,10 +1434,10 @@ out:
 	return ret;
 }
 
-static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
-			     struct clk *new_parent, u8 p_index)
+static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+			     struct clk_core *new_parent, u8 p_index)
 {
-	struct clk *child;
+	struct clk_core *child;
 
 	clk->new_rate = new_rate;
 	clk->new_parent = new_parent;
@@ -1376,10 +1457,10 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
  * calculate the new rates returning the topmost clock that has to be
  * changed.
  */
-static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
+static struct clk_core *clk_calc_new_rates(struct clk_core *clk, unsigned long rate)
 {
-	struct clk *top = clk;
-	struct clk *old_parent, *parent;
+	struct clk_core *top = clk;
+	struct clk_core *old_parent, *parent;
 	unsigned long best_parent_rate = 0;
 	unsigned long new_rate;
 	int p_index = 0;
@@ -1445,9 +1526,9 @@ out:
  * so that in case of an error we can walk down the whole tree again and
  * abort the change.
  */
-static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
+static struct clk_core *clk_propagate_rate_change(struct clk_core *clk, unsigned long event)
 {
-	struct clk *child, *tmp_clk, *fail_clk = NULL;
+	struct clk_core *child, *tmp_clk, *fail_clk = NULL;
 	int ret = NOTIFY_DONE;
 
 	if (clk->rate == clk->new_rate)
@@ -1482,13 +1563,13 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
  * walk down a subtree and set the new rates notifying the rate
  * change on the way
  */
-static void clk_change_rate(struct clk *clk)
+static void clk_change_rate(struct clk_core *clk)
 {
-	struct clk *child;
+	struct clk_core *child;
 	unsigned long old_rate;
 	unsigned long best_parent_rate = 0;
 	bool skip_set_rate = false;
-	struct clk *old_parent;
+	struct clk_core *old_parent;
 
 	old_rate = clk->rate;
 
@@ -1532,30 +1613,9 @@ static void clk_change_rate(struct clk *clk)
 		clk_change_rate(clk->new_child);
 }
 
-/**
- * clk_set_rate - specify a new rate for clk
- * @clk: the clk whose rate is being changed
- * @rate: the new rate for clk
- *
- * In the simplest case clk_set_rate will only adjust the rate of clk.
- *
- * Setting the CLK_SET_RATE_PARENT flag allows the rate change operation to
- * propagate up to clk's parent; whether or not this happens depends on the
- * outcome of clk's .round_rate implementation.  If *parent_rate is unchanged
- * after calling .round_rate then upstream parent propagation is ignored.  If
- * *parent_rate comes back with a new rate for clk's parent then we propagate
- * up to clk's parent and set its rate.  Upward propagation will continue
- * until either a clk does not support the CLK_SET_RATE_PARENT flag or
- * .round_rate stops requesting changes to clk's parent_rate.
- *
- * Rate changes are accomplished via tree traversal that also recalculates the
- * rates for the clocks and fires off POST_RATE_CHANGE notifiers.
- *
- * Returns 0 on success, -EERROR otherwise.
- */
-int clk_set_rate(struct clk *clk, unsigned long rate)
+int clk_provider_set_rate(struct clk_core *clk, unsigned long rate)
 {
-	struct clk *top, *fail_clk;
+	struct clk_core *top, *fail_clk;
 	int ret = 0;
 
 	if (!clk)
@@ -1565,7 +1625,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
 	clk_prepare_lock();
 
 	/* bail early if nothing to do */
-	if (rate == clk_get_rate(clk))
+	if (rate == clk_provider_get_rate(clk))
 		goto out;
 
 	if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
@@ -1598,17 +1658,41 @@ out:
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(clk_set_rate);
+EXPORT_SYMBOL_GPL(clk_provider_set_rate);
 
 /**
- * clk_get_parent - return the parent of a clk
- * @clk: the clk whose parent gets returned
+ * clk_set_rate - specify a new rate for clk
+ * @clk_user: the clk whose rate is being changed
+ * @rate: the new rate for clk
  *
- * Simply returns clk->parent.  Returns NULL if clk is NULL.
+ * In the simplest case clk_set_rate will only adjust the rate of clk.
+ *
+ * Setting the CLK_SET_RATE_PARENT flag allows the rate change operation to
+ * propagate up to clk's parent; whether or not this happens depends on the
+ * outcome of clk's .round_rate implementation.  If *parent_rate is unchanged
+ * after calling .round_rate then upstream parent propagation is ignored.  If
+ * *parent_rate comes back with a new rate for clk's parent then we propagate
+ * up to clk's parent and set its rate.  Upward propagation will continue
+ * until either a clk does not support the CLK_SET_RATE_PARENT flag or
+ * .round_rate stops requesting changes to clk's parent_rate.
+ *
+ * Rate changes are accomplished via tree traversal that also recalculates the
+ * rates for the clocks and fires off POST_RATE_CHANGE notifiers.
+ *
+ * Returns 0 on success, -EERROR otherwise.
  */
-struct clk *clk_get_parent(struct clk *clk)
+int clk_set_rate(struct clk *clk_user, unsigned long rate)
 {
-	struct clk *parent;
+	if (!clk_user)
+		return 0;
+
+	return clk_provider_set_rate(clk_to_clk_core(clk_user), rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+struct clk_core *clk_provider_get_parent(struct clk_core *clk)
+{
+	struct clk_core *parent;
 
 	clk_prepare_lock();
 	parent = __clk_get_parent(clk);
@@ -1616,8 +1700,35 @@ struct clk *clk_get_parent(struct clk *clk)
 
 	return parent;
 }
+EXPORT_SYMBOL_GPL(clk_provider_get_parent);
+
+/**
+ * clk_get_parent - return the parent of a clk
+ * @clk_user: the clk whose parent gets returned
+ *
+ * Simply returns clk->parent.  Returns NULL if clk is NULL.
+ */
+struct clk *clk_get_parent(struct clk *clk_user)
+{
+	struct clk_core *clk;
+	struct clk_core *parent;
+
+	if (!clk_user)
+		return NULL;
+
+	clk = clk_to_clk_core(clk_user);
+	parent = clk_provider_get_parent(clk);
+
+	return __clk_create_clk(parent);
+}
 EXPORT_SYMBOL_GPL(clk_get_parent);
 
+const char *clk_get_name(struct clk *clk_user)
+{
+	return __clk_get_name(clk_to_clk_core(clk_user));
+}
+EXPORT_SYMBOL_GPL(clk_get_name);
+
 /*
  * .get_parent is mandatory for clocks with multiple possible parents.  It is
  * optional for single-parent clocks.  Always call .get_parent if it is
@@ -1627,9 +1738,9 @@ EXPORT_SYMBOL_GPL(clk_get_parent);
  * .parents array exists, and if so use it to avoid an expensive tree
  * traversal.  If .parents does not exist then walk the tree with __clk_lookup.
  */
-static struct clk *__clk_init_parent(struct clk *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *clk)
 {
-	struct clk *ret = NULL;
+	struct clk_core *ret = NULL;
 	u8 index;
 
 	/* handle the trivial cases */
@@ -1661,7 +1772,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
 
 	if (!clk->parents)
 		clk->parents =
-			kcalloc(clk->num_parents, sizeof(struct clk *),
+			kcalloc(clk->num_parents, sizeof(struct clk_core *),
 					GFP_KERNEL);
 
 	ret = clk_get_parent_by_index(clk, index);
@@ -1670,31 +1781,14 @@ out:
 	return ret;
 }
 
-void __clk_reparent(struct clk *clk, struct clk *new_parent)
+void __clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
 {
 	clk_reparent(clk, new_parent);
 	__clk_recalc_accuracies(clk);
 	__clk_recalc_rates(clk, POST_RATE_CHANGE);
 }
 
-/**
- * clk_set_parent - switch the parent of a mux clk
- * @clk: the mux clk whose input we are switching
- * @parent: the new input to clk
- *
- * Re-parent clk to use parent as its new input source.  If clk is in
- * prepared state, the clk will get enabled for the duration of this call. If
- * that's not acceptable for a specific clk (Eg: the consumer can't handle
- * that, the reparenting is glitchy in hardware, etc), use the
- * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
- *
- * After successfully changing clk's parent clk_set_parent will update the
- * clk topology, sysfs topology and propagate rate recalculation via
- * __clk_recalc_rates.
- *
- * Returns 0 on success, -EERROR otherwise.
- */
-int clk_set_parent(struct clk *clk, struct clk *parent)
+int clk_provider_set_parent(struct clk_core *clk, struct clk_core *parent)
 {
 	int ret = 0;
 	int p_index = 0;
@@ -1754,6 +1848,38 @@ out:
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(clk_provider_set_parent);
+
+/**
+ * clk_set_parent - switch the parent of a mux clk
+ * @clk_user: the mux clk whose input we are switching
+ * @parent_user: the new input to clk
+ *
+ * Re-parent clk to use parent as its new input source.  If clk is in
+ * prepared state, the clk will get enabled for the duration of this call. If
+ * that's not acceptable for a specific clk (Eg: the consumer can't handle
+ * that, the reparenting is glitchy in hardware, etc), use the
+ * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
+ *
+ * After successfully changing clk's parent clk_set_parent will update the
+ * clk topology, sysfs topology and propagate rate recalculation via
+ * __clk_recalc_rates.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_parent(struct clk *clk_user, struct clk *parent_user)
+{
+	struct clk_core *clk;
+	struct clk_core *parent;
+
+	if (!clk_user)
+		return 0;
+
+	clk = clk_to_clk_core(clk_user);
+	parent = clk_to_clk_core(parent_user);
+
+	return clk_provider_set_parent(clk, parent);
+}
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
 /**
@@ -1764,10 +1890,10 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
  * Initializes the lists in struct clk, queries the hardware for the
  * parent and rate and sets them both.
  */
-int __clk_init(struct device *dev, struct clk *clk)
+int __clk_init(struct device *dev, struct clk_core *clk)
 {
 	int i, ret = 0;
-	struct clk *orphan;
+	struct clk_core *orphan;
 	struct hlist_node *tmp2;
 
 	if (!clk)
@@ -1815,7 +1941,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 				__func__, clk->name);
 
 	/*
-	 * Allocate an array of struct clk *'s to avoid unnecessary string
+	 * Allocate an array of struct clk_core *'s to avoid unnecessary string
 	 * look-ups of clk's possible parents.  This can fail for clocks passed
 	 * in to clk_init during early boot; thus any access to clk->parents[]
 	 * must always check for a NULL pointer and try to populate it if
@@ -1825,7 +1951,7 @@ int __clk_init(struct device *dev, struct clk *clk)
 	 * for clock drivers to statically initialize clk->parents.
 	 */
 	if (clk->num_parents > 1 && !clk->parents) {
-		clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
+		clk->parents = kcalloc(clk->num_parents, sizeof(struct clk_core *),
 					GFP_KERNEL);
 		/*
 		 * __clk_lookup returns NULL for parents that have not been
@@ -1931,7 +2057,7 @@ out:
  *
  * Same as clk_register, except that the .clk field inside hw shall point to a
  * preallocated (generally statically allocated) struct clk. None of the fields
- * of the struct clk need to be initialized.
+ * of the struct clk_core need to be initialized.
  *
  * The data pointed to by .init and .clk field shall NOT be marked as init
  * data.
@@ -1943,10 +2069,10 @@ out:
  * separate C file from the logic that implements its operations.  Returns 0
  * on success, otherwise an error code.
  */
-struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
+struct clk_core *__clk_register(struct device *dev, struct clk_hw *hw)
 {
 	int ret;
-	struct clk *clk;
+	struct clk_core *clk;
 
 	clk = hw->clk;
 	clk->name = hw->init->name;
@@ -1974,15 +2100,15 @@ EXPORT_SYMBOL_GPL(__clk_register);
  * @hw: link to hardware-specific clock data
  *
  * clk_register is the primary interface for populating the clock tree with new
- * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * clock nodes.  It returns a pointer to the newly allocated struct clk_core which
  * cannot be dereferenced by driver code but may be used in conjuction with the
  * rest of the clock API.  In the event of an error clk_register will return an
  * error code; drivers must test for an error code after calling clk_register.
  */
-struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+struct clk_core *clk_register(struct device *dev, struct clk_hw *hw)
 {
 	int i, ret;
-	struct clk *clk;
+	struct clk_core *clk;
 
 	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
 	if (!clk) {
@@ -2050,7 +2176,7 @@ EXPORT_SYMBOL_GPL(clk_register);
  */
 static void __clk_release(struct kref *ref)
 {
-	struct clk *clk = container_of(ref, struct clk, ref);
+	struct clk_core *clk = container_of(ref, struct clk_core, ref);
 	int i = clk->num_parents;
 
 	kfree(clk->parents);
@@ -2101,7 +2227,7 @@ static const struct clk_ops clk_nodrv_ops = {
  * clk_unregister - unregister a currently registered clock
  * @clk: clock to unregister
  */
-void clk_unregister(struct clk *clk)
+void clk_unregister(struct clk_core *clk)
 {
 	unsigned long flags;
 
@@ -2123,12 +2249,12 @@ void clk_unregister(struct clk *clk)
 	clk_enable_unlock(flags);
 
 	if (!hlist_empty(&clk->children)) {
-		struct clk *child;
+		struct clk_core *child;
 		struct hlist_node *t;
 
 		/* Reparent all children to the orphan list. */
 		hlist_for_each_entry_safe(child, t, &clk->children, child_node)
-			clk_set_parent(child, NULL);
+			clk_provider_set_parent(child, NULL);
 	}
 
 	clk_debug_unregister(clk);
@@ -2147,9 +2273,15 @@ EXPORT_SYMBOL_GPL(clk_unregister);
 
 static void devm_clk_release(struct device *dev, void *res)
 {
-	clk_unregister(*(struct clk **)res);
+	clk_unregister(*(struct clk_core **)res);
 }
 
+struct clk_core *clk_to_clk_core(struct clk *clk)
+{
+	return clk->core;
+}
+EXPORT_SYMBOL_GPL(clk_to_clk_core);
+
 /**
  * devm_clk_register - resource managed clk_register()
  * @dev: device that is registering this clock
@@ -2159,10 +2291,10 @@ static void devm_clk_release(struct device *dev, void *res)
  * automatically clk_unregister()ed on driver detach. See clk_register() for
  * more information.
  */
-struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
+struct clk_core *devm_clk_register(struct device *dev, struct clk_hw *hw)
 {
-	struct clk *clk;
-	struct clk **clkp;
+	struct clk_core *clk;
+	struct clk_core **clkp;
 
 	clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL);
 	if (!clkp)
@@ -2182,7 +2314,7 @@ EXPORT_SYMBOL_GPL(devm_clk_register);
 
 static int devm_clk_match(struct device *dev, void *res, void *data)
 {
-	struct clk *c = res;
+	struct clk_core *c = res;
 	if (WARN_ON(!c))
 		return 0;
 	return c == data;
@@ -2196,7 +2328,7 @@ static int devm_clk_match(struct device *dev, void *res, void *data)
  * this function will not need to be called and the resource management
  * code will ensure that the resource is freed.
  */
-void devm_clk_unregister(struct device *dev, struct clk *clk)
+void devm_clk_unregister(struct device *dev, struct clk_core *clk)
 {
 	WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
 }
@@ -2205,7 +2337,7 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);
 /*
  * clkdev helpers
  */
-int __clk_get(struct clk *clk)
+int __clk_get(struct clk_core *clk)
 {
 	if (clk) {
 		if (!try_module_get(clk->owner))
@@ -2216,7 +2348,7 @@ int __clk_get(struct clk *clk)
 	return 1;
 }
 
-void __clk_put(struct clk *clk)
+void __clk_put(struct clk_core *clk)
 {
 	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
 		return;
@@ -2230,28 +2362,7 @@ void __clk_put(struct clk *clk)
 
 /***        clk rate change notifiers        ***/
 
-/**
- * clk_notifier_register - add a clk rate change notifier
- * @clk: struct clk * to watch
- * @nb: struct notifier_block * with callback info
- *
- * Request notification when clk's rate changes.  This uses an SRCU
- * notifier because we want it to block and notifier unregistrations are
- * uncommon.  The callbacks associated with the notifier must not
- * re-enter into the clk framework by calling any top-level clk APIs;
- * this will cause a nested prepare_lock mutex.
- *
- * In all notification cases cases (pre, post and abort rate change) the
- * original clock rate is passed to the callback via struct
- * clk_notifier_data.old_rate and the new frequency is passed via struct
- * clk_notifier_data.new_rate.
- *
- * clk_notifier_register() must be called from non-atomic context.
- * Returns -EINVAL if called with null arguments, -ENOMEM upon
- * allocation failure; otherwise, passes along the return value of
- * srcu_notifier_chain_register().
- */
-int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
+int clk_provider_notifier_register(struct clk_core *clk, struct notifier_block *nb)
 {
 	struct clk_notifier *cn;
 	int ret = -ENOMEM;
@@ -2287,20 +2398,38 @@ out:
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(clk_notifier_register);
+EXPORT_SYMBOL_GPL(clk_provider_notifier_register);
 
 /**
- * clk_notifier_unregister - remove a clk rate change notifier
- * @clk: struct clk *
+ * clk_notifier_register - add a clk rate change notifier
+ * @clk_user: struct clk * to watch
  * @nb: struct notifier_block * with callback info
  *
- * Request no further notification for changes to 'clk' and frees memory
- * allocated in clk_notifier_register.
+ * Request notification when clk's rate changes.  This uses an SRCU
+ * notifier because we want it to block and notifier unregistrations are
+ * uncommon.  The callbacks associated with the notifier must not
+ * re-enter into the clk framework by calling any top-level clk APIs;
+ * this will cause a nested prepare_lock mutex.
  *
- * Returns -EINVAL if called with null arguments; otherwise, passes
- * along the return value of srcu_notifier_chain_unregister().
+ * In all notification cases cases (pre, post and abort rate change) the
+ * original clock rate is passed to the callback via struct
+ * clk_notifier_data.old_rate and the new frequency is passed via struct
+ * clk_notifier_data.new_rate.
+ *
+ * clk_notifier_register() must be called from non-atomic context.
+ * Returns -EINVAL if called with null arguments, -ENOMEM upon
+ * allocation failure; otherwise, passes along the return value of
+ * srcu_notifier_chain_register().
  */
-int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
+int clk_notifier_register(struct clk *clk_user, struct notifier_block *nb)
+{
+	struct clk_core *clk = clk_to_clk_core(clk_user);
+
+	return clk_provider_notifier_register(clk, nb);
+}
+EXPORT_SYMBOL_GPL(clk_notifier_register);
+
+int clk_provider_notifier_unregister(struct clk_core *clk, struct notifier_block *nb)
 {
 	struct clk_notifier *cn = NULL;
 	int ret = -EINVAL;
@@ -2334,6 +2463,25 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(clk_provider_notifier_unregister);
+
+/**
+ * clk_notifier_unregister - remove a clk rate change notifier
+ * @clk_user: struct clk_core *
+ * @nb: struct notifier_block * with callback info
+ *
+ * Request no further notification for changes to 'clk' and frees memory
+ * allocated in clk_notifier_register.
+ *
+ * Returns -EINVAL if called with null arguments; otherwise, passes
+ * along the return value of srcu_notifier_chain_unregister().
+ */
+int clk_notifier_unregister(struct clk *clk_user, struct notifier_block *nb)
+{
+	struct clk_core *clk = clk_to_clk_core(clk_user);
+
+	return clk_provider_notifier_unregister(clk, nb);
+}
 EXPORT_SYMBOL_GPL(clk_notifier_unregister);
 
 #ifdef CONFIG_OF
@@ -2341,7 +2489,7 @@ EXPORT_SYMBOL_GPL(clk_notifier_unregister);
  * struct of_clk_provider - Clock provider registration structure
  * @link: Entry in global list of clock providers
  * @node: Pointer to device tree node of clock provider
- * @get: Get clock callback.  Returns NULL or a struct clk for the
+ * @get: Get clock callback.  Returns NULL or a struct clk_core for the
  *       given clock specifier
  * @data: context pointer to be passed into @get callback
  */
@@ -2349,7 +2497,7 @@ struct of_clk_provider {
 	struct list_head link;
 
 	struct device_node *node;
-	struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
+	struct clk_core *(*get)(struct of_phandle_args *clkspec, void *data);
 	void *data;
 };
 
@@ -2370,14 +2518,14 @@ void of_clk_unlock(void)
 	mutex_unlock(&of_clk_mutex);
 }
 
-struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
+struct clk_core *of_clk_src_simple_get(struct of_phandle_args *clkspec,
 				     void *data)
 {
 	return data;
 }
 EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
 
-struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
+struct clk_core *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
 {
 	struct clk_onecell_data *clk_data = data;
 	unsigned int idx = clkspec->args[0];
@@ -2398,7 +2546,7 @@ EXPORT_SYMBOL_GPL(of_clk_src_onecell_get);
  * @data: context pointer for @clk_src_get callback.
  */
 int of_clk_add_provider(struct device_node *np,
-			struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
+			struct clk_core *(*clk_src_get)(struct of_phandle_args *clkspec,
 						   void *data),
 			void *data)
 {
@@ -2447,10 +2595,10 @@ void of_clk_del_provider(struct device_node *np)
 }
 EXPORT_SYMBOL_GPL(of_clk_del_provider);
 
-struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
+struct clk_core *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
 {
 	struct of_clk_provider *provider;
-	struct clk *clk = ERR_PTR(-EPROBE_DEFER);
+	struct clk_core *clk = ERR_PTR(-EPROBE_DEFER);
 
 	/* Check if we have such a provider in our array */
 	list_for_each_entry(provider, &of_clk_providers, link) {
@@ -2463,9 +2611,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
 	return clk;
 }
 
-struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
+struct clk_core *of_clk_get_from_provider(struct of_phandle_args *clkspec)
 {
-	struct clk *clk;
+	struct clk_core *clk;
 
 	mutex_lock(&of_clk_mutex);
 	clk = __of_clk_get_from_provider(clkspec);
@@ -2540,11 +2688,11 @@ static int parent_ready(struct device_node *np)
 	int i = 0;
 
 	while (true) {
-		struct clk *clk = of_clk_get(np, i);
+		struct clk_core *clk = of_clk_provider_get(np, i);
 
 		/* this parent is ready we can check the next one */
 		if (!IS_ERR(clk)) {
-			clk_put(clk);
+			__clk_put(clk);
 			i++;
 			continue;
 		}
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index d278572..3b3068b 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -9,9 +9,15 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/clk-private.h>
+
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk_core *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
 struct clk_core *__of_clk_get_from_provider(struct of_phandle_args *clkspec);
 void of_clk_lock(void);
 void of_clk_unlock(void);
 #endif
+
+#if defined(CONFIG_COMMON_CLK)
+struct clk *__clk_create_clk(struct clk_core *clk_core);
+#endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index c751d0c..810935f 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
+#include <linux/clk-private.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/of.h>
@@ -33,13 +34,13 @@ static DEFINE_MUTEX(clocks_mutex);
  * of_clk_get_by_clkspec() - Lookup a clock form a clock provider
  * @clkspec: pointer to a clock specifier data structure
  *
- * This function looks up a struct clk from the registered list of clock
+ * This function looks up a struct clk_core from the registered list of clock
  * providers, an input is a clock specifier data structure as returned
  * from the of_parse_phandle_with_args() function call.
  */
-struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
+struct clk_core *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
 {
-	struct clk *clk;
+	struct clk_core *clk;
 
 	if (!clkspec)
 		return ERR_PTR(-EINVAL);
@@ -54,10 +55,10 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
 	return clk;
 }
 
-struct clk *of_clk_get(struct device_node *np, int index)
+struct clk_core *of_clk_provider_get(struct device_node *np, int index)
 {
 	struct of_phandle_args clkspec;
-	struct clk *clk;
+	clk_core_t *clk;
 	int rc;
 
 	if (index < 0)
@@ -72,20 +73,16 @@ struct clk *of_clk_get(struct device_node *np, int index)
 	of_node_put(clkspec.np);
 	return clk;
 }
+
+struct clk *of_clk_get(struct device_node *np, int index)
+{
+	return __clk_create_clk(of_clk_provider_get(np, index));
+}
 EXPORT_SYMBOL(of_clk_get);
 
-/**
- * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
- * @np: pointer to clock consumer node
- * @name: name of consumer's clock input, or NULL for the first clock reference
- *
- * This function parses the clocks and clock-names properties,
- * and uses them to look up the struct clk from the registered list of clock
- * providers.
- */
-struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+struct clk_core *of_clk_provider_get_by_name(struct device_node *np, const char *name)
 {
-	struct clk *clk = ERR_PTR(-ENOENT);
+	struct clk_core *clk = ERR_PTR(-ENOENT);
 
 	/* Walk up the tree of devices looking for a clock that matches */
 	while (np) {
@@ -98,7 +95,7 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
 		 */
 		if (name)
 			index = of_property_match_string(np, "clock-names", name);
-		clk = of_clk_get(np, index);
+		clk = of_clk_provider_get(np, index);
 		if (!IS_ERR(clk))
 			break;
 		else if (name && index >= 0) {
@@ -120,11 +117,25 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
 
 	return clk;
 }
+
+/**
+ * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties,
+ * and uses them to look up the clock from the registered list of clock
+ * providers.
+ */
+struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+{
+	return __clk_create_clk(of_clk_provider_get_by_name(np, name));
+}
 EXPORT_SYMBOL(of_clk_get_by_name);
 #endif
 
 /*
- * Find the correct struct clk for the device and connection ID.
+ * Find the correct clock for the device and connection ID.
  * We do slightly fuzzy matching here:
  *  An entry with a NULL ID is assumed to be a wildcard.
  *  If an entry has a device ID, it must match
@@ -166,8 +177,32 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
 	return cl;
 }
 
+#if defined(CONFIG_COMMON_CLK)
+struct clk_core *clk_provider_get_sys(const char *dev_id, const char *con_id)
+{
+	struct clk_lookup *cl;
+
+	mutex_lock(&clocks_mutex);
+	cl = clk_find(dev_id, con_id);
+	if (cl && !__clk_get(cl->clk))
+		cl = NULL;
+	mutex_unlock(&clocks_mutex);
+
+	if (!cl)
+		return ERR_PTR(-ENOENT);
+
+	return cl->clk;
+}
+EXPORT_SYMBOL_GPL(clk_provider_get_sys);
+#endif
+
 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 {
+#if defined(CONFIG_COMMON_CLK)
+	struct clk_core *clk = clk_provider_get_sys(dev_id, con_id);
+
+	return __clk_create_clk(clk);
+#else
 	struct clk_lookup *cl;
 
 	mutex_lock(&clocks_mutex);
@@ -176,12 +211,40 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 		cl = NULL;
 	mutex_unlock(&clocks_mutex);
 
-	return cl ? cl->clk : ERR_PTR(-ENOENT);
+	if (!cl)
+		return ERR_PTR(-ENOENT);
+
+	return cl->clk;
+#endif
 }
 EXPORT_SYMBOL(clk_get_sys);
 
+#if defined(CONFIG_COMMON_CLK)
+struct clk_core *clk_provider_get(struct device *dev, const char *con_id)
+{
+	const char *dev_id = dev ? dev_name(dev) : NULL;
+	struct clk_core *clk;
+
+	if (dev) {
+		clk = of_clk_provider_get_by_name(dev->of_node, con_id);
+		if (!IS_ERR(clk))
+			return clk;
+		if (PTR_ERR(clk) == -EPROBE_DEFER)
+			return clk;
+	}
+
+	return clk_provider_get_sys(dev_id, con_id);
+}
+EXPORT_SYMBOL(clk_provider_get);
+#endif
+
 struct clk *clk_get(struct device *dev, const char *con_id)
 {
+#if defined(CONFIG_COMMON_CLK)
+	const char *dev_id = dev ? dev_name(dev) : NULL;
+
+	return __clk_create_clk(clk_provider_get(dev, con_id));
+#else
 	const char *dev_id = dev ? dev_name(dev) : NULL;
 	struct clk *clk;
 
@@ -194,12 +257,20 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 	}
 
 	return clk_get_sys(dev_id, con_id);
+#endif
 }
 EXPORT_SYMBOL(clk_get);
 
 void clk_put(struct clk *clk)
 {
+#if defined(CONFIG_COMMON_CLK)
+	clk_core_t *core = clk_to_clk_core(clk);
+
+	kfree(clk);
+	__clk_put(core);
+#else
 	__clk_put(clk);
+#endif
 }
 EXPORT_SYMBOL(clk_put);
 
@@ -231,7 +302,7 @@ struct clk_lookup_alloc {
 };
 
 static struct clk_lookup * __init_refok
-vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
+vclkdev_alloc(clk_core_t *clk, const char *con_id, const char *dev_fmt,
 	va_list ap)
 {
 	struct clk_lookup_alloc *cla;
@@ -255,7 +326,7 @@ vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
 }
 
 struct clk_lookup * __init_refok
-clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
+clkdev_alloc(clk_core_t *clk, const char *con_id, const char *dev_fmt, ...)
 {
 	struct clk_lookup *cl;
 	va_list ap;
@@ -277,7 +348,11 @@ int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
 	if (IS_ERR(r))
 		return PTR_ERR(r);
 
+#ifdef CONFIG_COMMON_CLK
+	l = clkdev_alloc(clk_to_clk_core(r), alias, alias_dev_name);
+#else
 	l = clkdev_alloc(r, alias, alias_dev_name);
+#endif
 	clk_put(r);
 	if (!l)
 		return -ENODEV;
@@ -300,7 +375,7 @@ EXPORT_SYMBOL(clkdev_drop);
 
 /**
  * clk_register_clkdev - register one clock lookup for a struct clk
- * @clk: struct clk to associate with all clk_lookups
+ * @clk: clock to associate with all clk_lookups
  * @con_id: connection ID string on device
  * @dev_id: format string describing device name
  *
@@ -312,7 +387,7 @@ EXPORT_SYMBOL(clkdev_drop);
  * those.  This is to permit this function to be called immediately
  * after clk_register().
  */
-int clk_register_clkdev(struct clk *clk, const char *con_id,
+int clk_register_clkdev(clk_core_t *clk, const char *con_id,
 	const char *dev_fmt, ...)
 {
 	struct clk_lookup *cl;
@@ -335,7 +410,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
 
 /**
  * clk_register_clkdevs - register a set of clk_lookup for a struct clk
- * @clk: struct clk to associate with all clk_lookups
+ * @clk: clock to associate with all clk_lookups
  * @cl: array of clk_lookup structures with con_id and dev_id pre-initialized
  * @num: number of clk_lookup structures to register
  *
@@ -344,7 +419,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
  * those.  This is to permit this function to be called immediately
  * after clk_register().
  */
-int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
+int clk_register_clkdevs(clk_core_t *clk, struct clk_lookup *cl, size_t num)
 {
 	unsigned i;
 
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index efbf70b..2c1ece9 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -28,20 +28,20 @@
 
 struct module;
 
-struct clk {
+struct clk_core {
 	const char		*name;
 	const struct clk_ops	*ops;
 	struct clk_hw		*hw;
 	struct module		*owner;
-	struct clk		*parent;
+	struct clk_core		*parent;
 	const char		**parent_names;
-	struct clk		**parents;
+	struct clk_core		**parents;
 	u8			num_parents;
 	u8			new_parent_index;
 	unsigned long		rate;
 	unsigned long		new_rate;
-	struct clk		*new_parent;
-	struct clk		*new_child;
+	struct clk_core		*new_parent;
+	struct clk_core		*new_child;
 	unsigned long		flags;
 	unsigned int		enable_count;
 	unsigned int		prepare_count;
@@ -55,6 +55,10 @@ struct clk {
 	struct kref		ref;
 };
 
+struct clk {
+	struct clk_core	*core;
+};
+
 /*
  * DOC: Basic clock implementations common to many platforms
  *
@@ -66,7 +70,7 @@ struct clk {
 
 #define DEFINE_CLK(_name, _ops, _flags, _parent_names,		\
 		_parents)					\
-	static struct clk _name = {				\
+	static struct clk_core _name = {				\
 		.name = #_name,					\
 		.ops = &_ops,					\
 		.hw = &_name##_hw.hw,				\
@@ -78,7 +82,7 @@ struct clk {
 
 #define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate,		\
 				_fixed_rate_flags)		\
-	static struct clk _name;				\
+	static struct clk_core _name;				\
 	static const char *_name##_parent_names[] = {};		\
 	static struct clk_fixed_rate _name##_hw = {		\
 		.hw = {						\
@@ -93,11 +97,11 @@ struct clk {
 #define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr,	\
 				_flags, _reg, _bit_idx,		\
 				_gate_flags, _lock)		\
-	static struct clk _name;				\
+	static struct clk_core _name;				\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
 	};							\
-	static struct clk *_name##_parents[] = {		\
+	static struct clk_core *_name##_parents[] = {		\
 		_parent_ptr,					\
 	};							\
 	static struct clk_gate _name##_hw = {			\
@@ -115,11 +119,11 @@ struct clk {
 #define _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr,	\
 				_flags, _reg, _shift, _width,	\
 				_divider_flags, _table, _lock)	\
-	static struct clk _name;				\
+	static struct clk_core _name;				\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
 	};							\
-	static struct clk *_name##_parents[] = {		\
+	static struct clk_core *_name##_parents[] = {		\
 		_parent_ptr,					\
 	};							\
 	static struct clk_divider _name##_hw = {		\
@@ -154,7 +158,7 @@ struct clk {
 #define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags,	\
 				_reg, _shift, _width,		\
 				_mux_flags, _lock)		\
-	static struct clk _name;				\
+	static struct clk_core _name;				\
 	static struct clk_mux _name##_hw = {			\
 		.hw = {						\
 			.clk = &_name,				\
@@ -171,11 +175,11 @@ struct clk {
 #define DEFINE_CLK_FIXED_FACTOR(_name, _parent_name,		\
 				_parent_ptr, _flags,		\
 				_mult, _div)			\
-	static struct clk _name;				\
+	static struct clk_core _name;				\
 	static const char *_name##_parent_names[] = {		\
 		_parent_name,					\
 	};							\
-	static struct clk *_name##_parents[] = {		\
+	static struct clk_core *_name##_parents[] = {		\
 		_parent_ptr,					\
 	};							\
 	static struct clk_fixed_factor _name##_hw = {		\
@@ -196,7 +200,7 @@ struct clk {
  * Initializes the lists in struct clk, queries the hardware for the
  * parent and rate and sets them both.
  *
- * Any struct clk passed into __clk_init must have the following members
+ * Any struct clk_core passed into __clk_init must have the following members
  * populated:
  * 	.name
  * 	.ops
@@ -210,9 +214,9 @@ struct clk {
  *
  * Returns 0 on success, otherwise an error code.
  */
-int __clk_init(struct device *dev, struct clk *clk);
+int __clk_init(struct device *dev, struct clk_core *clk);
 
-struct clk *__clk_register(struct device *dev, struct clk_hw *hw);
+struct clk_core *__clk_register(struct device *dev, struct clk_hw *hw);
 
 #endif /* CONFIG_COMMON_CLK */
 #endif /* CLK_PRIVATE_H */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index a1a7bb7..edf1beb 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -16,33 +16,8 @@
 
 #ifdef CONFIG_COMMON_CLK
 
-/* Temporarily map the to-be-added API to the old API, just so stuff compiles */
-#define clk_core			clk
-
-#define __clk_create_clk
-
-#define clk_provider_get			clk_get
-#define clk_provider_get_sys			clk_get_sys
-#define devm_clk_provider_get			devm_clk_get
-#define of_clk_provider_get			of_clk_get
-#define of_clk_provider_get_by_name		of_clk_get_by_name
-
-#define clk_provider_set_rate			clk_set_rate
-#define clk_provider_get_rate			clk_get_rate
-#define clk_provider_round_rate			clk_round_rate
-#define clk_provider_set_parent			clk_set_parent
-#define clk_provider_get_parent			clk_get_parent
-#define clk_provider_prepare			clk_prepare
-#define clk_provider_unprepare			clk_unprepare
-#define clk_provider_enable			clk_enable
-#define clk_provider_disable			clk_disable
-#define clk_provider_prepare_enable		clk_prepare_enable
-#define clk_provider_disable_unprepare		clk_unprepare
-#define clk_provider_notifier_register		clk_notifier_register
-#define clk_provider_notifier_unregister	clk_notifier_unregister
-
 /*
- * flags used across common struct clk.  these flags should only affect the
+ * flags used across common struct clk_core.  these flags should only affect the
  * top-level framework.  custom flags for dealing with hardware specifics
  * belong in struct clk_foo
  */
@@ -192,7 +167,7 @@ struct clk_ops {
 					unsigned long *parent_rate);
 	long		(*determine_rate)(struct clk_hw *hw, unsigned long rate,
 					unsigned long *best_parent_rate,
-					struct clk **best_parent_clk);
+					struct clk_core **best_parent_clk);
 	int		(*set_parent)(struct clk_hw *hw, u8 index);
 	u8		(*get_parent)(struct clk_hw *hw);
 	int		(*set_rate)(struct clk_hw *hw, unsigned long rate,
@@ -225,19 +200,19 @@ struct clk_init_data {
 };
 
 /**
- * struct clk_hw - handle for traversing from a struct clk to its corresponding
+ * struct clk_hw - handle for traversing from a struct clk_core to its corresponding
  * hardware-specific structure.  struct clk_hw should be declared within struct
- * clk_foo and then referenced by the struct clk instance that uses struct
+ * clk_foo and then referenced by the struct clk_core instance that uses struct
  * clk_foo's clk_ops
  *
- * @clk: pointer to the struct clk instance that points back to this struct
+ * @clk: pointer to the struct clk_core instance that points back to this struct
  * clk_hw instance
  *
  * @init: pointer to struct clk_init_data that contains the init data shared
  * with the common clock framework.
  */
 struct clk_hw {
-	struct clk *clk;
+	struct clk_core *clk;
 	const struct clk_init_data *init;
 };
 
@@ -263,10 +238,10 @@ struct clk_fixed_rate {
 };
 
 extern const struct clk_ops clk_fixed_rate_ops;
-struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
+struct clk_core *clk_register_fixed_rate(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		unsigned long fixed_rate);
-struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
+struct clk_core *clk_register_fixed_rate_with_accuracy(struct device *dev,
 		const char *name, const char *parent_name, unsigned long flags,
 		unsigned long fixed_rate, unsigned long fixed_accuracy);
 
@@ -304,7 +279,7 @@ struct clk_gate {
 #define CLK_GATE_HIWORD_MASK		BIT(1)
 
 extern const struct clk_ops clk_gate_ops;
-struct clk *clk_register_gate(struct device *dev, const char *name,
+struct clk_core *clk_register_gate(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 bit_idx,
 		u8 clk_gate_flags, spinlock_t *lock);
@@ -367,11 +342,11 @@ struct clk_divider {
 
 extern const struct clk_ops clk_divider_ops;
 extern const struct clk_ops clk_divider_ro_ops;
-struct clk *clk_register_divider(struct device *dev, const char *name,
+struct clk_core *clk_register_divider(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, spinlock_t *lock);
-struct clk *clk_register_divider_table(struct device *dev, const char *name,
+struct clk_core *clk_register_divider_table(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_divider_flags, const struct clk_div_table *table,
@@ -416,12 +391,12 @@ struct clk_mux {
 extern const struct clk_ops clk_mux_ops;
 extern const struct clk_ops clk_mux_ro_ops;
 
-struct clk *clk_register_mux(struct device *dev, const char *name,
+struct clk_core *clk_register_mux(struct device *dev, const char *name,
 		const char **parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u8 width,
 		u8 clk_mux_flags, spinlock_t *lock);
 
-struct clk *clk_register_mux_table(struct device *dev, const char *name,
+struct clk_core *clk_register_mux_table(struct device *dev, const char *name,
 		const char **parent_names, u8 num_parents, unsigned long flags,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
@@ -447,7 +422,7 @@ struct clk_fixed_factor {
 };
 
 extern struct clk_ops clk_fixed_factor_ops;
-struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
+struct clk_core *clk_register_fixed_factor(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
 		unsigned int mult, unsigned int div);
 
@@ -477,7 +452,7 @@ struct clk_fractional_divider {
 };
 
 extern const struct clk_ops clk_fractional_divider_ops;
-struct clk *clk_register_fractional_divider(struct device *dev,
+struct clk_core *clk_register_fractional_divider(struct device *dev,
 		const char *name, const char *parent_name, unsigned long flags,
 		void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
 		u8 clk_divider_flags, spinlock_t *lock);
@@ -506,7 +481,7 @@ struct clk_composite {
 	const struct clk_ops	*gate_ops;
 };
 
-struct clk *clk_register_composite(struct device *dev, const char *name,
+struct clk_core *clk_register_composite(struct device *dev, const char *name,
 		const char **parent_names, int num_parents,
 		struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
 		struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
@@ -519,49 +494,87 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
  * @hw: link to hardware-specific clock data
  *
  * clk_register is the primary interface for populating the clock tree with new
- * clock nodes.  It returns a pointer to the newly allocated struct clk which
+ * clock nodes.  It returns a pointer to the newly allocated struct clk_core which
  * cannot be dereferenced by driver code but may be used in conjuction with the
  * rest of the clock API.  In the event of an error clk_register will return an
  * error code; drivers must test for an error code after calling clk_register.
  */
-struct clk *clk_register(struct device *dev, struct clk_hw *hw);
-struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
+struct clk_core *clk_register(struct device *dev, struct clk_hw *hw);
+struct clk_core *devm_clk_register(struct device *dev, struct clk_hw *hw);
 
-void clk_unregister(struct clk *clk);
-void devm_clk_unregister(struct device *dev, struct clk *clk);
+void clk_unregister(struct clk_core *clk);
+void devm_clk_unregister(struct device *dev, struct clk_core *clk);
 
 /* helper functions */
-const char *__clk_get_name(struct clk *clk);
-struct clk_hw *__clk_get_hw(struct clk *clk);
-u8 __clk_get_num_parents(struct clk *clk);
-struct clk *__clk_get_parent(struct clk *clk);
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index);
-unsigned int __clk_get_enable_count(struct clk *clk);
-unsigned int __clk_get_prepare_count(struct clk *clk);
-unsigned long __clk_get_rate(struct clk *clk);
-unsigned long __clk_get_accuracy(struct clk *clk);
-unsigned long __clk_get_flags(struct clk *clk);
-bool __clk_is_prepared(struct clk *clk);
-bool __clk_is_enabled(struct clk *clk);
-struct clk *__clk_lookup(const char *name);
+const char *__clk_get_name(struct clk_core *clk);
+struct clk_hw *__clk_get_hw(struct clk_core *clk);
+u8 __clk_get_num_parents(struct clk_core *clk);
+struct clk_core *__clk_get_parent(struct clk_core *clk);
+struct clk_core *clk_get_parent_by_index(struct clk_core *clk, u8 index);
+unsigned int __clk_get_enable_count(struct clk_core *clk);
+unsigned int __clk_get_prepare_count(struct clk_core *clk);
+unsigned long __clk_get_rate(struct clk_core *clk);
+unsigned long __clk_get_accuracy(struct clk_core *clk);
+unsigned long __clk_get_flags(struct clk_core *clk);
+bool __clk_is_prepared(struct clk_core *clk);
+bool __clk_is_enabled(struct clk_core *clk);
+struct clk_core *__clk_lookup(const char *name);
 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 			      unsigned long *best_parent_rate,
-			      struct clk **best_parent_p);
+			      struct clk_core **best_parent_p);
+
+int clk_provider_prepare(struct clk_core *clk);
+void clk_provider_unprepare(struct clk_core *clk);
+int clk_provider_enable(struct clk_core *clk);
+void clk_provider_disable(struct clk_core *clk);
+int clk_provider_set_parent(struct clk_core *clk, struct clk_core *parent);
+int clk_provider_set_rate(struct clk_core *clk, unsigned long rate);
+struct clk_core *clk_provider_get_parent(struct clk_core *clk);
+unsigned long clk_provider_get_rate(struct clk_core *clk);
+long clk_provider_round_rate(struct clk_core *clk, unsigned long rate);
+struct clk_core *clk_provider_get_sys(const char *dev_id, const char *con_id);
+struct clk_core *clk_provider_get(struct device *dev, const char *con_id);
+struct clk_core *devm_clk_provider_get(struct device *dev, const char *id);
+int clk_provider_notifier_register(struct clk_core *clk, struct notifier_block *nb);
+int clk_provider_notifier_unregister(struct clk_core *clk, struct notifier_block *nb);
+struct clk_core *clk_to_clk_core(struct clk *clk);
+
+/* clk_provider_prepare_enable helps cases using clk_enable in non-atomic context. */
+static inline int clk_provider_prepare_enable(struct clk_core *clk)
+{
+	int ret;
+
+	ret = clk_provider_prepare(clk);
+	if (ret)
+		return ret;
+	ret = clk_provider_enable(clk);
+	if (ret)
+		clk_provider_unprepare(clk);
+
+	return ret;
+}
+
+/* clk_provider_disable_unprepare helps cases using clk_disable in non-atomic context. */
+static inline void clk_provider_disable_unprepare(struct clk_core *clk)
+{
+	clk_provider_disable(clk);
+	clk_provider_unprepare(clk);
+}
 
 /*
  * FIXME clock api without lock protection
  */
-int __clk_prepare(struct clk *clk);
-void __clk_unprepare(struct clk *clk);
-void __clk_reparent(struct clk *clk, struct clk *new_parent);
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
+int __clk_prepare(struct clk_core *clk);
+void __clk_unprepare(struct clk_core *clk);
+void __clk_reparent(struct clk_core *clk, struct clk_core *new_parent);
+unsigned long __clk_round_rate(struct clk_core *clk, unsigned long rate);
 
 struct of_device_id;
 
 typedef void (*of_clk_init_cb_t)(struct device_node *);
 
 struct clk_onecell_data {
-	struct clk **clks;
+	struct clk_core **clks;
 	unsigned int clk_num;
 };
 
@@ -571,22 +584,23 @@ extern struct of_device_id __clk_of_table;
 
 #ifdef CONFIG_OF
 int of_clk_add_provider(struct device_node *np,
-			struct clk *(*clk_src_get)(struct of_phandle_args *args,
+			struct clk_core *(*clk_src_get)(struct of_phandle_args *args,
 						   void *data),
 			void *data);
 void of_clk_del_provider(struct device_node *np);
-struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
+struct clk_core *of_clk_src_simple_get(struct of_phandle_args *clkspec,
 				  void *data);
-struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
+struct clk_core *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
 int of_clk_get_parent_count(struct device_node *np);
 const char *of_clk_get_parent_name(struct device_node *np, int index);
+struct clk_core *of_clk_provider_get(struct device_node *np, int index);
 
 void of_clk_init(const struct of_device_id *matches);
 
 #else /* !CONFIG_OF */
 
 static inline int of_clk_add_provider(struct device_node *np,
-			struct clk *(*clk_src_get)(struct of_phandle_args *args,
+			struct clk_core *(*clk_src_get)(struct of_phandle_args *args,
 						   void *data),
 			void *data)
 {
@@ -594,12 +608,12 @@ static inline int of_clk_add_provider(struct device_node *np,
 }
 #define of_clk_del_provider(np) \
 	{ while (0); }
-static inline struct clk *of_clk_src_simple_get(
+static inline struct clk_core *of_clk_src_simple_get(
 	struct of_phandle_args *clkspec, void *data)
 {
 	return ERR_PTR(-ENOENT);
 }
-static inline struct clk *of_clk_src_onecell_get(
+static inline struct clk_core *of_clk_src_onecell_get(
 	struct of_phandle_args *clkspec, void *data)
 {
 	return ERR_PTR(-ENOENT);
@@ -609,6 +623,10 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
 {
 	return NULL;
 }
+static inline struct clk_core *of_clk_provider_get(struct device_node *np, int index)
+{
+	return NULL;
+}
 #define of_clk_init(matches) \
 	{ while (0); }
 #endif /* CONFIG_OF */
@@ -645,7 +663,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
 #endif	/* platform dependent I/O accessors */
 
 #ifdef CONFIG_DEBUG_FS
-struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
+struct dentry *clk_debugfs_add_file(struct clk_core *clk, char *name, umode_t mode,
 				void *data, const struct file_operations *fops);
 #endif
 
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 2cd8d3c..0fa20ee 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -22,6 +22,8 @@ struct clk;
 
 #ifdef CONFIG_COMMON_CLK
 
+struct clk_core;
+
 /**
  * DOC: clk notifier callback types
  *
@@ -56,7 +58,7 @@ struct clk;
  * @notifier_head.
  */
 struct clk_notifier {
-	struct clk			*clk;
+	struct clk_core			*clk;
 	struct srcu_notifier_head	notifier_head;
 	struct list_head		node;
 };
@@ -73,7 +75,7 @@ struct clk_notifier {
  * current rate (this was done to optimize the implementation).
  */
 struct clk_notifier_data {
-	struct clk		*clk;
+	struct clk_core		*clk;
 	unsigned long		old_rate;
 	unsigned long		new_rate;
 };
@@ -315,6 +317,14 @@ struct clk *clk_get_parent(struct clk *clk);
  */
 struct clk *clk_get_sys(const char *dev_id, const char *con_id);
 
+/**
+ * clk_get_name - get a clock's name
+ * @clk: clock source
+ *
+ * Returns the name of the provided clock.
+ */
+const char *clk_get_name(struct clk *clk);
+
 #else /* !CONFIG_HAVE_CLK */
 
 static inline struct clk *clk_get(struct device *dev, const char *id)
@@ -411,7 +421,8 @@ struct of_phandle_args;
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
-struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
+struct clk_core *of_clk_provider_get_by_name(struct device_node *np, const char *name);
+struct clk_core *of_clk_get_from_provider(struct of_phandle_args *clkspec);
 #else
 static inline struct clk *of_clk_get(struct device_node *np, int index)
 {
@@ -422,6 +433,21 @@ static inline struct clk *of_clk_get_by_name(struct device_node *np,
 {
 	return ERR_PTR(-ENOENT);
 }
+
+#if defined(CONFIG_COMMON_CLK)
+static inline struct clk_core *of_clk_provider_get_by_name(struct device_node *np,
+							   const char *name)
+{
+	return ERR_PTR(-ENOENT);
+}
+#else
+static inline struct clk *of_clk_provider_get_by_name(struct device_node *np,
+						      const char *name)
+{
+	return ERR_PTR(-ENOENT);
+}
+#endif /* CONFIG_COMMON_CLK */
+
 #endif
 
 #endif
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
index 94bad77..a6c5d67 100644
--- a/include/linux/clkdev.h
+++ b/include/linux/clkdev.h
@@ -17,11 +17,23 @@
 struct clk;
 struct device;
 
+/*
+ * To avoid a mass-rename of all non-common clock implementations (spread out
+ * in arch-specific code), we let them use struct clk for both the internal and
+ * external view.
+ */
+#ifdef CONFIG_COMMON_CLK
+struct clk_core;
+#define clk_core_t struct clk_core
+#else
+#define clk_core_t struct clk
+#endif
+
 struct clk_lookup {
 	struct list_head	node;
 	const char		*dev_id;
 	const char		*con_id;
-	struct clk		*clk;
+	clk_core_t		*clk;
 };
 
 #define CLKDEV_INIT(d, n, c)	\
@@ -31,7 +43,7 @@ struct clk_lookup {
 		.clk = c,	\
 	}
 
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
+struct clk_lookup *clkdev_alloc(clk_core_t *clk, const char *con_id,
 	const char *dev_fmt, ...);
 
 void clkdev_add(struct clk_lookup *cl);
@@ -40,12 +52,12 @@ void clkdev_drop(struct clk_lookup *cl);
 void clkdev_add_table(struct clk_lookup *, size_t);
 int clk_add_alias(const char *, const char *, char *, struct device *);
 
-int clk_register_clkdev(struct clk *, const char *, const char *, ...);
-int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t);
+int clk_register_clkdev(clk_core_t *, const char *, const char *, ...);
+int clk_register_clkdevs(clk_core_t *, struct clk_lookup *, size_t);
 
 #ifdef CONFIG_COMMON_CLK
-int __clk_get(struct clk *clk);
-void __clk_put(struct clk *clk);
+int __clk_get(struct clk_core *clk);
+void __clk_put(struct clk_core *clk);
 #endif
 
 #endif
-- 
1.9.3


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

* [PATCH v7 7/8] clk: per-user clock accounting for debug
  2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
                   ` (4 preceding siblings ...)
  2014-08-18 15:30 ` [PATCH v7 6/8] clk: use struct clk only for external API Tomeu Vizoso
@ 2014-08-18 15:30 ` Tomeu Vizoso
  2014-08-18 15:30 ` [PATCH v7 8/8] clk: Add floor and ceiling constraints to clock rates Tomeu Vizoso
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-18 15:30 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Warren, Thierry Reding, Tomasz Figa, Peter De Schrijver,
	rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
	Tomeu Vizoso

When a clock has multiple users, the WARNING on imbalance of
enable/disable may not show the guilty party since although they may
have commited the error earlier, the warning is emitted later when some
other user, presumably innocent, disables the clock.

Provide per-user clock enable/disable accounting and disabler tracking
in order to help debug these problems.

Based on previous work by Rabin Vincent <rabin@rab.in>.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
 drivers/clk/clk.c           | 38 ++++++++++++++++++++++++++++++++++----
 drivers/clk/clk.h           |  3 ++-
 drivers/clk/clkdev.c        | 12 ++++++++----
 include/linux/clk-private.h |  4 ++++
 4 files changed, 48 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a2d0ee5..f94c444 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -543,7 +543,8 @@ static int clk_disable_unused(void)
 }
 late_initcall_sync(clk_disable_unused);
 
-struct clk *__clk_create_clk(struct clk_core *clk_core)
+struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
+			     const char *con)
 {
 	struct clk *clk;
 
@@ -556,6 +557,8 @@ struct clk *__clk_create_clk(struct clk_core *clk_core)
 		return ERR_PTR(-ENOMEM);
 
 	clk->core = clk_core;
+	clk->dev_id = dev;
+	clk->con_id = con;
 
 	return clk;
 }
@@ -936,10 +939,25 @@ EXPORT_SYMBOL_GPL(clk_provider_disable);
  */
 void clk_disable(struct clk *clk_user)
 {
+	struct clk_core *clk;
+	unsigned long flags;
+
 	if (IS_ERR_OR_NULL(clk_user))
 		return;
 
-	clk_provider_disable(clk_to_clk_core(clk_user));
+	clk = clk_to_clk_core(clk_user);
+
+	flags = clk_enable_lock();
+	if (!WARN(clk_user->enable_count == 0,
+		  "incorrect disable clk dev %s con %s last disabler %pF\n",
+		  clk_user->dev_id, clk_user->con_id, clk_user->last_disable)) {
+
+		clk_user->last_disable = __builtin_return_address(0);
+		clk_user->enable_count--;
+
+		__clk_disable(clk);
+	}
+	clk_enable_unlock(flags);
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
@@ -1000,10 +1018,22 @@ EXPORT_SYMBOL_GPL(clk_provider_enable);
  */
 int clk_enable(struct clk *clk_user)
 {
+	struct clk_core *clk;
+	unsigned long flags;
+	int ret;
+
 	if (!clk_user)
 		return 0;
 
-	return clk_provider_enable(clk_to_clk_core(clk_user));
+	clk = clk_to_clk_core(clk_user);
+
+	flags = clk_enable_lock();
+	ret = __clk_enable(clk);
+	if (!ret)
+		clk_user->enable_count++;
+	clk_enable_unlock(flags);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(clk_enable);
 
@@ -1719,7 +1749,7 @@ struct clk *clk_get_parent(struct clk *clk_user)
 	clk = clk_to_clk_core(clk_user);
 	parent = clk_provider_get_parent(clk);
 
-	return __clk_create_clk(parent);
+	return __clk_create_clk(parent, clk_user->dev_id, clk_user->con_id);
 }
 EXPORT_SYMBOL_GPL(clk_get_parent);
 
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index 3b3068b..49eff38 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -19,5 +19,6 @@ void of_clk_unlock(void);
 #endif
 
 #if defined(CONFIG_COMMON_CLK)
-struct clk *__clk_create_clk(struct clk_core *clk_core);
+struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
+			     const char *con);
 #endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 810935f..0752cc9 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -76,7 +76,9 @@ struct clk_core *of_clk_provider_get(struct device_node *np, int index)
 
 struct clk *of_clk_get(struct device_node *np, int index)
 {
-	return __clk_create_clk(of_clk_provider_get(np, index));
+	struct clk_core *clk = of_clk_provider_get(np, index);
+
+	return __clk_create_clk(clk, np->full_name, NULL);
 }
 EXPORT_SYMBOL(of_clk_get);
 
@@ -129,7 +131,9 @@ struct clk_core *of_clk_provider_get_by_name(struct device_node *np, const char
  */
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
 {
-	return __clk_create_clk(of_clk_provider_get_by_name(np, name));
+	struct clk_core *clk = of_clk_provider_get_by_name(np, name);
+
+	return __clk_create_clk(clk, np->full_name, NULL);
 }
 EXPORT_SYMBOL(of_clk_get_by_name);
 #endif
@@ -201,7 +205,7 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 #if defined(CONFIG_COMMON_CLK)
 	struct clk_core *clk = clk_provider_get_sys(dev_id, con_id);
 
-	return __clk_create_clk(clk);
+	return __clk_create_clk(clk, dev_id, con_id);
 #else
 	struct clk_lookup *cl;
 
@@ -243,7 +247,7 @@ struct clk *clk_get(struct device *dev, const char *con_id)
 #if defined(CONFIG_COMMON_CLK)
 	const char *dev_id = dev ? dev_name(dev) : NULL;
 
-	return __clk_create_clk(clk_provider_get(dev, con_id));
+	return __clk_create_clk(clk_provider_get(dev, con_id), dev_id, con_id);
 #else
 	const char *dev_id = dev ? dev_name(dev) : NULL;
 	struct clk *clk;
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 2c1ece9..9657fc8 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -57,6 +57,10 @@ struct clk_core {
 
 struct clk {
 	struct clk_core	*core;
+	unsigned int	enable_count;
+	const char	*dev_id;
+	const char	*con_id;
+	void		*last_disable;
 };
 
 /*
-- 
1.9.3


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

* [PATCH v7 8/8] clk: Add floor and ceiling constraints to clock rates
  2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
                   ` (5 preceding siblings ...)
  2014-08-18 15:30 ` [PATCH v7 7/8] clk: per-user clock accounting for debug Tomeu Vizoso
@ 2014-08-18 15:30 ` Tomeu Vizoso
  2014-08-21  2:12 ` [PATCH v7 0/8] Per-user clock constraints Andrew Lunn
  2014-08-26 13:20 ` Heiko Stübner
  8 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-18 15:30 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Warren, Thierry Reding, Tomasz Figa, Peter De Schrijver,
	rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
	Tomeu Vizoso

Adds a way for clock consumers to set maximum and minimum rates. This can be
used for thermal drivers to set ceiling rates, or by misc. drivers to set
floor rates to assure a minimum performance level.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>

---

v5: * Move the storage of constraints to the per-user clk struct, as suggested
      by Stephen Warren.
---
 drivers/clk/clk.c           | 36 ++++++++++++++++++++++++++++++++++++
 drivers/clk/clk.h           |  1 +
 drivers/clk/clkdev.c        |  2 +-
 include/linux/clk-private.h |  4 ++++
 include/linux/clk.h         | 18 ++++++++++++++++++
 5 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index f94c444..f743a4a 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -560,6 +560,8 @@ struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
 	clk->dev_id = dev;
 	clk->con_id = con;
 
+	hlist_add_head(&clk->child_node, &clk_core->per_user_clks);
+
 	return clk;
 }
 
@@ -1646,6 +1648,7 @@ static void clk_change_rate(struct clk_core *clk)
 int clk_provider_set_rate(struct clk_core *clk, unsigned long rate)
 {
 	struct clk_core *top, *fail_clk;
+	struct clk *clk_user;
 	int ret = 0;
 
 	if (!clk)
@@ -1654,6 +1657,13 @@ int clk_provider_set_rate(struct clk_core *clk, unsigned long rate)
 	/* prevent racing with updates to the clock topology */
 	clk_prepare_lock();
 
+	hlist_for_each_entry(clk_user, &clk->per_user_clks, child_node) {
+		rate = max(rate, clk_user->floor_constraint);
+
+		if (clk_user->ceiling_constraint > 0)
+			rate = min(rate, clk_user->ceiling_constraint);
+	}
+
 	/* bail early if nothing to do */
 	if (rate == clk_provider_get_rate(clk))
 		goto out;
@@ -1720,6 +1730,24 @@ int clk_set_rate(struct clk *clk_user, unsigned long rate)
 }
 EXPORT_SYMBOL_GPL(clk_set_rate);
 
+int clk_set_floor_rate(struct clk *clk_user, unsigned long rate)
+{
+	struct clk_core *clk = clk_to_clk_core(clk_user);
+
+	clk_user->floor_constraint = rate;
+	return clk_provider_set_rate(clk, clk_provider_get_rate(clk));
+}
+EXPORT_SYMBOL_GPL(clk_set_floor_rate);
+
+int clk_set_ceiling_rate(struct clk *clk_user, unsigned long rate)
+{
+	struct clk_core *clk = clk_to_clk_core(clk_user);
+
+	clk_user->ceiling_constraint = rate;
+	return clk_provider_set_rate(clk, clk_provider_get_rate(clk));
+}
+EXPORT_SYMBOL_GPL(clk_set_ceiling_rate);
+
 struct clk_core *clk_provider_get_parent(struct clk_core *clk)
 {
 	struct clk_core *parent;
@@ -2064,6 +2092,8 @@ int __clk_init(struct device *dev, struct clk_core *clk)
 			}
 	 }
 
+	INIT_HLIST_HEAD(&clk->per_user_clks);
+
 	/*
 	 * optional platform-specific magic
 	 *
@@ -2514,6 +2544,12 @@ int clk_notifier_unregister(struct clk *clk_user, struct notifier_block *nb)
 }
 EXPORT_SYMBOL_GPL(clk_notifier_unregister);
 
+void __clk_free_clk(struct clk *clk_user)
+{
+	hlist_del(&clk_user->child_node);
+	kfree(clk_user);
+}
+
 #ifdef CONFIG_OF
 /**
  * struct of_clk_provider - Clock provider registration structure
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index 49eff38..005deb3 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -21,4 +21,5 @@ void of_clk_unlock(void);
 #if defined(CONFIG_COMMON_CLK)
 struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
 			     const char *con);
+void __clk_free_clk(struct clk *clk_user);
 #endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 0752cc9..0db829c 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -270,7 +270,7 @@ void clk_put(struct clk *clk)
 #if defined(CONFIG_COMMON_CLK)
 	clk_core_t *core = clk_to_clk_core(clk);
 
-	kfree(clk);
+	__clk_free_clk(clk);
 	__clk_put(core);
 #else
 	__clk_put(clk);
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 9657fc8..c59d000 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -48,6 +48,7 @@ struct clk_core {
 	unsigned long		accuracy;
 	struct hlist_head	children;
 	struct hlist_node	child_node;
+	struct hlist_head	per_user_clks;
 	unsigned int		notifier_count;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry		*dentry;
@@ -61,6 +62,9 @@ struct clk {
 	const char	*dev_id;
 	const char	*con_id;
 	void		*last_disable;
+	unsigned long	floor_constraint;
+	unsigned long	ceiling_constraint;
+	struct hlist_node child_node;
 };
 
 /*
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0fa20ee..b3eae8d 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -283,6 +283,24 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
 int clk_set_rate(struct clk *clk, unsigned long rate);
 
 /**
+ * clk_set_floor_rate - set a minimum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired minimum clock rate in Hz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_floor_rate(struct clk *clk, unsigned long rate);
+
+/**
+ * clk_set_ceiling_rate - set a maximum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired maximum clock rate in Hz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_ceiling_rate(struct clk *clk, unsigned long rate);
+
+/**
  * clk_set_parent - set the parent clock source for this clock
  * @clk: clock source
  * @parent: parent clock source
-- 
1.9.3


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

* Re: [PATCH v7 0/8] Per-user clock constraints
  2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
                   ` (6 preceding siblings ...)
  2014-08-18 15:30 ` [PATCH v7 8/8] clk: Add floor and ceiling constraints to clock rates Tomeu Vizoso
@ 2014-08-21  2:12 ` Andrew Lunn
  2014-08-21  7:10   ` Tomeu Vizoso
  2014-08-26 13:20 ` Heiko Stübner
  8 siblings, 1 reply; 24+ messages in thread
From: Andrew Lunn @ 2014-08-21  2:12 UTC (permalink / raw)
  To: Tomeu Vizoso
  Cc: Mike Turquette, Stephen Warren, Tomasz Figa, linux-kernel,
	Javier Martinez Canillas, rabin, Thierry Reding,
	Peter De Schrijver, linux-arm-kernel

On Mon, Aug 18, 2014 at 05:30:26PM +0200, Tomeu Vizoso wrote:
> Hi,
> 
> in this v7 of the patchset I have only rebased on top of 3.17rc1, with no other
> changes. I have had to do a fair amount of fixing due to the rebase, more
> details below. Follows the original cover letter blurb:

Hi Tomeu

I would like to test this patchset, but patch 5 never made it to the
list. Do you have a git tree i can clone?

Thanks
	Andrew

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

* Re: [PATCH v7 0/8] Per-user clock constraints
  2014-08-21  2:12 ` [PATCH v7 0/8] Per-user clock constraints Andrew Lunn
@ 2014-08-21  7:10   ` Tomeu Vizoso
  0 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-21  7:10 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Mike Turquette, Stephen Warren, Tomasz Figa, linux-kernel,
	Javier Martinez Canillas, rabin, Thierry Reding,
	Peter De Schrijver, linux-arm-kernel

On 21 August 2014 04:12, Andrew Lunn <andrew@lunn.ch> wrote:
> On Mon, Aug 18, 2014 at 05:30:26PM +0200, Tomeu Vizoso wrote:
>> Hi,
>>
>> in this v7 of the patchset I have only rebased on top of 3.17rc1, with no other
>> changes. I have had to do a fair amount of fixing due to the rebase, more
>> details below. Follows the original cover letter blurb:
>
> Hi Tomeu
>
> I would like to test this patchset, but patch 5 never made it to the
> list. Do you have a git tree i can clone?

Sure:

http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=clk-refactoring-7

Though it seems to have made into at least one mailing list (the
others seem to have rejected it because of either its size, or the
number of recipients):

http://article.gmane.org/gmane.linux.ports.ppc64.devel/104392

Thanks for the interest!

Tomeu

> Thanks
>         Andrew
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
       [not found]   ` <20140820225513.5251.284@quantum>
@ 2014-08-21  7:53     ` Tomeu Vizoso
  2014-08-21 13:38       ` Andrew Lunn
  0 siblings, 1 reply; 24+ messages in thread
From: Tomeu Vizoso @ 2014-08-21  7:53 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Warren, Viresh Kumar, Thierry Reding, Rafael J. Wysocki,
	Javier Martinez Canillas, Rabin Vincent, linux-arm-kernel,
	linux-kernel, Tomasz Figa, Peter De Schrijver

On 08/21/2014 12:55 AM, Mike Turquette wrote:
> Quoting Tomeu Vizoso (2014-08-18 08:30:29)
>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>> ---
>>   drivers/cpufreq/kirkwood-cpufreq.c | 3 +--
>>   1 file changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
>> index 37a4806..f3d087f 100644
>> --- a/drivers/cpufreq/kirkwood-cpufreq.c
>> +++ b/drivers/cpufreq/kirkwood-cpufreq.c
>> @@ -12,7 +12,6 @@
>>   #include <linux/kernel.h>
>>   #include <linux/module.h>
>>   #include <linux/clk.h>
>> -#include <linux/clk-provider.h>
>>   #include <linux/cpufreq.h>
>>   #include <linux/of_device.h>
>>   #include <linux/platform_device.h>
>> @@ -50,7 +49,7 @@ static struct cpufreq_frequency_table kirkwood_freq_table[] = {
>>
>>   static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
>>   {
>> -       if (__clk_is_enabled(priv.powersave_clk))
>> +       if (clk_is_enabled(priv.powersave_clk))
>>                  return kirkwood_freq_table[1].frequency;
>>          return kirkwood_freq_table[0].frequency;
>>   }
>> --
>> 1.9.3
>>
>
> Tomeu,
>
> After taking a second look at clk_is_enabled and the Kirkwood driver, I
> would prefer to not implement clk_is_enabled. The main reason is that it
> is racey, since the clock's status could of course change as soon as as
> that call completes. Furthermore I am worried that drivers might do
> something like:
>
> if (!clk_is_enabled(clk))
> 	clk_enable(clk);
>
> Which is crap and the driver should just call clk_enable any time it
> needs the clock. To that end I propose to drop "clk: provide public
> clk_is_enabled function" and replace your update to kirkwood-cpufreq.c
> with the following patch. Let me know what you think.

Yep, this looks much better to me. I will replace 2/8 and 3/8 with this 
one for v8.

Reviewed-By: Tomeu Vizoso <tomeu.vizoso@collabora.com>

Thanks!

Tomeu

> Regards,
> Mike
>
>
>
>  From 713b46fd66abd26a4e4d584a0b8a2a28c0459a60 Mon Sep 17 00:00:00 2001
> From: Mike Turquette <mturquette@linaro.org>
> Date: Mon, 18 Aug 2014 17:30:29 +0200
> Subject: [PATCH] cpufreq: kirkwood: Remove use of the clk provider API
>
> Instead of checking the clock framework to see if the clock is enabled,
> track the cpu frequency within the driver as the powersave_clk is
> enabled and disabled.
>
> Cc: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> Cc: Viresh Kumar <viresh.kumar@linaro.org>
> Signed-off-by: Mike Turquette <mturquette@linaro.org>
> ---
>   drivers/cpufreq/kirkwood-cpufreq.c | 10 ++++++----
>   1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
> index 37a4806..88f4641 100644
> --- a/drivers/cpufreq/kirkwood-cpufreq.c
> +++ b/drivers/cpufreq/kirkwood-cpufreq.c
> @@ -12,7 +12,6 @@
>   #include <linux/kernel.h>
>   #include <linux/module.h>
>   #include <linux/clk.h>
> -#include <linux/clk-provider.h>
>   #include <linux/cpufreq.h>
>   #include <linux/of_device.h>
>   #include <linux/platform_device.h>
> @@ -33,6 +32,8 @@ static struct priv
>   #define STATE_CPU_FREQ 0x01
>   #define STATE_DDR_FREQ 0x02
>
> +static unsigned long cpu_frequency = 0;
> +
>   /*
>    * Kirkwood can swap the clock to the CPU between two clocks:
>    *
> @@ -50,9 +51,7 @@ static struct cpufreq_frequency_table kirkwood_freq_table[] = {
>
>   static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
>   {
> -	if (__clk_is_enabled(priv.powersave_clk))
> -		return kirkwood_freq_table[1].frequency;
> -	return kirkwood_freq_table[0].frequency;
> +	return cpu_frequency;
>   }
>
>   static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
> @@ -71,9 +70,11 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
>   	switch (state) {
>   	case STATE_CPU_FREQ:
>   		clk_disable(priv.powersave_clk);
> +		cpu_frequency = kirkwood_freq_table[0].frequency;
>   		break;
>   	case STATE_DDR_FREQ:
>   		clk_enable(priv.powersave_clk);
> +		cpu_frequency = kirkwood_freq_table[1].frequency;
>   		break;
>   	}
>
> @@ -133,6 +134,7 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
>
>   	clk_prepare_enable(priv.cpu_clk);
>   	kirkwood_freq_table[0].frequency = clk_get_rate(priv.cpu_clk) / 1000;
> +	cpu_frequency = kirkwood_freq_table[0].frequency;
>
>   	priv.ddr_clk = of_clk_get_by_name(np, "ddrclk");
>   	if (IS_ERR(priv.ddr_clk)) {
>


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

* Re: [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
  2014-08-21  7:53     ` Tomeu Vizoso
@ 2014-08-21 13:38       ` Andrew Lunn
  2014-08-22 19:29         ` Mike Turquette
  0 siblings, 1 reply; 24+ messages in thread
From: Andrew Lunn @ 2014-08-21 13:38 UTC (permalink / raw)
  To: Tomeu Vizoso
  Cc: Mike Turquette, Peter De Schrijver, Stephen Warren, Viresh Kumar,
	Tomasz Figa, Rafael J. Wysocki, linux-kernel, Rabin Vincent,
	Thierry Reding, Javier Martinez Canillas, linux-arm-kernel

On Thu, Aug 21, 2014 at 09:53:43AM +0200, Tomeu Vizoso wrote:
> On 08/21/2014 12:55 AM, Mike Turquette wrote:
> >Quoting Tomeu Vizoso (2014-08-18 08:30:29)
> >>Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >>---
> >>  drivers/cpufreq/kirkwood-cpufreq.c | 3 +--
> >>  1 file changed, 1 insertion(+), 2 deletions(-)
> >>
> >>diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
> >>index 37a4806..f3d087f 100644
> >>--- a/drivers/cpufreq/kirkwood-cpufreq.c
> >>+++ b/drivers/cpufreq/kirkwood-cpufreq.c
> >>@@ -12,7 +12,6 @@
> >>  #include <linux/kernel.h>
> >>  #include <linux/module.h>
> >>  #include <linux/clk.h>
> >>-#include <linux/clk-provider.h>
> >>  #include <linux/cpufreq.h>
> >>  #include <linux/of_device.h>
> >>  #include <linux/platform_device.h>
> >>@@ -50,7 +49,7 @@ static struct cpufreq_frequency_table kirkwood_freq_table[] = {
> >>
> >>  static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
> >>  {
> >>-       if (__clk_is_enabled(priv.powersave_clk))
> >>+       if (clk_is_enabled(priv.powersave_clk))
> >>                 return kirkwood_freq_table[1].frequency;
> >>         return kirkwood_freq_table[0].frequency;
> >>  }
> >>--
> >>1.9.3
> >>
> >
> >Tomeu,
> >
> >After taking a second look at clk_is_enabled and the Kirkwood driver, I
> >would prefer to not implement clk_is_enabled. The main reason is that it
> >is racey, since the clock's status could of course change as soon as as
> >that call completes. Furthermore I am worried that drivers might do
> >something like:
> >
> >if (!clk_is_enabled(clk))
> >	clk_enable(clk);
> >
> >Which is crap and the driver should just call clk_enable any time it
> >needs the clock. To that end I propose to drop "clk: provide public
> >clk_is_enabled function" and replace your update to kirkwood-cpufreq.c
> >with the following patch. Let me know what you think.

Hi Mike, Tomeu

> >+static unsigned long cpu_frequency = 0;


This has a problem. You are making an assumption about the initial
state. The way the hardware works, is you change the state of the
clock and then perform a Wait For Interrupt. Once the hardware has
finished adjusting its PLL, it raises an interrupt and things
continue.

However, if you don't cause an actual state change, the WFI never
returns. If this assumption is wrong, your box is dead the first time
it tries to change cpu frequency.

This is why the code reads the hardware register to find the real
current state, rather than assume it.

	Andrew

> >+
> >  /*
> >   * Kirkwood can swap the clock to the CPU between two clocks:
> >   *
> >@@ -50,9 +51,7 @@ static struct cpufreq_frequency_table kirkwood_freq_table[] = {
> >
> >  static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
> >  {
> >-	if (__clk_is_enabled(priv.powersave_clk))
> >-		return kirkwood_freq_table[1].frequency;
> >-	return kirkwood_freq_table[0].frequency;
> >+	return cpu_frequency;
> >  }
> >
> >  static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
> >@@ -71,9 +70,11 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
> >  	switch (state) {
> >  	case STATE_CPU_FREQ:
> >  		clk_disable(priv.powersave_clk);
> >+		cpu_frequency = kirkwood_freq_table[0].frequency;
> >  		break;
> >  	case STATE_DDR_FREQ:
> >  		clk_enable(priv.powersave_clk);
> >+		cpu_frequency = kirkwood_freq_table[1].frequency;
> >  		break;
> >  	}
> >
> >@@ -133,6 +134,7 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
> >
> >  	clk_prepare_enable(priv.cpu_clk);
> >  	kirkwood_freq_table[0].frequency = clk_get_rate(priv.cpu_clk) / 1000;
> >+	cpu_frequency = kirkwood_freq_table[0].frequency;
> >
> >  	priv.ddr_clk = of_clk_get_by_name(np, "ddrclk");
> >  	if (IS_ERR(priv.ddr_clk)) {
> >
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v7 1/8] clk: Add temporary mapping to the existing API
       [not found]   ` <20140820145006.5251.30923@quantum>
@ 2014-08-21 18:04     ` Tony Lindgren
  2014-08-21 18:10       ` Jason Cooper
  0 siblings, 1 reply; 24+ messages in thread
From: Tony Lindgren @ 2014-08-21 18:04 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Tomeu Vizoso, Stephen Warren, Thierry Reding, Tomasz Figa,
	Peter De Schrijver, rabin, linux-kernel, linux-arm-kernel,
	Javier Martinez Canillas, Simon Horman, Magnus Damm,
	Jason Cooper, Andrew Lunn, Mauro Carvalho Chehab, Kukjin Kim

* Mike Turquette <mturquette@linaro.org> [140820 07:53]:
> Quoting Tomeu Vizoso (2014-08-18 08:30:27)
> > To preserve git-bisectability, add aliases from the future provider API to the
> > existing public API.
> > 
> > Also includes clk-provider.h and clk-dev.h in a few places so the right
> > functions are defined.
> > 
> > Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> 
> Cc'ing Tony for the OMAP2+ parts, Simon & Magnus for the SHMobile parts,
> Jason & Andrew for the Orion parts, Mauro & Kukjin for the Exynos parts.
> 
> This change is super trivial but it's best not to touch these files
> without a heads-up for the owners.

As long as it compiles omap2plus_defconfig it seems safe to me:

Acked-by: Tony Lindgren <tony@atomide.com>

> > ---
> > v7: * Add mappings for clk_notifier_[un]register
> >     * Add more clk-provider.h includes to clk implementations
> > 
> > v4: * Add more clk-provider.h includes to clk implementations
> >     * Add mapping for clk_provider_round_rate
> > ---
> >  arch/arm/mach-omap2/display.c                 |  1 +
> >  arch/arm/mach-omap2/omap_device.c             |  1 +
> >  arch/arm/mach-shmobile/clock.c                |  1 +
> >  arch/arm/plat-orion/common.c                  |  1 +
> >  drivers/clk/berlin/bg2.c                      |  1 +
> >  drivers/clk/berlin/bg2q.c                     |  1 +
> >  drivers/clk/clk-conf.c                        |  1 +
> >  drivers/clk/clkdev.c                          |  1 +
> >  drivers/media/platform/exynos4-is/media-dev.c |  1 +
> >  include/linux/clk-provider.h                  | 25 +++++++++++++++++++++++++
> >  include/linux/clk/zynq.h                      |  1 +
> >  11 files changed, 35 insertions(+)
> > 
> > diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
> > index bf852d7..0f9e479 100644
> > --- a/arch/arm/mach-omap2/display.c
> > +++ b/arch/arm/mach-omap2/display.c
> > @@ -21,6 +21,7 @@
> >  #include <linux/platform_device.h>
> >  #include <linux/io.h>
> >  #include <linux/clk.h>
> > +#include <linux/clk-provider.h>
> >  #include <linux/err.h>
> >  #include <linux/delay.h>
> >  #include <linux/of.h>
> > diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
> > index 01ef59d..fbe8cf0 100644
> > --- a/arch/arm/mach-omap2/omap_device.c
> > +++ b/arch/arm/mach-omap2/omap_device.c
> > @@ -32,6 +32,7 @@
> >  #include <linux/io.h>
> >  #include <linux/clk.h>
> >  #include <linux/clkdev.h>
> > +#include <linux/clk-provider.h>
> >  #include <linux/pm_runtime.h>
> >  #include <linux/of.h>
> >  #include <linux/notifier.h>
> > diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
> > index 806f940..ed415dc 100644
> > --- a/arch/arm/mach-shmobile/clock.c
> > +++ b/arch/arm/mach-shmobile/clock.c
> > @@ -24,6 +24,7 @@
> >  
> >  #ifdef CONFIG_COMMON_CLK
> >  #include <linux/clk.h>
> > +#include <linux/clk-provider.h>
> >  #include <linux/clkdev.h>
> >  #include "clock.h"
> >  
> > diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
> > index 3ec6e8e..961b593 100644
> > --- a/arch/arm/plat-orion/common.c
> > +++ b/arch/arm/plat-orion/common.c
> > @@ -15,6 +15,7 @@
> >  #include <linux/serial_8250.h>
> >  #include <linux/ata_platform.h>
> >  #include <linux/clk.h>
> > +#include <linux/clk-provider.h>
> >  #include <linux/clkdev.h>
> >  #include <linux/mv643xx_eth.h>
> >  #include <linux/mv643xx_i2c.h>
> > diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c
> > index 515fb13..4c81e09 100644
> > --- a/drivers/clk/berlin/bg2.c
> > +++ b/drivers/clk/berlin/bg2.c
> > @@ -19,6 +19,7 @@
> >  
> >  #include <linux/clk.h>
> >  #include <linux/clk-provider.h>
> > +#include <linux/clkdev.h>
> >  #include <linux/kernel.h>
> >  #include <linux/of.h>
> >  #include <linux/of_address.h>
> > diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c
> > index 21784e4..748da9b 100644
> > --- a/drivers/clk/berlin/bg2q.c
> > +++ b/drivers/clk/berlin/bg2q.c
> > @@ -19,6 +19,7 @@
> >  
> >  #include <linux/clk.h>
> >  #include <linux/clk-provider.h>
> > +#include <linux/clkdev.h>
> >  #include <linux/kernel.h>
> >  #include <linux/of.h>
> >  #include <linux/of_address.h>
> > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> > index aad4796..d36a7b3 100644
> > --- a/drivers/clk/clk-conf.c
> > +++ b/drivers/clk/clk-conf.c
> > @@ -8,6 +8,7 @@
> >   */
> >  
> >  #include <linux/clk.h>
> > +#include <linux/clkdev.h>
> >  #include <linux/clk-provider.h>
> >  #include <linux/clk/clk-conf.h>
> >  #include <linux/device.h>
> > diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> > index da4bda8..c751d0c 100644
> > --- a/drivers/clk/clkdev.c
> > +++ b/drivers/clk/clkdev.c
> > @@ -18,6 +18,7 @@
> >  #include <linux/string.h>
> >  #include <linux/mutex.h>
> >  #include <linux/clk.h>
> > +#include <linux/clk-provider.h>
> >  #include <linux/clkdev.h>
> >  #include <linux/of.h>
> >  
> > diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> > index 344718d..2620c48 100644
> > --- a/drivers/media/platform/exynos4-is/media-dev.c
> > +++ b/drivers/media/platform/exynos4-is/media-dev.c
> > @@ -13,6 +13,7 @@
> >  #include <linux/bug.h>
> >  #include <linux/clk.h>
> >  #include <linux/clk-provider.h>
> > +#include <linux/clkdev.h>
> >  #include <linux/device.h>
> >  #include <linux/errno.h>
> >  #include <linux/i2c.h>
> > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> > index 411dd7e..a1a7bb7 100644
> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -16,6 +16,31 @@
> >  
> >  #ifdef CONFIG_COMMON_CLK
> >  
> > +/* Temporarily map the to-be-added API to the old API, just so stuff compiles */
> > +#define clk_core                       clk
> > +
> > +#define __clk_create_clk
> > +
> > +#define clk_provider_get                       clk_get
> > +#define clk_provider_get_sys                   clk_get_sys
> > +#define devm_clk_provider_get                  devm_clk_get
> > +#define of_clk_provider_get                    of_clk_get
> > +#define of_clk_provider_get_by_name            of_clk_get_by_name
> > +
> > +#define clk_provider_set_rate                  clk_set_rate
> > +#define clk_provider_get_rate                  clk_get_rate
> > +#define clk_provider_round_rate                        clk_round_rate
> > +#define clk_provider_set_parent                        clk_set_parent
> > +#define clk_provider_get_parent                        clk_get_parent
> > +#define clk_provider_prepare                   clk_prepare
> > +#define clk_provider_unprepare                 clk_unprepare
> > +#define clk_provider_enable                    clk_enable
> > +#define clk_provider_disable                   clk_disable
> > +#define clk_provider_prepare_enable            clk_prepare_enable
> > +#define clk_provider_disable_unprepare         clk_unprepare
> > +#define clk_provider_notifier_register         clk_notifier_register
> > +#define clk_provider_notifier_unregister       clk_notifier_unregister
> > +
> >  /*
> >   * flags used across common struct clk.  these flags should only affect the
> >   * top-level framework.  custom flags for dealing with hardware specifics
> > diff --git a/include/linux/clk/zynq.h b/include/linux/clk/zynq.h
> > index 7a5633b..a990a59 100644
> > --- a/include/linux/clk/zynq.h
> > +++ b/include/linux/clk/zynq.h
> > @@ -21,6 +21,7 @@
> >  #define __LINUX_CLK_ZYNQ_H_
> >  
> >  #include <linux/spinlock.h>
> > +#include <linux/clk-provider.h>
> >  
> >  void zynq_clock_init(void);
> >  
> > -- 
> > 1.9.3
> > 

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

* Re: [PATCH v7 1/8] clk: Add temporary mapping to the existing API
  2014-08-21 18:04     ` Tony Lindgren
@ 2014-08-21 18:10       ` Jason Cooper
  2014-08-22  3:49         ` Simon Horman
  2014-08-25  9:18         ` Sebastian Hesselbarth
  0 siblings, 2 replies; 24+ messages in thread
From: Jason Cooper @ 2014-08-21 18:10 UTC (permalink / raw)
  To: Tony Lindgren, Sebastian Hesselbarth
  Cc: Mike Turquette, Tomeu Vizoso, Stephen Warren, Thierry Reding,
	Tomasz Figa, Peter De Schrijver, rabin, linux-kernel,
	linux-arm-kernel, Javier Martinez Canillas, Simon Horman,
	Magnus Damm, Andrew Lunn, Mauro Carvalho Chehab, Kukjin Kim

On Thu, Aug 21, 2014 at 11:04:48AM -0700, Tony Lindgren wrote:
> * Mike Turquette <mturquette@linaro.org> [140820 07:53]:
> > Quoting Tomeu Vizoso (2014-08-18 08:30:27)
> > > To preserve git-bisectability, add aliases from the future provider API to the
> > > existing public API.
> > > 
> > > Also includes clk-provider.h and clk-dev.h in a few places so the right
> > > functions are defined.
> > > 
> > > Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > 
> > Cc'ing Tony for the OMAP2+ parts, Simon & Magnus for the SHMobile parts,
> > Jason & Andrew for the Orion parts, Mauro & Kukjin for the Exynos parts.
> > 
> > This change is super trivial but it's best not to touch these files
> > without a heads-up for the owners.
> 
> As long as it compiles omap2plus_defconfig it seems safe to me:
> 
> Acked-by: Tony Lindgren <tony@atomide.com>

Same here for orion5x_defconfig, dove_defconfig, and mv78xx_defconfig.

Acked-by: Jason Cooper <jason@lakedaemon.net>

Also, added Sebastian to the Cc as he's the maintainer of mach-berlin.

thx,

Jason.

> 
> > > ---
> > > v7: * Add mappings for clk_notifier_[un]register
> > >     * Add more clk-provider.h includes to clk implementations
> > > 
> > > v4: * Add more clk-provider.h includes to clk implementations
> > >     * Add mapping for clk_provider_round_rate
> > > ---
> > >  arch/arm/mach-omap2/display.c                 |  1 +
> > >  arch/arm/mach-omap2/omap_device.c             |  1 +
> > >  arch/arm/mach-shmobile/clock.c                |  1 +
> > >  arch/arm/plat-orion/common.c                  |  1 +
> > >  drivers/clk/berlin/bg2.c                      |  1 +
> > >  drivers/clk/berlin/bg2q.c                     |  1 +
> > >  drivers/clk/clk-conf.c                        |  1 +
> > >  drivers/clk/clkdev.c                          |  1 +
> > >  drivers/media/platform/exynos4-is/media-dev.c |  1 +
> > >  include/linux/clk-provider.h                  | 25 +++++++++++++++++++++++++
> > >  include/linux/clk/zynq.h                      |  1 +
> > >  11 files changed, 35 insertions(+)
> > > 
> > > diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
> > > index bf852d7..0f9e479 100644
> > > --- a/arch/arm/mach-omap2/display.c
> > > +++ b/arch/arm/mach-omap2/display.c
> > > @@ -21,6 +21,7 @@
> > >  #include <linux/platform_device.h>
> > >  #include <linux/io.h>
> > >  #include <linux/clk.h>
> > > +#include <linux/clk-provider.h>
> > >  #include <linux/err.h>
> > >  #include <linux/delay.h>
> > >  #include <linux/of.h>
> > > diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
> > > index 01ef59d..fbe8cf0 100644
> > > --- a/arch/arm/mach-omap2/omap_device.c
> > > +++ b/arch/arm/mach-omap2/omap_device.c
> > > @@ -32,6 +32,7 @@
> > >  #include <linux/io.h>
> > >  #include <linux/clk.h>
> > >  #include <linux/clkdev.h>
> > > +#include <linux/clk-provider.h>
> > >  #include <linux/pm_runtime.h>
> > >  #include <linux/of.h>
> > >  #include <linux/notifier.h>
> > > diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
> > > index 806f940..ed415dc 100644
> > > --- a/arch/arm/mach-shmobile/clock.c
> > > +++ b/arch/arm/mach-shmobile/clock.c
> > > @@ -24,6 +24,7 @@
> > >  
> > >  #ifdef CONFIG_COMMON_CLK
> > >  #include <linux/clk.h>
> > > +#include <linux/clk-provider.h>
> > >  #include <linux/clkdev.h>
> > >  #include "clock.h"
> > >  
> > > diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
> > > index 3ec6e8e..961b593 100644
> > > --- a/arch/arm/plat-orion/common.c
> > > +++ b/arch/arm/plat-orion/common.c
> > > @@ -15,6 +15,7 @@
> > >  #include <linux/serial_8250.h>
> > >  #include <linux/ata_platform.h>
> > >  #include <linux/clk.h>
> > > +#include <linux/clk-provider.h>
> > >  #include <linux/clkdev.h>
> > >  #include <linux/mv643xx_eth.h>
> > >  #include <linux/mv643xx_i2c.h>
> > > diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c
> > > index 515fb13..4c81e09 100644
> > > --- a/drivers/clk/berlin/bg2.c
> > > +++ b/drivers/clk/berlin/bg2.c
> > > @@ -19,6 +19,7 @@
> > >  
> > >  #include <linux/clk.h>
> > >  #include <linux/clk-provider.h>
> > > +#include <linux/clkdev.h>
> > >  #include <linux/kernel.h>
> > >  #include <linux/of.h>
> > >  #include <linux/of_address.h>
> > > diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c
> > > index 21784e4..748da9b 100644
> > > --- a/drivers/clk/berlin/bg2q.c
> > > +++ b/drivers/clk/berlin/bg2q.c
> > > @@ -19,6 +19,7 @@
> > >  
> > >  #include <linux/clk.h>
> > >  #include <linux/clk-provider.h>
> > > +#include <linux/clkdev.h>
> > >  #include <linux/kernel.h>
> > >  #include <linux/of.h>
> > >  #include <linux/of_address.h>
> > > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> > > index aad4796..d36a7b3 100644
> > > --- a/drivers/clk/clk-conf.c
> > > +++ b/drivers/clk/clk-conf.c
> > > @@ -8,6 +8,7 @@
> > >   */
> > >  
> > >  #include <linux/clk.h>
> > > +#include <linux/clkdev.h>
> > >  #include <linux/clk-provider.h>
> > >  #include <linux/clk/clk-conf.h>
> > >  #include <linux/device.h>
> > > diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> > > index da4bda8..c751d0c 100644
> > > --- a/drivers/clk/clkdev.c
> > > +++ b/drivers/clk/clkdev.c
> > > @@ -18,6 +18,7 @@
> > >  #include <linux/string.h>
> > >  #include <linux/mutex.h>
> > >  #include <linux/clk.h>
> > > +#include <linux/clk-provider.h>
> > >  #include <linux/clkdev.h>
> > >  #include <linux/of.h>
> > >  
> > > diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> > > index 344718d..2620c48 100644
> > > --- a/drivers/media/platform/exynos4-is/media-dev.c
> > > +++ b/drivers/media/platform/exynos4-is/media-dev.c
> > > @@ -13,6 +13,7 @@
> > >  #include <linux/bug.h>
> > >  #include <linux/clk.h>
> > >  #include <linux/clk-provider.h>
> > > +#include <linux/clkdev.h>
> > >  #include <linux/device.h>
> > >  #include <linux/errno.h>
> > >  #include <linux/i2c.h>
> > > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> > > index 411dd7e..a1a7bb7 100644
> > > --- a/include/linux/clk-provider.h
> > > +++ b/include/linux/clk-provider.h
> > > @@ -16,6 +16,31 @@
> > >  
> > >  #ifdef CONFIG_COMMON_CLK
> > >  
> > > +/* Temporarily map the to-be-added API to the old API, just so stuff compiles */
> > > +#define clk_core                       clk
> > > +
> > > +#define __clk_create_clk
> > > +
> > > +#define clk_provider_get                       clk_get
> > > +#define clk_provider_get_sys                   clk_get_sys
> > > +#define devm_clk_provider_get                  devm_clk_get
> > > +#define of_clk_provider_get                    of_clk_get
> > > +#define of_clk_provider_get_by_name            of_clk_get_by_name
> > > +
> > > +#define clk_provider_set_rate                  clk_set_rate
> > > +#define clk_provider_get_rate                  clk_get_rate
> > > +#define clk_provider_round_rate                        clk_round_rate
> > > +#define clk_provider_set_parent                        clk_set_parent
> > > +#define clk_provider_get_parent                        clk_get_parent
> > > +#define clk_provider_prepare                   clk_prepare
> > > +#define clk_provider_unprepare                 clk_unprepare
> > > +#define clk_provider_enable                    clk_enable
> > > +#define clk_provider_disable                   clk_disable
> > > +#define clk_provider_prepare_enable            clk_prepare_enable
> > > +#define clk_provider_disable_unprepare         clk_unprepare
> > > +#define clk_provider_notifier_register         clk_notifier_register
> > > +#define clk_provider_notifier_unregister       clk_notifier_unregister
> > > +
> > >  /*
> > >   * flags used across common struct clk.  these flags should only affect the
> > >   * top-level framework.  custom flags for dealing with hardware specifics
> > > diff --git a/include/linux/clk/zynq.h b/include/linux/clk/zynq.h
> > > index 7a5633b..a990a59 100644
> > > --- a/include/linux/clk/zynq.h
> > > +++ b/include/linux/clk/zynq.h
> > > @@ -21,6 +21,7 @@
> > >  #define __LINUX_CLK_ZYNQ_H_
> > >  
> > >  #include <linux/spinlock.h>
> > > +#include <linux/clk-provider.h>
> > >  
> > >  void zynq_clock_init(void);
> > >  
> > > -- 
> > > 1.9.3
> > > 

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

* Re: [PATCH v7 1/8] clk: Add temporary mapping to the existing API
  2014-08-21 18:10       ` Jason Cooper
@ 2014-08-22  3:49         ` Simon Horman
  2014-08-25  9:18         ` Sebastian Hesselbarth
  1 sibling, 0 replies; 24+ messages in thread
From: Simon Horman @ 2014-08-22  3:49 UTC (permalink / raw)
  To: Jason Cooper
  Cc: Tony Lindgren, Sebastian Hesselbarth, Mike Turquette,
	Tomeu Vizoso, Stephen Warren, Thierry Reding, Tomasz Figa,
	Peter De Schrijver, rabin, linux-kernel, linux-arm-kernel,
	Javier Martinez Canillas, Magnus Damm, Andrew Lunn,
	Mauro Carvalho Chehab, Kukjin Kim

On Thu, Aug 21, 2014 at 02:10:07PM -0400, Jason Cooper wrote:
> On Thu, Aug 21, 2014 at 11:04:48AM -0700, Tony Lindgren wrote:
> > * Mike Turquette <mturquette@linaro.org> [140820 07:53]:
> > > Quoting Tomeu Vizoso (2014-08-18 08:30:27)
> > > > To preserve git-bisectability, add aliases from the future provider API to the
> > > > existing public API.
> > > > 
> > > > Also includes clk-provider.h and clk-dev.h in a few places so the right
> > > > functions are defined.
> > > > 
> > > > Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > > 
> > > Cc'ing Tony for the OMAP2+ parts, Simon & Magnus for the SHMobile parts,
> > > Jason & Andrew for the Orion parts, Mauro & Kukjin for the Exynos parts.
> > > 
> > > This change is super trivial but it's best not to touch these files
> > > without a heads-up for the owners.
> > 
> > As long as it compiles omap2plus_defconfig it seems safe to me:
> > 
> > Acked-by: Tony Lindgren <tony@atomide.com>
> 
> Same here for orion5x_defconfig, dove_defconfig, and mv78xx_defconfig.
> 
> Acked-by: Jason Cooper <jason@lakedaemon.net>
> 
> Also, added Sebastian to the Cc as he's the maintainer of mach-berlin.

I will add my usual 2c worth about global changes vs adding things to
infrastructure, updating the platforms, then removing things from
infrastructure, in separate patches picked up by the relevant maintainers.
But if everyone else is happy with doing things this way I won't say no.

Ideally I'd like the shmobile portion patch to apply cleanly to linux-next
(it looks like it should) and for the following to still compile:
ape6evm_defconfig, armadillo800eva_defconfig, bockw_defconfig,
koelsch_defconfig, kzm9g_defconfig, lager_defconfig, mackerel_defconfig,
marzen_defconfig, shmobile_defconfig.

With all that said and done:

Acked-by: Simon Horman <horms+renesas@verge.net.au>

> thx,
> 
> Jason.
> 
> > 
> > > > ---
> > > > v7: * Add mappings for clk_notifier_[un]register
> > > >     * Add more clk-provider.h includes to clk implementations
> > > > 
> > > > v4: * Add more clk-provider.h includes to clk implementations
> > > >     * Add mapping for clk_provider_round_rate
> > > > ---
> > > >  arch/arm/mach-omap2/display.c                 |  1 +
> > > >  arch/arm/mach-omap2/omap_device.c             |  1 +
> > > >  arch/arm/mach-shmobile/clock.c                |  1 +
> > > >  arch/arm/plat-orion/common.c                  |  1 +
> > > >  drivers/clk/berlin/bg2.c                      |  1 +
> > > >  drivers/clk/berlin/bg2q.c                     |  1 +
> > > >  drivers/clk/clk-conf.c                        |  1 +
> > > >  drivers/clk/clkdev.c                          |  1 +
> > > >  drivers/media/platform/exynos4-is/media-dev.c |  1 +
> > > >  include/linux/clk-provider.h                  | 25 +++++++++++++++++++++++++
> > > >  include/linux/clk/zynq.h                      |  1 +
> > > >  11 files changed, 35 insertions(+)
> > > > 
> > > > diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
> > > > index bf852d7..0f9e479 100644
> > > > --- a/arch/arm/mach-omap2/display.c
> > > > +++ b/arch/arm/mach-omap2/display.c
> > > > @@ -21,6 +21,7 @@
> > > >  #include <linux/platform_device.h>
> > > >  #include <linux/io.h>
> > > >  #include <linux/clk.h>
> > > > +#include <linux/clk-provider.h>
> > > >  #include <linux/err.h>
> > > >  #include <linux/delay.h>
> > > >  #include <linux/of.h>
> > > > diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
> > > > index 01ef59d..fbe8cf0 100644
> > > > --- a/arch/arm/mach-omap2/omap_device.c
> > > > +++ b/arch/arm/mach-omap2/omap_device.c
> > > > @@ -32,6 +32,7 @@
> > > >  #include <linux/io.h>
> > > >  #include <linux/clk.h>
> > > >  #include <linux/clkdev.h>
> > > > +#include <linux/clk-provider.h>
> > > >  #include <linux/pm_runtime.h>
> > > >  #include <linux/of.h>
> > > >  #include <linux/notifier.h>
> > > > diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
> > > > index 806f940..ed415dc 100644
> > > > --- a/arch/arm/mach-shmobile/clock.c
> > > > +++ b/arch/arm/mach-shmobile/clock.c
> > > > @@ -24,6 +24,7 @@
> > > >  
> > > >  #ifdef CONFIG_COMMON_CLK
> > > >  #include <linux/clk.h>
> > > > +#include <linux/clk-provider.h>
> > > >  #include <linux/clkdev.h>
> > > >  #include "clock.h"
> > > >  
> > > > diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
> > > > index 3ec6e8e..961b593 100644
> > > > --- a/arch/arm/plat-orion/common.c
> > > > +++ b/arch/arm/plat-orion/common.c
> > > > @@ -15,6 +15,7 @@
> > > >  #include <linux/serial_8250.h>
> > > >  #include <linux/ata_platform.h>
> > > >  #include <linux/clk.h>
> > > > +#include <linux/clk-provider.h>
> > > >  #include <linux/clkdev.h>
> > > >  #include <linux/mv643xx_eth.h>
> > > >  #include <linux/mv643xx_i2c.h>
> > > > diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c
> > > > index 515fb13..4c81e09 100644
> > > > --- a/drivers/clk/berlin/bg2.c
> > > > +++ b/drivers/clk/berlin/bg2.c
> > > > @@ -19,6 +19,7 @@
> > > >  
> > > >  #include <linux/clk.h>
> > > >  #include <linux/clk-provider.h>
> > > > +#include <linux/clkdev.h>
> > > >  #include <linux/kernel.h>
> > > >  #include <linux/of.h>
> > > >  #include <linux/of_address.h>
> > > > diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c
> > > > index 21784e4..748da9b 100644
> > > > --- a/drivers/clk/berlin/bg2q.c
> > > > +++ b/drivers/clk/berlin/bg2q.c
> > > > @@ -19,6 +19,7 @@
> > > >  
> > > >  #include <linux/clk.h>
> > > >  #include <linux/clk-provider.h>
> > > > +#include <linux/clkdev.h>
> > > >  #include <linux/kernel.h>
> > > >  #include <linux/of.h>
> > > >  #include <linux/of_address.h>
> > > > diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
> > > > index aad4796..d36a7b3 100644
> > > > --- a/drivers/clk/clk-conf.c
> > > > +++ b/drivers/clk/clk-conf.c
> > > > @@ -8,6 +8,7 @@
> > > >   */
> > > >  
> > > >  #include <linux/clk.h>
> > > > +#include <linux/clkdev.h>
> > > >  #include <linux/clk-provider.h>
> > > >  #include <linux/clk/clk-conf.h>
> > > >  #include <linux/device.h>
> > > > diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> > > > index da4bda8..c751d0c 100644
> > > > --- a/drivers/clk/clkdev.c
> > > > +++ b/drivers/clk/clkdev.c
> > > > @@ -18,6 +18,7 @@
> > > >  #include <linux/string.h>
> > > >  #include <linux/mutex.h>
> > > >  #include <linux/clk.h>
> > > > +#include <linux/clk-provider.h>
> > > >  #include <linux/clkdev.h>
> > > >  #include <linux/of.h>
> > > >  
> > > > diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
> > > > index 344718d..2620c48 100644
> > > > --- a/drivers/media/platform/exynos4-is/media-dev.c
> > > > +++ b/drivers/media/platform/exynos4-is/media-dev.c
> > > > @@ -13,6 +13,7 @@
> > > >  #include <linux/bug.h>
> > > >  #include <linux/clk.h>
> > > >  #include <linux/clk-provider.h>
> > > > +#include <linux/clkdev.h>
> > > >  #include <linux/device.h>
> > > >  #include <linux/errno.h>
> > > >  #include <linux/i2c.h>
> > > > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> > > > index 411dd7e..a1a7bb7 100644
> > > > --- a/include/linux/clk-provider.h
> > > > +++ b/include/linux/clk-provider.h
> > > > @@ -16,6 +16,31 @@
> > > >  
> > > >  #ifdef CONFIG_COMMON_CLK
> > > >  
> > > > +/* Temporarily map the to-be-added API to the old API, just so stuff compiles */
> > > > +#define clk_core                       clk
> > > > +
> > > > +#define __clk_create_clk
> > > > +
> > > > +#define clk_provider_get                       clk_get
> > > > +#define clk_provider_get_sys                   clk_get_sys
> > > > +#define devm_clk_provider_get                  devm_clk_get
> > > > +#define of_clk_provider_get                    of_clk_get
> > > > +#define of_clk_provider_get_by_name            of_clk_get_by_name
> > > > +
> > > > +#define clk_provider_set_rate                  clk_set_rate
> > > > +#define clk_provider_get_rate                  clk_get_rate
> > > > +#define clk_provider_round_rate                        clk_round_rate
> > > > +#define clk_provider_set_parent                        clk_set_parent
> > > > +#define clk_provider_get_parent                        clk_get_parent
> > > > +#define clk_provider_prepare                   clk_prepare
> > > > +#define clk_provider_unprepare                 clk_unprepare
> > > > +#define clk_provider_enable                    clk_enable
> > > > +#define clk_provider_disable                   clk_disable
> > > > +#define clk_provider_prepare_enable            clk_prepare_enable
> > > > +#define clk_provider_disable_unprepare         clk_unprepare
> > > > +#define clk_provider_notifier_register         clk_notifier_register
> > > > +#define clk_provider_notifier_unregister       clk_notifier_unregister
> > > > +
> > > >  /*
> > > >   * flags used across common struct clk.  these flags should only affect the
> > > >   * top-level framework.  custom flags for dealing with hardware specifics
> > > > diff --git a/include/linux/clk/zynq.h b/include/linux/clk/zynq.h
> > > > index 7a5633b..a990a59 100644
> > > > --- a/include/linux/clk/zynq.h
> > > > +++ b/include/linux/clk/zynq.h
> > > > @@ -21,6 +21,7 @@
> > > >  #define __LINUX_CLK_ZYNQ_H_
> > > >  
> > > >  #include <linux/spinlock.h>
> > > > +#include <linux/clk-provider.h>
> > > >  
> > > >  void zynq_clock_init(void);
> > > >  
> > > > -- 
> > > > 1.9.3
> > > > 
> 

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

* Re: [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
  2014-08-21 13:38       ` Andrew Lunn
@ 2014-08-22 19:29         ` Mike Turquette
  2014-08-22 20:11           ` Andrew Lunn
  0 siblings, 1 reply; 24+ messages in thread
From: Mike Turquette @ 2014-08-22 19:29 UTC (permalink / raw)
  To: Andrew Lunn, Tomeu Vizoso
  Cc: Peter De Schrijver, Stephen Warren, Viresh Kumar, Tomasz Figa,
	Rafael J. Wysocki, linux-kernel, Rabin Vincent, Thierry Reding,
	Javier Martinez Canillas, linux-arm-kernel

Quoting Andrew Lunn (2014-08-21 06:38:25)
> On Thu, Aug 21, 2014 at 09:53:43AM +0200, Tomeu Vizoso wrote:
> > On 08/21/2014 12:55 AM, Mike Turquette wrote:
> > >Quoting Tomeu Vizoso (2014-08-18 08:30:29)
> > >>Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> > >>---
> > >>  drivers/cpufreq/kirkwood-cpufreq.c | 3 +--
> > >>  1 file changed, 1 insertion(+), 2 deletions(-)
> > >>
> > >>diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
> > >>index 37a4806..f3d087f 100644
> > >>--- a/drivers/cpufreq/kirkwood-cpufreq.c
> > >>+++ b/drivers/cpufreq/kirkwood-cpufreq.c
> > >>@@ -12,7 +12,6 @@
> > >>  #include <linux/kernel.h>
> > >>  #include <linux/module.h>
> > >>  #include <linux/clk.h>
> > >>-#include <linux/clk-provider.h>
> > >>  #include <linux/cpufreq.h>
> > >>  #include <linux/of_device.h>
> > >>  #include <linux/platform_device.h>
> > >>@@ -50,7 +49,7 @@ static struct cpufreq_frequency_table kirkwood_freq_table[] = {
> > >>
> > >>  static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
> > >>  {
> > >>-       if (__clk_is_enabled(priv.powersave_clk))
> > >>+       if (clk_is_enabled(priv.powersave_clk))
> > >>                 return kirkwood_freq_table[1].frequency;
> > >>         return kirkwood_freq_table[0].frequency;
> > >>  }
> > >>--
> > >>1.9.3
> > >>
> > >
> > >Tomeu,
> > >
> > >After taking a second look at clk_is_enabled and the Kirkwood driver, I
> > >would prefer to not implement clk_is_enabled. The main reason is that it
> > >is racey, since the clock's status could of course change as soon as as
> > >that call completes. Furthermore I am worried that drivers might do
> > >something like:
> > >
> > >if (!clk_is_enabled(clk))
> > >     clk_enable(clk);
> > >
> > >Which is crap and the driver should just call clk_enable any time it
> > >needs the clock. To that end I propose to drop "clk: provide public
> > >clk_is_enabled function" and replace your update to kirkwood-cpufreq.c
> > >with the following patch. Let me know what you think.
> 
> Hi Mike, Tomeu
> 
> > >+static unsigned long cpu_frequency = 0;
> 
> 
> This has a problem. You are making an assumption about the initial
> state. The way the hardware works, is you change the state of the
> clock and then perform a Wait For Interrupt. Once the hardware has
> finished adjusting its PLL, it raises an interrupt and things
> continue.

Andrew,

Thanks for reviewing. I think my patch is equivalent to the old way of
doing things, with one exception that I will address later below.

struct cpufreq_frequency_table kirkwood_freq_table has clock rates
initialized to zero, so there is no regression compared to my unsigned
long cpu_frequency variable used for tracking the clock rate. Both
implementations start with unknown rates in hardware and initialize a
variable to zero until that rate can be discovered later on in
kirkwood_cpufreq_probe().

kirkwood_cpufreq_get_cpu_frequency() returns the frequency based on the
state of the clock. As best I can tell, this clock is only touched by
this cpufreq driver and nowhere else, so the driver knows the state of
the clock implicitly and doesn't need to read any hardware registers to
see if it is enabled or not. Every time we enable or disable the clock
we can know the cpu frequency.

> 
> However, if you don't cause an actual state change, the WFI never
> returns. If this assumption is wrong, your box is dead the first time
> it tries to change cpu frequency.

So if a state change in hardware never occurs, the cpu will not wake up?
That sounds like a bad situation but I do not understand how it relates
to the changes I made in the driver. Could you explain how tracking
cpu_frequency in the driver would result in the cpu not waking up from
wfi?

> 
> This is why the code reads the hardware register to find the real
> current state, rather than assume it.

OK, so this is the point that I referenced above that needs to be
addressed. The *only* difference between my implementation and yours is
that you do read the enable bit on the powersave clock every time you
query the frequency. Note that this driver controls the state of the
powersave clock directly via calls to clk_enable & clk_disable.

Is there ever a case where hardware will change the state of the clock
behind our backs? If the driver calls clk_enable(priv.powersave_clk),
then is there ever a possibility that the clock will in fact be
disabled? Likewise if we disable the clock with a call to
clk_disable(priv.powersave_clk), is there ever an instance where the
hardware will re-enable that clock without telling us? Can the driver's
view of the clock status be out of sync with the actual hardware?

Thanks,
Mike

> 
>         Andrew
> 
> > >+
> > >  /*
> > >   * Kirkwood can swap the clock to the CPU between two clocks:
> > >   *
> > >@@ -50,9 +51,7 @@ static struct cpufreq_frequency_table kirkwood_freq_table[] = {
> > >
> > >  static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
> > >  {
> > >-    if (__clk_is_enabled(priv.powersave_clk))
> > >-            return kirkwood_freq_table[1].frequency;
> > >-    return kirkwood_freq_table[0].frequency;
> > >+    return cpu_frequency;
> > >  }
> > >
> > >  static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
> > >@@ -71,9 +70,11 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
> > >     switch (state) {
> > >     case STATE_CPU_FREQ:
> > >             clk_disable(priv.powersave_clk);
> > >+            cpu_frequency = kirkwood_freq_table[0].frequency;
> > >             break;
> > >     case STATE_DDR_FREQ:
> > >             clk_enable(priv.powersave_clk);
> > >+            cpu_frequency = kirkwood_freq_table[1].frequency;
> > >             break;
> > >     }
> > >
> > >@@ -133,6 +134,7 @@ static int kirkwood_cpufreq_probe(struct platform_device *pdev)
> > >
> > >     clk_prepare_enable(priv.cpu_clk);
> > >     kirkwood_freq_table[0].frequency = clk_get_rate(priv.cpu_clk) / 1000;
> > >+    cpu_frequency = kirkwood_freq_table[0].frequency;
> > >
> > >     priv.ddr_clk = of_clk_get_by_name(np, "ddrclk");
> > >     if (IS_ERR(priv.ddr_clk)) {
> > >
> > 
> > 
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
  2014-08-22 19:29         ` Mike Turquette
@ 2014-08-22 20:11           ` Andrew Lunn
  2014-08-22 20:27             ` Andrew Lunn
       [not found]             ` <20140826214631.5251.66177@quantum>
  0 siblings, 2 replies; 24+ messages in thread
From: Andrew Lunn @ 2014-08-22 20:11 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Andrew Lunn, Tomeu Vizoso, Stephen Warren, Viresh Kumar,
	Peter De Schrijver, Rafael J. Wysocki, linux-kernel,
	Javier Martinez Canillas, Rabin Vincent, Thierry Reding,
	Tomasz Figa, linux-arm-kernel

> Thanks for reviewing. I think my patch is equivalent to the old way of
> doing things, with one exception that I will address later below.
> 
> struct cpufreq_frequency_table kirkwood_freq_table has clock rates
> initialized to zero, so there is no regression compared to my unsigned
> long cpu_frequency variable used for tracking the clock rate. Both
> implementations start with unknown rates in hardware and initialize a
> variable to zero until that rate can be discovered later on in
> kirkwood_cpufreq_probe().
> 
> kirkwood_cpufreq_get_cpu_frequency() returns the frequency based on the
> state of the clock. As best I can tell, this clock is only touched by
> this cpufreq driver and nowhere else

Not quite true. u-boot might of touch the clock. Weird things happen
with some kirkwood boards. Some don't have the ability to control
there power supplies. So some boards implement "power off" by
rebooting, and letting u-boot spin until a button is pressed. I hope
such a u-boot powers off as much as possible, and e.g. drops the CPU
clock to the lower frequency. One would also hope it puts it back to
high speed before calling the kernel.

There is also the somewhat unlikely case that somebody uses kexec to
go from one kernel to another. You have no idea what state the
previous kernel left the clock in.

> , so the driver knows the state of
> the clock implicitly and doesn't need to read any hardware registers to
> see if it is enabled or not. Every time we enable or disable the clock
> we can know the cpu frequency.
> 
> > 
> > However, if you don't cause an actual state change, the WFI never
> > returns. If this assumption is wrong, your box is dead the first time
> > it tries to change cpu frequency.
> 
> So if a state change in hardware never occurs, the cpu will not wake up?

Correct. I had that situation a few times while developing this
driver. And it is not obvious what has happened, since it does not
happen immediately, but when the governor decides the CPU load passes
a threshold and the frequency can be changed. I had it stop dead while
i assume it executed some sleep in an /etc/init.d script.

> That sounds like a bad situation but I do not understand how it relates
> to the changes I made in the driver. Could you explain how tracking
> cpu_frequency in the driver would result in the cpu not waking up from
> wfi?

It was clearer in earlier versions of the driver, but code has been
refactored into the cpufreq core. The core should call
kirkwood_cpufreq_get_cpu_frequency() in order to get the current
frequency, and only perform a change if the requested frequency is
different. In the current code, kirkwood_cpufreq_get_cpu_frequency()
reads from the hardware what the current frequency is. So we are
guaranteed to only call kirkwood_cpufreq_target() when there is a real
change.

[snip]

> Can the driver's
> view of the clock status be out of sync with the actual hardware?

Yes, at startup, as explained above, we have no idea what the current
state of the hardware is. Once we do know the real state, we can track
it within the driver, but we need to get that initial state correct,
or we WFI forever on the first frequency change.

   Andrew

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

* Re: [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
  2014-08-22 20:11           ` Andrew Lunn
@ 2014-08-22 20:27             ` Andrew Lunn
       [not found]             ` <20140826214631.5251.66177@quantum>
  1 sibling, 0 replies; 24+ messages in thread
From: Andrew Lunn @ 2014-08-22 20:27 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Mike Turquette, Tomeu Vizoso, Stephen Warren, Viresh Kumar,
	Peter De Schrijver, Rafael J. Wysocki, linux-kernel,
	Rabin Vincent, Tomasz Figa, Thierry Reding,
	Javier Martinez Canillas, linux-arm-kernel

> It was clearer in earlier versions of the driver, but code has been
> refactored into the cpufreq core. The core should call
> kirkwood_cpufreq_get_cpu_frequency() in order to get the current
> frequency, and only perform a change if the requested frequency is
> different. In the current code, kirkwood_cpufreq_get_cpu_frequency()
> reads from the hardware what the current frequency is. So we are
> guaranteed to only call kirkwood_cpufreq_target() when there is a real
> change.

Hi Mike

I went looking at the core.

drivers/cpufreq/cpufreq.c:__cpufreq_add_dev() contains:

        if (cpufreq_driver->get && !cpufreq_driver->setpolicy) {
                policy->cur = cpufreq_driver->get(policy->cpu);
                if (!policy->cur) {
                        pr_err("%s: ->get() failed\n", __func__);
                        goto err_get_freq;
                }
        }

So this gets the current frequency from the driver, when the driver is
added. So for the current code, this gets the real state of the
hardware.

and

drivers/cpufreq/cpufreq.c:__cpufreq_driver_target() contains:

        /*
         * This might look like a redundant call as we are checking it again
         * after finding index. But it is left intentionally for cases where
         * exactly same freq is called again and so we can save on few function
         * calls.
         */
        if (target_freq == policy->cur)
                return 0;

        /* Save last value to restore later on errors */
        policy->restore_freq = policy->cur;

        if (cpufreq_driver->target)
                retval = cpufreq_driver->target(policy, target_freq, relation);

and here it will only call the function to change the frequency, if it
is different from the current frequency.

   Andrew

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

* Re: [PATCH v7 1/8] clk: Add temporary mapping to the existing API
  2014-08-21 18:10       ` Jason Cooper
  2014-08-22  3:49         ` Simon Horman
@ 2014-08-25  9:18         ` Sebastian Hesselbarth
  1 sibling, 0 replies; 24+ messages in thread
From: Sebastian Hesselbarth @ 2014-08-25  9:18 UTC (permalink / raw)
  To: Jason Cooper, Tony Lindgren, Sebastian Hesselbarth
  Cc: Mike Turquette, Tomeu Vizoso, Stephen Warren, Thierry Reding,
	Tomasz Figa, Peter De Schrijver, rabin, linux-kernel,
	linux-arm-kernel, Javier Martinez Canillas, Simon Horman,
	Magnus Damm, Andrew Lunn, Mauro Carvalho Chehab, Kukjin Kim

On 08/21/2014 08:10 PM, Jason Cooper wrote:
> On Thu, Aug 21, 2014 at 11:04:48AM -0700, Tony Lindgren wrote:
>> * Mike Turquette <mturquette@linaro.org> [140820 07:53]:
>>> Quoting Tomeu Vizoso (2014-08-18 08:30:27)
>>>> To preserve git-bisectability, add aliases from the future provider API to the
>>>> existing public API.
>>>>
>>>> Also includes clk-provider.h and clk-dev.h in a few places so the right
>>>> functions are defined.
>>>>
>>>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>>>
>>> Cc'ing Tony for the OMAP2+ parts, Simon & Magnus for the SHMobile parts,
>>> Jason & Andrew for the Orion parts, Mauro & Kukjin for the Exynos parts.
>>>
>>> This change is super trivial but it's best not to touch these files
>>> without a heads-up for the owners.
>>
>> As long as it compiles omap2plus_defconfig it seems safe to me:
>>
>> Acked-by: Tony Lindgren <tony@atomide.com>
>
> Same here for orion5x_defconfig, dove_defconfig, and mv78xx_defconfig.
>
> Acked-by: Jason Cooper <jason@lakedaemon.net>
>
> Also, added Sebastian to the Cc as he's the maintainer of mach-berlin.

If it still compiles for multi_v7,

Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

I'll come back to mach-berlin later this week.

Sebastian


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

* Re: [PATCH v7 0/8] Per-user clock constraints
  2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
                   ` (7 preceding siblings ...)
  2014-08-21  2:12 ` [PATCH v7 0/8] Per-user clock constraints Andrew Lunn
@ 2014-08-26 13:20 ` Heiko Stübner
  8 siblings, 0 replies; 24+ messages in thread
From: Heiko Stübner @ 2014-08-26 13:20 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Tomeu Vizoso, Mike Turquette, Stephen Warren, Tomasz Figa,
	linux-kernel, Javier Martinez Canillas, rabin, Thierry Reding,
	Peter De Schrijver, kever.yang

Hi Tomeu,

Am Montag, 18. August 2014, 17:30:26 schrieb Tomeu Vizoso:
> Hi,
> 
> in this v7 of the patchset I have only rebased on top of 3.17rc1, with no
> other changes. I have had to do a fair amount of fixing due to the rebase,
> more details below. Follows the original cover letter blurb:
> 
> I'm retaking Rabin's patches [0] for splitting the clk API in two: one API
> for clk consumers and another for providers. The consumer API uses a clk
> structure that just keeps track of the consumer and has a reference to the
> actual clk_core struct, which is used internally.
> 
> I have kept a patch from Rabin that aims to aid in debugging nested
> enable/disable calls, though my personal aim is to allow more than one
> consumer to influence the final, effective frequency rate. For now this is
> limited to setting floor and ceiling constraints, with the short-term aim
> of allowing devfreq and thermal drivers to set floor and ceiling
> frequencies on the memory clock, respectively.

sounds interesting. I've tested your clk-refactoring-7 branch on a Rockchip 
rk3188-radxarock and rk3288-evb-rk808 board, so

Tested-by: Heiko Stuebner <heiko@sntech.de>


Heiko


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

* Re: [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
       [not found]             ` <20140826214631.5251.66177@quantum>
@ 2014-08-26 22:36               ` Andrew Lunn
       [not found]                 ` <20140826233008.5251.50447@quantum>
  0 siblings, 1 reply; 24+ messages in thread
From: Andrew Lunn @ 2014-08-26 22:36 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Andrew Lunn, Tomeu Vizoso, Stephen Warren, Viresh Kumar,
	Peter De Schrijver, Rafael J. Wysocki, linux-kernel,
	Rabin Vincent, Tomasz Figa, Thierry Reding,
	Javier Martinez Canillas, linux-arm-kernel

> > Not quite true. u-boot might of touch the clock. Weird things happen
> > with some kirkwood boards. Some don't have the ability to control
> > there power supplies. So some boards implement "power off" by
> > rebooting, and letting u-boot spin until a button is pressed. I hope
> > such a u-boot powers off as much as possible, and e.g. drops the CPU
> > clock to the lower frequency. One would also hope it puts it back to
> > high speed before calling the kernel.
> 
> I have a doubt about this.
> 
> The powersave clock in drivers/clk/mvebu/kirkwood.c does not set
> CLK_IGNORE_UNUSED, nor do any of the clocks in kirkwood_gating_desc[].
> 
> So regardless of what U-boot does, if no driver has called clk_enable() on
> powersave_clk by late_initcall-time then clk_disable_unused() will
> disable it as a power-saving mechanism.
> 
> So are kirkwood systems that use cpufreq simply getting lucky and not
> hanging?

Hi Mike

Its a good question.

However, the reset value of the clock is off. off means the CPU is
running at its high speed. Turning this clock on, actually reduces the
clock speed! So for 99% of the time, the late_initcall does nothing.

It gets more interesting when uboot, or a previous kernel has turned
the clock on. I admit, i don't expect this to happen very often, but
if it does, and there is no cpufreq driver, interesting things could
happen. The cpufreq driver can only be builtin, not a module. So if it
is available, it should be guaranteed to claim the clock before the
late_initcall could turn it off. And since it reads the hardware
state, it will do the right thing.

       Andrew

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

* Re: [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
       [not found]                 ` <20140826233008.5251.50447@quantum>
@ 2014-08-27  0:35                   ` Andrew Lunn
  2014-08-27  5:04                     ` Mike Turquette
  2014-08-27 15:58                   ` Jason Gunthorpe
  1 sibling, 1 reply; 24+ messages in thread
From: Andrew Lunn @ 2014-08-27  0:35 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Andrew Lunn, Tomeu Vizoso, Stephen Warren, Viresh Kumar,
	Peter De Schrijver, Rafael J. Wysocki, linux-kernel,
	Rabin Vincent, Tomasz Figa, Thierry Reding,
	Javier Martinez Canillas, linux-arm-kernel

> One final thought I have had is that it might be a good idea to have a
> mux clock which represents the clock signal that feeds into the cpu. It
> seems that a mux is exactly what is going on here with cpuclk rate and
> ddrclk rate.

I did think of this when i implemented the cpufreq driver. What makes
it hard is that this bit is mixed in the same 32 bit register as the
gate clocks. It would mean two clock providers sharing the same
register, sharing a spinlock, etc. And the gating provider is shared
with all mvebu platforms, dove, kirkword, orion5x, and four different
armada SoCs. So i'm pushing complexity into this shared code, which
none of the others need. Does the standard mux clock do what is
needed? Or would i have to write a new clock provider?

> I even wonder if it is even appropriate to model this transition with a
> clock enable operation? Maybe it is only a multiplex operation, or
> perhaps a combination of enabling the powersave clock and changing the
> parent input to the cpu?
> 
> My idea is instead of relying on a cpufreq driver to parse the state of
> your clocks and understand the multiplexing, you can use the clock
> framework for that. In fact that might help you get one step closer to
> using the cpufreq-cpu0.c/cpufreq-generic.c implementation.

So you want the whole disabling of interrupt delivery to the cpu,
flipping the mux, wait for interrupt and re-enabling of interrupt
delivery to the cpu inside the clock provider? That is way past a
simple mux clock.

       Andrew

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

* Re: [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
  2014-08-27  0:35                   ` Andrew Lunn
@ 2014-08-27  5:04                     ` Mike Turquette
  0 siblings, 0 replies; 24+ messages in thread
From: Mike Turquette @ 2014-08-27  5:04 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Tomeu Vizoso, Stephen Warren, Viresh Kumar, Peter De Schrijver,
	Rafael J. Wysocki, linux-kernel, Rabin Vincent, Tomasz Figa,
	Thierry Reding, Javier Martinez Canillas, linux-arm-kernel

On Tue, Aug 26, 2014 at 5:35 PM, Andrew Lunn <andrew@lunn.ch> wrote:
>> One final thought I have had is that it might be a good idea to have a
>> mux clock which represents the clock signal that feeds into the cpu. It
>> seems that a mux is exactly what is going on here with cpuclk rate and
>> ddrclk rate.
>
> I did think of this when i implemented the cpufreq driver. What makes
> it hard is that this bit is mixed in the same 32 bit register as the
> gate clocks. It would mean two clock providers sharing the same
> register, sharing a spinlock, etc. And the gating provider is shared
> with all mvebu platforms, dove, kirkword, orion5x, and four different
> armada SoCs. So i'm pushing complexity into this shared code, which
> none of the others need. Does the standard mux clock do what is
> needed? Or would i have to write a new clock provider?

Well I think that the mux-clock type should suffice. Both the standard
gate and mux can have a spinlock passed in at registration-time, so it
could be a shared spinlock. The standard mux clock expects a bitfield
in a register, similar to the single-bit approach taken by the gate
clock. So I think it could do just fine.

>
>> I even wonder if it is even appropriate to model this transition with a
>> clock enable operation? Maybe it is only a multiplex operation, or
>> perhaps a combination of enabling the powersave clock and changing the
>> parent input to the cpu?
>>
>> My idea is instead of relying on a cpufreq driver to parse the state of
>> your clocks and understand the multiplexing, you can use the clock
>> framework for that. In fact that might help you get one step closer to
>> using the cpufreq-cpu0.c/cpufreq-generic.c implementation.
>
> So you want the whole disabling of interrupt delivery to the cpu,
> flipping the mux, wait for interrupt and re-enabling of interrupt
> delivery to the cpu inside the clock provider? That is way past a
> simple mux clock.

No way! I said, "one step closer" for a reason. The interrupt stuff is
clearly out of scope.

Regards,
Mike

>
>        Andrew

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

* Re: [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API
       [not found]                 ` <20140826233008.5251.50447@quantum>
  2014-08-27  0:35                   ` Andrew Lunn
@ 2014-08-27 15:58                   ` Jason Gunthorpe
  1 sibling, 0 replies; 24+ messages in thread
From: Jason Gunthorpe @ 2014-08-27 15:58 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Andrew Lunn, Tomeu Vizoso, Stephen Warren, Viresh Kumar,
	Peter De Schrijver, Rafael J. Wysocki, linux-kernel,
	Javier Martinez Canillas, Rabin Vincent, Thierry Reding,
	Tomasz Figa, linux-arm-kernel

On Tue, Aug 26, 2014 at 04:30:08PM -0700, Mike Turquette wrote:

> 2) for the kexec-kernel-case, the responsibility is on the first kernel
> to set things up in a good state for the second kernel, with the
> exception of using kexec to debug/examime/recover from a kernel crash,
> in which case you likely don't care about this stuff as much

FWIW, we frequently use a kexec flow on Kirkwood for development here
- and I have not been able to get the initial kernel to cleanly shut
down before kexec'ing the second kernel.

The flow we've had to use involved including a pre-kernel stub in the
kexec flow that goes around and cleans up all the registers enough so
that the 2nd kernel will work properly. Critically it does things like
turn off ethernet DMA, because the initial kernel won't even do that
:|

There is some kind of support for doing this, but I ran out of time
unraveling the mess of config options to actually turn it on for
kirkwood.. It is tied to PM support which was/is missing elements on
Kirkwood..

Jason

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

end of thread, other threads:[~2014-08-27 15:59 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-18 15:30 [PATCH v7 0/8] Per-user clock constraints Tomeu Vizoso
2014-08-18 15:30 ` [PATCH v7 1/8] clk: Add temporary mapping to the existing API Tomeu Vizoso
     [not found]   ` <20140820145006.5251.30923@quantum>
2014-08-21 18:04     ` Tony Lindgren
2014-08-21 18:10       ` Jason Cooper
2014-08-22  3:49         ` Simon Horman
2014-08-25  9:18         ` Sebastian Hesselbarth
2014-08-18 15:30 ` [PATCH v7 2/8] clk: provide public clk_is_enabled function Tomeu Vizoso
2014-08-18 15:30 ` [PATCH v7 3/8] cpufreq: kirkwood: Remove use of the clk provider API Tomeu Vizoso
     [not found]   ` <20140820225513.5251.284@quantum>
2014-08-21  7:53     ` Tomeu Vizoso
2014-08-21 13:38       ` Andrew Lunn
2014-08-22 19:29         ` Mike Turquette
2014-08-22 20:11           ` Andrew Lunn
2014-08-22 20:27             ` Andrew Lunn
     [not found]             ` <20140826214631.5251.66177@quantum>
2014-08-26 22:36               ` Andrew Lunn
     [not found]                 ` <20140826233008.5251.50447@quantum>
2014-08-27  0:35                   ` Andrew Lunn
2014-08-27  5:04                     ` Mike Turquette
2014-08-27 15:58                   ` Jason Gunthorpe
2014-08-18 15:30 ` [PATCH v7 4/8] ASoC: mxs-saif: fix mixed use of public and provider clk API Tomeu Vizoso
2014-08-18 15:30 ` [PATCH v7 6/8] clk: use struct clk only for external API Tomeu Vizoso
2014-08-18 15:30 ` [PATCH v7 7/8] clk: per-user clock accounting for debug Tomeu Vizoso
2014-08-18 15:30 ` [PATCH v7 8/8] clk: Add floor and ceiling constraints to clock rates Tomeu Vizoso
2014-08-21  2:12 ` [PATCH v7 0/8] Per-user clock constraints Andrew Lunn
2014-08-21  7:10   ` Tomeu Vizoso
2014-08-26 13:20 ` Heiko Stübner

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