All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
@ 2014-09-11 20:18 ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez,
	chris-OsFVWbfNK3isTnJN9+BGXg, david.lanzendoerfer-Z7Kmv9EsliU,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA, wens-jdAy2FN1RRM,
	Maxime Ripard

Hi everyone,

Here is an attempt at improving the MMC clock support in the Allwinner
SoCs.

Until now, the MMC clocks were having a custom phase function that was
directly setting an obscure value in the right register, because we
were not really having any idea of what these values were.

Now that we have more informations, we can introduce a common function
call to get and set the phase of a particular clock, and use this in
both our provider and our client.

Thanks,
Maxime

Changes from v2:
  - Reworked the get_phase operation handling to call it from
    _clk_init instead of the ugly hack
  - Added the clocks to the A23
  - Modified the output and sample clock names to have a consistent
    naming

Changes from v1:
  - Dropped the patches to enforce rate boundaries on the clocks. This
    is partly covered by the Tomeu, and should be based on this
    whenever it will be merged.
  - Fixed a few typos here and there
  - Added a patch to include of.h from clk-provider.h

Maxime Ripard (11):
  clk: Include of.h in clock-provider.h
  clk: Add a function to retrieve phase
  clk: sunxi: factors: Invert the probing logic
  clk: sunxi: Introduce mbus compatible
  ARM: sunxi: dt: Switch to the new mbus compatible
  clk: sunxi: Move mod0 clock to a file of its own
  clk: sunxi: Move mbus to mod0 file
  ARM: sunxi: dt: Add sample and output mmc clocks
  clk: sunxi: mod0: Introduce MMC proper phase handling
  mmc: sunxi: Convert MMC driver to the standard clock phase API
  clk: sunxi: Remove custom phase function

Mike Turquette (1):
  clk: introduce clk_set_phase function & callback

 Documentation/devicetree/bindings/clock/sunxi.txt  |   3 +
 .../devicetree/bindings/mmc/sunxi-mmc.txt          |   8 +-
 arch/arm/boot/dts/sun4i-a10.dtsi                   | 104 +++++++-
 arch/arm/boot/dts/sun5i-a10s.dtsi                  |  81 +++++-
 arch/arm/boot/dts/sun5i-a13.dtsi                   |  82 +++++-
 arch/arm/boot/dts/sun6i-a31.dtsi                   | 104 +++++++-
 arch/arm/boot/dts/sun7i-a20.dtsi                   | 106 +++++++-
 arch/arm/boot/dts/sun8i-a23.dtsi                   |  78 +++++-
 drivers/clk/clk.c                                  |  95 ++++++-
 drivers/clk/sunxi/Makefile                         |   1 +
 drivers/clk/sunxi/clk-factors.c                    | 101 +++++++-
 drivers/clk/sunxi/clk-factors.h                    |  16 +-
 drivers/clk/sunxi/clk-mod0.c                       | 283 +++++++++++++++++++++
 drivers/clk/sunxi/clk-sunxi.c                      | 189 +-------------
 drivers/mmc/host/sunxi-mmc.c                       |  72 ++++--
 include/linux/clk-private.h                        |   1 +
 include/linux/clk-provider.h                       |  11 +
 include/linux/clk.h                                |  29 +++
 include/linux/clk/sunxi.h                          |  22 --
 19 files changed, 1090 insertions(+), 296 deletions(-)
 create mode 100644 drivers/clk/sunxi/clk-mod0.c
 delete mode 100644 include/linux/clk/sunxi.h

-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
@ 2014-09-11 20:18 ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi everyone,

Here is an attempt at improving the MMC clock support in the Allwinner
SoCs.

Until now, the MMC clocks were having a custom phase function that was
directly setting an obscure value in the right register, because we
were not really having any idea of what these values were.

Now that we have more informations, we can introduce a common function
call to get and set the phase of a particular clock, and use this in
both our provider and our client.

Thanks,
Maxime

Changes from v2:
  - Reworked the get_phase operation handling to call it from
    _clk_init instead of the ugly hack
  - Added the clocks to the A23
  - Modified the output and sample clock names to have a consistent
    naming

Changes from v1:
  - Dropped the patches to enforce rate boundaries on the clocks. This
    is partly covered by the Tomeu, and should be based on this
    whenever it will be merged.
  - Fixed a few typos here and there
  - Added a patch to include of.h from clk-provider.h

Maxime Ripard (11):
  clk: Include of.h in clock-provider.h
  clk: Add a function to retrieve phase
  clk: sunxi: factors: Invert the probing logic
  clk: sunxi: Introduce mbus compatible
  ARM: sunxi: dt: Switch to the new mbus compatible
  clk: sunxi: Move mod0 clock to a file of its own
  clk: sunxi: Move mbus to mod0 file
  ARM: sunxi: dt: Add sample and output mmc clocks
  clk: sunxi: mod0: Introduce MMC proper phase handling
  mmc: sunxi: Convert MMC driver to the standard clock phase API
  clk: sunxi: Remove custom phase function

Mike Turquette (1):
  clk: introduce clk_set_phase function & callback

 Documentation/devicetree/bindings/clock/sunxi.txt  |   3 +
 .../devicetree/bindings/mmc/sunxi-mmc.txt          |   8 +-
 arch/arm/boot/dts/sun4i-a10.dtsi                   | 104 +++++++-
 arch/arm/boot/dts/sun5i-a10s.dtsi                  |  81 +++++-
 arch/arm/boot/dts/sun5i-a13.dtsi                   |  82 +++++-
 arch/arm/boot/dts/sun6i-a31.dtsi                   | 104 +++++++-
 arch/arm/boot/dts/sun7i-a20.dtsi                   | 106 +++++++-
 arch/arm/boot/dts/sun8i-a23.dtsi                   |  78 +++++-
 drivers/clk/clk.c                                  |  95 ++++++-
 drivers/clk/sunxi/Makefile                         |   1 +
 drivers/clk/sunxi/clk-factors.c                    | 101 +++++++-
 drivers/clk/sunxi/clk-factors.h                    |  16 +-
 drivers/clk/sunxi/clk-mod0.c                       | 283 +++++++++++++++++++++
 drivers/clk/sunxi/clk-sunxi.c                      | 189 +-------------
 drivers/mmc/host/sunxi-mmc.c                       |  72 ++++--
 include/linux/clk-private.h                        |   1 +
 include/linux/clk-provider.h                       |  11 +
 include/linux/clk.h                                |  29 +++
 include/linux/clk/sunxi.h                          |  22 --
 19 files changed, 1090 insertions(+), 296 deletions(-)
 create mode 100644 drivers/clk/sunxi/clk-mod0.c
 delete mode 100644 include/linux/clk/sunxi.h

-- 
2.1.0

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

* [PATCH v3 01/12] clk: introduce clk_set_phase function & callback
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

From: Mike Turquette <mturquette@linaro.org>

A common operation for a clock signal generator is to shift the phase of
that signal. This patch introduces a new function to the clk.h API to
dynamically adjust the phase of a clock signal. Additionally this patch
introduces support for the new function in the common clock framework
via the .set_phase call back in struct clk_ops.

Signed-off-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/clk.c            | 85 +++++++++++++++++++++++++++++++++++++++++---
 include/linux/clk-private.h  |  1 +
 include/linux/clk-provider.h |  5 +++
 include/linux/clk.h          | 29 +++++++++++++++
 4 files changed, 116 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b76fa69b44cb..d87661af0c72 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -117,11 +117,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
 	if (!c)
 		return;
 
-	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",
+	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
 		   level * 3 + 1, "",
 		   30 - level * 3, c->name,
 		   c->enable_count, c->prepare_count, clk_get_rate(c),
-		   clk_get_accuracy(c));
+		   clk_get_accuracy(c), clk_get_phase(c));
 }
 
 static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
@@ -143,8 +143,8 @@ static int clk_summary_show(struct seq_file *s, void *data)
 	struct clk *c;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
-	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy\n");
-	seq_puts(s, "--------------------------------------------------------------------------------\n");
+	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase\n");
+	seq_puts(s, "----------------------------------------------------------------------------------------\n");
 
 	clk_prepare_lock();
 
@@ -180,6 +180,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
 	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, "\"phase\": %d", clk_get_phase(c));
 }
 
 static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
@@ -264,6 +265,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
 	if (!d)
 		goto err_out;
 
+	d = debugfs_create_u32("clk_phase", S_IRUGO, clk->dentry,
+			(u32 *)&clk->phase);
+	if (!d)
+		goto err_out;
+
 	d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
 			(u32 *)&clk->flags);
 	if (!d)
@@ -1739,6 +1745,77 @@ out:
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
 /**
+ * clk_set_phase - adjust the phase shift of a clock signal
+ * @clk: clock signal source
+ * @degrees: number of degrees the signal is shifted
+ *
+ * Shifts the phase of a clock signal by the specified
+ * degrees. Returns 0 on success, -EERROR otherwise.
+ *
+ * This function makes no distinction about the input or reference
+ * signal that we adjust the clock signal phase against. For example
+ * phase locked-loop clock signal generators we may shift phase with
+ * respect to feedback clock signal input, but for other cases the
+ * clock phase may be shifted with respect to some other, unspecified
+ * signal.
+ *
+ * Additionally the concept of phase shift does not propagate through
+ * the clock tree hierarchy, which sets it apart from clock rates and
+ * clock accuracy. A parent clock phase attribute does not have an
+ * impact on the phase attribute of a child clock.
+ */
+int clk_set_phase(struct clk *clk, int degrees)
+{
+	int ret = 0;
+
+	if (!clk)
+		goto out;
+
+	/* sanity check degrees */
+	degrees %= 360;
+	if (degrees < 0)
+		degrees += 360;
+
+	clk_prepare_lock();
+
+	if (!clk->ops->set_phase)
+		goto out_unlock;
+
+	ret = clk->ops->set_phase(clk->hw, degrees);
+
+	if (!ret)
+		clk->phase = degrees;
+
+out_unlock:
+	clk_prepare_unlock();
+
+out:
+	return ret;
+}
+
+/**
+ * clk_get_phase - return the phase shift of a clock signal
+ * @clk: clock signal source
+ *
+ * Returns the phase shift of a clock node in degrees, otherwise returns
+ * -EERROR.
+ */
+int clk_get_phase(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk)
+		goto out;
+
+	clk_prepare_lock();
+	ret = clk->phase;
+	clk_prepare_unlock();
+
+out:
+	return ret;
+}
+
+/**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now
  * @clk:	clk being initialized
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index efbf70b9fd84..845be30be50f 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -46,6 +46,7 @@ struct clk {
 	unsigned int		enable_count;
 	unsigned int		prepare_count;
 	unsigned long		accuracy;
+	int			phase;
 	struct hlist_head	children;
 	struct hlist_node	child_node;
 	unsigned int		notifier_count;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 411dd7eb2653..201a6195a3eb 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -129,6 +129,10 @@ struct dentry;
  *		set then clock accuracy will be initialized to parent accuracy
  *		or 0 (perfect clock) if clock has no parent.
  *
+ * @set_phase:	Shift the phase this clock signal in degrees specified
+ *		by the second argument. Valid values for degrees are
+ *		0-359. Return 0 on success, otherwise -EERROR.
+ *
  * @init:	Perform platform-specific initialization magic.
  *		This is not not used by any of the basic clock types.
  *		Please consider other ways of solving initialization problems
@@ -177,6 +181,7 @@ struct clk_ops {
 				    unsigned long parent_rate, u8 index);
 	unsigned long	(*recalc_accuracy)(struct clk_hw *hw,
 					   unsigned long parent_accuracy);
+	int		(*set_phase)(struct clk_hw *hw, int degrees);
 	void		(*init)(struct clk_hw *hw);
 	int		(*debug_init)(struct clk_hw *hw, struct dentry *dentry);
 };
diff --git a/include/linux/clk.h b/include/linux/clk.h
index fb5e097d8f72..38bdedd3e389 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -106,6 +106,25 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
  */
 long clk_get_accuracy(struct clk *clk);
 
+/**
+ * clk_set_phase - adjust the phase shift of a clock signal
+ * @clk: clock signal source
+ * @degrees: number of degrees the signal is shifted
+ *
+ * Shifts the phase of a clock signal by the specified degrees. Returns 0 on
+ * success, -EERROR otherwise.
+ */
+int clk_set_phase(struct clk *clk, int degrees);
+
+/**
+ * clk_get_phase - return the phase shift of a clock signal
+ * @clk: clock signal source
+ *
+ * Returns the phase shift of a clock node in degrees, otherwise returns
+ * -EERROR.
+ */
+int clk_get_phase(struct clk *clk);
+
 #else
 
 static inline long clk_get_accuracy(struct clk *clk)
@@ -113,6 +132,16 @@ static inline long clk_get_accuracy(struct clk *clk)
 	return -ENOTSUPP;
 }
 
+static inline long clk_set_phase(struct clk *clk, int phase)
+{
+	return -ENOTSUPP;
+}
+
+static inline long clk_get_phase(struct clk *clk)
+{
+	return -ENOTSUPP;
+}
+
 #endif
 
 /**
-- 
2.1.0


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

* [PATCH v3 01/12] clk: introduce clk_set_phase function & callback
@ 2014-09-11 20:18   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

From: Mike Turquette <mturquette@linaro.org>

A common operation for a clock signal generator is to shift the phase of
that signal. This patch introduces a new function to the clk.h API to
dynamically adjust the phase of a clock signal. Additionally this patch
introduces support for the new function in the common clock framework
via the .set_phase call back in struct clk_ops.

Signed-off-by: Mike Turquette <mturquette@linaro.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/clk.c            | 85 +++++++++++++++++++++++++++++++++++++++++---
 include/linux/clk-private.h  |  1 +
 include/linux/clk-provider.h |  5 +++
 include/linux/clk.h          | 29 +++++++++++++++
 4 files changed, 116 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b76fa69b44cb..d87661af0c72 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -117,11 +117,11 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
 	if (!c)
 		return;
 
-	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",
+	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
 		   level * 3 + 1, "",
 		   30 - level * 3, c->name,
 		   c->enable_count, c->prepare_count, clk_get_rate(c),
-		   clk_get_accuracy(c));
+		   clk_get_accuracy(c), clk_get_phase(c));
 }
 
 static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
@@ -143,8 +143,8 @@ static int clk_summary_show(struct seq_file *s, void *data)
 	struct clk *c;
 	struct hlist_head **lists = (struct hlist_head **)s->private;
 
-	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy\n");
-	seq_puts(s, "--------------------------------------------------------------------------------\n");
+	seq_puts(s, "   clock                         enable_cnt  prepare_cnt        rate   accuracy   phase\n");
+	seq_puts(s, "----------------------------------------------------------------------------------------\n");
 
 	clk_prepare_lock();
 
@@ -180,6 +180,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
 	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, "\"phase\": %d", clk_get_phase(c));
 }
 
 static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
@@ -264,6 +265,11 @@ static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
 	if (!d)
 		goto err_out;
 
+	d = debugfs_create_u32("clk_phase", S_IRUGO, clk->dentry,
+			(u32 *)&clk->phase);
+	if (!d)
+		goto err_out;
+
 	d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
 			(u32 *)&clk->flags);
 	if (!d)
@@ -1739,6 +1745,77 @@ out:
 EXPORT_SYMBOL_GPL(clk_set_parent);
 
 /**
+ * clk_set_phase - adjust the phase shift of a clock signal
+ * @clk: clock signal source
+ * @degrees: number of degrees the signal is shifted
+ *
+ * Shifts the phase of a clock signal by the specified
+ * degrees. Returns 0 on success, -EERROR otherwise.
+ *
+ * This function makes no distinction about the input or reference
+ * signal that we adjust the clock signal phase against. For example
+ * phase locked-loop clock signal generators we may shift phase with
+ * respect to feedback clock signal input, but for other cases the
+ * clock phase may be shifted with respect to some other, unspecified
+ * signal.
+ *
+ * Additionally the concept of phase shift does not propagate through
+ * the clock tree hierarchy, which sets it apart from clock rates and
+ * clock accuracy. A parent clock phase attribute does not have an
+ * impact on the phase attribute of a child clock.
+ */
+int clk_set_phase(struct clk *clk, int degrees)
+{
+	int ret = 0;
+
+	if (!clk)
+		goto out;
+
+	/* sanity check degrees */
+	degrees %= 360;
+	if (degrees < 0)
+		degrees += 360;
+
+	clk_prepare_lock();
+
+	if (!clk->ops->set_phase)
+		goto out_unlock;
+
+	ret = clk->ops->set_phase(clk->hw, degrees);
+
+	if (!ret)
+		clk->phase = degrees;
+
+out_unlock:
+	clk_prepare_unlock();
+
+out:
+	return ret;
+}
+
+/**
+ * clk_get_phase - return the phase shift of a clock signal
+ * @clk: clock signal source
+ *
+ * Returns the phase shift of a clock node in degrees, otherwise returns
+ * -EERROR.
+ */
+int clk_get_phase(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk)
+		goto out;
+
+	clk_prepare_lock();
+	ret = clk->phase;
+	clk_prepare_unlock();
+
+out:
+	return ret;
+}
+
+/**
  * __clk_init - initialize the data structures in a struct clk
  * @dev:	device initializing this clk, placeholder for now
  * @clk:	clk being initialized
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index efbf70b9fd84..845be30be50f 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -46,6 +46,7 @@ struct clk {
 	unsigned int		enable_count;
 	unsigned int		prepare_count;
 	unsigned long		accuracy;
+	int			phase;
 	struct hlist_head	children;
 	struct hlist_node	child_node;
 	unsigned int		notifier_count;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 411dd7eb2653..201a6195a3eb 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -129,6 +129,10 @@ struct dentry;
  *		set then clock accuracy will be initialized to parent accuracy
  *		or 0 (perfect clock) if clock has no parent.
  *
+ * @set_phase:	Shift the phase this clock signal in degrees specified
+ *		by the second argument. Valid values for degrees are
+ *		0-359. Return 0 on success, otherwise -EERROR.
+ *
  * @init:	Perform platform-specific initialization magic.
  *		This is not not used by any of the basic clock types.
  *		Please consider other ways of solving initialization problems
@@ -177,6 +181,7 @@ struct clk_ops {
 				    unsigned long parent_rate, u8 index);
 	unsigned long	(*recalc_accuracy)(struct clk_hw *hw,
 					   unsigned long parent_accuracy);
+	int		(*set_phase)(struct clk_hw *hw, int degrees);
 	void		(*init)(struct clk_hw *hw);
 	int		(*debug_init)(struct clk_hw *hw, struct dentry *dentry);
 };
diff --git a/include/linux/clk.h b/include/linux/clk.h
index fb5e097d8f72..38bdedd3e389 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -106,6 +106,25 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
  */
 long clk_get_accuracy(struct clk *clk);
 
+/**
+ * clk_set_phase - adjust the phase shift of a clock signal
+ * @clk: clock signal source
+ * @degrees: number of degrees the signal is shifted
+ *
+ * Shifts the phase of a clock signal by the specified degrees. Returns 0 on
+ * success, -EERROR otherwise.
+ */
+int clk_set_phase(struct clk *clk, int degrees);
+
+/**
+ * clk_get_phase - return the phase shift of a clock signal
+ * @clk: clock signal source
+ *
+ * Returns the phase shift of a clock node in degrees, otherwise returns
+ * -EERROR.
+ */
+int clk_get_phase(struct clk *clk);
+
 #else
 
 static inline long clk_get_accuracy(struct clk *clk)
@@ -113,6 +132,16 @@ static inline long clk_get_accuracy(struct clk *clk)
 	return -ENOTSUPP;
 }
 
+static inline long clk_set_phase(struct clk *clk, int phase)
+{
+	return -ENOTSUPP;
+}
+
+static inline long clk_get_phase(struct clk *clk)
+{
+	return -ENOTSUPP;
+}
+
 #endif
 
 /**
-- 
2.1.0

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

* [PATCH v3 02/12] clk: Include of.h in clock-provider.h
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

CLK_OF_DECLARE relies on OF_DECLARE_1 that is defined in of.h. Fixes build
errors when one use CLK_OF_DECLARE but doesn't include of.h

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 include/linux/clk-provider.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 201a6195a3eb..69b20d4c1e1a 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -13,6 +13,7 @@
 
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of.h>
 
 #ifdef CONFIG_COMMON_CLK
 
-- 
2.1.0


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

* [PATCH v3 02/12] clk: Include of.h in clock-provider.h
@ 2014-09-11 20:18   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

CLK_OF_DECLARE relies on OF_DECLARE_1 that is defined in of.h. Fixes build
errors when one use CLK_OF_DECLARE but doesn't include of.h

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 include/linux/clk-provider.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 201a6195a3eb..69b20d4c1e1a 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -13,6 +13,7 @@
 
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of.h>
 
 #ifdef CONFIG_COMMON_CLK
 
-- 
2.1.0

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

* [PATCH v3 03/12] clk: Add a function to retrieve phase
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

The current phase API doesn't look into the actual hardware to get the phase
value, but will rather get it from a variable only set by the set_phase
function.

This will cause issue when the client driver will never call the set_phase
function, where we can end up having a reported phase that will not match what
the hardware has been programmed to by the bootloader or what phase is
programmed out of reset.

Add a new get_phase function for the drivers to implement so that we can get
this value.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/clk.c            | 10 ++++++++++
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index d87661af0c72..113d75db371d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
 		clk->accuracy = 0;
 
 	/*
+	 * Set clk's phase.
+	 * Since a phase is by definition relative to its parent, just
+	 * query the current clock phase, or just assume it's in phase.
+	 */
+	if (clk->ops->get_phase)
+		clk->phase = clk->ops->get_phase(clk->hw);
+	else
+		clk->phase = 0;
+
+	/*
 	 * Set clk's rate.  The preferred method is to use .recalc_rate.  For
 	 * simple clocks and lazy developers the default fallback is to use the
 	 * parent's rate.  If a clock doesn't have a parent (or is orphaned)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 69b20d4c1e1a..abec961092a7 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -130,6 +130,10 @@ struct dentry;
  *		set then clock accuracy will be initialized to parent accuracy
  *		or 0 (perfect clock) if clock has no parent.
  *
+ * @get_phase:	Queries the hardware to get the current phase of a clock.
+ *		Returned values are 0-359 degrees on success, negative
+ *		error codes on failure.
+ *
  * @set_phase:	Shift the phase this clock signal in degrees specified
  *		by the second argument. Valid values for degrees are
  *		0-359. Return 0 on success, otherwise -EERROR.
@@ -182,6 +186,7 @@ struct clk_ops {
 				    unsigned long parent_rate, u8 index);
 	unsigned long	(*recalc_accuracy)(struct clk_hw *hw,
 					   unsigned long parent_accuracy);
+	int		(*get_phase)(struct clk_hw *hw);
 	int		(*set_phase)(struct clk_hw *hw, int degrees);
 	void		(*init)(struct clk_hw *hw);
 	int		(*debug_init)(struct clk_hw *hw, struct dentry *dentry);
-- 
2.1.0


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

* [PATCH v3 03/12] clk: Add a function to retrieve phase
@ 2014-09-11 20:18   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

The current phase API doesn't look into the actual hardware to get the phase
value, but will rather get it from a variable only set by the set_phase
function.

This will cause issue when the client driver will never call the set_phase
function, where we can end up having a reported phase that will not match what
the hardware has been programmed to by the bootloader or what phase is
programmed out of reset.

Add a new get_phase function for the drivers to implement so that we can get
this value.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/clk.c            | 10 ++++++++++
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index d87661af0c72..113d75db371d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
 		clk->accuracy = 0;
 
 	/*
+	 * Set clk's phase.
+	 * Since a phase is by definition relative to its parent, just
+	 * query the current clock phase, or just assume it's in phase.
+	 */
+	if (clk->ops->get_phase)
+		clk->phase = clk->ops->get_phase(clk->hw);
+	else
+		clk->phase = 0;
+
+	/*
 	 * Set clk's rate.  The preferred method is to use .recalc_rate.  For
 	 * simple clocks and lazy developers the default fallback is to use the
 	 * parent's rate.  If a clock doesn't have a parent (or is orphaned)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 69b20d4c1e1a..abec961092a7 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -130,6 +130,10 @@ struct dentry;
  *		set then clock accuracy will be initialized to parent accuracy
  *		or 0 (perfect clock) if clock has no parent.
  *
+ * @get_phase:	Queries the hardware to get the current phase of a clock.
+ *		Returned values are 0-359 degrees on success, negative
+ *		error codes on failure.
+ *
  * @set_phase:	Shift the phase this clock signal in degrees specified
  *		by the second argument. Valid values for degrees are
  *		0-359. Return 0 on success, otherwise -EERROR.
@@ -182,6 +186,7 @@ struct clk_ops {
 				    unsigned long parent_rate, u8 index);
 	unsigned long	(*recalc_accuracy)(struct clk_hw *hw,
 					   unsigned long parent_accuracy);
+	int		(*get_phase)(struct clk_hw *hw);
 	int		(*set_phase)(struct clk_hw *hw, int degrees);
 	void		(*init)(struct clk_hw *hw);
 	int		(*debug_init)(struct clk_hw *hw, struct dentry *dentry);
-- 
2.1.0

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

* [PATCH v3 04/12] clk: sunxi: factors: Invert the probing logic
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18     ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez,
	chris-OsFVWbfNK3isTnJN9+BGXg, david.lanzendoerfer-Z7Kmv9EsliU,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA, wens-jdAy2FN1RRM,
	Maxime Ripard

Until now, the factors clock probing was done directly by sunxi_init_clocks,
with the factors registration being called directly with the clocks data passed
as an argument.

This approch has shown its limits when we added more clocks, since we couldn't
really split code with such a logic in smaller files, and led to a huge file
having all the clocks.

Introduce an intermediate probing function, so that factor clocks will be able
to directly be called by CLK_OF_DECLARE, which will in turn ease the split into
several files.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 drivers/clk/sunxi/clk-factors.c | 101 +++++++++++++++++++++++++++++++++++++---
 drivers/clk/sunxi/clk-factors.h |  16 ++++++-
 drivers/clk/sunxi/clk-sunxi.c   |  95 ++-----------------------------------
 3 files changed, 113 insertions(+), 99 deletions(-)

diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 2057c8ac648f..f83ba097126c 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -9,18 +9,18 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/err.h>
 #include <linux/string.h>
 
-#include <linux/delay.h>
-
 #include "clk-factors.h"
 
 /*
- * DOC: basic adjustable factor-based clock that cannot gate
+ * DOC: basic adjustable factor-based clock
  *
  * Traits of this clock:
  * prepare - clk_prepare only ensures that parents are prepared
@@ -32,6 +32,8 @@
 
 #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
 
+#define FACTORS_MAX_PARENTS		5
+
 #define SETMASK(len, pos)		(((1U << (len)) - 1) << (pos))
 #define CLRMASK(len, pos)		(~(SETMASK(len, pos)))
 #define FACTOR_GET(bit, len, reg)	(((reg) & SETMASK(len, bit)) >> (bit))
@@ -147,9 +149,96 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
 	return 0;
 }
 
-const struct clk_ops clk_factors_ops = {
+static const struct clk_ops clk_factors_ops = {
 	.determine_rate = clk_factors_determine_rate,
 	.recalc_rate = clk_factors_recalc_rate,
 	.round_rate = clk_factors_round_rate,
 	.set_rate = clk_factors_set_rate,
 };
+
+struct clk * __init sunxi_factors_register(struct device_node *node,
+					   const struct factors_data *data,
+					   spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk_factors *factors;
+	struct clk_gate *gate = NULL;
+	struct clk_mux *mux = NULL;
+	struct clk_hw *gate_hw = NULL;
+	struct clk_hw *mux_hw = NULL;
+	const char *clk_name = node->name;
+	const char *parents[FACTORS_MAX_PARENTS];
+	void __iomem *reg;
+	int i = 0;
+
+	reg = of_iomap(node, 0);
+
+	/* if we have a mux, we will have >1 parents */
+	while (i < FACTORS_MAX_PARENTS &&
+	       (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	/*
+	 * some factor clocks, such as pll5 and pll6, may have multiple
+	 * outputs, and have their name designated in factors_data
+	 */
+	if (data->name)
+		clk_name = data->name;
+	else
+		of_property_read_string(node, "clock-output-names", &clk_name);
+
+	factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
+	if (!factors)
+		return NULL;
+
+	/* set up factors properties */
+	factors->reg = reg;
+	factors->config = data->table;
+	factors->get_factors = data->getter;
+	factors->lock = lock;
+
+	/* Add a gate if this factor clock can be gated */
+	if (data->enable) {
+		gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+		if (!gate) {
+			kfree(factors);
+			return NULL;
+		}
+
+		/* set up gate properties */
+		gate->reg = reg;
+		gate->bit_idx = data->enable;
+		gate->lock = factors->lock;
+		gate_hw = &gate->hw;
+	}
+
+	/* Add a mux if this factor clock can be muxed */
+	if (data->mux) {
+		mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+		if (!mux) {
+			kfree(factors);
+			kfree(gate);
+			return NULL;
+		}
+
+		/* set up gate properties */
+		mux->reg = reg;
+		mux->shift = data->mux;
+		mux->mask = SUNXI_FACTORS_MUX_MASK;
+		mux->lock = factors->lock;
+		mux_hw = &mux->hw;
+	}
+
+	clk = clk_register_composite(NULL, clk_name,
+			parents, i,
+			mux_hw, &clk_mux_ops,
+			&factors->hw, &clk_factors_ops,
+			gate_hw, &clk_gate_ops, 0);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+	}
+
+	return clk;
+}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index d2d0efa39379..9913840018d3 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -3,9 +3,12 @@
 
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/spinlock.h>
 
 #define SUNXI_FACTORS_NOT_APPLICABLE	(0)
 
