Skip to contentSkip to conversation

clk: sunxi: Improve MMC clocks support

PATCH Superseded Maxime Ripard 5 participants 23 messages Aug 30, 2014 – Sep 4, 2014

Subsystems (6)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

v2 cover clk: sunxi: Improve MMC clocks support

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 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 +++++++-
 drivers/clk/clk.c                                  |  96 ++++++-
 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 --
 18 files changed, 1019 insertions(+), 290 deletions(-)
 create mode 100644 drivers/clk/sunxi/clk-mod0.c
 delete mode 100644 include/linux/clk/sunxi.h
Signature · 1 line
2.0.2
#1 lore raw

PATCH v2 1/12 clk: introduce clk_set_phase function & callback

From: Mike Turquette <[email protected]>

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.

---
 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(-)
drivers/clk/clk.c +81 -4
index b76fa69b44cb..d87661af0c72 100644
@@ -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
include/linux/clk-private.h +1 -0
index efbf70b9fd84..845be30be50f 100644
@@ -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;
include/linux/clk-provider.h +5 -0
index 411dd7eb2653..201a6195a3eb 100644
@@ -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);
 };
include/linux/clk.h +29 -0
index fb5e097d8f72..38bdedd3e389 100644
@@ -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
 
 /**
Signature · 1 line
2.0.2
#2 lore raw

PATCH v2 2/12 clk: Include of.h in clock-provider.h

In reply to 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

---
 include/linux/clk-provider.h | 1 +
 1 file changed, 1 insertion(+)
include/linux/clk-provider.h +1 -0
index 201a6195a3eb..69b20d4c1e1a 100644
@@ -13,6 +13,7 @@
 
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/of.h>
 
 #ifdef CONFIG_COMMON_CLK
 
Signature · 1 line
2.0.2
#3 lore raw

PATCH v2 3/12 clk: Add a function to retrieve phase

In reply to 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.

---
 drivers/clk/clk.c            | 17 ++++++++++++++---
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 19 insertions(+), 3 deletions(-)
drivers/clk/clk.c +14 -3
index d87661af0c72..7dbceca694f1 100644
@@ -1797,8 +1797,8 @@ out:
  * 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.
+ * Returns the phase shift of a clock node in degrees. Any negative
+ * values are errors.
  */
 int clk_get_phase(struct clk *clk)
 {
@@ -1808,7 +1808,18 @@ int clk_get_phase(struct clk *clk)
 		goto out;
 
 	clk_prepare_lock();
-	ret = clk->phase;
+
+	if (clk->phase) {
+		ret = clk->phase;
+		goto out_unlock;
+	}
+
+	if (!clk->ops->get_phase)
+		goto out_unlock;
+
+	ret = clk->ops->get_phase(clk->hw);
+
+out_unlock:
 	clk_prepare_unlock();
 
 out:
include/linux/clk-provider.h +5 -0
index 69b20d4c1e1a..abec961092a7 100644
@@ -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);
Signature · 1 line
2.0.2
#4 lore raw

PATCH v2 3/12 clk: Add a function to retrieve phase

Hi,

Quoted 34 lines · 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.

---
 drivers/clk/clk.c            | 17 ++++++++++++++---
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 19 insertions(+), 3 deletions(-)
drivers/clk/clk.c +2 -2
index d87661af0c72..7dbceca694f1 100644
@@ -1797,8 +1797,8 @@ out:
  * 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.
+ * Returns the phase shift of a clock node in degrees. Any negative
+ * values are errors.
  */
 int clk_get_phase(struct clk *clk)
 {

drivers/clk/clk.c int clk_get_phase(struct clk *clk) · line 1815

Quoted 9 lines
drivers/clk/clk.c +5 -1
@@ -1808,7 +1808,18 @@ int clk_get_phase(struct clk *clk)
 		goto out;
 
 	clk_prepare_lock();
-	ret = clk->phase;
+
+	if (clk->phase) {
+		ret = clk->phase;
+		goto out_unlock;
+	}

0 is a valid phase, so this will cause the phase to be read from the hardware each time if the phase is 0.

Perhaps make clk->phase signed (if it is not already), init it to -1, and check for it not being -1 ?

Regards,

Hans

Quoted 34 lines
drivers/clk/clk.c +7 -0
+
+	if (!clk->ops->get_phase)
+		goto out_unlock;
+
+	ret = clk->ops->get_phase(clk->hw);
+
+out_unlock:
 	clk_prepare_unlock();
 
 out:
include/linux/clk-provider.h +5 -0
index 69b20d4c1e1a..abec961092a7 100644
@@ -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);
#5 lore raw