+#define SUNXI_FACTORS_MUX_MASK 0x3
+
 struct clk_factors_config {
 	u8 nshift;
 	u8 nwidth;
@@ -18,6 +21,14 @@ struct clk_factors_config {
 	u8 n_start;
 };
 
+struct factors_data {
+	int enable;
+	int mux;
+	struct clk_factors_config *table;
+	void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
+	const char *name;
+};
+
 struct clk_factors {
 	struct clk_hw hw;
 	void __iomem *reg;
@@ -26,5 +37,8 @@ struct clk_factors {
 	spinlock_t *lock;
 };
 
-extern const struct clk_ops clk_factors_ops;
+struct clk * __init sunxi_factors_register(struct device_node *node,
+					   const struct factors_data *data,
+					   spinlock_t *lock);
+
 #endif
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index b654b7b1d137..953479041431 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
+#include <linux/spinlock.h>
 
 #include "clk-factors.h"
 
@@ -440,16 +441,6 @@ EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
  * sunxi_factors_clk_setup() - Setup function for factor clocks
  */
 
-#define SUNXI_FACTORS_MUX_MASK 0x3
-
-struct factors_data {
-	int enable;
-	int mux;
-	struct clk_factors_config *table;
-	void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
-	const char *name;
-};
-
 static struct clk_factors_config sun4i_pll1_config = {
 	.nshift = 8,
 	.nwidth = 5,
@@ -583,89 +574,9 @@ static const struct factors_data sun7i_a20_out_data __initconst = {
 };
 
 static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
-						const struct factors_data *data)
+						   const struct factors_data *data)
 {
-	struct clk *clk;
-	struct clk_factors *factors;
-	struct clk_gate *gate = NULL;
-	struct clk_mux *mux = NULL;
-	struct clk_hw *gate_hw = NULL;
-	struct clk_hw *mux_hw = NULL;
-	const char *clk_name = node->name;
-	const char *parents[SUNXI_MAX_PARENTS];
-	void __iomem *reg;
-	int i = 0;
-
-	reg = of_iomap(node, 0);
-
-	/* if we have a mux, we will have >1 parents */
-	while (i < SUNXI_MAX_PARENTS &&
-	       (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
-		i++;
-
-	/*
-	 * some factor clocks, such as pll5 and pll6, may have multiple
-	 * outputs, and have their name designated in factors_data
-	 */
-	if (data->name)
-		clk_name = data->name;
-	else
-		of_property_read_string(node, "clock-output-names", &clk_name);
-
-	factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
-	if (!factors)
-		return NULL;
-
-	/* Add a gate if this factor clock can be gated */
-	if (data->enable) {
-		gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
-		if (!gate) {
-			kfree(factors);
-			return NULL;
-		}
-
-		/* set up gate properties */
-		gate->reg = reg;
-		gate->bit_idx = data->enable;
-		gate->lock = &clk_lock;
-		gate_hw = &gate->hw;
-	}
-
-	/* Add a mux if this factor clock can be muxed */
-	if (data->mux) {
-		mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
-		if (!mux) {
-			kfree(factors);
-			kfree(gate);
-			return NULL;
-		}
-
-		/* set up gate properties */
-		mux->reg = reg;
-		mux->shift = data->mux;
-		mux->mask = SUNXI_FACTORS_MUX_MASK;
-		mux->lock = &clk_lock;
-		mux_hw = &mux->hw;
-	}
-
-	/* set up factors properties */
-	factors->reg = reg;
-	factors->config = data->table;
-	factors->get_factors = data->getter;
-	factors->lock = &clk_lock;
-
-	clk = clk_register_composite(NULL, clk_name,
-			parents, i,
-			mux_hw, &clk_mux_ops,
-			&factors->hw, &clk_factors_ops,
-			gate_hw, &clk_gate_ops, 0);
-
-	if (!IS_ERR(clk)) {
-		of_clk_add_provider(node, of_clk_src_simple_get, clk);
-		clk_register_clkdev(clk, clk_name, NULL);
-	}
-
-	return clk;
+	return sunxi_factors_register(node, data, &clk_lock);
 }
 
 
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 04/12] clk: sunxi: factors: Invert the probing logic
@ 2014-09-11 20:18     ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Until now, the factors clock probing was done directly by sunxi_init_clocks,
with the factors registration being called directly with the clocks data passed
as an argument.

This approch has shown its limits when we added more clocks, since we couldn't
really split code with such a logic in smaller files, and led to a huge file
having all the clocks.

Introduce an intermediate probing function, so that factor clocks will be able
to directly be called by CLK_OF_DECLARE, which will in turn ease the split into
several files.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi/clk-factors.c | 101 +++++++++++++++++++++++++++++++++++++---
 drivers/clk/sunxi/clk-factors.h |  16 ++++++-
 drivers/clk/sunxi/clk-sunxi.c   |  95 ++-----------------------------------
 3 files changed, 113 insertions(+), 99 deletions(-)

diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
index 2057c8ac648f..f83ba097126c 100644
--- a/drivers/clk/sunxi/clk-factors.c
+++ b/drivers/clk/sunxi/clk-factors.c
@@ -9,18 +9,18 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
 #include <linux/module.h>
+#include <linux/of_address.h>
 #include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/err.h>
 #include <linux/string.h>
 
-#include <linux/delay.h>
-
 #include "clk-factors.h"
 
 /*
- * DOC: basic adjustable factor-based clock that cannot gate
+ * DOC: basic adjustable factor-based clock
  *
  * Traits of this clock:
  * prepare - clk_prepare only ensures that parents are prepared
@@ -32,6 +32,8 @@
 
 #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
 
+#define FACTORS_MAX_PARENTS		5
+
 #define SETMASK(len, pos)		(((1U << (len)) - 1) << (pos))
 #define CLRMASK(len, pos)		(~(SETMASK(len, pos)))
 #define FACTOR_GET(bit, len, reg)	(((reg) & SETMASK(len, bit)) >> (bit))
@@ -147,9 +149,96 @@ static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
 	return 0;
 }
 
-const struct clk_ops clk_factors_ops = {
+static const struct clk_ops clk_factors_ops = {
 	.determine_rate = clk_factors_determine_rate,
 	.recalc_rate = clk_factors_recalc_rate,
 	.round_rate = clk_factors_round_rate,
 	.set_rate = clk_factors_set_rate,
 };
+
+struct clk * __init sunxi_factors_register(struct device_node *node,
+					   const struct factors_data *data,
+					   spinlock_t *lock)
+{
+	struct clk *clk;
+	struct clk_factors *factors;
+	struct clk_gate *gate = NULL;
+	struct clk_mux *mux = NULL;
+	struct clk_hw *gate_hw = NULL;
+	struct clk_hw *mux_hw = NULL;
+	const char *clk_name = node->name;
+	const char *parents[FACTORS_MAX_PARENTS];
+	void __iomem *reg;
+	int i = 0;
+
+	reg = of_iomap(node, 0);
+
+	/* if we have a mux, we will have >1 parents */
+	while (i < FACTORS_MAX_PARENTS &&
+	       (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+		i++;
+
+	/*
+	 * some factor clocks, such as pll5 and pll6, may have multiple
+	 * outputs, and have their name designated in factors_data
+	 */
+	if (data->name)
+		clk_name = data->name;
+	else
+		of_property_read_string(node, "clock-output-names", &clk_name);
+
+	factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
+	if (!factors)
+		return NULL;
+
+	/* set up factors properties */
+	factors->reg = reg;
+	factors->config = data->table;
+	factors->get_factors = data->getter;
+	factors->lock = lock;
+
+	/* Add a gate if this factor clock can be gated */
+	if (data->enable) {
+		gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+		if (!gate) {
+			kfree(factors);
+			return NULL;
+		}
+
+		/* set up gate properties */
+		gate->reg = reg;
+		gate->bit_idx = data->enable;
+		gate->lock = factors->lock;
+		gate_hw = &gate->hw;
+	}
+
+	/* Add a mux if this factor clock can be muxed */
+	if (data->mux) {
+		mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+		if (!mux) {
+			kfree(factors);
+			kfree(gate);
+			return NULL;
+		}
+
+		/* set up gate properties */
+		mux->reg = reg;
+		mux->shift = data->mux;
+		mux->mask = SUNXI_FACTORS_MUX_MASK;
+		mux->lock = factors->lock;
+		mux_hw = &mux->hw;
+	}
+
+	clk = clk_register_composite(NULL, clk_name,
+			parents, i,
+			mux_hw, &clk_mux_ops,
+			&factors->hw, &clk_factors_ops,
+			gate_hw, &clk_gate_ops, 0);
+
+	if (!IS_ERR(clk)) {
+		of_clk_add_provider(node, of_clk_src_simple_get, clk);
+		clk_register_clkdev(clk, clk_name, NULL);
+	}
+
+	return clk;
+}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
index d2d0efa39379..9913840018d3 100644
--- a/drivers/clk/sunxi/clk-factors.h
+++ b/drivers/clk/sunxi/clk-factors.h
@@ -3,9 +3,12 @@
 
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/spinlock.h>
 
 #define SUNXI_FACTORS_NOT_APPLICABLE	(0)
 
+#define SUNXI_FACTORS_MUX_MASK 0x3
+
 struct clk_factors_config {
 	u8 nshift;
 	u8 nwidth;
@@ -18,6 +21,14 @@ struct clk_factors_config {
 	u8 n_start;
 };
 
+struct factors_data {
+	int enable;
+	int mux;
+	struct clk_factors_config *table;
+	void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
+	const char *name;
+};
+
 struct clk_factors {
 	struct clk_hw hw;
 	void __iomem *reg;
@@ -26,5 +37,8 @@ struct clk_factors {
 	spinlock_t *lock;
 };
 
-extern const struct clk_ops clk_factors_ops;
+struct clk * __init sunxi_factors_register(struct device_node *node,
+					   const struct factors_data *data,
+					   spinlock_t *lock);
+
 #endif
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index b654b7b1d137..953479041431 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/reset-controller.h>
+#include <linux/spinlock.h>
 
 #include "clk-factors.h"
 
@@ -440,16 +441,6 @@ EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
  * sunxi_factors_clk_setup() - Setup function for factor clocks
  */
 
-#define SUNXI_FACTORS_MUX_MASK 0x3
-
-struct factors_data {
-	int enable;
-	int mux;
-	struct clk_factors_config *table;
-	void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
-	const char *name;
-};
-
 static struct clk_factors_config sun4i_pll1_config = {
 	.nshift = 8,
 	.nwidth = 5,
@@ -583,89 +574,9 @@ static const struct factors_data sun7i_a20_out_data __initconst = {
 };
 
 static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
-						const struct factors_data *data)
+						   const struct factors_data *data)
 {
-	struct clk *clk;
-	struct clk_factors *factors;
-	struct clk_gate *gate = NULL;
-	struct clk_mux *mux = NULL;
-	struct clk_hw *gate_hw = NULL;
-	struct clk_hw *mux_hw = NULL;
-	const char *clk_name = node->name;
-	const char *parents[SUNXI_MAX_PARENTS];
-	void __iomem *reg;
-	int i = 0;
-
-	reg = of_iomap(node, 0);
-
-	/* if we have a mux, we will have >1 parents */
-	while (i < SUNXI_MAX_PARENTS &&
-	       (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
-		i++;
-
-	/*
-	 * some factor clocks, such as pll5 and pll6, may have multiple
-	 * outputs, and have their name designated in factors_data
-	 */
-	if (data->name)
-		clk_name = data->name;
-	else
-		of_property_read_string(node, "clock-output-names", &clk_name);
-
-	factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
-	if (!factors)
-		return NULL;
-
-	/* Add a gate if this factor clock can be gated */
-	if (data->enable) {
-		gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
-		if (!gate) {
-			kfree(factors);
-			return NULL;
-		}
-
-		/* set up gate properties */
-		gate->reg = reg;
-		gate->bit_idx = data->enable;
-		gate->lock = &clk_lock;
-		gate_hw = &gate->hw;
-	}
-
-	/* Add a mux if this factor clock can be muxed */
-	if (data->mux) {
-		mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
-		if (!mux) {
-			kfree(factors);
-			kfree(gate);
-			return NULL;
-		}
-
-		/* set up gate properties */
-		mux->reg = reg;
-		mux->shift = data->mux;
-		mux->mask = SUNXI_FACTORS_MUX_MASK;
-		mux->lock = &clk_lock;
-		mux_hw = &mux->hw;
-	}
-
-	/* set up factors properties */
-	factors->reg = reg;
-	factors->config = data->table;
-	factors->get_factors = data->getter;
-	factors->lock = &clk_lock;
-
-	clk = clk_register_composite(NULL, clk_name,
-			parents, i,
-			mux_hw, &clk_mux_ops,
-			&factors->hw, &clk_factors_ops,
-			gate_hw, &clk_gate_ops, 0);
-
-	if (!IS_ERR(clk)) {
-		of_clk_add_provider(node, of_clk_src_simple_get, clk);
-		clk_register_clkdev(clk, clk_name, NULL);
-	}
-
-	return clk;
+	return sunxi_factors_register(node, data, &clk_lock);
 }
 
 
-- 
2.1.0

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

* [PATCH v3 05/12] clk: sunxi: Introduce mbus compatible
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

Even though the mbus clock is a regular module clock, given its nature, it
needs to be enabled all the time.

Introduce a new compatible, to differentiate it from the other module clocks.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
 drivers/clk/sunxi/clk-sunxi.c                     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index d3a5c3c6d677..b938a990602a 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -46,6 +46,7 @@ Required properties:
 	"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
 	"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
 	"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
+	"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
 	"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
 	"allwinner,sun7i-a20-out-clk" - for the external output clocks
 	"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 953479041431..a3d8c633c2d6 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1110,6 +1110,7 @@ static const struct of_device_id clk_factors_match[] __initconst = {
 	{.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
 	{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
 	{.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
+	{.compatible = "allwinner,sun5i-a13-mbus-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
 	{}
-- 
2.1.0


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

* [PATCH v3 05/12] clk: sunxi: Introduce mbus compatible
@ 2014-09-11 20:18   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Even though the mbus clock is a regular module clock, given its nature, it
needs to be enabled all the time.

Introduce a new compatible, to differentiate it from the other module clocks.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
 drivers/clk/sunxi/clk-sunxi.c                     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index d3a5c3c6d677..b938a990602a 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -46,6 +46,7 @@ Required properties:
 	"allwinner,sun6i-a31-apb2-div-clk" - for the APB2 gates on A31
 	"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
 	"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
+	"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
 	"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
 	"allwinner,sun7i-a20-out-clk" - for the external output clocks
 	"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 953479041431..a3d8c633c2d6 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1110,6 +1110,7 @@ static const struct of_device_id clk_factors_match[] __initconst = {
 	{.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
 	{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
 	{.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
+	{.compatible = "allwinner,sun5i-a13-mbus-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
 	{}
-- 
2.1.0

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

* [PATCH v3 06/12] ARM: sunxi: dt: Switch to the new mbus compatible
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18     ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez,
	chris-OsFVWbfNK3isTnJN9+BGXg, david.lanzendoerfer-Z7Kmv9EsliU,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA, wens-jdAy2FN1RRM,
	Maxime Ripard

Now that we have a compatible of its own for the mbus clock, switch to it.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 arch/arm/boot/dts/sun5i-a10s.dtsi | 2 +-
 arch/arm/boot/dts/sun5i-a13.dtsi  | 2 +-
 arch/arm/boot/dts/sun7i-a20.dtsi  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index d73a2287b37a..531272c0e526 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -287,7 +287,7 @@
 
 		mbus_clk: clk@01c2015c {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun5i-a13-mbus-clk";
 			reg = <0x01c2015c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mbus";
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index c4b5d7825b9f..b131068f4f35 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -285,7 +285,7 @@
 
 		mbus_clk: clk@01c2015c {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun5i-a13-mbus-clk";
 			reg = <0x01c2015c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mbus";
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index a96b99465069..82097c905c48 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -382,7 +382,7 @@
 
 		mbus_clk: clk@01c2015c {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun5i-a13-mbus-clk";
 			reg = <0x01c2015c 0x4>;
 			clocks = <&osc24M>, <&pll6 2>, <&pll5 1>;
 			clock-output-names = "mbus";
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 06/12] ARM: sunxi: dt: Switch to the new mbus compatible
@ 2014-09-11 20:18     ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we have a compatible of its own for the mbus clock, switch to it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun5i-a10s.dtsi | 2 +-
 arch/arm/boot/dts/sun5i-a13.dtsi  | 2 +-
 arch/arm/boot/dts/sun7i-a20.dtsi  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index d73a2287b37a..531272c0e526 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -287,7 +287,7 @@
 
 		mbus_clk: clk at 01c2015c {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun5i-a13-mbus-clk";
 			reg = <0x01c2015c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mbus";
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index c4b5d7825b9f..b131068f4f35 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -285,7 +285,7 @@
 
 		mbus_clk: clk at 01c2015c {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun5i-a13-mbus-clk";
 			reg = <0x01c2015c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mbus";
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index a96b99465069..82097c905c48 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -382,7 +382,7 @@
 
 		mbus_clk: clk at 01c2015c {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun5i-a13-mbus-clk";
 			reg = <0x01c2015c 0x4>;
 			clocks = <&osc24M>, <&pll6 2>, <&pll5 1>;
 			clock-output-names = "mbus";
-- 
2.1.0

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

* [PATCH v3 07/12] clk: sunxi: Move mod0 clock to a file of its own
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

Since we know have the ability to declare factors clock outside of clk-sunxi,
create a new mod0 driver to deal with the mod0 clocks.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi/Makefile    |  1 +
 drivers/clk/sunxi/clk-mod0.c  | 82 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi/clk-sunxi.c |  1 -
 3 files changed, 83 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sunxi/clk-mod0.c

diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 6850cba35871..833f086d4a52 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -5,6 +5,7 @@
 obj-y += clk-sunxi.o clk-factors.o
 obj-y += clk-a10-hosc.o
 obj-y += clk-a20-gmac.o
+obj-y += clk-mod0.o
 
 obj-$(CONFIG_MFD_SUN6I_PRCM) += \
 	clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
new file mode 100644
index 000000000000..bce09a84ab4f
--- /dev/null
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013 Emilio López
+ *
+ * Emilio López <emilio@elopez.com.ar>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+#include "clk-factors.h"
+
+/**
+ * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
+ * MOD0 rate is calculated as follows
+ * rate = (parent_rate >> p) / (m + 1);
+ */
+
+static void sun4i_a10_get_mod0_factors(u32 *freq, u32 parent_rate,
+				       u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u8 div, calcm, calcp;
+
+	/* These clocks can only divide, so we will never be able to achieve
+	 * frequencies higher than the parent frequency */
+	if (*freq > parent_rate)
+		*freq = parent_rate;
+
+	div = DIV_ROUND_UP(parent_rate, *freq);
+
+	if (div < 16)
+		calcp = 0;
+	else if (div / 2 < 16)
+		calcp = 1;
+	else if (div / 4 < 16)
+		calcp = 2;
+	else
+		calcp = 3;
+
+	calcm = DIV_ROUND_UP(div, 1 << calcp);
+
+	*freq = (parent_rate >> calcp) / calcm;
+
+	/* we were called to round the frequency, we can now return */
+	if (n == NULL)
+		return;
+
+	*m = calcm - 1;
+	*p = calcp;
+}
+
+/* user manual says "n" but it's really "p" */
+static struct clk_factors_config sun4i_a10_mod0_config = {
+	.mshift = 0,
+	.mwidth = 4,
+	.pshift = 16,
+	.pwidth = 2,
+};
+
+static const struct factors_data sun4i_a10_mod0_data __initconst = {
+	.enable = 31,
+	.mux = 24,
+	.table = &sun4i_a10_mod0_config,
+	.getter = sun4i_a10_get_mod0_factors,
+};
+
+static DEFINE_SPINLOCK(sun4i_a10_mod0_lock);
+
+static void __init sun4i_a10_mod0_setup(struct device_node *node)
+{
+	sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock);
+}
+CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index a3d8c633c2d6..6eec82b29bb4 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1111,7 +1111,6 @@ static const struct of_device_id clk_factors_match[] __initconst = {
 	{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
 	{.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
 	{.compatible = "allwinner,sun5i-a13-mbus-clk", .data = &sun4i_mod0_data,},
-	{.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
 	{}
 };
-- 
2.1.0


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

* [PATCH v3 07/12] clk: sunxi: Move mod0 clock to a file of its own
@ 2014-09-11 20:18   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Since we know have the ability to declare factors clock outside of clk-sunxi,
create a new mod0 driver to deal with the mod0 clocks.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi/Makefile    |  1 +
 drivers/clk/sunxi/clk-mod0.c  | 82 +++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sunxi/clk-sunxi.c |  1 -
 3 files changed, 83 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/sunxi/clk-mod0.c

diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 6850cba35871..833f086d4a52 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -5,6 +5,7 @@
 obj-y += clk-sunxi.o clk-factors.o
 obj-y += clk-a10-hosc.o
 obj-y += clk-a20-gmac.o
+obj-y += clk-mod0.o
 
 obj-$(CONFIG_MFD_SUN6I_PRCM) += \
 	clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
new file mode 100644
index 000000000000..bce09a84ab4f
--- /dev/null
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013 Emilio L?pez
+ *
+ * Emilio L?pez <emilio@elopez.com.ar>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+#include "clk-factors.h"
+
+/**
+ * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
+ * MOD0 rate is calculated as follows
+ * rate = (parent_rate >> p) / (m + 1);
+ */
+
+static void sun4i_a10_get_mod0_factors(u32 *freq, u32 parent_rate,
+				       u8 *n, u8 *k, u8 *m, u8 *p)
+{
+	u8 div, calcm, calcp;
+
+	/* These clocks can only divide, so we will never be able to achieve
+	 * frequencies higher than the parent frequency */
+	if (*freq > parent_rate)
+		*freq = parent_rate;
+
+	div = DIV_ROUND_UP(parent_rate, *freq);
+
+	if (div < 16)
+		calcp = 0;
+	else if (div / 2 < 16)
+		calcp = 1;
+	else if (div / 4 < 16)
+		calcp = 2;
+	else
+		calcp = 3;
+
+	calcm = DIV_ROUND_UP(div, 1 << calcp);
+
+	*freq = (parent_rate >> calcp) / calcm;
+
+	/* we were called to round the frequency, we can now return */
+	if (n == NULL)
+		return;
+
+	*m = calcm - 1;
+	*p = calcp;
+}
+
+/* user manual says "n" but it's really "p" */
+static struct clk_factors_config sun4i_a10_mod0_config = {
+	.mshift = 0,
+	.mwidth = 4,
+	.pshift = 16,
+	.pwidth = 2,
+};
+
+static const struct factors_data sun4i_a10_mod0_data __initconst = {
+	.enable = 31,
+	.mux = 24,
+	.table = &sun4i_a10_mod0_config,
+	.getter = sun4i_a10_get_mod0_factors,
+};
+
+static DEFINE_SPINLOCK(sun4i_a10_mod0_lock);
+
+static void __init sun4i_a10_mod0_setup(struct device_node *node)
+{
+	sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock);
+}
+CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index a3d8c633c2d6..6eec82b29bb4 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -1111,7 +1111,6 @@ static const struct of_device_id clk_factors_match[] __initconst = {
 	{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
 	{.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
 	{.compatible = "allwinner,sun5i-a13-mbus-clk", .data = &sun4i_mod0_data,},
-	{.compatible = "allwinner,sun4i-a10-mod0-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
 	{}
 };
-- 
2.1.0

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

* [PATCH v3 08/12] clk: sunxi: Move mbus to mod0 file
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

Move the MBUS clock to the module clocks file. It's pretty trivial, but still
requires to enable the clocks to make sure it won't get disabled.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi/clk-mod0.c  | 12 +++++++++
 drivers/clk/sunxi/clk-sunxi.c | 57 -------------------------------------------
 2 files changed, 12 insertions(+), 57 deletions(-)

diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index bce09a84ab4f..8a7f7036aea3 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -80,3 +80,15 @@ static void __init sun4i_a10_mod0_setup(struct device_node *node)
 	sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock);
 }
 CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
+
+static DEFINE_SPINLOCK(sun5i_a13_mbus_lock);
+
+static void __init sun5i_a13_mbus_setup(struct device_node *node)
+{
+	struct clk *mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun5i_a13_mbus_lock);
+
+	/* The MBUS clocks needs to be always enabled */
+	__clk_get(mbus);
+	clk_prepare_enable(mbus);
+}
+CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 6eec82b29bb4..4e189be3e23f 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -320,46 +320,6 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
 
 
 
-/**
- * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
- * MOD0 rate is calculated as follows
- * rate = (parent_rate >> p) / (m + 1);
- */
-
-static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
-				   u8 *n, u8 *k, u8 *m, u8 *p)
-{
-	u8 div, calcm, calcp;
-
-	/* These clocks can only divide, so we will never be able to achieve
-	 * frequencies higher than the parent frequency */
-	if (*freq > parent_rate)
-		*freq = parent_rate;
-
-	div = DIV_ROUND_UP(parent_rate, *freq);
-
-	if (div < 16)
-		calcp = 0;
-	else if (div / 2 < 16)
-		calcp = 1;
-	else if (div / 4 < 16)
-		calcp = 2;
-	else
-		calcp = 3;
-
-	calcm = DIV_ROUND_UP(div, 1 << calcp);
-
-	*freq = (parent_rate >> calcp) / calcm;
-
-	/* we were called to round the frequency, we can now return */
-	if (n == NULL)
-		return;
-
-	*m = calcm - 1;
-	*p = calcp;
-}
-
-
 
 /**
  * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B
@@ -495,14 +455,6 @@ static struct clk_factors_config sun4i_apb1_config = {
 };
 
 /* user manual says "n" but it's really "p" */
-static struct clk_factors_config sun4i_mod0_config = {
-	.mshift = 0,
-	.mwidth = 4,
-	.pshift = 16,
-	.pwidth = 2,
-};
-
-/* user manual says "n" but it's really "p" */
 static struct clk_factors_config sun7i_a20_out_config = {
 	.mshift = 8,
 	.mwidth = 5,
@@ -559,13 +511,6 @@ static const struct factors_data sun4i_apb1_data __initconst = {
 	.getter = sun4i_get_apb1_factors,
 };
 
-static const struct factors_data sun4i_mod0_data __initconst = {
-	.enable = 31,
-	.mux = 24,
-	.table = &sun4i_mod0_config,
-	.getter = sun4i_get_mod0_factors,
-};
-
 static const struct factors_data sun7i_a20_out_data __initconst = {
 	.enable = 31,
 	.mux = 24,
@@ -1110,7 +1055,6 @@ static const struct of_device_id clk_factors_match[] __initconst = {
 	{.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
 	{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
 	{.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
-	{.compatible = "allwinner,sun5i-a13-mbus-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
 	{}
 };
@@ -1222,7 +1166,6 @@ static void __init sun4i_a10_init_clocks(struct device_node *node)
 CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks);
 
 static const char *sun5i_critical_clocks[] __initdata = {
-	"mbus",
 	"pll5_ddr",
 	"ahb_sdram",
 };
-- 
2.1.0


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

* [PATCH v3 08/12] clk: sunxi: Move mbus to mod0 file
@ 2014-09-11 20:18   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Move the MBUS clock to the module clocks file. It's pretty trivial, but still
requires to enable the clocks to make sure it won't get disabled.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi/clk-mod0.c  | 12 +++++++++
 drivers/clk/sunxi/clk-sunxi.c | 57 -------------------------------------------
 2 files changed, 12 insertions(+), 57 deletions(-)

diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index bce09a84ab4f..8a7f7036aea3 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -80,3 +80,15 @@ static void __init sun4i_a10_mod0_setup(struct device_node *node)
 	sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun4i_a10_mod0_lock);
 }
 CLK_OF_DECLARE(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", sun4i_a10_mod0_setup);
+
+static DEFINE_SPINLOCK(sun5i_a13_mbus_lock);
+
+static void __init sun5i_a13_mbus_setup(struct device_node *node)
+{
+	struct clk *mbus = sunxi_factors_register(node, &sun4i_a10_mod0_data, &sun5i_a13_mbus_lock);
+
+	/* The MBUS clocks needs to be always enabled */
+	__clk_get(mbus);
+	clk_prepare_enable(mbus);
+}
+CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 6eec82b29bb4..4e189be3e23f 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -320,46 +320,6 @@ static void sun4i_get_apb1_factors(u32 *freq, u32 parent_rate,
 
 
 
-/**
- * sun4i_get_mod0_factors() - calculates m, n factors for MOD0-style clocks
- * MOD0 rate is calculated as follows
- * rate = (parent_rate >> p) / (m + 1);
- */
-
-static void sun4i_get_mod0_factors(u32 *freq, u32 parent_rate,
-				   u8 *n, u8 *k, u8 *m, u8 *p)
-{
-	u8 div, calcm, calcp;
-
-	/* These clocks can only divide, so we will never be able to achieve
-	 * frequencies higher than the parent frequency */
-	if (*freq > parent_rate)
-		*freq = parent_rate;
-
-	div = DIV_ROUND_UP(parent_rate, *freq);
-
-	if (div < 16)
-		calcp = 0;
-	else if (div / 2 < 16)
-		calcp = 1;
-	else if (div / 4 < 16)
-		calcp = 2;
-	else
-		calcp = 3;
-
-	calcm = DIV_ROUND_UP(div, 1 << calcp);
-
-	*freq = (parent_rate >> calcp) / calcm;
-
-	/* we were called to round the frequency, we can now return */
-	if (n == NULL)
-		return;
-
-	*m = calcm - 1;
-	*p = calcp;
-}
-
-
 
 /**
  * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B
@@ -495,14 +455,6 @@ static struct clk_factors_config sun4i_apb1_config = {
 };
 
 /* user manual says "n" but it's really "p" */
-static struct clk_factors_config sun4i_mod0_config = {
-	.mshift = 0,
-	.mwidth = 4,
-	.pshift = 16,
-	.pwidth = 2,
-};
-
-/* user manual says "n" but it's really "p" */
 static struct clk_factors_config sun7i_a20_out_config = {
 	.mshift = 8,
 	.mwidth = 5,
@@ -559,13 +511,6 @@ static const struct factors_data sun4i_apb1_data __initconst = {
 	.getter = sun4i_get_apb1_factors,
 };
 
-static const struct factors_data sun4i_mod0_data __initconst = {
-	.enable = 31,
-	.mux = 24,
-	.table = &sun4i_mod0_config,
-	.getter = sun4i_get_mod0_factors,
-};
-
 static const struct factors_data sun7i_a20_out_data __initconst = {
 	.enable = 31,
 	.mux = 24,
@@ -1110,7 +1055,6 @@ static const struct of_device_id clk_factors_match[] __initconst = {
 	{.compatible = "allwinner,sun7i-a20-pll4-clk", .data = &sun7i_a20_pll4_data,},
 	{.compatible = "allwinner,sun6i-a31-pll6-clk", .data = &sun6i_a31_pll6_data,},
 	{.compatible = "allwinner,sun4i-a10-apb1-clk", .data = &sun4i_apb1_data,},
-	{.compatible = "allwinner,sun5i-a13-mbus-clk", .data = &sun4i_mod0_data,},
 	{.compatible = "allwinner,sun7i-a20-out-clk", .data = &sun7i_a20_out_data,},
 	{}
 };
@@ -1222,7 +1166,6 @@ static void __init sun4i_a10_init_clocks(struct device_node *node)
 CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks);
 
 static const char *sun5i_critical_clocks[] __initdata = {
-	"mbus",
 	"pll5_ddr",
 	"ahb_sdram",
 };
-- 
2.1.0

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

* [PATCH v3 09/12] ARM: sunxi: dt: Add sample and output mmc clocks
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18     ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez,
	chris-OsFVWbfNK3isTnJN9+BGXg, david.lanzendoerfer-Z7Kmv9EsliU,
	ulf.hansson-QSEj5FYQhm4dnm+yROfE0A
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA, wens-jdAy2FN1RRM,
	Maxime Ripard

Add the sample and output clocks for the MMC phase support.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 arch/arm/boot/dts/sun4i-a10.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
 arch/arm/boot/dts/sun5i-a10s.dtsi |  79 ++++++++++++++++++++++++++---
 arch/arm/boot/dts/sun5i-a13.dtsi  |  80 +++++++++++++++++++++++++----
 arch/arm/boot/dts/sun6i-a31.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
 arch/arm/boot/dts/sun7i-a20.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
 arch/arm/boot/dts/sun8i-a23.dtsi  |  78 +++++++++++++++++++++++++---
 6 files changed, 502 insertions(+), 47 deletions(-)

diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 380f914b226d..57ca74a149eb 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -227,6 +227,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk@01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -235,6 +251,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk@01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -243,6 +275,22 @@
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		mmc3_clk: clk@01c20094 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -251,6 +299,22 @@
 			clock-output-names = "mmc3";
 		};
 
+		mmc3_output_clk: mmc_output_clk@01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_output";
+		};
+
+		mmc3_sample_clk: mmc_sample_clk@01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_sample";
+		};
+
 		ts_clk: clk@01c20098 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -392,8 +456,14 @@
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <32>;
 			status = "disabled";
 		};
@@ -401,8 +471,14 @@
 		mmc1: mmc@01c10000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <33>;
 			status = "disabled";
 		};
@@ -410,8 +486,14 @@
 		mmc2: mmc@01c11000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <34>;
 			status = "disabled";
 		};
@@ -419,8 +501,14 @@
 		mmc3: mmc@01c12000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c12000 0x1000>;
-			clocks = <&ahb_gates 11>, <&mmc3_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 11>,
+				 <&mmc3_clk>,
+				 <&mmc3_sample_clk>,
+				 <&mmc3_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <35>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 531272c0e526..59c93287fd66 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -212,6 +212,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk@01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -220,6 +236,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk@01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -228,6 +260,22 @@
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		ts_clk: clk@01c20098 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -353,8 +401,14 @@
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <32>;
 			status = "disabled";
 		};
@@ -362,8 +416,14 @@
 		mmc1: mmc@01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <33>;
 			status = "disabled";
 		};
@@ -371,12 +431,17 @@
 		mmc2: mmc@01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <34>;
 			status = "disabled";
 		};
-
 		usbphy: phy@01c13400 {
 			#phy-cells = <1>;
 			compatible = "allwinner,sun5i-a13-usb-phy";
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index b131068f4f35..2c5cee912f33 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -202,30 +202,78 @@
 			clock-output-names = "ms";
 		};
 
-		mmc0_clk: clk@01c20088 {
+		mmc0_clk: clk_mmc@01c20088 {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20088 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mmc0";
 		};
 
-		mmc1_clk: clk@01c2008c {
+		mmc0_output_clk: mmc_output_clk@01c20088 {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
+		mmc1_clk: clk_mmc@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c2008c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mmc1";
 		};
 
-		mmc2_clk: clk@01c20090 {
+		mmc1_output_clk: mmc_output_clk@01c2008c {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
+		mmc2_clk: clk_mmc@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20090 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		ts_clk: clk@01c20098 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -335,8 +383,14 @@
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <32>;
 			status = "disabled";
 		};
@@ -344,8 +398,14 @@
 		mmc2: mmc@01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <34>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 543f895d18d3..436eb7429a7d 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -252,6 +252,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk@01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -260,6 +276,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk@01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -268,6 +300,22 @@
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		mmc3_clk: clk@01c20094 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -276,6 +324,22 @@
 			clock-output-names = "mmc3";
 		};
 
+		mmc3_output_clk: mmc_output_clk@01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_output";
+		};
+
+		mmc3_sample_clk: mmc_sample_clk@01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_sample";
+		};
+
 		spi0_clk: clk@01c200a0 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -366,8 +430,14 @@
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb1_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 8>;
 			reset-names = "ahb";
 			interrupts = <0 60 4>;
@@ -377,8 +447,14 @@
 		mmc1: mmc@01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb1_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 9>;
 			reset-names = "ahb";
 			interrupts = <0 61 4>;
@@ -388,8 +464,14 @@
 		mmc2: mmc@01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb1_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 10>;
 			reset-names = "ahb";
 			interrupts = <0 62 4>;
@@ -399,8 +481,14 @@
 		mmc3: mmc@01c12000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c12000 0x1000>;
-			clocks = <&ahb1_gates 11>, <&mmc3_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 11>,
+				 <&mmc3_clk>,
+				 <&mmc3_sample_clk>,
+				 <&mmc3_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 11>;
 			reset-names = "ahb";
 			interrupts = <0 63 4>;
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 82097c905c48..aa61f4887a5e 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -275,6 +275,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk@01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -283,6 +299,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk@01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -291,6 +323,22 @@
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		mmc3_clk: clk@01c20094 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -299,6 +347,22 @@
 			clock-output-names = "mmc3";
 		};
 
+		mmc3_output_clk: mmc_output_clk@01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_output";
+		};
+
+		mmc3_sample_clk: mmc_sample_clk@01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_sample";
+		};
+
 		ts_clk: clk@01c20098 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -512,8 +576,14 @@
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <0 32 4>;
 			status = "disabled";
 		};
@@ -521,8 +591,14 @@
 		mmc1: mmc@01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <0 33 4>;
 			status = "disabled";
 		};
@@ -530,8 +606,14 @@
 		mmc2: mmc@01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <0 34 4>;
 			status = "disabled";
 		};
@@ -539,8 +621,14 @@
 		mmc3: mmc@01c12000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c12000 0x1000>;
-			clocks = <&ahb_gates 11>, <&mmc3_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 11>,
+				 <&mmc3_clk>,
+				 <&mmc3_sample_clk>,
+				 <&mmc3_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <0 35 4>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi
index a35039224cb5..4379ae93b217 100644
--- a/arch/arm/boot/dts/sun8i-a23.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23.dtsi
@@ -224,6 +224,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk@01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk@01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -232,6 +248,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk@01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk@01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -239,6 +271,22 @@
 			clocks = <&osc24M>, <&pll6>;
 			clock-output-names = "mmc2";
 		};
+
+		mmc2_output_clk: mmc_output_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk@01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
 	};
 
 	soc@01c00000 {
@@ -250,8 +298,14 @@
 		mmc0: mmc@01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb1_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 8>;
 			reset-names = "ahb";
 			interrupts = <0 60 4>;
@@ -261,8 +315,14 @@
 		mmc1: mmc@01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb1_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 9>;
 			reset-names = "ahb";
 			interrupts = <0 61 4>;
@@ -272,8 +332,14 @@
 		mmc2: mmc@01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb1_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 10>;
 			reset-names = "ahb";
 			interrupts = <0 62 4>;
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v3 09/12] ARM: sunxi: dt: Add sample and output mmc clocks
@ 2014-09-11 20:18     ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Add the sample and output clocks for the MMC phase support.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 arch/arm/boot/dts/sun4i-a10.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
 arch/arm/boot/dts/sun5i-a10s.dtsi |  79 ++++++++++++++++++++++++++---
 arch/arm/boot/dts/sun5i-a13.dtsi  |  80 +++++++++++++++++++++++++----
 arch/arm/boot/dts/sun6i-a31.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
 arch/arm/boot/dts/sun7i-a20.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
 arch/arm/boot/dts/sun8i-a23.dtsi  |  78 +++++++++++++++++++++++++---
 6 files changed, 502 insertions(+), 47 deletions(-)

diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
index 380f914b226d..57ca74a149eb 100644
--- a/arch/arm/boot/dts/sun4i-a10.dtsi
+++ b/arch/arm/boot/dts/sun4i-a10.dtsi
@@ -227,6 +227,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk at 01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -235,6 +251,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk at 01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -243,6 +275,22 @@
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		mmc3_clk: clk at 01c20094 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -251,6 +299,22 @@
 			clock-output-names = "mmc3";
 		};
 
+		mmc3_output_clk: mmc_output_clk at 01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_output";
+		};
+
+		mmc3_sample_clk: mmc_sample_clk at 01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_sample";
+		};
+
 		ts_clk: clk at 01c20098 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -392,8 +456,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <32>;
 			status = "disabled";
 		};
@@ -401,8 +471,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <33>;
 			status = "disabled";
 		};
@@ -410,8 +486,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <34>;
 			status = "disabled";
 		};
@@ -419,8 +501,14 @@
 		mmc3: mmc at 01c12000 {
 			compatible = "allwinner,sun4i-a10-mmc";
 			reg = <0x01c12000 0x1000>;
-			clocks = <&ahb_gates 11>, <&mmc3_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 11>,
+				 <&mmc3_clk>,
+				 <&mmc3_sample_clk>,
+				 <&mmc3_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <35>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
index 531272c0e526..59c93287fd66 100644
--- a/arch/arm/boot/dts/sun5i-a10s.dtsi
+++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
@@ -212,6 +212,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk at 01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -220,6 +236,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk at 01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -228,6 +260,22 @@
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		ts_clk: clk at 01c20098 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -353,8 +401,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <32>;
 			status = "disabled";
 		};
@@ -362,8 +416,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <33>;
 			status = "disabled";
 		};
@@ -371,12 +431,17 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <34>;
 			status = "disabled";
 		};
-
 		usbphy: phy at 01c13400 {
 			#phy-cells = <1>;
 			compatible = "allwinner,sun5i-a13-usb-phy";
diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
index b131068f4f35..2c5cee912f33 100644
--- a/arch/arm/boot/dts/sun5i-a13.dtsi
+++ b/arch/arm/boot/dts/sun5i-a13.dtsi
@@ -202,30 +202,78 @@
 			clock-output-names = "ms";
 		};
 
-		mmc0_clk: clk at 01c20088 {
+		mmc0_clk: clk_mmc at 01c20088 {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20088 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mmc0";
 		};
 
-		mmc1_clk: clk at 01c2008c {
+		mmc0_output_clk: mmc_output_clk at 01c20088 {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
+		mmc1_clk: clk_mmc at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c2008c 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mmc1";
 		};
 
-		mmc2_clk: clk at 01c20090 {
+		mmc1_output_clk: mmc_output_clk at 01c2008c {
 			#clock-cells = <0>;
-			compatible = "allwinner,sun4i-a10-mod0-clk";
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
+		mmc2_clk: clk_mmc at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-clk";
 			reg = <0x01c20090 0x4>;
 			clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		ts_clk: clk at 01c20098 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -335,8 +383,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <32>;
 			status = "disabled";
 		};
@@ -344,8 +398,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <34>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
index 543f895d18d3..436eb7429a7d 100644
--- a/arch/arm/boot/dts/sun6i-a31.dtsi
+++ b/arch/arm/boot/dts/sun6i-a31.dtsi
@@ -252,6 +252,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk at 01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -260,6 +276,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk at 01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -268,6 +300,22 @@
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		mmc3_clk: clk at 01c20094 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -276,6 +324,22 @@
 			clock-output-names = "mmc3";
 		};
 
+		mmc3_output_clk: mmc_output_clk at 01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_output";
+		};
+
+		mmc3_sample_clk: mmc_sample_clk at 01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_sample";
+		};
+
 		spi0_clk: clk at 01c200a0 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -366,8 +430,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb1_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 8>;
 			reset-names = "ahb";
 			interrupts = <0 60 4>;
@@ -377,8 +447,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb1_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 9>;
 			reset-names = "ahb";
 			interrupts = <0 61 4>;
@@ -388,8 +464,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb1_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 10>;
 			reset-names = "ahb";
 			interrupts = <0 62 4>;
@@ -399,8 +481,14 @@
 		mmc3: mmc at 01c12000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c12000 0x1000>;
-			clocks = <&ahb1_gates 11>, <&mmc3_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 11>,
+				 <&mmc3_clk>,
+				 <&mmc3_sample_clk>,
+				 <&mmc3_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 11>;
 			reset-names = "ahb";
 			interrupts = <0 63 4>;
diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
index 82097c905c48..aa61f4887a5e 100644
--- a/arch/arm/boot/dts/sun7i-a20.dtsi
+++ b/arch/arm/boot/dts/sun7i-a20.dtsi
@@ -275,6 +275,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk at 01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -283,6 +299,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk at 01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -291,6 +323,22 @@
 			clock-output-names = "mmc2";
 		};
 
+		mmc2_output_clk: mmc_output_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
+
 		mmc3_clk: clk at 01c20094 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -299,6 +347,22 @@
 			clock-output-names = "mmc3";
 		};
 
+		mmc3_output_clk: mmc_output_clk at 01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_output";
+		};
+
+		mmc3_sample_clk: mmc_sample_clk at 01c20094 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20094 0x4>;
+			clocks = <&mmc3_clk>;
+			clock-output-names = "mmc3_sample";
+		};
+
 		ts_clk: clk at 01c20098 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -512,8 +576,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <0 32 4>;
 			status = "disabled";
 		};
@@ -521,8 +591,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <0 33 4>;
 			status = "disabled";
 		};
@@ -530,8 +606,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <0 34 4>;
 			status = "disabled";
 		};
@@ -539,8 +621,14 @@
 		mmc3: mmc at 01c12000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c12000 0x1000>;
-			clocks = <&ahb_gates 11>, <&mmc3_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb_gates 11>,
+				 <&mmc3_clk>,
+				 <&mmc3_sample_clk>,
+				 <&mmc3_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			interrupts = <0 35 4>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi
index a35039224cb5..4379ae93b217 100644
--- a/arch/arm/boot/dts/sun8i-a23.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23.dtsi
@@ -224,6 +224,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: mmc_output_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_output";
+		};
+
+		mmc0_sample_clk: mmc_sample_clk at 01c20088 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20088 0x4>;
+			clocks = <&mmc0_clk>;
+			clock-output-names = "mmc0_sample";
+		};
+
 		mmc1_clk: clk at 01c2008c {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -232,6 +248,22 @@
 			clock-output-names = "mmc1";
 		};
 