PATCH v2 3/12 clk: Add a function to retrieve phase

Hi,

Quoted 50 lines · Hans de Goede

Hi,

Quoted 34 lines · 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.

---
 drivers/clk/clk.c            | 17 ++++++++++++++---
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 19 insertions(+), 3 deletions(-)
drivers/clk/clk.c +2 -2
index d87661af0c72..7dbceca694f1 100644
@@ -1797,8 +1797,8 @@ out:
  * 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.
+ * Returns the phase shift of a clock node in degrees. Any negative
+ * values are errors.
  */
 int clk_get_phase(struct clk *clk)
 {

drivers/clk/clk.c int clk_get_phase(struct clk *clk) · line 1815

Quoted 9 lines
drivers/clk/clk.c +5 -1
@@ -1808,7 +1808,18 @@ int clk_get_phase(struct clk *clk)
 		goto out;
 
 	clk_prepare_lock();
-	ret = clk->phase;
+
+	if (clk->phase) {
+		ret = clk->phase;
+		goto out_unlock;
+	}

0 is a valid phase, so this will cause the phase to be read from the hardware each time if the phase is 0.

Quoted 2 lines

Perhaps make clk->phase signed (if it is not already), init it to -1, and check for it not being -1 ?

Yeah, I'm not really proud of this code either, but yours would expose this -1 into debugfs, so I'm not sure it's really better :)

(with -1 being a valid phase too)

Maxime

Signature · 10 lines
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/20140901/c1ed9049/attachment-0001.sig>
#6 lore raw

PATCH v2 3/12 clk: Add a function to retrieve phase

Hi,

Quoted 53 lines · Maxime Ripard

Hi,

Quoted 50 lines · Hans de Goede

Hi,

Quoted 34 lines · 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.

---
 drivers/clk/clk.c            | 17 ++++++++++++++---
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 19 insertions(+), 3 deletions(-)
drivers/clk/clk.c +2 -2
index d87661af0c72..7dbceca694f1 100644
@@ -1797,8 +1797,8 @@ out:
  * 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.
+ * Returns the phase shift of a clock node in degrees. Any negative
+ * values are errors.
  */
 int clk_get_phase(struct clk *clk)
 {

drivers/clk/clk.c int clk_get_phase(struct clk *clk) · line 1815

Quoted 9 lines
drivers/clk/clk.c +5 -1
@@ -1808,7 +1808,18 @@ int clk_get_phase(struct clk *clk)
 		goto out;
 
 	clk_prepare_lock();
-	ret = clk->phase;
+
+	if (clk->phase) {
+		ret = clk->phase;
+		goto out_unlock;
+	}

0 is a valid phase, so this will cause the phase to be read from the hardware each time if the phase is 0.

Quoted 7 lines
Quoted 2 lines

Perhaps make clk->phase signed (if it is not already), init it to -1, and check for it not being -1 ?

Yeah, I'm not really proud of this code either, but yours would expose this -1 into debugfs, so I'm not sure it's really better :)

(with -1 being a valid phase too)

According to the comments in the patch adding the original phase functions valid values are 0 - 359. And you could use clk_get_phase from the debugfs code.

Regards,

Hans

#7 lore raw

PATCH v2 3/12 clk: Add a function to retrieve phase

Quoted 59 lines · Hans de Goede

Hi,

Quoted 56 lines · Maxime Ripard

Hi,

Quoted 52 lines · Hans de Goede

Hi,

Quoted 34 lines · 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.

---
 drivers/clk/clk.c            | 17 ++++++++++++++---
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 19 insertions(+), 3 deletions(-)
drivers/clk/clk.c +2 -2
index d87661af0c72..7dbceca694f1 100644
@@ -1797,8 +1797,8 @@ out:
  * 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.
+ * Returns the phase shift of a clock node in degrees. Any negative
+ * values are errors.
  */
 int clk_get_phase(struct clk *clk)
 {

drivers/clk/clk.c int clk_get_phase(struct clk *clk) · line 1815

Quoted 9 lines
drivers/clk/clk.c +5 -1
@@ -1808,7 +1808,18 @@ int clk_get_phase(struct clk *clk)
 		goto out;
 
 	clk_prepare_lock();
-	ret = clk->phase;
+
+	if (clk->phase) {
+		ret = clk->phase;
+		goto out_unlock;
+	}

0 is a valid phase, so this will cause the phase to be read from the hardware each time if the phase is 0.

Perhaps make clk->phase signed (if it is not already), init it to -1, and check for it not being -1 ?

Quoted 8 lines
Quoted 4 lines

Yeah, I'm not really proud of this code either, but yours would expose this -1 into debugfs, so I'm not sure it's really better :)

(with -1 being a valid phase too)

According to the comments in the patch adding the original phase functions valid values are 0 - 359. And you could use clk_get_phase from the debugfs code.

Yep, except that if I see a value -1 as a phase, I would assume that it's 359, but maybe it's just me :)

Mike's solution seem great, I'll go for that.

Maxime

Signature · 10 lines
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/20140902/9d927a97/attachment-0001.sig>
#8 lore raw

PATCH v2 3/12 clk: Add a function to retrieve phase

Hi

Quoted 2 lines

Yep, except that if I see a value -1 as a phase, I would assume that it's 359, but maybe it's just me :)

-1 looks suspiciously like an error return value from somewhere...

Signature · 11 lines
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/20140902/1cbeee30/attachment-0001.sig>
#9 lore raw

PATCH v2 3/12 clk: Add a function to retrieve phase

In reply to Maxime Ripard

Quoting Maxime Ripard (2014-08-30 13:03:02)

Quoted 34 lines

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.

---
 drivers/clk/clk.c            | 17 ++++++++++++++---
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 19 insertions(+), 3 deletions(-)
drivers/clk/clk.c +2 -2
index d87661af0c72..7dbceca694f1 100644
@@ -1797,8 +1797,8 @@ out:
  * 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.
+ * Returns the phase shift of a clock node in degrees. Any negative
+ * values are errors.
  */
 int clk_get_phase(struct clk *clk)
 {

drivers/clk/clk.c int clk_get_phase(struct clk *clk) · line 1812

Quoted 6 lines
drivers/clk/clk.c +2 -1
@@ -1808,7 +1808,18 @@ int clk_get_phase(struct clk *clk)
                goto out;
 
        clk_prepare_lock();
-       ret = clk->phase;
+
+       if (clk->phase) {

So if a phase is zero, then we fall through and query the hardware? Seems like this case might be hit a lot for clocks that implement .get_phase but never have their phase shifted, and accesses to the registers may be much slower than to memory.

Do you expect the phase to be changed behind our backs? E.g. firmware changes it, or coming in and out of idle state, etc. If not then we can store the phase at clock registration time and use a cached value.

See how the CLK_GET_RATE_NOCACHE and CLK_GET_ACCURACY_NOCACHE flags are used for details on how we can handle the case where the phase might change behind our back.

Regards,
Mike

Quoted 39 lines
drivers/clk/clk.c +10 -0
+               ret = clk->phase;
+               goto out_unlock;
+       }
+
+       if (!clk->ops->get_phase)
+               goto out_unlock;
+
+       ret = clk->ops->get_phase(clk->hw);
+
+out_unlock:
        clk_prepare_unlock();
 
 out:
include/linux/clk-provider.h +5 -0
index 69b20d4c1e1a..abec961092a7 100644
@@ -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);
Signature · 1 line
2.0.2
#10 lore raw

PATCH v2 3/12 clk: Add a function to retrieve phase

Hi,

Quoted 37 lines · Mike Turquette

Quoting Maxime Ripard (2014-08-30 13:03:02)

Quoted 36 lines

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.

---
 drivers/clk/clk.c            | 17 ++++++++++++++---
 include/linux/clk-provider.h |  5 +++++
 2 files changed, 19 insertions(+), 3 deletions(-)
drivers/clk/clk.c +2 -2
index d87661af0c72..7dbceca694f1 100644
@@ -1797,8 +1797,8 @@ out:
  * 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.
+ * Returns the phase shift of a clock node in degrees. Any negative
+ * values are errors.
  */
 int clk_get_phase(struct clk *clk)
 {
@@ -1808,7 +1808,18 @@ int clk_get_phase(struct clk *clk)
                goto out;
 
Quoted 9 lines

drivers/clk/clk.c int clk_get_phase(struct clk *clk) · line 1812

Quoted 4 lines
drivers/clk/clk.c +2 -1
        clk_prepare_lock();
-       ret = clk->phase;
+
+       if (clk->phase) {

So if a phase is zero, then we fall through and query the hardware? Seems like this case might be hit a lot for clocks that implement .get_phase but never have their phase shifted, and accesses to the registers may be much slower than to memory.

Yep, which is exactly why I'm not that proud of it :)

Quoted 3 lines

Do you expect the phase to be changed behind our backs? E.g. firmware changes it, or coming in and out of idle state, etc. If not then we can store the phase at clock registration time and use a cached value.

This is exactly what happens in our case. Since in order to use the MMC, you have to change the phase of the output and sample clocks, every time the firmware will have to use the MMC, it will change these clocks phase. Which happens pretty much all the time.

Quoted 3 lines

See how the CLK_GET_RATE_NOCACHE and CLK_GET_ACCURACY_NOCACHE flags are used for details on how we can handle the case where the phase might change behind our back.

Ah, yes, of course. Thanks!

Maxime

Signature · 10 lines
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/20140902/a528d5ca/attachment.sig>
#11 lore raw

PATCH v2 4/12 clk: sunxi: factors: Invert the probing logic

In reply to 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.

---
 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(-)
drivers/clk/sunxi/clk-factors.c +95 -6
index 2057c8ac648f..f83ba097126c 100644
@@ -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;
+}
drivers/clk/sunxi/clk-factors.h +15 -1
index d2d0efa39379..9913840018d3 100644
@@ -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
drivers/clk/sunxi/clk-sunxi.c +3 -92

114 lines not on this page · raw message

Signature · 1 line
2.0.2
#12 lore raw

PATCH v2 5/12 clk: sunxi: Introduce mbus compatible

In reply to 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.

---
 Documentation/devicetree/bindings/clock/sunxi.txt | 1 +
 drivers/clk/sunxi/clk-sunxi.c                     | 1 +
 2 files changed, 2 insertions(+)
Documentation/devicetree/bindings/clock/sunxi.txt +1 -0
index d3a5c3c6d677..b938a990602a 100644
@@ -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
drivers/clk/sunxi/clk-sunxi.c +1 -0
index 953479041431..a3d8c633c2d6 100644
@@ -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,},
 	{}
Signature · 1 line
2.0.2
#13 lore raw

PATCH v2 6/12 ARM: sunxi: dt: Switch to the new mbus compatible

In reply to Maxime Ripard

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

---
 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(-)
arch/arm/boot/dts/sun5i-a10s.dtsi +1 -1
index d73a2287b37a..531272c0e526 100644
@@ -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";
arch/arm/boot/dts/sun5i-a13.dtsi +1 -1
index c4b5d7825b9f..b131068f4f35 100644
@@ -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";
arch/arm/boot/dts/sun7i-a20.dtsi +1 -1
index c658e343ce11..ec5603da595e 100644
@@ -346,7 +346,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";
Signature · 1 line
2.0.2
#14 lore raw

PATCH v2 7/12 clk: sunxi: Move mod0 clock to a file of its own

In reply to 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.

---
 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
drivers/clk/sunxi/Makefile +1 -0
index 6850cba35871..833f086d4a52 100644
@@ -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 \
drivers/clk/sunxi/clk-mod0.c new file +82 -0

82 lines not on this page · raw message

drivers/clk/sunxi/clk-sunxi.c +0 -1
index a3d8c633c2d6..6eec82b29bb4 100644
@@ -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,},
 	{}
 };