+		mmc1_output_clk: mmc_output_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_output";
+		};
+
+		mmc1_sample_clk: mmc_sample_clk at 01c2008c {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c2008c 0x4>;
+			clocks = <&mmc1_clk>;
+			clock-output-names = "mmc1_sample";
+		};
+
 		mmc2_clk: clk at 01c20090 {
 			#clock-cells = <0>;
 			compatible = "allwinner,sun4i-a10-mod0-clk";
@@ -239,6 +271,22 @@
 			clocks = <&osc24M>, <&pll6>;
 			clock-output-names = "mmc2";
 		};
+
+		mmc2_output_clk: mmc_output_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-output-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_output";
+		};
+
+		mmc2_sample_clk: mmc_sample_clk at 01c20090 {
+			#clock-cells = <0>;
+			compatible = "allwinner,sun4i-a10-mmc-sample-clk";
+			reg = <0x01c20090 0x4>;
+			clocks = <&mmc2_clk>;
+			clock-output-names = "mmc2_sample";
+		};
 	};
 
 	soc at 01c00000 {
@@ -250,8 +298,14 @@
 		mmc0: mmc at 01c0f000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c0f000 0x1000>;
-			clocks = <&ahb1_gates 8>, <&mmc0_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 8>,
+				 <&mmc0_clk>,
+				 <&mmc0_sample_clk>,
+				 <&mmc0_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 8>;
 			reset-names = "ahb";
 			interrupts = <0 60 4>;
@@ -261,8 +315,14 @@
 		mmc1: mmc at 01c10000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c10000 0x1000>;
-			clocks = <&ahb1_gates 9>, <&mmc1_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 9>,
+				 <&mmc1_clk>,
+				 <&mmc1_sample_clk>,
+				 <&mmc1_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 9>;
 			reset-names = "ahb";
 			interrupts = <0 61 4>;
@@ -272,8 +332,14 @@
 		mmc2: mmc at 01c11000 {
 			compatible = "allwinner,sun5i-a13-mmc";
 			reg = <0x01c11000 0x1000>;
-			clocks = <&ahb1_gates 10>, <&mmc2_clk>;
-			clock-names = "ahb", "mmc";
+			clocks = <&ahb1_gates 10>,
+				 <&mmc2_clk>,
+				 <&mmc2_sample_clk>,
+				 <&mmc2_output_clk>;
+			clock-names = "ahb",
+				      "mmc",
+				      "sample",
+				      "output";
 			resets = <&ahb1_rst 10>;
 			reset-names = "ahb";
 			interrupts = <0 62 4>;
-- 
2.1.0

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

* [PATCH v3 10/12] clk: sunxi: mod0: Introduce MMC proper phase handling
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

The MMC clock we thought we had until now are actually not one but three
different clocks.

The main one is unchanged, and will have three outputs:
  - The clock fed into the MMC
  - a sample and output clocks, to deal with when should we output/sample data
    to/from the MMC bus

The phase control we had are actually controlling the two latter clocks, but
the main MMC one is unchanged.

We can adjust the phase with a 3 bits value, from 0 to 7, 0 meaning a 180 phase
shift, and the other values being the number of periods from the MMC parent
clock to outphase the clock of.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/clock/sunxi.txt |   2 +
 drivers/clk/sunxi/clk-mod0.c                      | 189 ++++++++++++++++++++++
 2 files changed, 191 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index b938a990602a..eb690ed92a53 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -47,6 +47,8 @@ Required properties:
 	"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
 	"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
 	"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
+	"allwinner,sun4i-a10-mmc-output-clk" - for the MMC output clock on A10
+	"allwinner,sun4i-a10-mmc-sample-clk" - for the MMC sample clock on A10
 	"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
 	"allwinner,sun7i-a20-out-clk" - for the external output clocks
 	"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index 8a7f7036aea3..4a563850ee6e 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -16,6 +16,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/of_address.h>
 
 #include "clk-factors.h"
 
@@ -92,3 +93,191 @@ static void __init sun5i_a13_mbus_setup(struct device_node *node)
 	clk_prepare_enable(mbus);
 }
 CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
+
+struct mmc_phase_data {
+	u8	offset;
+};
+
+struct mmc_phase {
+	struct clk_hw		hw;
+	void __iomem		*reg;
+	struct mmc_phase_data	*data;
+	spinlock_t		*lock;
+};
+
+#define to_mmc_phase(_hw) container_of(_hw, struct mmc_phase, hw)
+
+static int mmc_get_phase(struct clk_hw *hw)
+{
+	struct clk *mmc, *mmc_parent, *clk = hw->clk;
+	struct mmc_phase *phase = to_mmc_phase(hw);
+	unsigned int mmc_rate, mmc_parent_rate;
+	u16 step, mmc_div;
+	u32 value;
+	u8 delay;
+
+	value = readl(phase->reg);
+	delay = (value >> phase->data->offset) & 0x3;
+
+	if (!delay)
+		return 180;
+
+	/* Get the main MMC clock */
+	mmc = clk_get_parent(clk);
+	if (!mmc)
+		return -EINVAL;
+
+	/* And its rate */
+	mmc_rate = clk_get_rate(mmc);
+	if (!mmc_rate)
+		return -EINVAL;
+
+	/* Now, get the MMC parent (most likely some PLL) */
+	mmc_parent = clk_get_parent(mmc);
+	if (!mmc_parent)
+		return -EINVAL;
+
+	/* And its rate */
+	mmc_parent_rate = clk_get_rate(mmc_parent);
+	if (!mmc_parent_rate)
+		return -EINVAL;
+
+	/* Get MMC clock divider */
+	mmc_div = mmc_parent_rate / mmc_rate;
+
+	step = DIV_ROUND_CLOSEST(360, mmc_div);
+	return delay * step;
+}
+
+static int mmc_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct clk *mmc, *mmc_parent, *clk = hw->clk;
+	struct mmc_phase *phase = to_mmc_phase(hw);
+	unsigned int mmc_rate, mmc_parent_rate;
+	unsigned long flags;
+	u32 value;
+	u8 delay;
+
+	/* Get the main MMC clock */
+	mmc = clk_get_parent(clk);
+	if (!mmc)
+		return -EINVAL;
+
+	/* And its rate */
+	mmc_rate = clk_get_rate(mmc);
+	if (!mmc_rate)
+		return -EINVAL;
+
+	/* Now, get the MMC parent (most likely some PLL) */
+	mmc_parent = clk_get_parent(mmc);
+	if (!mmc_parent)
+		return -EINVAL;
+
+	/* And its rate */
+	mmc_parent_rate = clk_get_rate(mmc_parent);
+	if (!mmc_parent_rate)
+		return -EINVAL;
+
+	if (degrees != 180) {
+		u16 step, mmc_div;
+
+		/* Get MMC clock divider */
+		mmc_div = mmc_parent_rate / mmc_rate;
+
+		/*
+		 * We can only outphase the clocks by multiple of the
+		 * PLL's period.
+		 *
+		 * Since the MMC clock in only a divider, and the
+		 * formula to get the outphasing in degrees is deg =
+		 * 360 * delta / period
+		 *
+		 * If we simplify this formula, we can see that the
+		 * only thing that we're concerned about is the number
+		 * of period we want to outphase our clock from, and
+		 * the divider set by the MMC clock.
+		 */
+		step = DIV_ROUND_CLOSEST(360, mmc_div);
+		delay = DIV_ROUND_CLOSEST(degrees, step);
+	} else {
+		delay = 0;
+	}
+
+	spin_lock_irqsave(phase->lock, flags);
+	value = readl(phase->reg);
+	value &= ~GENMASK(phase->data->offset + 3, phase->data->offset);
+	value |= delay << phase->data->offset;
+	writel(value, phase->reg);
+	spin_unlock_irqrestore(phase->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops mmc_clk_ops = {
+	.get_phase	= mmc_get_phase,
+	.set_phase	= mmc_set_phase,
+};
+
+static void __init sun4i_a10_mmc_phase_setup(struct device_node *node,
+					     struct mmc_phase_data *data)
+{
+	const char *parent_names[1] = { of_clk_get_parent_name(node, 0) };
+	struct clk_init_data init = {
+		.num_parents	= 1,
+		.parent_names	= parent_names,
+		.ops		= &mmc_clk_ops,
+	};
+
+	struct mmc_phase *phase;
+	struct clk *clk;
+
+	phase = kmalloc(sizeof(*phase), GFP_KERNEL);
+	if (!phase)
+		return;
+
+	phase->hw.init = &init;
+
+	phase->reg = of_iomap(node, 0);
+	if (!phase->reg)
+		goto err_free;
+
+	phase->data = data;
+	phase->lock = &sun4i_a10_mod0_lock;
+
+	if (of_property_read_string(node, "clock-output-names", &init.name))
+		init.name = node->name;
+
+	clk = clk_register(NULL, &phase->hw);
+	if (IS_ERR(clk))
+		goto err_unmap;
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+	return;
+
+err_unmap:
+	iounmap(phase->reg);
+err_free:
+	kfree(phase);
+}
+
+
+static struct mmc_phase_data mmc_output_clk = {
+	.offset	= 8,
+};
+
+static struct mmc_phase_data mmc_sample_clk = {
+	.offset	= 20,
+};
+
+static void __init sun4i_a10_mmc_output_setup(struct device_node *node)
+{
+	sun4i_a10_mmc_phase_setup(node, &mmc_output_clk);
+}
+CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup);
+
+static void __init sun4i_a10_mmc_sample_setup(struct device_node *node)
+{
+	sun4i_a10_mmc_phase_setup(node, &mmc_sample_clk);
+}
+CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup);
-- 
2.1.0


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

* [PATCH v3 10/12] clk: sunxi: mod0: Introduce MMC proper phase handling
@ 2014-09-11 20:18   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

The MMC clock we thought we had until now are actually not one but three
different clocks.

The main one is unchanged, and will have three outputs:
  - The clock fed into the MMC
  - a sample and output clocks, to deal with when should we output/sample data
    to/from the MMC bus

The phase control we had are actually controlling the two latter clocks, but
the main MMC one is unchanged.

We can adjust the phase with a 3 bits value, from 0 to 7, 0 meaning a 180 phase
shift, and the other values being the number of periods from the MMC parent
clock to outphase the clock of.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/clock/sunxi.txt |   2 +
 drivers/clk/sunxi/clk-mod0.c                      | 189 ++++++++++++++++++++++
 2 files changed, 191 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index b938a990602a..eb690ed92a53 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -47,6 +47,8 @@ Required properties:
 	"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
 	"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
 	"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
+	"allwinner,sun4i-a10-mmc-output-clk" - for the MMC output clock on A10
+	"allwinner,sun4i-a10-mmc-sample-clk" - for the MMC sample clock on A10
 	"allwinner,sun4i-a10-mod0-clk" - for the module 0 family of clocks
 	"allwinner,sun7i-a20-out-clk" - for the external output clocks
 	"allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c
index 8a7f7036aea3..4a563850ee6e 100644
--- a/drivers/clk/sunxi/clk-mod0.c
+++ b/drivers/clk/sunxi/clk-mod0.c
@@ -16,6 +16,7 @@
 
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
+#include <linux/of_address.h>
 
 #include "clk-factors.h"
 
@@ -92,3 +93,191 @@ static void __init sun5i_a13_mbus_setup(struct device_node *node)
 	clk_prepare_enable(mbus);
 }
 CLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup);
+
+struct mmc_phase_data {
+	u8	offset;
+};
+
+struct mmc_phase {
+	struct clk_hw		hw;
+	void __iomem		*reg;
+	struct mmc_phase_data	*data;
+	spinlock_t		*lock;
+};
+
+#define to_mmc_phase(_hw) container_of(_hw, struct mmc_phase, hw)
+
+static int mmc_get_phase(struct clk_hw *hw)
+{
+	struct clk *mmc, *mmc_parent, *clk = hw->clk;
+	struct mmc_phase *phase = to_mmc_phase(hw);
+	unsigned int mmc_rate, mmc_parent_rate;
+	u16 step, mmc_div;
+	u32 value;
+	u8 delay;
+
+	value = readl(phase->reg);
+	delay = (value >> phase->data->offset) & 0x3;
+
+	if (!delay)
+		return 180;
+
+	/* Get the main MMC clock */
+	mmc = clk_get_parent(clk);
+	if (!mmc)
+		return -EINVAL;
+
+	/* And its rate */
+	mmc_rate = clk_get_rate(mmc);
+	if (!mmc_rate)
+		return -EINVAL;
+
+	/* Now, get the MMC parent (most likely some PLL) */
+	mmc_parent = clk_get_parent(mmc);
+	if (!mmc_parent)
+		return -EINVAL;
+
+	/* And its rate */
+	mmc_parent_rate = clk_get_rate(mmc_parent);
+	if (!mmc_parent_rate)
+		return -EINVAL;
+
+	/* Get MMC clock divider */
+	mmc_div = mmc_parent_rate / mmc_rate;
+
+	step = DIV_ROUND_CLOSEST(360, mmc_div);
+	return delay * step;
+}
+
+static int mmc_set_phase(struct clk_hw *hw, int degrees)
+{
+	struct clk *mmc, *mmc_parent, *clk = hw->clk;
+	struct mmc_phase *phase = to_mmc_phase(hw);
+	unsigned int mmc_rate, mmc_parent_rate;
+	unsigned long flags;
+	u32 value;
+	u8 delay;
+
+	/* Get the main MMC clock */
+	mmc = clk_get_parent(clk);
+	if (!mmc)
+		return -EINVAL;
+
+	/* And its rate */
+	mmc_rate = clk_get_rate(mmc);
+	if (!mmc_rate)
+		return -EINVAL;
+
+	/* Now, get the MMC parent (most likely some PLL) */
+	mmc_parent = clk_get_parent(mmc);
+	if (!mmc_parent)
+		return -EINVAL;
+
+	/* And its rate */
+	mmc_parent_rate = clk_get_rate(mmc_parent);
+	if (!mmc_parent_rate)
+		return -EINVAL;
+
+	if (degrees != 180) {
+		u16 step, mmc_div;
+
+		/* Get MMC clock divider */
+		mmc_div = mmc_parent_rate / mmc_rate;
+
+		/*
+		 * We can only outphase the clocks by multiple of the
+		 * PLL's period.
+		 *
+		 * Since the MMC clock in only a divider, and the
+		 * formula to get the outphasing in degrees is deg =
+		 * 360 * delta / period
+		 *
+		 * If we simplify this formula, we can see that the
+		 * only thing that we're concerned about is the number
+		 * of period we want to outphase our clock from, and
+		 * the divider set by the MMC clock.
+		 */
+		step = DIV_ROUND_CLOSEST(360, mmc_div);
+		delay = DIV_ROUND_CLOSEST(degrees, step);
+	} else {
+		delay = 0;
+	}
+
+	spin_lock_irqsave(phase->lock, flags);
+	value = readl(phase->reg);
+	value &= ~GENMASK(phase->data->offset + 3, phase->data->offset);
+	value |= delay << phase->data->offset;
+	writel(value, phase->reg);
+	spin_unlock_irqrestore(phase->lock, flags);
+
+	return 0;
+}
+
+static const struct clk_ops mmc_clk_ops = {
+	.get_phase	= mmc_get_phase,
+	.set_phase	= mmc_set_phase,
+};
+
+static void __init sun4i_a10_mmc_phase_setup(struct device_node *node,
+					     struct mmc_phase_data *data)
+{
+	const char *parent_names[1] = { of_clk_get_parent_name(node, 0) };
+	struct clk_init_data init = {
+		.num_parents	= 1,
+		.parent_names	= parent_names,
+		.ops		= &mmc_clk_ops,
+	};
+
+	struct mmc_phase *phase;
+	struct clk *clk;
+
+	phase = kmalloc(sizeof(*phase), GFP_KERNEL);
+	if (!phase)
+		return;
+
+	phase->hw.init = &init;
+
+	phase->reg = of_iomap(node, 0);
+	if (!phase->reg)
+		goto err_free;
+
+	phase->data = data;
+	phase->lock = &sun4i_a10_mod0_lock;
+
+	if (of_property_read_string(node, "clock-output-names", &init.name))
+		init.name = node->name;
+
+	clk = clk_register(NULL, &phase->hw);
+	if (IS_ERR(clk))
+		goto err_unmap;
+
+	of_clk_add_provider(node, of_clk_src_simple_get, clk);
+
+	return;
+
+err_unmap:
+	iounmap(phase->reg);
+err_free:
+	kfree(phase);
+}
+
+
+static struct mmc_phase_data mmc_output_clk = {
+	.offset	= 8,
+};
+
+static struct mmc_phase_data mmc_sample_clk = {
+	.offset	= 20,
+};
+
+static void __init sun4i_a10_mmc_output_setup(struct device_node *node)
+{
+	sun4i_a10_mmc_phase_setup(node, &mmc_output_clk);
+}
+CLK_OF_DECLARE(sun4i_a10_mmc_output, "allwinner,sun4i-a10-mmc-output-clk", sun4i_a10_mmc_output_setup);
+
+static void __init sun4i_a10_mmc_sample_setup(struct device_node *node)
+{
+	sun4i_a10_mmc_phase_setup(node, &mmc_sample_clk);
+}
+CLK_OF_DECLARE(sun4i_a10_mmc_sample, "allwinner,sun4i-a10-mmc-sample-clk", sun4i_a10_mmc_sample_setup);
-- 
2.1.0

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

* [PATCH v3 11/12] mmc: sunxi: Convert MMC driver to the standard clock phase API
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

Now that we have proper support to use the generic phase API in our clock
driver, switch the MMC driver to use it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 .../devicetree/bindings/mmc/sunxi-mmc.txt          |  8 +--
 drivers/mmc/host/sunxi-mmc.c                       | 72 +++++++++++++++-------
 2 files changed, 53 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
index 91b3a3467150..4bf41d833804 100644
--- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
@@ -10,8 +10,8 @@ Absolute maximum transfer rate is 200MB/s
 Required properties:
  - compatible : "allwinner,sun4i-a10-mmc" or "allwinner,sun5i-a13-mmc"
  - reg : mmc controller base registers
- - clocks : a list with 2 phandle + clock specifier pairs
- - clock-names : must contain "ahb" and "mmc"
+ - clocks : a list with 4 phandle + clock specifier pairs
+ - clock-names : must contain "ahb", "mmc", "output" and "sample"
  - interrupts : mmc controller interrupt
 
 Optional properties:
@@ -25,8 +25,8 @@ Examples:
 	mmc0: mmc@01c0f000 {
 		compatible = "allwinner,sun5i-a13-mmc";
 		reg = <0x01c0f000 0x1000>;
-		clocks = <&ahb_gates 8>, <&mmc0_clk>;
-		clock-names = "ahb", "mod";
+		clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>;
+		clock-names = "ahb", "mod", "output", "sample";
 		interrupts = <0 32 4>;
 		status = "disabled";
 	};
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 024f67c98cdc..8719cefa590d 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -22,7 +22,6 @@
 
 #include <linux/clk.h>
 #include <linux/clk-private.h>
-#include <linux/clk/sunxi.h>
 
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
@@ -230,6 +229,8 @@ struct sunxi_mmc_host {
 	/* clock management */
 	struct clk	*clk_ahb;
 	struct clk	*clk_mmc;
+	struct clk	*clk_sample;
+	struct clk	*clk_output;
 
 	/* irq */
 	spinlock_t	lock;
@@ -617,7 +618,7 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
 static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
 				  struct mmc_ios *ios)
 {
-	u32 rate, oclk_dly, rval, sclk_dly, src_clk;
+	u32 rate, oclk_dly, rval, sclk_dly;
 	int ret;
 
 	rate = clk_round_rate(host->clk_mmc, ios->clock);
@@ -643,34 +644,31 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
 
 	/* determine delays */
 	if (rate <= 400000) {
-		oclk_dly = 0;
-		sclk_dly = 7;
+		oclk_dly = 180;
+		sclk_dly = 42;
 	} else if (rate <= 25000000) {
-		oclk_dly = 0;
-		sclk_dly = 5;
+		oclk_dly = 180;
+		sclk_dly = 75;
 	} else if (rate <= 50000000) {
 		if (ios->timing == MMC_TIMING_UHS_DDR50) {
-			oclk_dly = 2;
-			sclk_dly = 4;
+			oclk_dly = 60;
+			sclk_dly = 120;
 		} else {
-			oclk_dly = 3;
-			sclk_dly = 5;
+			oclk_dly = 90;
+			sclk_dly = 150;
 		}
+	} else if (rate <= 100000000) {
+		oclk_dly = 6;
+		sclk_dly = 24;
+	} else if (rate <= 200000000) {
+		oclk_dly = 3;
+		sclk_dly = 12;
 	} else {
-		/* rate > 50000000 */
-		oclk_dly = 2;
-		sclk_dly = 4;
+		return -EINVAL;
 	}
 
-	src_clk = clk_get_rate(clk_get_parent(host->clk_mmc));
-	if (src_clk >= 300000000 && src_clk <= 400000000) {
-		if (oclk_dly)
-			oclk_dly--;
-		if (sclk_dly)
-			sclk_dly--;
-	}
-
-	clk_sunxi_mmc_phase_control(host->clk_mmc, sclk_dly, oclk_dly);
+	clk_set_phase(host->clk_sample, sclk_dly);
+	clk_set_phase(host->clk_output, oclk_dly);
 
 	return sunxi_mmc_oclk_onoff(host, 1);
 }
@@ -909,6 +907,18 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
 		return PTR_ERR(host->clk_mmc);
 	}
 
+	host->clk_output = devm_clk_get(&pdev->dev, "output");
+	if (IS_ERR(host->clk_output)) {
+		dev_err(&pdev->dev, "Could not get output clock\n");
+		return PTR_ERR(host->clk_output);
+	}
+
+	host->clk_sample = devm_clk_get(&pdev->dev, "sample");
+	if (IS_ERR(host->clk_sample)) {
+		dev_err(&pdev->dev, "Could not get sample clock\n");
+		return PTR_ERR(host->clk_sample);
+	}
+
 	host->reset = devm_reset_control_get(&pdev->dev, "ahb");
 
 	ret = clk_prepare_enable(host->clk_ahb);
@@ -923,11 +933,23 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
 		goto error_disable_clk_ahb;
 	}
 
+	ret = clk_prepare_enable(host->clk_output);
+	if (ret) {
+		dev_err(&pdev->dev, "Enable output clk err %d\n", ret);
+		goto error_disable_clk_mmc;
+	}
+
+	ret = clk_prepare_enable(host->clk_sample);
+	if (ret) {
+		dev_err(&pdev->dev, "Enable sample clk err %d\n", ret);
+		goto error_disable_clk_output;
+	}
+
 	if (!IS_ERR(host->reset)) {
 		ret = reset_control_deassert(host->reset);
 		if (ret) {
 			dev_err(&pdev->dev, "reset err %d\n", ret);
-			goto error_disable_clk_mmc;
+			goto error_disable_clk_sample;
 		}
 	}
 
@@ -946,6 +968,10 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
 error_assert_reset:
 	if (!IS_ERR(host->reset))
 		reset_control_assert(host->reset);
+error_disable_clk_sample:
+	clk_disable_unprepare(host->clk_sample);
+error_disable_clk_output:
+	clk_disable_unprepare(host->clk_output);
 error_disable_clk_mmc:
 	clk_disable_unprepare(host->clk_mmc);
 error_disable_clk_ahb:
-- 
2.1.0


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

* [PATCH v3 11/12] mmc: sunxi: Convert MMC driver to the standard clock phase API
@ 2014-09-11 20:18   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we have proper support to use the generic phase API in our clock
driver, switch the MMC driver to use it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
---
 .../devicetree/bindings/mmc/sunxi-mmc.txt          |  8 +--
 drivers/mmc/host/sunxi-mmc.c                       | 72 +++++++++++++++-------
 2 files changed, 53 insertions(+), 27 deletions(-)

diff --git a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
index 91b3a3467150..4bf41d833804 100644
--- a/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/sunxi-mmc.txt
@@ -10,8 +10,8 @@ Absolute maximum transfer rate is 200MB/s
 Required properties:
  - compatible : "allwinner,sun4i-a10-mmc" or "allwinner,sun5i-a13-mmc"
  - reg : mmc controller base registers
- - clocks : a list with 2 phandle + clock specifier pairs
- - clock-names : must contain "ahb" and "mmc"
+ - clocks : a list with 4 phandle + clock specifier pairs
+ - clock-names : must contain "ahb", "mmc", "output" and "sample"
  - interrupts : mmc controller interrupt
 
 Optional properties:
@@ -25,8 +25,8 @@ Examples:
 	mmc0: mmc at 01c0f000 {
 		compatible = "allwinner,sun5i-a13-mmc";
 		reg = <0x01c0f000 0x1000>;
-		clocks = <&ahb_gates 8>, <&mmc0_clk>;
-		clock-names = "ahb", "mod";
+		clocks = <&ahb_gates 8>, <&mmc0_clk>, <&mmc0_output_clk>, <&mmc0_sample_clk>;
+		clock-names = "ahb", "mod", "output", "sample";
 		interrupts = <0 32 4>;
 		status = "disabled";
 	};
diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c
index 024f67c98cdc..8719cefa590d 100644
--- a/drivers/mmc/host/sunxi-mmc.c
+++ b/drivers/mmc/host/sunxi-mmc.c
@@ -22,7 +22,6 @@
 
 #include <linux/clk.h>
 #include <linux/clk-private.h>
-#include <linux/clk/sunxi.h>
 
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
@@ -230,6 +229,8 @@ struct sunxi_mmc_host {
 	/* clock management */
 	struct clk	*clk_ahb;
 	struct clk	*clk_mmc;
+	struct clk	*clk_sample;
+	struct clk	*clk_output;
 
 	/* irq */
 	spinlock_t	lock;
@@ -617,7 +618,7 @@ static int sunxi_mmc_oclk_onoff(struct sunxi_mmc_host *host, u32 oclk_en)
 static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
 				  struct mmc_ios *ios)
 {
-	u32 rate, oclk_dly, rval, sclk_dly, src_clk;
+	u32 rate, oclk_dly, rval, sclk_dly;
 	int ret;
 
 	rate = clk_round_rate(host->clk_mmc, ios->clock);
@@ -643,34 +644,31 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host,
 
 	/* determine delays */
 	if (rate <= 400000) {
-		oclk_dly = 0;
-		sclk_dly = 7;
+		oclk_dly = 180;
+		sclk_dly = 42;
 	} else if (rate <= 25000000) {
-		oclk_dly = 0;
-		sclk_dly = 5;
+		oclk_dly = 180;
+		sclk_dly = 75;
 	} else if (rate <= 50000000) {
 		if (ios->timing == MMC_TIMING_UHS_DDR50) {
-			oclk_dly = 2;
-			sclk_dly = 4;
+			oclk_dly = 60;
+			sclk_dly = 120;
 		} else {
-			oclk_dly = 3;
-			sclk_dly = 5;
+			oclk_dly = 90;
+			sclk_dly = 150;
 		}
+	} else if (rate <= 100000000) {
+		oclk_dly = 6;
+		sclk_dly = 24;
+	} else if (rate <= 200000000) {
+		oclk_dly = 3;
+		sclk_dly = 12;
 	} else {
-		/* rate > 50000000 */
-		oclk_dly = 2;
-		sclk_dly = 4;
+		return -EINVAL;
 	}
 
-	src_clk = clk_get_rate(clk_get_parent(host->clk_mmc));
-	if (src_clk >= 300000000 && src_clk <= 400000000) {
-		if (oclk_dly)
-			oclk_dly--;
-		if (sclk_dly)
-			sclk_dly--;
-	}
-
-	clk_sunxi_mmc_phase_control(host->clk_mmc, sclk_dly, oclk_dly);
+	clk_set_phase(host->clk_sample, sclk_dly);
+	clk_set_phase(host->clk_output, oclk_dly);
 
 	return sunxi_mmc_oclk_onoff(host, 1);
 }
@@ -909,6 +907,18 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
 		return PTR_ERR(host->clk_mmc);
 	}
 
+	host->clk_output = devm_clk_get(&pdev->dev, "output");
+	if (IS_ERR(host->clk_output)) {
+		dev_err(&pdev->dev, "Could not get output clock\n");
+		return PTR_ERR(host->clk_output);
+	}
+
+	host->clk_sample = devm_clk_get(&pdev->dev, "sample");
+	if (IS_ERR(host->clk_sample)) {
+		dev_err(&pdev->dev, "Could not get sample clock\n");
+		return PTR_ERR(host->clk_sample);
+	}
+
 	host->reset = devm_reset_control_get(&pdev->dev, "ahb");
 
 	ret = clk_prepare_enable(host->clk_ahb);
@@ -923,11 +933,23 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
 		goto error_disable_clk_ahb;
 	}
 
+	ret = clk_prepare_enable(host->clk_output);
+	if (ret) {
+		dev_err(&pdev->dev, "Enable output clk err %d\n", ret);
+		goto error_disable_clk_mmc;
+	}
+
+	ret = clk_prepare_enable(host->clk_sample);
+	if (ret) {
+		dev_err(&pdev->dev, "Enable sample clk err %d\n", ret);
+		goto error_disable_clk_output;
+	}
+
 	if (!IS_ERR(host->reset)) {
 		ret = reset_control_deassert(host->reset);
 		if (ret) {
 			dev_err(&pdev->dev, "reset err %d\n", ret);
-			goto error_disable_clk_mmc;
+			goto error_disable_clk_sample;
 		}
 	}
 
@@ -946,6 +968,10 @@ static int sunxi_mmc_resource_request(struct sunxi_mmc_host *host,
 error_assert_reset:
 	if (!IS_ERR(host->reset))
 		reset_control_assert(host->reset);
+error_disable_clk_sample:
+	clk_disable_unprepare(host->clk_sample);
+error_disable_clk_output:
+	clk_disable_unprepare(host->clk_output);
 error_disable_clk_mmc:
 	clk_disable_unprepare(host->clk_mmc);
 error_disable_clk_ahb:
-- 
2.1.0

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

* [PATCH v3 12/12] clk: sunxi: Remove custom phase function
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-11 20:18   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: Mike Turquette, Hans de Goede, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

Now that we don't have any user left for our custom phase function, we can
safely remove this hack from the code.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi/clk-sunxi.c | 37 -------------------------------------
 include/linux/clk/sunxi.h     | 22 ----------------------
 2 files changed, 59 deletions(-)
 delete mode 100644 include/linux/clk/sunxi.h

diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 4e189be3e23f..e46f3f2748d3 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -361,43 +361,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
 }
 
 /**
- * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
- */
-
-void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output)
-{
-	#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
-	#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
-
-	struct clk_hw *hw = __clk_get_hw(clk);
-	struct clk_composite *composite = to_clk_composite(hw);
-	struct clk_hw *rate_hw = composite->rate_hw;
-	struct clk_factors *factors = to_clk_factors(rate_hw);
-	unsigned long flags = 0;
-	u32 reg;
-
-	if (factors->lock)
-		spin_lock_irqsave(factors->lock, flags);
-
-	reg = readl(factors->reg);
-
-	/* set sample clock phase control */
-	reg &= ~(0x7 << 20);
-	reg |= ((sample & 0x7) << 20);
-
-	/* set output clock phase control */
-	reg &= ~(0x7 << 8);
-	reg |= ((output & 0x7) << 8);
-
-	writel(reg, factors->reg);
-
-	if (factors->lock)
-		spin_unlock_irqrestore(factors->lock, flags);
-}
-EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
-
-
-/**
  * sunxi_factors_clk_setup() - Setup function for factor clocks
  */
 
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
deleted file mode 100644
index aed28c4451d9..000000000000
--- a/include/linux/clk/sunxi.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2013 - Hans de Goede <hdegoede@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __LINUX_CLK_SUNXI_H_
-#define __LINUX_CLK_SUNXI_H_
-
-#include <linux/clk.h>
-
-void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output);
-
-#endif
-- 
2.1.0


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

* [PATCH v3 12/12] clk: sunxi: Remove custom phase function
@ 2014-09-11 20:18   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-11 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we don't have any user left for our custom phase function, we can
safely remove this hack from the code.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/clk/sunxi/clk-sunxi.c | 37 -------------------------------------
 include/linux/clk/sunxi.h     | 22 ----------------------
 2 files changed, 59 deletions(-)
 delete mode 100644 include/linux/clk/sunxi.h

diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
index 4e189be3e23f..e46f3f2748d3 100644
--- a/drivers/clk/sunxi/clk-sunxi.c
+++ b/drivers/clk/sunxi/clk-sunxi.c
@@ -361,43 +361,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
 }
 
 /**
- * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
- */
-
-void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output)
-{
-	#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
-	#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
-
-	struct clk_hw *hw = __clk_get_hw(clk);
-	struct clk_composite *composite = to_clk_composite(hw);
-	struct clk_hw *rate_hw = composite->rate_hw;
-	struct clk_factors *factors = to_clk_factors(rate_hw);
-	unsigned long flags = 0;
-	u32 reg;
-
-	if (factors->lock)
-		spin_lock_irqsave(factors->lock, flags);
-
-	reg = readl(factors->reg);
-
-	/* set sample clock phase control */
-	reg &= ~(0x7 << 20);
-	reg |= ((sample & 0x7) << 20);
-
-	/* set output clock phase control */
-	reg &= ~(0x7 << 8);
-	reg |= ((output & 0x7) << 8);
-
-	writel(reg, factors->reg);
-
-	if (factors->lock)
-		spin_unlock_irqrestore(factors->lock, flags);
-}
-EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
-
-
-/**
  * sunxi_factors_clk_setup() - Setup function for factor clocks
  */
 
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
deleted file mode 100644
index aed28c4451d9..000000000000
--- a/include/linux/clk/sunxi.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2013 - Hans de Goede <hdegoede@redhat.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __LINUX_CLK_SUNXI_H_
-#define __LINUX_CLK_SUNXI_H_
-
-#include <linux/clk.h>
-
-void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output);
-
-#endif
-- 
2.1.0

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

* Re: [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-12  7:22   ` Hans de Goede
  -1 siblings, 0 replies; 58+ messages in thread
From: Hans de Goede @ 2014-09-12  7:22 UTC (permalink / raw)
  To: Maxime Ripard, Mike Turquette, Emilio Lopez, chris,
	david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens

Hi,

On 09/11/2014 10:18 PM, Maxime Ripard wrote:
> Hi everyone,
> 
> Here is an attempt at improving the MMC clock support in the Allwinner
> SoCs.
> 
> Until now, the MMC clocks were having a custom phase function that was
> directly setting an obscure value in the right register, because we
> were not really having any idea of what these values were.
> 
> Now that we have more informations, we can introduce a common function
> call to get and set the phase of a particular clock, and use this in
> both our provider and our client.
> 
> Thanks,
> Maxime

I've not done a full review this time around (-ENOTIME), but I've taken
a look at the changed bits, and those look good to me.

Regards,

Hans

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

* [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
@ 2014-09-12  7:22   ` Hans de Goede
  0 siblings, 0 replies; 58+ messages in thread
From: Hans de Goede @ 2014-09-12  7:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 09/11/2014 10:18 PM, Maxime Ripard wrote:
> Hi everyone,
> 
> Here is an attempt at improving the MMC clock support in the Allwinner
> SoCs.
> 
> Until now, the MMC clocks were having a custom phase function that was
> directly setting an obscure value in the right register, because we
> were not really having any idea of what these values were.
> 
> Now that we have more informations, we can introduce a common function
> call to get and set the phase of a particular clock, and use this in
> both our provider and our client.
> 
> Thanks,
> Maxime

I've not done a full review this time around (-ENOTIME), but I've taken
a look at the changed bits, and those look good to me.

Regards,

Hans

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

* Re: [PATCH v3 09/12] ARM: sunxi: dt: Add sample and output mmc clocks
  2014-09-11 20:18     ` Maxime Ripard
@ 2014-09-12 10:23       ` Chen-Yu Tsai
  -1 siblings, 0 replies; 58+ messages in thread
From: Chen-Yu Tsai @ 2014-09-12 10:23 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mike Turquette, Hans de Goede, Emilio Lopez, Chris Ball,
	David Lanzendörfer, Ulf Hansson, devicetree,
	linux-arm-kernel, linux-mmc

On Fri, Sep 12, 2014 at 4:18 AM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Add the sample and output clocks for the MMC phase support.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  arch/arm/boot/dts/sun4i-a10.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
>  arch/arm/boot/dts/sun5i-a10s.dtsi |  79 ++++++++++++++++++++++++++---
>  arch/arm/boot/dts/sun5i-a13.dtsi  |  80 +++++++++++++++++++++++++----
>  arch/arm/boot/dts/sun6i-a31.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
>  arch/arm/boot/dts/sun7i-a20.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
>  arch/arm/boot/dts/sun8i-a23.dtsi  |  78 +++++++++++++++++++++++++---

Tested on my a23 tablet, looks good.

>  6 files changed, 502 insertions(+), 47 deletions(-)
>
> diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
> index 380f914b226d..57ca74a149eb 100644
> --- a/arch/arm/boot/dts/sun4i-a10.dtsi
> +++ b/arch/arm/boot/dts/sun4i-a10.dtsi
> @@ -227,6 +227,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk@01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -235,6 +251,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk@01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -243,6 +275,22 @@
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 mmc3_clk: clk@01c20094 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -251,6 +299,22 @@
>                         clock-output-names = "mmc3";
>                 };
>
> +               mmc3_output_clk: mmc_output_clk@01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_output";
> +               };
> +
> +               mmc3_sample_clk: mmc_sample_clk@01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_sample";
> +               };
> +
>                 ts_clk: clk@01c20098 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -392,8 +456,14 @@
>                 mmc0: mmc@01c0f000 {
>                         compatible = "allwinner,sun4i-a10-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";

Just a stylish nitpick. All the other resources in these files
are listed inline if possible, not one phandle/value per line.

But otherwise, it looks good.

ChenYu

>                         interrupts = <32>;
>                         status = "disabled";
>                 };
> @@ -401,8 +471,14 @@
>                 mmc1: mmc@01c10000 {
>                         compatible = "allwinner,sun4i-a10-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <33>;
>                         status = "disabled";
>                 };
> @@ -410,8 +486,14 @@
>                 mmc2: mmc@01c11000 {
>                         compatible = "allwinner,sun4i-a10-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <34>;
>                         status = "disabled";
>                 };
> @@ -419,8 +501,14 @@
>                 mmc3: mmc@01c12000 {
>                         compatible = "allwinner,sun4i-a10-mmc";
>                         reg = <0x01c12000 0x1000>;
> -                       clocks = <&ahb_gates 11>, <&mmc3_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 11>,
> +                                <&mmc3_clk>,
> +                                <&mmc3_sample_clk>,
> +                                <&mmc3_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <35>;
>                         status = "disabled";
>                 };
> diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
> index 531272c0e526..59c93287fd66 100644
> --- a/arch/arm/boot/dts/sun5i-a10s.dtsi
> +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
> @@ -212,6 +212,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk@01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -220,6 +236,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk@01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -228,6 +260,22 @@
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 ts_clk: clk@01c20098 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -353,8 +401,14 @@
>                 mmc0: mmc@01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <32>;
>                         status = "disabled";
>                 };
> @@ -362,8 +416,14 @@
>                 mmc1: mmc@01c10000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <33>;
>                         status = "disabled";
>                 };
> @@ -371,12 +431,17 @@
>                 mmc2: mmc@01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <34>;
>                         status = "disabled";
>                 };
> -
>                 usbphy: phy@01c13400 {
>                         #phy-cells = <1>;
>                         compatible = "allwinner,sun5i-a13-usb-phy";
> diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
> index b131068f4f35..2c5cee912f33 100644
> --- a/arch/arm/boot/dts/sun5i-a13.dtsi
> +++ b/arch/arm/boot/dts/sun5i-a13.dtsi
> @@ -202,30 +202,78 @@
>                         clock-output-names = "ms";
>                 };
>
> -               mmc0_clk: clk@01c20088 {
> +               mmc0_clk: clk_mmc@01c20088 {
>                         #clock-cells = <0>;
> -                       compatible = "allwinner,sun4i-a10-mod0-clk";
> +                       compatible = "allwinner,sun4i-a10-mmc-clk";
>                         reg = <0x01c20088 0x4>;
>                         clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
>                         clock-output-names = "mmc0";
>                 };
>
> -               mmc1_clk: clk@01c2008c {
> +               mmc0_output_clk: mmc_output_clk@01c20088 {
>                         #clock-cells = <0>;
> -                       compatible = "allwinner,sun4i-a10-mod0-clk";
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
> +               mmc1_clk: clk_mmc@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-clk";
>                         reg = <0x01c2008c 0x4>;
>                         clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
>                         clock-output-names = "mmc1";
>                 };
>
> -               mmc2_clk: clk@01c20090 {
> +               mmc1_output_clk: mmc_output_clk@01c2008c {
>                         #clock-cells = <0>;
> -                       compatible = "allwinner,sun4i-a10-mod0-clk";
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
> +               mmc2_clk: clk_mmc@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-clk";
>                         reg = <0x01c20090 0x4>;
>                         clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 ts_clk: clk@01c20098 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -335,8 +383,14 @@
>                 mmc0: mmc@01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <32>;
>                         status = "disabled";
>                 };
> @@ -344,8 +398,14 @@
>                 mmc2: mmc@01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <34>;
>                         status = "disabled";
>                 };
> diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
> index 543f895d18d3..436eb7429a7d 100644
> --- a/arch/arm/boot/dts/sun6i-a31.dtsi
> +++ b/arch/arm/boot/dts/sun6i-a31.dtsi
> @@ -252,6 +252,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk@01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -260,6 +276,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk@01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -268,6 +300,22 @@
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 mmc3_clk: clk@01c20094 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -276,6 +324,22 @@
>                         clock-output-names = "mmc3";
>                 };
>
> +               mmc3_output_clk: mmc_output_clk@01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_output";
> +               };
> +
> +               mmc3_sample_clk: mmc_sample_clk@01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_sample";
> +               };
> +
>                 spi0_clk: clk@01c200a0 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -366,8 +430,14 @@
>                 mmc0: mmc@01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb1_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 8>;
>                         reset-names = "ahb";
>                         interrupts = <0 60 4>;
> @@ -377,8 +447,14 @@
>                 mmc1: mmc@01c10000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb1_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 9>;
>                         reset-names = "ahb";
>                         interrupts = <0 61 4>;
> @@ -388,8 +464,14 @@
>                 mmc2: mmc@01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb1_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 10>;
>                         reset-names = "ahb";
>                         interrupts = <0 62 4>;
> @@ -399,8 +481,14 @@
>                 mmc3: mmc@01c12000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c12000 0x1000>;
> -                       clocks = <&ahb1_gates 11>, <&mmc3_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 11>,
> +                                <&mmc3_clk>,
> +                                <&mmc3_sample_clk>,
> +                                <&mmc3_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 11>;
>                         reset-names = "ahb";
>                         interrupts = <0 63 4>;
> diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
> index 82097c905c48..aa61f4887a5e 100644
> --- a/arch/arm/boot/dts/sun7i-a20.dtsi
> +++ b/arch/arm/boot/dts/sun7i-a20.dtsi
> @@ -275,6 +275,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk@01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -283,6 +299,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk@01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -291,6 +323,22 @@
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 mmc3_clk: clk@01c20094 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -299,6 +347,22 @@
>                         clock-output-names = "mmc3";
>                 };
>
> +               mmc3_output_clk: mmc_output_clk@01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_output";
> +               };
> +
> +               mmc3_sample_clk: mmc_sample_clk@01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_sample";
> +               };
> +
>                 ts_clk: clk@01c20098 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -512,8 +576,14 @@
>                 mmc0: mmc@01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <0 32 4>;
>                         status = "disabled";
>                 };
> @@ -521,8 +591,14 @@
>                 mmc1: mmc@01c10000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <0 33 4>;
>                         status = "disabled";
>                 };
> @@ -530,8 +606,14 @@
>                 mmc2: mmc@01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <0 34 4>;
>                         status = "disabled";
>                 };
> @@ -539,8 +621,14 @@
>                 mmc3: mmc@01c12000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c12000 0x1000>;
> -                       clocks = <&ahb_gates 11>, <&mmc3_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 11>,
> +                                <&mmc3_clk>,
> +                                <&mmc3_sample_clk>,
> +                                <&mmc3_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <0 35 4>;
>                         status = "disabled";
>                 };
> diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi
> index a35039224cb5..4379ae93b217 100644
> --- a/arch/arm/boot/dts/sun8i-a23.dtsi
> +++ b/arch/arm/boot/dts/sun8i-a23.dtsi
> @@ -224,6 +224,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk@01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk@01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -232,6 +248,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk@01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk@01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -239,6 +271,22 @@
>                         clocks = <&osc24M>, <&pll6>;
>                         clock-output-names = "mmc2";
>                 };
> +
> +               mmc2_output_clk: mmc_output_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk@01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
>         };
>
>         soc@01c00000 {
> @@ -250,8 +298,14 @@
>                 mmc0: mmc@01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb1_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 8>;
>                         reset-names = "ahb";
>                         interrupts = <0 60 4>;
> @@ -261,8 +315,14 @@
>                 mmc1: mmc@01c10000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb1_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 9>;
>                         reset-names = "ahb";
>                         interrupts = <0 61 4>;
> @@ -272,8 +332,14 @@
>                 mmc2: mmc@01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb1_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 10>;
>                         reset-names = "ahb";
>                         interrupts = <0 62 4>;
> --
> 2.1.0
>

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

* [PATCH v3 09/12] ARM: sunxi: dt: Add sample and output mmc clocks
@ 2014-09-12 10:23       ` Chen-Yu Tsai
  0 siblings, 0 replies; 58+ messages in thread
From: Chen-Yu Tsai @ 2014-09-12 10:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 12, 2014 at 4:18 AM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Add the sample and output clocks for the MMC phase support.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  arch/arm/boot/dts/sun4i-a10.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
>  arch/arm/boot/dts/sun5i-a10s.dtsi |  79 ++++++++++++++++++++++++++---
>  arch/arm/boot/dts/sun5i-a13.dtsi  |  80 +++++++++++++++++++++++++----
>  arch/arm/boot/dts/sun6i-a31.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
>  arch/arm/boot/dts/sun7i-a20.dtsi  | 104 +++++++++++++++++++++++++++++++++++---
>  arch/arm/boot/dts/sun8i-a23.dtsi  |  78 +++++++++++++++++++++++++---

Tested on my a23 tablet, looks good.

>  6 files changed, 502 insertions(+), 47 deletions(-)
>
> diff --git a/arch/arm/boot/dts/sun4i-a10.dtsi b/arch/arm/boot/dts/sun4i-a10.dtsi
> index 380f914b226d..57ca74a149eb 100644
> --- a/arch/arm/boot/dts/sun4i-a10.dtsi
> +++ b/arch/arm/boot/dts/sun4i-a10.dtsi
> @@ -227,6 +227,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk at 01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -235,6 +251,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk at 01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -243,6 +275,22 @@
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 mmc3_clk: clk at 01c20094 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -251,6 +299,22 @@
>                         clock-output-names = "mmc3";
>                 };
>
> +               mmc3_output_clk: mmc_output_clk at 01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_output";
> +               };
> +
> +               mmc3_sample_clk: mmc_sample_clk at 01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_sample";
> +               };
> +
>                 ts_clk: clk at 01c20098 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -392,8 +456,14 @@
>                 mmc0: mmc at 01c0f000 {
>                         compatible = "allwinner,sun4i-a10-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";

Just a stylish nitpick. All the other resources in these files
are listed inline if possible, not one phandle/value per line.

But otherwise, it looks good.

ChenYu

>                         interrupts = <32>;
>                         status = "disabled";
>                 };
> @@ -401,8 +471,14 @@
>                 mmc1: mmc at 01c10000 {
>                         compatible = "allwinner,sun4i-a10-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <33>;
>                         status = "disabled";
>                 };
> @@ -410,8 +486,14 @@
>                 mmc2: mmc at 01c11000 {
>                         compatible = "allwinner,sun4i-a10-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <34>;
>                         status = "disabled";
>                 };
> @@ -419,8 +501,14 @@
>                 mmc3: mmc at 01c12000 {
>                         compatible = "allwinner,sun4i-a10-mmc";
>                         reg = <0x01c12000 0x1000>;
> -                       clocks = <&ahb_gates 11>, <&mmc3_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 11>,
> +                                <&mmc3_clk>,
> +                                <&mmc3_sample_clk>,
> +                                <&mmc3_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <35>;
>                         status = "disabled";
>                 };
> diff --git a/arch/arm/boot/dts/sun5i-a10s.dtsi b/arch/arm/boot/dts/sun5i-a10s.dtsi
> index 531272c0e526..59c93287fd66 100644
> --- a/arch/arm/boot/dts/sun5i-a10s.dtsi
> +++ b/arch/arm/boot/dts/sun5i-a10s.dtsi
> @@ -212,6 +212,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk at 01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -220,6 +236,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk at 01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -228,6 +260,22 @@
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 ts_clk: clk at 01c20098 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -353,8 +401,14 @@
>                 mmc0: mmc at 01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <32>;
>                         status = "disabled";
>                 };
> @@ -362,8 +416,14 @@
>                 mmc1: mmc at 01c10000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <33>;
>                         status = "disabled";
>                 };
> @@ -371,12 +431,17 @@
>                 mmc2: mmc at 01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <34>;
>                         status = "disabled";
>                 };
> -
>                 usbphy: phy at 01c13400 {
>                         #phy-cells = <1>;
>                         compatible = "allwinner,sun5i-a13-usb-phy";
> diff --git a/arch/arm/boot/dts/sun5i-a13.dtsi b/arch/arm/boot/dts/sun5i-a13.dtsi
> index b131068f4f35..2c5cee912f33 100644
> --- a/arch/arm/boot/dts/sun5i-a13.dtsi
> +++ b/arch/arm/boot/dts/sun5i-a13.dtsi
> @@ -202,30 +202,78 @@
>                         clock-output-names = "ms";
>                 };
>
> -               mmc0_clk: clk at 01c20088 {
> +               mmc0_clk: clk_mmc at 01c20088 {
>                         #clock-cells = <0>;
> -                       compatible = "allwinner,sun4i-a10-mod0-clk";
> +                       compatible = "allwinner,sun4i-a10-mmc-clk";
>                         reg = <0x01c20088 0x4>;
>                         clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
>                         clock-output-names = "mmc0";
>                 };
>
> -               mmc1_clk: clk at 01c2008c {
> +               mmc0_output_clk: mmc_output_clk at 01c20088 {
>                         #clock-cells = <0>;
> -                       compatible = "allwinner,sun4i-a10-mod0-clk";
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
> +               mmc1_clk: clk_mmc at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-clk";
>                         reg = <0x01c2008c 0x4>;
>                         clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
>                         clock-output-names = "mmc1";
>                 };
>
> -               mmc2_clk: clk at 01c20090 {
> +               mmc1_output_clk: mmc_output_clk at 01c2008c {
>                         #clock-cells = <0>;
> -                       compatible = "allwinner,sun4i-a10-mod0-clk";
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
> +               mmc2_clk: clk_mmc at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-clk";
>                         reg = <0x01c20090 0x4>;
>                         clocks = <&osc24M>, <&pll6 1>, <&pll5 1>;
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 ts_clk: clk at 01c20098 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -335,8 +383,14 @@
>                 mmc0: mmc at 01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <32>;
>                         status = "disabled";
>                 };
> @@ -344,8 +398,14 @@
>                 mmc2: mmc at 01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <34>;
>                         status = "disabled";
>                 };
> diff --git a/arch/arm/boot/dts/sun6i-a31.dtsi b/arch/arm/boot/dts/sun6i-a31.dtsi
> index 543f895d18d3..436eb7429a7d 100644
> --- a/arch/arm/boot/dts/sun6i-a31.dtsi
> +++ b/arch/arm/boot/dts/sun6i-a31.dtsi
> @@ -252,6 +252,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk at 01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -260,6 +276,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk at 01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -268,6 +300,22 @@
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 mmc3_clk: clk at 01c20094 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -276,6 +324,22 @@
>                         clock-output-names = "mmc3";
>                 };
>
> +               mmc3_output_clk: mmc_output_clk at 01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_output";
> +               };
> +
> +               mmc3_sample_clk: mmc_sample_clk at 01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_sample";
> +               };
> +
>                 spi0_clk: clk at 01c200a0 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -366,8 +430,14 @@
>                 mmc0: mmc at 01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb1_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 8>;
>                         reset-names = "ahb";
>                         interrupts = <0 60 4>;
> @@ -377,8 +447,14 @@
>                 mmc1: mmc at 01c10000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb1_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 9>;
>                         reset-names = "ahb";
>                         interrupts = <0 61 4>;
> @@ -388,8 +464,14 @@
>                 mmc2: mmc at 01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb1_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 10>;
>                         reset-names = "ahb";
>                         interrupts = <0 62 4>;
> @@ -399,8 +481,14 @@
>                 mmc3: mmc at 01c12000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c12000 0x1000>;
> -                       clocks = <&ahb1_gates 11>, <&mmc3_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 11>,
> +                                <&mmc3_clk>,
> +                                <&mmc3_sample_clk>,
> +                                <&mmc3_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 11>;
>                         reset-names = "ahb";
>                         interrupts = <0 63 4>;
> diff --git a/arch/arm/boot/dts/sun7i-a20.dtsi b/arch/arm/boot/dts/sun7i-a20.dtsi
> index 82097c905c48..aa61f4887a5e 100644
> --- a/arch/arm/boot/dts/sun7i-a20.dtsi
> +++ b/arch/arm/boot/dts/sun7i-a20.dtsi
> @@ -275,6 +275,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk at 01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -283,6 +299,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk at 01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -291,6 +323,22 @@
>                         clock-output-names = "mmc2";
>                 };
>
> +               mmc2_output_clk: mmc_output_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
> +
>                 mmc3_clk: clk at 01c20094 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -299,6 +347,22 @@
>                         clock-output-names = "mmc3";
>                 };
>
> +               mmc3_output_clk: mmc_output_clk at 01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_output";
> +               };
> +
> +               mmc3_sample_clk: mmc_sample_clk at 01c20094 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20094 0x4>;
> +                       clocks = <&mmc3_clk>;
> +                       clock-output-names = "mmc3_sample";
> +               };
> +
>                 ts_clk: clk at 01c20098 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -512,8 +576,14 @@
>                 mmc0: mmc at 01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <0 32 4>;
>                         status = "disabled";
>                 };
> @@ -521,8 +591,14 @@
>                 mmc1: mmc at 01c10000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <0 33 4>;
>                         status = "disabled";
>                 };
> @@ -530,8 +606,14 @@
>                 mmc2: mmc at 01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <0 34 4>;
>                         status = "disabled";
>                 };
> @@ -539,8 +621,14 @@
>                 mmc3: mmc at 01c12000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c12000 0x1000>;
> -                       clocks = <&ahb_gates 11>, <&mmc3_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb_gates 11>,
> +                                <&mmc3_clk>,
> +                                <&mmc3_sample_clk>,
> +                                <&mmc3_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         interrupts = <0 35 4>;
>                         status = "disabled";
>                 };
> diff --git a/arch/arm/boot/dts/sun8i-a23.dtsi b/arch/arm/boot/dts/sun8i-a23.dtsi
> index a35039224cb5..4379ae93b217 100644
> --- a/arch/arm/boot/dts/sun8i-a23.dtsi
> +++ b/arch/arm/boot/dts/sun8i-a23.dtsi
> @@ -224,6 +224,22 @@
>                         clock-output-names = "mmc0";
>                 };
>
> +               mmc0_output_clk: mmc_output_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_output";
> +               };
> +
> +               mmc0_sample_clk: mmc_sample_clk at 01c20088 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20088 0x4>;
> +                       clocks = <&mmc0_clk>;
> +                       clock-output-names = "mmc0_sample";
> +               };
> +
>                 mmc1_clk: clk at 01c2008c {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -232,6 +248,22 @@
>                         clock-output-names = "mmc1";
>                 };
>
> +               mmc1_output_clk: mmc_output_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_output";
> +               };
> +
> +               mmc1_sample_clk: mmc_sample_clk at 01c2008c {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c2008c 0x4>;
> +                       clocks = <&mmc1_clk>;
> +                       clock-output-names = "mmc1_sample";
> +               };
> +
>                 mmc2_clk: clk at 01c20090 {
>                         #clock-cells = <0>;
>                         compatible = "allwinner,sun4i-a10-mod0-clk";
> @@ -239,6 +271,22 @@
>                         clocks = <&osc24M>, <&pll6>;
>                         clock-output-names = "mmc2";
>                 };
> +
> +               mmc2_output_clk: mmc_output_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_output";
> +               };
> +
> +               mmc2_sample_clk: mmc_sample_clk at 01c20090 {
> +                       #clock-cells = <0>;
> +                       compatible = "allwinner,sun4i-a10-mmc-sample-clk";
> +                       reg = <0x01c20090 0x4>;
> +                       clocks = <&mmc2_clk>;
> +                       clock-output-names = "mmc2_sample";
> +               };
>         };
>
>         soc at 01c00000 {
> @@ -250,8 +298,14 @@
>                 mmc0: mmc at 01c0f000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c0f000 0x1000>;
> -                       clocks = <&ahb1_gates 8>, <&mmc0_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 8>,
> +                                <&mmc0_clk>,
> +                                <&mmc0_sample_clk>,
> +                                <&mmc0_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 8>;
>                         reset-names = "ahb";
>                         interrupts = <0 60 4>;
> @@ -261,8 +315,14 @@
>                 mmc1: mmc at 01c10000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c10000 0x1000>;
> -                       clocks = <&ahb1_gates 9>, <&mmc1_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 9>,
> +                                <&mmc1_clk>,
> +                                <&mmc1_sample_clk>,
> +                                <&mmc1_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 9>;
>                         reset-names = "ahb";
>                         interrupts = <0 61 4>;
> @@ -272,8 +332,14 @@
>                 mmc2: mmc at 01c11000 {
>                         compatible = "allwinner,sun5i-a13-mmc";
>                         reg = <0x01c11000 0x1000>;
> -                       clocks = <&ahb1_gates 10>, <&mmc2_clk>;
> -                       clock-names = "ahb", "mmc";
> +                       clocks = <&ahb1_gates 10>,
> +                                <&mmc2_clk>,
> +                                <&mmc2_sample_clk>,
> +                                <&mmc2_output_clk>;
> +                       clock-names = "ahb",
> +                                     "mmc",
> +                                     "sample",
> +                                     "output";
>                         resets = <&ahb1_rst 10>;
>                         reset-names = "ahb";
>                         interrupts = <0 62 4>;
> --
> 2.1.0
>

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

* Re: [PATCH v3 09/12] ARM: sunxi: dt: Add sample and output mmc clocks
  2014-09-12 10:23       ` Chen-Yu Tsai
@ 2014-09-13  8:18         ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-13  8:18 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Mike Turquette, Hans de Goede, Emilio Lopez, Chris Ball,
	David Lanzendörfer, Ulf Hansson, devicetree,
	linux-arm-kernel, linux-mmc

[-- Attachment #1: Type: text/plain, Size: 1104 bytes --]

On Fri, Sep 12, 2014 at 06:23:02PM +0800, Chen-Yu Tsai wrote:
> >                 mmc0: mmc@01c0f000 {
> >                         compatible = "allwinner,sun4i-a10-mmc";
> >                         reg = <0x01c0f000 0x1000>;
> > -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> > -                       clock-names = "ahb", "mmc";
> > +                       clocks = <&ahb_gates 8>,
> > +                                <&mmc0_clk>,
> > +                                <&mmc0_sample_clk>,
> > +                                <&mmc0_output_clk>;
> > +                       clock-names = "ahb",
> > +                                     "mmc",
> > +                                     "sample",
> > +                                     "output";
> 
> Just a stylish nitpick. All the other resources in these files
> are listed inline if possible, not one phandle/value per line.

Look at the PIO interrupts, every USB PHY resources, etc. ;)

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v3 09/12] ARM: sunxi: dt: Add sample and output mmc clocks
@ 2014-09-13  8:18         ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-13  8:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 12, 2014 at 06:23:02PM +0800, Chen-Yu Tsai wrote:
> >                 mmc0: mmc at 01c0f000 {
> >                         compatible = "allwinner,sun4i-a10-mmc";
> >                         reg = <0x01c0f000 0x1000>;
> > -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
> > -                       clock-names = "ahb", "mmc";
> > +                       clocks = <&ahb_gates 8>,
> > +                                <&mmc0_clk>,
> > +                                <&mmc0_sample_clk>,
> > +                                <&mmc0_output_clk>;
> > +                       clock-names = "ahb",
> > +                                     "mmc",
> > +                                     "sample",
> > +                                     "output";
> 
> Just a stylish nitpick. All the other resources in these files
> are listed inline if possible, not one phandle/value per line.

Look at the PIO interrupts, every USB PHY resources, etc. ;)

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140913/3cf98b29/attachment.sig>

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

* Re: [PATCH v3 09/12] ARM: sunxi: dt: Add sample and output mmc clocks
  2014-09-13  8:18         ` Maxime Ripard
@ 2014-09-13  8:24           ` Chen-Yu Tsai
  -1 siblings, 0 replies; 58+ messages in thread
From: Chen-Yu Tsai @ 2014-09-13  8:24 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mike Turquette, Hans de Goede, Emilio Lopez, Chris Ball,
	David Lanzendörfer, Ulf Hansson, devicetree,
	linux-arm-kernel, linux-mmc

On Sat, Sep 13, 2014 at 4:18 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Fri, Sep 12, 2014 at 06:23:02PM +0800, Chen-Yu Tsai wrote:
>> >                 mmc0: mmc@01c0f000 {
>> >                         compatible = "allwinner,sun4i-a10-mmc";
>> >                         reg = <0x01c0f000 0x1000>;
>> > -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
>> > -                       clock-names = "ahb", "mmc";
>> > +                       clocks = <&ahb_gates 8>,
>> > +                                <&mmc0_clk>,
>> > +                                <&mmc0_sample_clk>,
>> > +                                <&mmc0_output_clk>;
>> > +                       clock-names = "ahb",
>> > +                                     "mmc",
>> > +                                     "sample",
>> > +                                     "output";
>>
>> Just a stylish nitpick. All the other resources in these files
>> are listed inline if possible, not one phandle/value per line.
>
> Look at the PIO interrupts, every USB PHY resources, etc. ;)

I guess we need some styling cleanups. :)