Signature · 1 line
2.0.2
#15 lore raw

PATCH v2 8/12 clk: sunxi: Move mbus to mod0 file

In reply to 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.

---
 drivers/clk/sunxi/clk-mod0.c  | 12 +++++++++
 drivers/clk/sunxi/clk-sunxi.c | 57 -------------------------------------------
 2 files changed, 12 insertions(+), 57 deletions(-)
drivers/clk/sunxi/clk-mod0.c +12 -0
index bce09a84ab4f..8a7f7036aea3 100644
@@ -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);
drivers/clk/sunxi/clk-sunxi.c +0 -57

87 lines not on this page · raw message

Signature · 1 line
2.0.2
#16 lore raw

PATCH v2 9/12 ARM: sunxi: dt: Add sample and output mmc clocks

In reply to Maxime Ripard

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

---
 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 +++++++++++++++++++++++++++++++++++---
 5 files changed, 430 insertions(+), 41 deletions(-)
arch/arm/boot/dts/sun4i-a10.dtsi +96 -8
index 380f914b226d..3183436528e1 100644
@@ -227,6 +227,22 @@
 			clock-output-names = "mmc0";
 		};
 
+		mmc0_output_clk: clk_mmc_output 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: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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";
 		};
arch/arm/boot/dts/sun5i-a10s.dtsi +72 -7