ChenYu

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

* [PATCH v3 09/12] ARM: sunxi: dt: Add sample and output mmc clocks
@ 2014-09-13  8:24           ` Chen-Yu Tsai
  0 siblings, 0 replies; 58+ messages in thread
From: Chen-Yu Tsai @ 2014-09-13  8:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Sep 13, 2014 at 4:18 PM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Fri, Sep 12, 2014 at 06:23:02PM +0800, Chen-Yu Tsai wrote:
>> >                 mmc0: mmc at 01c0f000 {
>> >                         compatible = "allwinner,sun4i-a10-mmc";
>> >                         reg = <0x01c0f000 0x1000>;
>> > -                       clocks = <&ahb_gates 8>, <&mmc0_clk>;
>> > -                       clock-names = "ahb", "mmc";
>> > +                       clocks = <&ahb_gates 8>,
>> > +                                <&mmc0_clk>,
>> > +                                <&mmc0_sample_clk>,
>> > +                                <&mmc0_output_clk>;
>> > +                       clock-names = "ahb",
>> > +                                     "mmc",
>> > +                                     "sample",
>> > +                                     "output";
>>
>> Just a stylish nitpick. All the other resources in these files
>> are listed inline if possible, not one phandle/value per line.
>
> Look at the PIO interrupts, every USB PHY resources, etc. ;)

I guess we need some styling cleanups. :)

ChenYu

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

* Re: [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
  2014-09-11 20:18 ` Maxime Ripard
@ 2014-09-22 11:31   ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-22 11:31 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Hans de Goede, Emilio Lopez, chris, david.lanzendoerfer,
	ulf.hansson, devicetree, linux-arm-kernel, linux-mmc, wens