118 lines not on this page · raw message

arch/arm/boot/dts/sun5i-a13.dtsi +70 -10

116 lines not on this page · raw message

arch/arm/boot/dts/sun6i-a31.dtsi +96 -8

152 lines not on this page · raw message

arch/arm/boot/dts/sun7i-a20.dtsi +96 -8

152 lines not on this page · raw message

Signature · 1 line
2.0.2
#17 lore raw

PATCH v2 9/12 ARM: sunxi: dt: Add sample and output mmc clocks

Hi,

Quoted 16 lines · Maxime Ripard

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

---
 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 +++++++++++++++++++++++++++++++++++---
 5 files changed, 430 insertions(+), 41 deletions(-)
arch/arm/boot/dts/sun4i-a10.dtsi +0 -0
index 380f914b226d..3183436528e1 100644

arch/arm/boot/dts/sun4i-a10.dtsi line 230

Quoted 4 lines
arch/arm/boot/dts/sun4i-a10.dtsi +1 -0
@@ -227,6 +227,22 @@
                        clock-output-names = "mmc0";
                };
 
+               mmc0_output_clk: clk_mmc_output at 01c20088 {

Nitpick, but could we have the node name use "clk" as a suffix, like the label? And also change the node name of the original mmc clks to "mmc_clk" to differentiate.

Quoted 724 lines
arch/arm/boot/dts/sun4i-a10.dtsi +95 -8
+                       #clock-cells = <0>;
+                       compatible = "allwinner,sun4i-a10-mmc-output-clk";
+                       reg = <0x01c20088 0x4>;
+                       clocks = <&mmc0_clk>;
+                       clock-output-names = "mmc0_output";
+               };
+
+               mmc0_sample_clk: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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";
                };