[-- Attachment #1: Type: text/plain, Size: 890 bytes --]

Mike,

On Thu, Sep 11, 2014 at 10:18:14PM +0200, Maxime Ripard wrote:
> Hi everyone,
> 
> Here is an attempt at improving the MMC clock support in the Allwinner
> SoCs.
> 
> Until now, the MMC clocks were having a custom phase function that was
> directly setting an obscure value in the right register, because we
> were not really having any idea of what these values were.
> 
> Now that we have more informations, we can introduce a common function
> call to get and set the phase of a particular clock, and use this in
> both our provider and our client.

It would be great that we have that custom phase API out of the kernel
for 3.18, and you were one of the greatest supporters to that idea,
could we please have your view on this?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
@ 2014-09-22 11:31   ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-22 11:31 UTC (permalink / raw)
  To: linux-arm-kernel

Mike,

On Thu, Sep 11, 2014 at 10:18:14PM +0200, Maxime Ripard wrote:
> Hi everyone,
> 
> Here is an attempt at improving the MMC clock support in the Allwinner
> SoCs.
> 
> Until now, the MMC clocks were having a custom phase function that was
> directly setting an obscure value in the right register, because we
> were not really having any idea of what these values were.
> 
> Now that we have more informations, we can introduce a common function
> call to get and set the phase of a particular clock, and use this in
> both our provider and our client.

It would be great that we have that custom phase API out of the kernel
for 3.18, and you were one of the greatest supporters to that idea,
could we please have your view on this?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140922/b6ddffc8/attachment.sig>

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

* Re: [PATCH v3 01/12] clk: introduce clk_set_phase function & callback
  2014-09-11 20:18   ` Maxime Ripard
@ 2014-09-24 10:41     ` Heiko Stübner
  -1 siblings, 0 replies; 58+ messages in thread
From: Heiko Stübner @ 2014-09-24 10:41 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Maxime Ripard, Mike Turquette, Hans de Goede, Emilio Lopez,
	chris, david.lanzendoerfer, ulf.hansson, devicetree, wens,
	linux-mmc

Am Donnerstag, 11. September 2014, 22:18:15 schrieb Maxime Ripard:
> From: Mike Turquette <mturquette@linaro.org>
> 
> A common operation for a clock signal generator is to shift the phase of
> that signal. This patch introduces a new function to the clk.h API to
> dynamically adjust the phase of a clock signal. Additionally this patch
> introduces support for the new function in the common clock framework
> via the .set_phase call back in struct clk_ops.
> 
> Signed-off-by: Mike Turquette <mturquette@linaro.org>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

This looks nice and would also be very useful for Rockchip SoCs I'm working 
on. And the implementation looks very straightforward.

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

> ---
>  drivers/clk/clk.c            | 85
> +++++++++++++++++++++++++++++++++++++++++--- include/linux/clk-private.h  |
>  1 +
>  include/linux/clk-provider.h |  5 +++
>  include/linux/clk.h          | 29 +++++++++++++++
>  4 files changed, 116 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index b76fa69b44cb..d87661af0c72 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -117,11 +117,11 @@ static void clk_summary_show_one(struct seq_file *s,
> struct clk *c, int level) if (!c)
>  		return;
> 
> -	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",
> +	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
>  		   level * 3 + 1, "",
>  		   30 - level * 3, c->name,
>  		   c->enable_count, c->prepare_count, clk_get_rate(c),
> -		   clk_get_accuracy(c));
> +		   clk_get_accuracy(c), clk_get_phase(c));
>  }
> 
>  static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
> @@ -143,8 +143,8 @@ static int clk_summary_show(struct seq_file *s, void
> *data) struct clk *c;
>  	struct hlist_head **lists = (struct hlist_head **)s->private;
> 
> -	seq_puts(s, "   clock                         enable_cnt  prepare_cnt     
>   rate   accuracy\n"); -	seq_puts(s,
> "--------------------------------------------------------------------------
> ------\n"); +	seq_puts(s, "   clock                         enable_cnt 
> prepare_cnt        rate   accuracy   phase\n"); +	seq_puts(s,
> "--------------------------------------------------------------------------
> --------------\n");
> 
>  	clk_prepare_lock();
> 
> @@ -180,6 +180,7 @@ static void clk_dump_one(struct seq_file *s, struct clk
> *c, int level) 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, "\"phase\": %d", clk_get_phase(c));
>  }
> 
>  static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
> @@ -264,6 +265,11 @@ static int clk_debug_create_one(struct clk *clk, struct
> dentry *pdentry) if (!d)
>  		goto err_out;
> 
> +	d = debugfs_create_u32("clk_phase", S_IRUGO, clk->dentry,
> +			(u32 *)&clk->phase);
> +	if (!d)
> +		goto err_out;
> +
>  	d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
>  			(u32 *)&clk->flags);
>  	if (!d)
> @@ -1739,6 +1745,77 @@ out:
>  EXPORT_SYMBOL_GPL(clk_set_parent);
> 
>  /**
> + * clk_set_phase - adjust the phase shift of a clock signal
> + * @clk: clock signal source
> + * @degrees: number of degrees the signal is shifted
> + *
> + * Shifts the phase of a clock signal by the specified
> + * degrees. Returns 0 on success, -EERROR otherwise.
> + *
> + * This function makes no distinction about the input or reference
> + * signal that we adjust the clock signal phase against. For example
> + * phase locked-loop clock signal generators we may shift phase with
> + * respect to feedback clock signal input, but for other cases the
> + * clock phase may be shifted with respect to some other, unspecified
> + * signal.
> + *
> + * Additionally the concept of phase shift does not propagate through
> + * the clock tree hierarchy, which sets it apart from clock rates and
> + * clock accuracy. A parent clock phase attribute does not have an
> + * impact on the phase attribute of a child clock.
> + */
> +int clk_set_phase(struct clk *clk, int degrees)
> +{
> +	int ret = 0;
> +
> +	if (!clk)
> +		goto out;
> +
> +	/* sanity check degrees */
> +	degrees %= 360;
> +	if (degrees < 0)
> +		degrees += 360;
> +
> +	clk_prepare_lock();
> +
> +	if (!clk->ops->set_phase)
> +		goto out_unlock;
> +
> +	ret = clk->ops->set_phase(clk->hw, degrees);
> +
> +	if (!ret)
> +		clk->phase = degrees;
> +
> +out_unlock:
> +	clk_prepare_unlock();
> +
> +out:
> +	return ret;
> +}
> +
> +/**
> + * clk_get_phase - return the phase shift of a clock signal
> + * @clk: clock signal source
> + *
> + * Returns the phase shift of a clock node in degrees, otherwise returns
> + * -EERROR.
> + */
> +int clk_get_phase(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk)
> +		goto out;
> +
> +	clk_prepare_lock();
> +	ret = clk->phase;
> +	clk_prepare_unlock();
> +
> +out:
> +	return ret;
> +}
> +
> +/**
>   * __clk_init - initialize the data structures in a struct clk
>   * @dev:	device initializing this clk, placeholder for now
>   * @clk:	clk being initialized
> diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
> index efbf70b9fd84..845be30be50f 100644
> --- a/include/linux/clk-private.h
> +++ b/include/linux/clk-private.h
> @@ -46,6 +46,7 @@ struct clk {
>  	unsigned int		enable_count;
>  	unsigned int		prepare_count;
>  	unsigned long		accuracy;
> +	int			phase;
>  	struct hlist_head	children;
>  	struct hlist_node	child_node;
>  	unsigned int		notifier_count;
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 411dd7eb2653..201a6195a3eb 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -129,6 +129,10 @@ struct dentry;
>   *		set then clock accuracy will be initialized to parent accuracy
>   *		or 0 (perfect clock) if clock has no parent.
>   *
> + * @set_phase:	Shift the phase this clock signal in degrees specified
> + *		by the second argument. Valid values for degrees are
> + *		0-359. Return 0 on success, otherwise -EERROR.
> + *
>   * @init:	Perform platform-specific initialization magic.
>   *		This is not not used by any of the basic clock types.
>   *		Please consider other ways of solving initialization problems
> @@ -177,6 +181,7 @@ struct clk_ops {
>  				    unsigned long parent_rate, u8 index);
>  	unsigned long	(*recalc_accuracy)(struct clk_hw *hw,
>  					   unsigned long parent_accuracy);
> +	int		(*set_phase)(struct clk_hw *hw, int degrees);
>  	void		(*init)(struct clk_hw *hw);
>  	int		(*debug_init)(struct clk_hw *hw, struct dentry *dentry);
>  };
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fb5e097d8f72..38bdedd3e389 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -106,6 +106,25 @@ int clk_notifier_unregister(struct clk *clk, struct
> notifier_block *nb); */
>  long clk_get_accuracy(struct clk *clk);
> 
> +/**
> + * clk_set_phase - adjust the phase shift of a clock signal
> + * @clk: clock signal source
> + * @degrees: number of degrees the signal is shifted
> + *
> + * Shifts the phase of a clock signal by the specified degrees. Returns 0
> on + * success, -EERROR otherwise.
> + */
> +int clk_set_phase(struct clk *clk, int degrees);
> +
> +/**
> + * clk_get_phase - return the phase shift of a clock signal
> + * @clk: clock signal source
> + *
> + * Returns the phase shift of a clock node in degrees, otherwise returns
> + * -EERROR.
> + */
> +int clk_get_phase(struct clk *clk);
> +
>  #else
> 
>  static inline long clk_get_accuracy(struct clk *clk)
> @@ -113,6 +132,16 @@ static inline long clk_get_accuracy(struct clk *clk)
>  	return -ENOTSUPP;
>  }
> 
> +static inline long clk_set_phase(struct clk *clk, int phase)
> +{
> +	return -ENOTSUPP;
> +}
> +
> +static inline long clk_get_phase(struct clk *clk)
> +{
> +	return -ENOTSUPP;
> +}
> +
>  #endif
> 
>  /**


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

* [PATCH v3 01/12] clk: introduce clk_set_phase function & callback
@ 2014-09-24 10:41     ` Heiko Stübner
  0 siblings, 0 replies; 58+ messages in thread
From: Heiko Stübner @ 2014-09-24 10:41 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, 11. September 2014, 22:18:15 schrieb Maxime Ripard:
> From: Mike Turquette <mturquette@linaro.org>
> 
> A common operation for a clock signal generator is to shift the phase of
> that signal. This patch introduces a new function to the clk.h API to
> dynamically adjust the phase of a clock signal. Additionally this patch
> introduces support for the new function in the common clock framework
> via the .set_phase call back in struct clk_ops.
> 
> Signed-off-by: Mike Turquette <mturquette@linaro.org>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

This looks nice and would also be very useful for Rockchip SoCs I'm working 
on. And the implementation looks very straightforward.

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

> ---
>  drivers/clk/clk.c            | 85
> +++++++++++++++++++++++++++++++++++++++++--- include/linux/clk-private.h  |
>  1 +
>  include/linux/clk-provider.h |  5 +++
>  include/linux/clk.h          | 29 +++++++++++++++
>  4 files changed, 116 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index b76fa69b44cb..d87661af0c72 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -117,11 +117,11 @@ static void clk_summary_show_one(struct seq_file *s,
> struct clk *c, int level) if (!c)
>  		return;
> 
> -	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",
> +	seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu %-3d\n",
>  		   level * 3 + 1, "",
>  		   30 - level * 3, c->name,
>  		   c->enable_count, c->prepare_count, clk_get_rate(c),
> -		   clk_get_accuracy(c));
> +		   clk_get_accuracy(c), clk_get_phase(c));
>  }
> 
>  static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
> @@ -143,8 +143,8 @@ static int clk_summary_show(struct seq_file *s, void
> *data) struct clk *c;
>  	struct hlist_head **lists = (struct hlist_head **)s->private;
> 
> -	seq_puts(s, "   clock                         enable_cnt  prepare_cnt     
>   rate   accuracy\n"); -	seq_puts(s,
> "--------------------------------------------------------------------------
> ------\n"); +	seq_puts(s, "   clock                         enable_cnt 
> prepare_cnt        rate   accuracy   phase\n"); +	seq_puts(s,
> "--------------------------------------------------------------------------
> --------------\n");
> 
>  	clk_prepare_lock();
> 
> @@ -180,6 +180,7 @@ static void clk_dump_one(struct seq_file *s, struct clk
> *c, int level) 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, "\"phase\": %d", clk_get_phase(c));
>  }
> 
>  static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
> @@ -264,6 +265,11 @@ static int clk_debug_create_one(struct clk *clk, struct
> dentry *pdentry) if (!d)
>  		goto err_out;
> 
> +	d = debugfs_create_u32("clk_phase", S_IRUGO, clk->dentry,
> +			(u32 *)&clk->phase);
> +	if (!d)
> +		goto err_out;
> +
>  	d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry,
>  			(u32 *)&clk->flags);
>  	if (!d)
> @@ -1739,6 +1745,77 @@ out:
>  EXPORT_SYMBOL_GPL(clk_set_parent);
> 
>  /**
> + * clk_set_phase - adjust the phase shift of a clock signal
> + * @clk: clock signal source
> + * @degrees: number of degrees the signal is shifted
> + *
> + * Shifts the phase of a clock signal by the specified
> + * degrees. Returns 0 on success, -EERROR otherwise.
> + *
> + * This function makes no distinction about the input or reference
> + * signal that we adjust the clock signal phase against. For example
> + * phase locked-loop clock signal generators we may shift phase with
> + * respect to feedback clock signal input, but for other cases the
> + * clock phase may be shifted with respect to some other, unspecified
> + * signal.
> + *
> + * Additionally the concept of phase shift does not propagate through
> + * the clock tree hierarchy, which sets it apart from clock rates and
> + * clock accuracy. A parent clock phase attribute does not have an
> + * impact on the phase attribute of a child clock.
> + */
> +int clk_set_phase(struct clk *clk, int degrees)
> +{
> +	int ret = 0;
> +
> +	if (!clk)
> +		goto out;
> +
> +	/* sanity check degrees */
> +	degrees %= 360;
> +	if (degrees < 0)
> +		degrees += 360;
> +
> +	clk_prepare_lock();
> +
> +	if (!clk->ops->set_phase)
> +		goto out_unlock;
> +
> +	ret = clk->ops->set_phase(clk->hw, degrees);
> +
> +	if (!ret)
> +		clk->phase = degrees;
> +
> +out_unlock:
> +	clk_prepare_unlock();
> +
> +out:
> +	return ret;
> +}
> +
> +/**
> + * clk_get_phase - return the phase shift of a clock signal
> + * @clk: clock signal source
> + *
> + * Returns the phase shift of a clock node in degrees, otherwise returns
> + * -EERROR.
> + */
> +int clk_get_phase(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (!clk)
> +		goto out;
> +
> +	clk_prepare_lock();
> +	ret = clk->phase;
> +	clk_prepare_unlock();
> +
> +out:
> +	return ret;
> +}
> +
> +/**
>   * __clk_init - initialize the data structures in a struct clk
>   * @dev:	device initializing this clk, placeholder for now
>   * @clk:	clk being initialized
> diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
> index efbf70b9fd84..845be30be50f 100644
> --- a/include/linux/clk-private.h
> +++ b/include/linux/clk-private.h
> @@ -46,6 +46,7 @@ struct clk {
>  	unsigned int		enable_count;
>  	unsigned int		prepare_count;
>  	unsigned long		accuracy;
> +	int			phase;
>  	struct hlist_head	children;
>  	struct hlist_node	child_node;
>  	unsigned int		notifier_count;
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 411dd7eb2653..201a6195a3eb 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -129,6 +129,10 @@ struct dentry;
>   *		set then clock accuracy will be initialized to parent accuracy
>   *		or 0 (perfect clock) if clock has no parent.
>   *
> + * @set_phase:	Shift the phase this clock signal in degrees specified
> + *		by the second argument. Valid values for degrees are
> + *		0-359. Return 0 on success, otherwise -EERROR.
> + *
>   * @init:	Perform platform-specific initialization magic.
>   *		This is not not used by any of the basic clock types.
>   *		Please consider other ways of solving initialization problems
> @@ -177,6 +181,7 @@ struct clk_ops {
>  				    unsigned long parent_rate, u8 index);
>  	unsigned long	(*recalc_accuracy)(struct clk_hw *hw,
>  					   unsigned long parent_accuracy);
> +	int		(*set_phase)(struct clk_hw *hw, int degrees);
>  	void		(*init)(struct clk_hw *hw);
>  	int		(*debug_init)(struct clk_hw *hw, struct dentry *dentry);
>  };
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index fb5e097d8f72..38bdedd3e389 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -106,6 +106,25 @@ int clk_notifier_unregister(struct clk *clk, struct
> notifier_block *nb); */
>  long clk_get_accuracy(struct clk *clk);
> 
> +/**
> + * clk_set_phase - adjust the phase shift of a clock signal
> + * @clk: clock signal source
> + * @degrees: number of degrees the signal is shifted
> + *
> + * Shifts the phase of a clock signal by the specified degrees. Returns 0
> on + * success, -EERROR otherwise.
> + */
> +int clk_set_phase(struct clk *clk, int degrees);
> +
> +/**
> + * clk_get_phase - return the phase shift of a clock signal
> + * @clk: clock signal source
> + *
> + * Returns the phase shift of a clock node in degrees, otherwise returns
> + * -EERROR.
> + */
> +int clk_get_phase(struct clk *clk);
> +
>  #else
> 
>  static inline long clk_get_accuracy(struct clk *clk)
> @@ -113,6 +132,16 @@ static inline long clk_get_accuracy(struct clk *clk)
>  	return -ENOTSUPP;
>  }
> 
> +static inline long clk_set_phase(struct clk *clk, int phase)
> +{
> +	return -ENOTSUPP;
> +}
> +
> +static inline long clk_get_phase(struct clk *clk)
> +{
> +	return -ENOTSUPP;
> +}
> +
>  #endif
> 
>  /**

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

* Re: [PATCH v3 03/12] clk: Add a function to retrieve phase
  2014-09-11 20:18   ` Maxime Ripard
@ 2014-09-24 10:42     ` Heiko Stübner
  -1 siblings, 0 replies; 58+ messages in thread
From: Heiko Stübner @ 2014-09-24 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Maxime Ripard, Mike Turquette, Hans de Goede, Emilio Lopez,
	chris, david.lanzendoerfer, ulf.hansson, devicetree, wens,
	linux-mmc

Am Donnerstag, 11. September 2014, 22:18:17 schrieb Maxime Ripard:
> The current phase API doesn't look into the actual hardware to get the phase
> value, but will rather get it from a variable only set by the set_phase
> function.
> 
> This will cause issue when the client driver will never call the set_phase
> function, where we can end up having a reported phase that will not match
> what the hardware has been programmed to by the bootloader or what phase is
> programmed out of reset.
> 
> Add a new get_phase function for the drivers to implement so that we can get
> this value.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

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

> ---
>  drivers/clk/clk.c            | 10 ++++++++++
>  include/linux/clk-provider.h |  5 +++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index d87661af0c72..113d75db371d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
>  		clk->accuracy = 0;
> 
>  	/*
> +	 * Set clk's phase.
> +	 * Since a phase is by definition relative to its parent, just
> +	 * query the current clock phase, or just assume it's in phase.
> +	 */
> +	if (clk->ops->get_phase)
> +		clk->phase = clk->ops->get_phase(clk->hw);
> +	else
> +		clk->phase = 0;
> +
> +	/*
>  	 * Set clk's rate.  The preferred method is to use .recalc_rate.  For
>  	 * simple clocks and lazy developers the default fallback is to use the
>  	 * parent's rate.  If a clock doesn't have a parent (or is orphaned)
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 69b20d4c1e1a..abec961092a7 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -130,6 +130,10 @@ struct dentry;
>   *		set then clock accuracy will be initialized to parent accuracy
>   *		or 0 (perfect clock) if clock has no parent.
>   *
> + * @get_phase:	Queries the hardware to get the current phase of a clock.
> + *		Returned values are 0-359 degrees on success, negative
> + *		error codes on failure.
> + *
>   * @set_phase:	Shift the phase this clock signal in degrees specified
>   *		by the second argument. Valid values for degrees are
>   *		0-359. Return 0 on success, otherwise -EERROR.
> @@ -182,6 +186,7 @@ struct clk_ops {
>  				    unsigned long parent_rate, u8 index);
>  	unsigned long	(*recalc_accuracy)(struct clk_hw *hw,
>  					   unsigned long parent_accuracy);
> +	int		(*get_phase)(struct clk_hw *hw);
>  	int		(*set_phase)(struct clk_hw *hw, int degrees);
>  	void		(*init)(struct clk_hw *hw);
>  	int		(*debug_init)(struct clk_hw *hw, struct dentry *dentry);


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

* [PATCH v3 03/12] clk: Add a function to retrieve phase
@ 2014-09-24 10:42     ` Heiko Stübner
  0 siblings, 0 replies; 58+ messages in thread
From: Heiko Stübner @ 2014-09-24 10:42 UTC (permalink / raw)
  To: linux-arm-kernel

Am Donnerstag, 11. September 2014, 22:18:17 schrieb Maxime Ripard:
> The current phase API doesn't look into the actual hardware to get the phase
> value, but will rather get it from a variable only set by the set_phase
> function.
> 
> This will cause issue when the client driver will never call the set_phase
> function, where we can end up having a reported phase that will not match
> what the hardware has been programmed to by the bootloader or what phase is
> programmed out of reset.
> 
> Add a new get_phase function for the drivers to implement so that we can get
> this value.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

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

> ---
>  drivers/clk/clk.c            | 10 ++++++++++
>  include/linux/clk-provider.h |  5 +++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index d87661af0c72..113d75db371d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
>  		clk->accuracy = 0;
> 
>  	/*
> +	 * Set clk's phase.
> +	 * Since a phase is by definition relative to its parent, just
> +	 * query the current clock phase, or just assume it's in phase.
> +	 */
> +	if (clk->ops->get_phase)
> +		clk->phase = clk->ops->get_phase(clk->hw);
> +	else
> +		clk->phase = 0;
> +
> +	/*
>  	 * Set clk's rate.  The preferred method is to use .recalc_rate.  For
>  	 * simple clocks and lazy developers the default fallback is to use the
>  	 * parent's rate.  If a clock doesn't have a parent (or is orphaned)
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 69b20d4c1e1a..abec961092a7 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -130,6 +130,10 @@ struct dentry;
>   *		set then clock accuracy will be initialized to parent accuracy
>   *		or 0 (perfect clock) if clock has no parent.
>   *
> + * @get_phase:	Queries the hardware to get the current phase of a clock.
> + *		Returned values are 0-359 degrees on success, negative
> + *		error codes on failure.
> + *
>   * @set_phase:	Shift the phase this clock signal in degrees specified
>   *		by the second argument. Valid values for degrees are
>   *		0-359. Return 0 on success, otherwise -EERROR.
> @@ -182,6 +186,7 @@ struct clk_ops {
>  				    unsigned long parent_rate, u8 index);
>  	unsigned long	(*recalc_accuracy)(struct clk_hw *hw,
>  					   unsigned long parent_accuracy);
> +	int		(*get_phase)(struct clk_hw *hw);
>  	int		(*set_phase)(struct clk_hw *hw, int degrees);
>  	void		(*init)(struct clk_hw *hw);
>  	int		(*debug_init)(struct clk_hw *hw, struct dentry *dentry);

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

* Re: [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
  2014-09-22 11:31   ` Maxime Ripard
@ 2014-09-26  0:42     ` Mike Turquette
  -1 siblings, 0 replies; 58+ messages in thread
From: Mike Turquette @ 2014-09-26  0:42 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: devicetree, ulf.hansson, Emilio Lopez, linux-mmc, chris,
	Hans de Goede, wens, david.lanzendoerfer, linux-arm-kernel

Quoting Maxime Ripard (2014-09-22 04:31:33)
> Mike,
> 
> On Thu, Sep 11, 2014 at 10:18:14PM +0200, Maxime Ripard wrote:
> > Hi everyone,
> > 
> > Here is an attempt at improving the MMC clock support in the Allwinner
> > SoCs.
> > 
> > Until now, the MMC clocks were having a custom phase function that was
> > directly setting an obscure value in the right register, because we
> > were not really having any idea of what these values were.
> > 
> > Now that we have more informations, we can introduce a common function
> > call to get and set the phase of a particular clock, and use this in
> > both our provider and our client.
> 
> It would be great that we have that custom phase API out of the kernel
> for 3.18, and you were one of the greatest supporters to that idea,
> could we please have your view on this?

Patches all look good to me. Did you want the whole series to go through
the clk tree? If so we'll need an Ack for the MMC patch and for the ARM
DTS patches as well.

Regards,
Mike

> 
> Thanks,
> Maxime
> 
> -- 
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

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

* [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
@ 2014-09-26  0:42     ` Mike Turquette
  0 siblings, 0 replies; 58+ messages in thread
From: Mike Turquette @ 2014-09-26  0:42 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Maxime Ripard (2014-09-22 04:31:33)
> Mike,
> 
> On Thu, Sep 11, 2014 at 10:18:14PM +0200, Maxime Ripard wrote:
> > Hi everyone,
> > 
> > Here is an attempt at improving the MMC clock support in the Allwinner
> > SoCs.
> > 
> > Until now, the MMC clocks were having a custom phase function that was
> > directly setting an obscure value in the right register, because we
> > were not really having any idea of what these values were.
> > 
> > Now that we have more informations, we can introduce a common function
> > call to get and set the phase of a particular clock, and use this in
> > both our provider and our client.
> 
> It would be great that we have that custom phase API out of the kernel
> for 3.18, and you were one of the greatest supporters to that idea,
> could we please have your view on this?

Patches all look good to me. Did you want the whole series to go through
the clk tree? If so we'll need an Ack for the MMC patch and for the ARM
DTS patches as well.

Regards,
Mike

> 
> Thanks,
> Maxime
> 
> -- 
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

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

* Re: [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
  2014-09-26  0:42     ` Mike Turquette
@ 2014-09-26  6:55       ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-26  6:55 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Hans de Goede, Emilio Lopez, chris, david.lanzendoerfer,
	ulf.hansson, devicetree, linux-arm-kernel, linux-mmc, wens

[-- Attachment #1: Type: text/plain, Size: 1447 bytes --]

Hi Mike,

On Thu, Sep 25, 2014 at 05:42:18PM -0700, Mike Turquette wrote:
> Quoting Maxime Ripard (2014-09-22 04:31:33)
> > Mike,
> > 
> > On Thu, Sep 11, 2014 at 10:18:14PM +0200, Maxime Ripard wrote:
> > > Hi everyone,
> > > 
> > > Here is an attempt at improving the MMC clock support in the Allwinner
> > > SoCs.
> > > 
> > > Until now, the MMC clocks were having a custom phase function that was
> > > directly setting an obscure value in the right register, because we
> > > were not really having any idea of what these values were.
> > > 
> > > Now that we have more informations, we can introduce a common function
> > > call to get and set the phase of a particular clock, and use this in
> > > both our provider and our client.
> > 
> > It would be great that we have that custom phase API out of the kernel
> > for 3.18, and you were one of the greatest supporters to that idea,
> > could we please have your view on this?
> 
> Patches all look good to me. Did you want the whole series to go through
> the clk tree?

I guess it would be where it most make sense yes.

> If so we'll need an Ack for the MMC patch and for the ARM DTS
> patches as well.

We already have an Ack from Ulf on the MMC patch, and I'm the
maintainer of the DTS involved, so we should be ok :)

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
@ 2014-09-26  6:55       ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-26  6:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mike,

On Thu, Sep 25, 2014 at 05:42:18PM -0700, Mike Turquette wrote:
> Quoting Maxime Ripard (2014-09-22 04:31:33)
> > Mike,
> > 
> > On Thu, Sep 11, 2014 at 10:18:14PM +0200, Maxime Ripard wrote:
> > > Hi everyone,
> > > 
> > > Here is an attempt at improving the MMC clock support in the Allwinner
> > > SoCs.
> > > 
> > > Until now, the MMC clocks were having a custom phase function that was
> > > directly setting an obscure value in the right register, because we
> > > were not really having any idea of what these values were.
> > > 
> > > Now that we have more informations, we can introduce a common function
> > > call to get and set the phase of a particular clock, and use this in
> > > both our provider and our client.
> > 
> > It would be great that we have that custom phase API out of the kernel
> > for 3.18, and you were one of the greatest supporters to that idea,
> > could we please have your view on this?
> 
> Patches all look good to me. Did you want the whole series to go through
> the clk tree?

I guess it would be where it most make sense yes.

> If so we'll need an Ack for the MMC patch and for the ARM DTS
> patches as well.

We already have an Ack from Ulf on the MMC patch, and I'm the
maintainer of the DTS involved, so we should be ok :)

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140926/c3dd532a/attachment.sig>

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

* Re: [PATCH v3 11/12] mmc: sunxi: Convert MMC driver to the standard clock phase API
  2014-09-11 20:18   ` Maxime Ripard
@ 2014-09-26 14:27     ` David Lanzendörfer
  -1 siblings, 0 replies; 58+ messages in thread
From: David Lanzendörfer @ 2014-09-26 14:27 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mike Turquette, Hans de Goede, Emilio Lopez, chris, ulf.hansson,
	devicetree, linux-arm-kernel, linux-mmc, wens

[-- Attachment #1: Type: text/plain, Size: 472 bytes --]

Hello
> Now that we have proper support to use the generic phase API in our clock
> driver, switch the MMC driver to use it.
> [...]
>  	/* determine delays */
>  	if (rate <= 400000) {
> -		oclk_dly = 0;
> -		sclk_dly = 7;
> +		oclk_dly = 180;
> +		sclk_dly = 42;
> [...]
How did you calculate the actual phase values from the original parameters?

greatings
-- 
David Lanzendörfer
OpenSourceSupport GmbH
System engineer and supporter
http://www.o2s.ch/

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

* [PATCH v3 11/12] mmc: sunxi: Convert MMC driver to the standard clock phase API
@ 2014-09-26 14:27     ` David Lanzendörfer
  0 siblings, 0 replies; 58+ messages in thread
From: David Lanzendörfer @ 2014-09-26 14:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hello
> Now that we have proper support to use the generic phase API in our clock
> driver, switch the MMC driver to use it.
> [...]
>  	/* determine delays */
>  	if (rate <= 400000) {
> -		oclk_dly = 0;
> -		sclk_dly = 7;
> +		oclk_dly = 180;
> +		sclk_dly = 42;
> [...]
How did you calculate the actual phase values from the original parameters?

greatings
-- 
David Lanzend?rfer
OpenSourceSupport GmbH
System engineer and supporter
http://www.o2s.ch/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140926/8bc39436/attachment.sig>

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

* Re: [PATCH v3 11/12] mmc: sunxi: Convert MMC driver to the standard clock phase API
  2014-09-26 14:27     ` David Lanzendörfer
@ 2014-09-26 15:02         ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-26 15:02 UTC (permalink / raw)
  To: David Lanzendörfer
  Cc: Mike Turquette, Hans de Goede, Emilio Lopez,
	chris-OsFVWbfNK3isTnJN9+BGXg, ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA, wens-jdAy2FN1RRM

[-- Attachment #1: Type: text/plain, Size: 1112 bytes --]

On Fri, Sep 26, 2014 at 04:27:10PM +0200, David Lanzendörfer wrote:
> Hello
> > Now that we have proper support to use the generic phase API in our clock
> > driver, switch the MMC driver to use it.
> > [...]
> >  	/* determine delays */
> >  	if (rate <= 400000) {
> > -		oclk_dly = 0;
> > -		sclk_dly = 7;
> > +		oclk_dly = 180;
> > +		sclk_dly = 42;
> > [...]
> How did you calculate the actual phase values from the original parameters?

Like shown in the clock driver. 0 is always a 180 deg phase shift, and
any other value is the number of the parent clock cycle to outphase
the clock of.

the clock out phase is calculating using:

phase = 360 * interval / period.

with period = 1 / (parent_freq / divider)
and interval = reg / parent_freq

which makes

phase = 360 * (reg / parent_freq) * (parent_freq / divider)

If we simplify by removing the parent_freq, we end up with

phase = 360 * reg / divider, which makes it rather trivial to
calculate.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v3 11/12] mmc: sunxi: Convert MMC driver to the standard clock phase API
@ 2014-09-26 15:02         ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-26 15:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Sep 26, 2014 at 04:27:10PM +0200, David Lanzend?rfer wrote:
> Hello
> > Now that we have proper support to use the generic phase API in our clock
> > driver, switch the MMC driver to use it.
> > [...]
> >  	/* determine delays */
> >  	if (rate <= 400000) {
> > -		oclk_dly = 0;
> > -		sclk_dly = 7;
> > +		oclk_dly = 180;
> > +		sclk_dly = 42;
> > [...]
> How did you calculate the actual phase values from the original parameters?

Like shown in the clock driver. 0 is always a 180 deg phase shift, and
any other value is the number of the parent clock cycle to outphase
the clock of.

the clock out phase is calculating using:

phase = 360 * interval / period.

with period = 1 / (parent_freq / divider)
and interval = reg / parent_freq

which makes

phase = 360 * (reg / parent_freq) * (parent_freq / divider)

If we simplify by removing the parent_freq, we end up with

phase = 360 * reg / divider, which makes it rather trivial to
calculate.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140926/6476fba8/attachment.sig>

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

* Re: [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
  2014-09-26  6:55       ` Maxime Ripard
@ 2014-09-26 17:52         ` Mike Turquette
  -1 siblings, 0 replies; 58+ messages in thread
From: Mike Turquette @ 2014-09-26 17:52 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: devicetree, ulf.hansson, Emilio Lopez, linux-mmc, chris,
	Hans de Goede, wens, david.lanzendoerfer, linux-arm-kernel

Quoting Maxime Ripard (2014-09-25 23:55:07)
> Hi Mike,
> 
> On Thu, Sep 25, 2014 at 05:42:18PM -0700, Mike Turquette wrote:
> > Quoting Maxime Ripard (2014-09-22 04:31:33)
> > > Mike,
> > > 
> > > On Thu, Sep 11, 2014 at 10:18:14PM +0200, Maxime Ripard wrote:
> > > > Hi everyone,
> > > > 
> > > > Here is an attempt at improving the MMC clock support in the Allwinner
> > > > SoCs.
> > > > 
> > > > Until now, the MMC clocks were having a custom phase function that was
> > > > directly setting an obscure value in the right register, because we
> > > > were not really having any idea of what these values were.
> > > > 
> > > > Now that we have more informations, we can introduce a common function
> > > > call to get and set the phase of a particular clock, and use this in
> > > > both our provider and our client.
> > > 
> > > It would be great that we have that custom phase API out of the kernel
> > > for 3.18, and you were one of the greatest supporters to that idea,
> > > could we please have your view on this?
> > 
> > Patches all look good to me. Did you want the whole series to go through
> > the clk tree?
> 
> I guess it would be where it most make sense yes.
> 
> > If so we'll need an Ack for the MMC patch and for the ARM DTS
> > patches as well.
> 
> We already have an Ack from Ulf on the MMC patch, and I'm the
> maintainer of the DTS involved, so we should be ok :)

Oops, I didn't notice Ulf's Ack. Will either your or Emilio be sending a
pull request for the sunxi clock changes?

Regards,
Mike

> 
> Thanks!
> Maxime
> 
> -- 
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

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

* [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support
@ 2014-09-26 17:52         ` Mike Turquette
  0 siblings, 0 replies; 58+ messages in thread
From: Mike Turquette @ 2014-09-26 17:52 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Maxime Ripard (2014-09-25 23:55:07)
> Hi Mike,
> 
> On Thu, Sep 25, 2014 at 05:42:18PM -0700, Mike Turquette wrote:
> > Quoting Maxime Ripard (2014-09-22 04:31:33)
> > > Mike,
> > > 
> > > On Thu, Sep 11, 2014 at 10:18:14PM +0200, Maxime Ripard wrote:
> > > > Hi everyone,
> > > > 
> > > > Here is an attempt at improving the MMC clock support in the Allwinner
> > > > SoCs.
> > > > 
> > > > Until now, the MMC clocks were having a custom phase function that was
> > > > directly setting an obscure value in the right register, because we
> > > > were not really having any idea of what these values were.
> > > > 
> > > > Now that we have more informations, we can introduce a common function
> > > > call to get and set the phase of a particular clock, and use this in
> > > > both our provider and our client.
> > > 
> > > It would be great that we have that custom phase API out of the kernel
> > > for 3.18, and you were one of the greatest supporters to that idea,
> > > could we please have your view on this?
> > 
> > Patches all look good to me. Did you want the whole series to go through
> > the clk tree?
> 
> I guess it would be where it most make sense yes.
> 
> > If so we'll need an Ack for the MMC patch and for the ARM DTS
> > patches as well.
> 
> We already have an Ack from Ulf on the MMC patch, and I'm the
> maintainer of the DTS involved, so we should be ok :)

Oops, I didn't notice Ulf's Ack. Will either your or Emilio be sending a
pull request for the sunxi clock changes?

Regards,
Mike

> 
> Thanks!
> Maxime
> 
> -- 
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

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

* Re: [PATCH v3 11/12] mmc: sunxi: Convert MMC driver to the standard clock phase API
  2014-09-26 15:02         ` Maxime Ripard
@ 2014-09-26 20:47           ` David Lanzendörfer
  -1 siblings, 0 replies; 58+ messages in thread
From: David Lanzendörfer @ 2014-09-26 20:47 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Mike Turquette, Hans de Goede, Emilio Lopez, chris, ulf.hansson,
	devicetree, linux-arm-kernel, linux-mmc, wens

[-- Attachment #1: Type: text/plain, Size: 1180 bytes --]

Hi
Great! Since I didn't see any mistakes from my side it shouldn't be a problem.
Because someone has borrowed my UART2USB(FT232)-cable I unfortunately can't
test the code for now.
If you can verfiy that all the adaptions are working properly on A10/A20 and
all the others you my assume my:
	Acked-by: David Lanzendörfer <david.lanzendoerfer@o2s.ch>

chears and all the best
david

> > > [...]
> > How did you calculate the actual phase values from the original
> > parameters?
>
> Like shown in the clock driver. 0 is always a 180 deg phase shift, and
> any other value is the number of the parent clock cycle to outphase
> the clock of.
> 
> the clock out phase is calculating using:
> 
> phase = 360 * interval / period.
> 
> with period = 1 / (parent_freq / divider)
> and interval = reg / parent_freq
> 
> which makes
> 
> phase = 360 * (reg / parent_freq) * (parent_freq / divider)
> 
> If we simplify by removing the parent_freq, we end up with
> 
> phase = 360 * reg / divider, which makes it rather trivial to
> calculate.
> 
> Maxime

-- 
David Lanzendörfer
OpenSourceSupport GmbH
System engineer and supporter
http://www.o2s.ch/

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

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

* [PATCH v3 11/12] mmc: sunxi: Convert MMC driver to the standard clock phase API
@ 2014-09-26 20:47           ` David Lanzendörfer
  0 siblings, 0 replies; 58+ messages in thread
From: David Lanzendörfer @ 2014-09-26 20:47 UTC (permalink / raw)
  To: linux-arm-kernel

Hi
Great! Since I didn't see any mistakes from my side it shouldn't be a problem.
Because someone has borrowed my UART2USB(FT232)-cable I unfortunately can't
test the code for now.
If you can verfiy that all the adaptions are working properly on A10/A20 and
all the others you my assume my:
	Acked-by: David Lanzend?rfer <david.lanzendoerfer@o2s.ch>

chears and all the best
david

> > > [...]
> > How did you calculate the actual phase values from the original
> > parameters?
>
> Like shown in the clock driver. 0 is always a 180 deg phase shift, and
> any other value is the number of the parent clock cycle to outphase
> the clock of.
> 
> the clock out phase is calculating using:
> 
> phase = 360 * interval / period.
> 
> with period = 1 / (parent_freq / divider)
> and interval = reg / parent_freq
> 
> which makes
> 
> phase = 360 * (reg / parent_freq) * (parent_freq / divider)
> 
> If we simplify by removing the parent_freq, we end up with
> 
> phase = 360 * reg / divider, which makes it rather trivial to
> calculate.
> 
> Maxime

-- 
David Lanzend?rfer
OpenSourceSupport GmbH
System engineer and supporter
http://www.o2s.ch/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140926/074b17e2/attachment.sig>

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

* Re: [PATCH v3 03/12] clk: Add a function to retrieve phase
  2014-09-11 20:18   ` Maxime Ripard
@ 2014-09-28  0:17     ` Mike Turquette
  -1 siblings, 0 replies; 58+ messages in thread
From: Mike Turquette @ 2014-09-28  0:17 UTC (permalink / raw)
  To: Hans de Goede, Emilio Lopez, chris, david.lanzendoerfer, ulf.hansson
  Cc: devicetree, linux-arm-kernel, linux-mmc, wens, Maxime Ripard

Quoting Maxime Ripard (2014-09-11 13:18:17)
> The current phase API doesn't look into the actual hardware to get the phase
> value, but will rather get it from a variable only set by the set_phase
> function.
> 
> This will cause issue when the client driver will never call the set_phase
> function, where we can end up having a reported phase that will not match what
> the hardware has been programmed to by the bootloader or what phase is
> programmed out of reset.
> 
> Add a new get_phase function for the drivers to implement so that we can get
> this value.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/clk/clk.c            | 10 ++++++++++
>  include/linux/clk-provider.h |  5 +++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index d87661af0c72..113d75db371d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
>                 clk->accuracy = 0;
>  
>         /*
> +        * Set clk's phase.
> +        * Since a phase is by definition relative to its parent, just
> +        * query the current clock phase, or just assume it's in phase.
> +        */
> +       if (clk->ops->get_phase)
> +               clk->phase = clk->ops->get_phase(clk->hw);
> +       else
> +               clk->phase = 0;

I probably wasn't paying enough attention to this. Based on the
coverletter I thought that v3 would introduce something like
CLK_GET_PHASE_NOCACHE and stuff that logic into a __clk_get_phase
function? Looks like this version of the series doesn't handle phases
that can be changed by hardware (e.g. coming out of idle).

Correct me if I am wrong, but it looks like we retrieve the phase only
once at init and then never again? The rest of the time we rely on
clk->phase to always be accurate...

Regards,
Mike

> +
> +       /*
>          * Set clk's rate.  The preferred method is to use .recalc_rate.  For
>          * simple clocks and lazy developers the default fallback is to use the
>          * parent's rate.  If a clock doesn't have a parent (or is orphaned)
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 69b20d4c1e1a..abec961092a7 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -130,6 +130,10 @@ struct dentry;
>   *             set then clock accuracy will be initialized to parent accuracy
>   *             or 0 (perfect clock) if clock has no parent.
>   *
> + * @get_phase: Queries the hardware to get the current phase of a clock.
> + *             Returned values are 0-359 degrees on success, negative
> + *             error codes on failure.
> + *
>   * @set_phase: Shift the phase this clock signal in degrees specified
>   *             by the second argument. Valid values for degrees are
>   *             0-359. Return 0 on success, otherwise -EERROR.
> @@ -182,6 +186,7 @@ struct clk_ops {
>                                     unsigned long parent_rate, u8 index);
>         unsigned long   (*recalc_accuracy)(struct clk_hw *hw,
>                                            unsigned long parent_accuracy);
> +       int             (*get_phase)(struct clk_hw *hw);
>         int             (*set_phase)(struct clk_hw *hw, int degrees);
>         void            (*init)(struct clk_hw *hw);
>         int             (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
> -- 
> 2.1.0
> 

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

* [PATCH v3 03/12] clk: Add a function to retrieve phase
@ 2014-09-28  0:17     ` Mike Turquette
  0 siblings, 0 replies; 58+ messages in thread
From: Mike Turquette @ 2014-09-28  0:17 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Maxime Ripard (2014-09-11 13:18:17)
> The current phase API doesn't look into the actual hardware to get the phase
> value, but will rather get it from a variable only set by the set_phase
> function.
> 
> This will cause issue when the client driver will never call the set_phase
> function, where we can end up having a reported phase that will not match what
> the hardware has been programmed to by the bootloader or what phase is
> programmed out of reset.
> 
> Add a new get_phase function for the drivers to implement so that we can get
> this value.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/clk/clk.c            | 10 ++++++++++
>  include/linux/clk-provider.h |  5 +++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index d87661af0c72..113d75db371d 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
>                 clk->accuracy = 0;
>  
>         /*
> +        * Set clk's phase.
> +        * Since a phase is by definition relative to its parent, just
> +        * query the current clock phase, or just assume it's in phase.
> +        */
> +       if (clk->ops->get_phase)
> +               clk->phase = clk->ops->get_phase(clk->hw);
> +       else
> +               clk->phase = 0;

I probably wasn't paying enough attention to this. Based on the
coverletter I thought that v3 would introduce something like
CLK_GET_PHASE_NOCACHE and stuff that logic into a __clk_get_phase
function? Looks like this version of the series doesn't handle phases
that can be changed by hardware (e.g. coming out of idle).

Correct me if I am wrong, but it looks like we retrieve the phase only
once at init and then never again? The rest of the time we rely on
clk->phase to always be accurate...

Regards,
Mike

> +
> +       /*
>          * Set clk's rate.  The preferred method is to use .recalc_rate.  For
>          * simple clocks and lazy developers the default fallback is to use the
>          * parent's rate.  If a clock doesn't have a parent (or is orphaned)
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 69b20d4c1e1a..abec961092a7 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -130,6 +130,10 @@ struct dentry;
>   *             set then clock accuracy will be initialized to parent accuracy
>   *             or 0 (perfect clock) if clock has no parent.
>   *
> + * @get_phase: Queries the hardware to get the current phase of a clock.
> + *             Returned values are 0-359 degrees on success, negative
> + *             error codes on failure.
> + *
>   * @set_phase: Shift the phase this clock signal in degrees specified
>   *             by the second argument. Valid values for degrees are
>   *             0-359. Return 0 on success, otherwise -EERROR.
> @@ -182,6 +186,7 @@ struct clk_ops {
>                                     unsigned long parent_rate, u8 index);
>         unsigned long   (*recalc_accuracy)(struct clk_hw *hw,
>                                            unsigned long parent_accuracy);
> +       int             (*get_phase)(struct clk_hw *hw);
>         int             (*set_phase)(struct clk_hw *hw, int degrees);
>         void            (*init)(struct clk_hw *hw);
>         int             (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
> -- 
> 2.1.0
> 

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

* Re: [PATCH v3 03/12] clk: Add a function to retrieve phase
  2014-09-28  0:17     ` Mike Turquette
@ 2014-09-29  8:24       ` Maxime Ripard
  -1 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-29  8:24 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Hans de Goede, Emilio Lopez, chris, david.lanzendoerfer,
	ulf.hansson, devicetree, linux-arm-kernel, linux-mmc, wens

[-- Attachment #1: Type: text/plain, Size: 2436 bytes --]

Hi Mike,

On Sat, Sep 27, 2014 at 05:17:32PM -0700, Mike Turquette wrote:
> Quoting Maxime Ripard (2014-09-11 13:18:17)
> > The current phase API doesn't look into the actual hardware to get the phase
> > value, but will rather get it from a variable only set by the set_phase
> > function.
> > 
> > This will cause issue when the client driver will never call the set_phase
> > function, where we can end up having a reported phase that will not match what
> > the hardware has been programmed to by the bootloader or what phase is
> > programmed out of reset.
> > 
> > Add a new get_phase function for the drivers to implement so that we can get
> > this value.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/clk/clk.c            | 10 ++++++++++
> >  include/linux/clk-provider.h |  5 +++++
> >  2 files changed, 15 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index d87661af0c72..113d75db371d 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
> >                 clk->accuracy = 0;
> >  
> >         /*
> > +        * Set clk's phase.
> > +        * Since a phase is by definition relative to its parent, just
> > +        * query the current clock phase, or just assume it's in phase.
> > +        */
> > +       if (clk->ops->get_phase)
> > +               clk->phase = clk->ops->get_phase(clk->hw);
> > +       else
> > +               clk->phase = 0;
> 
> I probably wasn't paying enough attention to this. Based on the
> coverletter I thought that v3 would introduce something like
> CLK_GET_PHASE_NOCACHE and stuff that logic into a __clk_get_phase
> function? Looks like this version of the series doesn't handle phases
> that can be changed by hardware (e.g. coming out of idle).
> 
> Correct me if I am wrong, but it looks like we retrieve the phase only
> once at init and then never again? The rest of the time we rely on
> clk->phase to always be accurate...

Yeah, I didn't have any use for it at the moment, and thought that if
someone ever needed it, it would be trivial to add, so I left it out.

If you want me to still do it, I can send an additional patch.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v3 03/12] clk: Add a function to retrieve phase
@ 2014-09-29  8:24       ` Maxime Ripard
  0 siblings, 0 replies; 58+ messages in thread
From: Maxime Ripard @ 2014-09-29  8:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Mike,

On Sat, Sep 27, 2014 at 05:17:32PM -0700, Mike Turquette wrote:
> Quoting Maxime Ripard (2014-09-11 13:18:17)
> > The current phase API doesn't look into the actual hardware to get the phase
> > value, but will rather get it from a variable only set by the set_phase
> > function.
> > 
> > This will cause issue when the client driver will never call the set_phase
> > function, where we can end up having a reported phase that will not match what
> > the hardware has been programmed to by the bootloader or what phase is
> > programmed out of reset.
> > 
> > Add a new get_phase function for the drivers to implement so that we can get
> > this value.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  drivers/clk/clk.c            | 10 ++++++++++
> >  include/linux/clk-provider.h |  5 +++++
> >  2 files changed, 15 insertions(+)
> > 
> > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > index d87661af0c72..113d75db371d 100644
> > --- a/drivers/clk/clk.c
> > +++ b/drivers/clk/clk.c
> > @@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
> >                 clk->accuracy = 0;
> >  
> >         /*
> > +        * Set clk's phase.
> > +        * Since a phase is by definition relative to its parent, just
> > +        * query the current clock phase, or just assume it's in phase.
> > +        */
> > +       if (clk->ops->get_phase)
> > +               clk->phase = clk->ops->get_phase(clk->hw);
> > +       else
> > +               clk->phase = 0;
> 
> I probably wasn't paying enough attention to this. Based on the
> coverletter I thought that v3 would introduce something like
> CLK_GET_PHASE_NOCACHE and stuff that logic into a __clk_get_phase
> function? Looks like this version of the series doesn't handle phases
> that can be changed by hardware (e.g. coming out of idle).
> 
> Correct me if I am wrong, but it looks like we retrieve the phase only
> once at init and then never again? The rest of the time we rely on
> clk->phase to always be accurate...

Yeah, I didn't have any use for it at the moment, and thought that if
someone ever needed it, it would be trivial to add, so I left it out.

If you want me to still do it, I can send an additional patch.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140929/fa5f33c9/attachment.sig>

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

* Re: [PATCH v3 03/12] clk: Add a function to retrieve phase
  2014-09-29  8:24       ` Maxime Ripard
@ 2014-09-30  7:01         ` Mike Turquette
  -1 siblings, 0 replies; 58+ messages in thread
From: Mike Turquette @ 2014-09-30  7:01 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: devicetree, ulf.hansson, Emilio Lopez, linux-mmc, chris,
	Hans de Goede, wens, david.lanzendoerfer, linux-arm-kernel

Quoting Maxime Ripard (2014-09-29 01:24:21)
> Hi Mike,
> 
> On Sat, Sep 27, 2014 at 05:17:32PM -0700, Mike Turquette wrote:
> > Quoting Maxime Ripard (2014-09-11 13:18:17)
> > > The current phase API doesn't look into the actual hardware to get the phase
> > > value, but will rather get it from a variable only set by the set_phase
> > > function.
> > > 
> > > This will cause issue when the client driver will never call the set_phase
> > > function, where we can end up having a reported phase that will not match what
> > > the hardware has been programmed to by the bootloader or what phase is
> > > programmed out of reset.
> > > 
> > > Add a new get_phase function for the drivers to implement so that we can get
> > > this value.
> > > 
> > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > ---
> > >  drivers/clk/clk.c            | 10 ++++++++++
> > >  include/linux/clk-provider.h |  5 +++++
> > >  2 files changed, 15 insertions(+)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index d87661af0c72..113d75db371d 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
> > >                 clk->accuracy = 0;
> > >  
> > >         /*
> > > +        * Set clk's phase.
> > > +        * Since a phase is by definition relative to its parent, just
> > > +        * query the current clock phase, or just assume it's in phase.
> > > +        */
> > > +       if (clk->ops->get_phase)
> > > +               clk->phase = clk->ops->get_phase(clk->hw);
> > > +       else
> > > +               clk->phase = 0;
> > 
> > I probably wasn't paying enough attention to this. Based on the
> > coverletter I thought that v3 would introduce something like
> > CLK_GET_PHASE_NOCACHE and stuff that logic into a __clk_get_phase
> > function? Looks like this version of the series doesn't handle phases
> > that can be changed by hardware (e.g. coming out of idle).
> > 
> > Correct me if I am wrong, but it looks like we retrieve the phase only
> > once at init and then never again? The rest of the time we rely on
> > clk->phase to always be accurate...
> 
> Yeah, I didn't have any use for it at the moment, and thought that if
> someone ever needed it, it would be trivial to add, so I left it out.
> 
> If you want me to still do it, I can send an additional patch.

No it is fine. A bit asymmetrical for my brain but it is dead code if no
one is using it (yet).

Regards,
Mike

> 
> Thanks!
> Maxime
> 
> -- 
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

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

* [PATCH v3 03/12] clk: Add a function to retrieve phase
@ 2014-09-30  7:01         ` Mike Turquette
  0 siblings, 0 replies; 58+ messages in thread
From: Mike Turquette @ 2014-09-30  7:01 UTC (permalink / raw)
  To: linux-arm-kernel

Quoting Maxime Ripard (2014-09-29 01:24:21)
> Hi Mike,
> 
> On Sat, Sep 27, 2014 at 05:17:32PM -0700, Mike Turquette wrote:
> > Quoting Maxime Ripard (2014-09-11 13:18:17)
> > > The current phase API doesn't look into the actual hardware to get the phase
> > > value, but will rather get it from a variable only set by the set_phase
> > > function.
> > > 
> > > This will cause issue when the client driver will never call the set_phase
> > > function, where we can end up having a reported phase that will not match what
> > > the hardware has been programmed to by the bootloader or what phase is
> > > programmed out of reset.
> > > 
> > > Add a new get_phase function for the drivers to implement so that we can get
> > > this value.
> > > 
> > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > ---
> > >  drivers/clk/clk.c            | 10 ++++++++++
> > >  include/linux/clk-provider.h |  5 +++++
> > >  2 files changed, 15 insertions(+)
> > > 
> > > diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> > > index d87661af0c72..113d75db371d 100644
> > > --- a/drivers/clk/clk.c
> > > +++ b/drivers/clk/clk.c
> > > @@ -1934,6 +1934,16 @@ int __clk_init(struct device *dev, struct clk *clk)
> > >                 clk->accuracy = 0;
> > >  
> > >         /*
> > > +        * Set clk's phase.
> > > +        * Since a phase is by definition relative to its parent, just
> > > +        * query the current clock phase, or just assume it's in phase.
> > > +        */
> > > +       if (clk->ops->get_phase)
> > > +               clk->phase = clk->ops->get_phase(clk->hw);
> > > +       else
> > > +               clk->phase = 0;
> > 
> > I probably wasn't paying enough attention to this. Based on the
> > coverletter I thought that v3 would introduce something like
> > CLK_GET_PHASE_NOCACHE and stuff that logic into a __clk_get_phase
> > function? Looks like this version of the series doesn't handle phases
> > that can be changed by hardware (e.g. coming out of idle).
> > 
> > Correct me if I am wrong, but it looks like we retrieve the phase only
> > once at init and then never again? The rest of the time we rely on
> > clk->phase to always be accurate...
> 
> Yeah, I didn't have any use for it at the moment, and thought that if
> someone ever needed it, it would be trivial to add, so I left it out.
> 
> If you want me to still do it, I can send an additional patch.

No it is fine. A bit asymmetrical for my brain but it is dead code if no
one is using it (yet).

Regards,
Mike

> 
> Thanks!
> Maxime
> 
> -- 
> Maxime Ripard, Free Electrons
> Embedded Linux, Kernel and Android engineering
> http://free-electrons.com

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

end of thread, other threads:[~2014-09-30  7:01 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-11 20:18 [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support Maxime Ripard
2014-09-11 20:18 ` Maxime Ripard
2014-09-11 20:18 ` [PATCH v3 01/12] clk: introduce clk_set_phase function & callback Maxime Ripard
2014-09-11 20:18   ` Maxime Ripard
2014-09-24 10:41   ` Heiko Stübner
2014-09-24 10:41     ` Heiko Stübner
2014-09-11 20:18 ` [PATCH v3 02/12] clk: Include of.h in clock-provider.h Maxime Ripard
2014-09-11 20:18   ` Maxime Ripard
2014-09-11 20:18 ` [PATCH v3 03/12] clk: Add a function to retrieve phase Maxime Ripard
2014-09-11 20:18   ` Maxime Ripard
2014-09-24 10:42   ` Heiko Stübner
2014-09-24 10:42     ` Heiko Stübner
2014-09-28  0:17   ` Mike Turquette
2014-09-28  0:17     ` Mike Turquette
2014-09-29  8:24     ` Maxime Ripard
2014-09-29  8:24       ` Maxime Ripard
2014-09-30  7:01       ` Mike Turquette
2014-09-30  7:01         ` Mike Turquette
2014-09-11 20:18 ` [PATCH v3 05/12] clk: sunxi: Introduce mbus compatible Maxime Ripard
2014-09-11 20:18   ` Maxime Ripard
2014-09-11 20:18 ` [PATCH v3 07/12] clk: sunxi: Move mod0 clock to a file of its own Maxime Ripard
2014-09-11 20:18   ` Maxime Ripard
2014-09-11 20:18 ` [PATCH v3 08/12] clk: sunxi: Move mbus to mod0 file Maxime Ripard
2014-09-11 20:18   ` Maxime Ripard
     [not found] ` <1410466706-27386-1-git-send-email-maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
2014-09-11 20:18   ` [PATCH v3 04/12] clk: sunxi: factors: Invert the probing logic Maxime Ripard
2014-09-11 20:18     ` Maxime Ripard
2014-09-11 20:18   ` [PATCH v3 06/12] ARM: sunxi: dt: Switch to the new mbus compatible Maxime Ripard
2014-09-11 20:18     ` Maxime Ripard
2014-09-11 20:18   ` [PATCH v3 09/12] ARM: sunxi: dt: Add sample and output mmc clocks Maxime Ripard
2014-09-11 20:18     ` Maxime Ripard
2014-09-12 10:23     ` Chen-Yu Tsai
2014-09-12 10:23       ` Chen-Yu Tsai
2014-09-13  8:18       ` Maxime Ripard
2014-09-13  8:18         ` Maxime Ripard
2014-09-13  8:24         ` Chen-Yu Tsai
2014-09-13  8:24           ` Chen-Yu Tsai
2014-09-11 20:18 ` [PATCH v3 10/12] clk: sunxi: mod0: Introduce MMC proper phase handling Maxime Ripard
2014-09-11 20:18   ` Maxime Ripard
2014-09-11 20:18 ` [PATCH v3 11/12] mmc: sunxi: Convert MMC driver to the standard clock phase API Maxime Ripard
2014-09-11 20:18   ` Maxime Ripard
2014-09-26 14:27   ` David Lanzendörfer
2014-09-26 14:27     ` David Lanzendörfer
     [not found]     ` <3992138.y6J8TjIuMq-pgFh0Jf6HD9Xzn/AsuzBOg@public.gmane.org>
2014-09-26 15:02       ` Maxime Ripard
2014-09-26 15:02         ` Maxime Ripard
2014-09-26 20:47         ` David Lanzendörfer
2014-09-26 20:47           ` David Lanzendörfer
2014-09-11 20:18 ` [PATCH v3 12/12] clk: sunxi: Remove custom phase function Maxime Ripard
2014-09-11 20:18   ` Maxime Ripard
2014-09-12  7:22 ` [PATCH v3 00/12] clk: sunxi: Improve MMC clocks support Hans de Goede
2014-09-12  7:22   ` Hans de Goede
2014-09-22 11:31 ` Maxime Ripard
2014-09-22 11:31   ` Maxime Ripard
2014-09-26  0:42   ` Mike Turquette
2014-09-26  0:42     ` Mike Turquette
2014-09-26  6:55     ` Maxime Ripard
2014-09-26  6:55       ` Maxime Ripard
2014-09-26 17:52       ` Mike Turquette
2014-09-26 17:52         ` Mike Turquette

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