arch/arm/boot/dts/sun5i-a10s.dtsi +72 -7
index 531272c0e526..4f5eb763e05a 100644
@@ -212,6 +212,22 @@
                        clock-output-names = "mmc0";
                };
 
+               mmc0_output_clk: clk_mmc_output 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: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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";
arch/arm/boot/dts/sun5i-a13.dtsi +70 -10
index b131068f4f35..73f99ff6ac6f 100644
@@ -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: clk_mmc_output 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: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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: clk_mmc_output 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: clk_mmc_sample 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";
                };
arch/arm/boot/dts/sun6i-a31.dtsi +96 -8
index 1c2ec913e650..574e6f19a0f6 100644
@@ -216,6 +216,22 @@
                        clock-output-names = "mmc0";
                };
 
+               mmc0_output_clk: clk_mmc_output 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: clk_mmc_sample 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";
@@ -224,6 +240,22 @@
                        clock-output-names = "mmc1";
                };
 
+               mmc1_output_clk: clk_mmc_output 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: clk_mmc_sample 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";
@@ -232,6 +264,22 @@
                        clock-output-names = "mmc2";
                };
 
+               mmc2_output_clk: clk_mmc_output 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: clk_mmc_sample 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";
@@ -240,6 +288,22 @@
                        clock-output-names = "mmc3";
                };
 
+               mmc3_output_clk: clk_mmc_output 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: clk_mmc_sample 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";
@@ -330,8 +394,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>;
@@ -341,8 +411,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>;
@@ -352,8 +428,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>;
@@ -363,8 +445,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>;
arch/arm/boot/dts/sun7i-a20.dtsi +89 -8
index ec5603da595e..fc0a90d54d63 100644
@@ -239,6 +239,22 @@
                        clock-output-names = "mmc0";
                };
 
+               mmc0_output_clk: clk_mmc_output 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: clk_mmc_sample 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";
@@ -247,6 +263,22 @@
                        clock-output-names = "mmc1";
                };
 
+               mmc1_output_clk: clk_mmc_output 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: clk_mmc_sample 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";
@@ -255,6 +287,22 @@
                        clock-output-names = "mmc2";
                };
 
+               mmc2_output_clk: clk_mmc_output 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: clk_mmc_sample 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";
@@ -263,6 +311,22 @@
                        clock-output-names = "mmc3";
                };
 
+               mmc3_output_clk: clk_mmc_output 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: clk_mmc_sample 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";
@@ -476,8 +540,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";
                };
@@ -485,8 +555,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";
                };
@@ -494,8 +570,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";
                };
@@ -503,8 +585,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>,

arch/arm/boot/dts/sun7i-a20.dtsi line 598

Quoted 10 lines
arch/arm/boot/dts/sun7i-a20.dtsi +7 -0
+                                <&mmc3_clk>,
+                                <&mmc3_sample_clk>,
+                                <&mmc3_output_clk>;
+                       clock-names = "ahb",
+                                     "mmc",
+                                     "sample",
+                                     "output";
                        interrupts = <0 35 4>;
                        status = "disabled";
                };

Also sun8i is missing from this patch. I can add that later.

Thanks

ChenYu

#18 lore raw

PATCH v2 10/12 clk: sunxi: mod0: Introduce MMC proper phase handling

In reply to 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.

---
 Documentation/devicetree/bindings/clock/sunxi.txt |   2 +
 drivers/clk/sunxi/clk-mod0.c                      | 189 ++++++++++++++++++++++
 2 files changed, 191 insertions(+)
Documentation/devicetree/bindings/clock/sunxi.txt +2 -0
index b938a990602a..eb690ed92a53 100644
@@ -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
drivers/clk/sunxi/clk-mod0.c +189 -0

198 lines not on this page · raw message

Signature · 1 line
2.0.2
#19 lore raw

PATCH v2 10/12 clk: sunxi: mod0: Introduce MMC proper phase handling

Quoting Maxime Ripard (2014-08-30 13:03:09)

Quoted 8 lines

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

Quoted 8 lines

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.

Looks good. Thanks a lot for revisiting this after talking to your hardware team!

Regards,
Mike

Quoted 225 lines
---
 Documentation/devicetree/bindings/clock/sunxi.txt |   2 +
 drivers/clk/sunxi/clk-mod0.c                      | 189 ++++++++++++++++++++++
 2 files changed, 191 insertions(+)
Documentation/devicetree/bindings/clock/sunxi.txt +2 -0
index b938a990602a..eb690ed92a53 100644
@@ -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
drivers/clk/sunxi/clk-mod0.c +189 -0
index 8a7f7036aea3..4a563850ee6e 100644
@@ -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);
Signature · 1 line
2.0.2
#20 lore raw

PATCH v2 10/12 clk: sunxi: mod0: Introduce MMC proper phase handling

Hi,

Quoted 12 lines · Mike Turquette

Quoting Maxime Ripard (2014-08-30 13:03:09)

Quoted 11 lines

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.

Quoted 8 lines
Quoted 5 lines

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.

Looks good. Thanks a lot for revisiting this after talking to your hardware team!

It's not *our* hardware team, but I'll let them know :)

Maxime

Signature · 10 lines
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/20140902/3984ede1/attachment-0001.sig>
#21 lore raw

PATCH v2 11/12 mmc: sunxi: Convert MMC driver to the standard clock phase API

In reply to 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.

---
 .../devicetree/bindings/mmc/sunxi-mmc.txt          |  8 +--
 drivers/mmc/host/sunxi-mmc.c                       | 72 +++++++++++++++-------
 2 files changed, 53 insertions(+), 27 deletions(-)
Documentation/devicetree/bindings/mmc/sunxi-mmc.txt +4 -4
index 91b3a3467150..4bf41d833804 100644
@@ -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";
 	};
drivers/mmc/host/sunxi-mmc.c +49 -23

126 lines not on this page · raw message

Signature · 1 line
2.0.2
#22 lore raw

PATCH v2 12/12 clk: sunxi: Remove custom phase function

In reply to 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.

---
 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
drivers/clk/sunxi/clk-sunxi.c +0 -37
index 4e189be3e23f..e46f3f2748d3 100644
@@ -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
  */
 
include/linux/clk/sunxi.h deleted +0 -22
deleted file mode 100644
index aed28c4451d9..000000000000
@@ -1,22 +0,0 @@
-/*
- * Copyright 2013 - Hans de Goede <[email protected]>
- *
- * 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
Signature · 1 line
2.0.2