diff mbox

[4/9] clk: sunxi-ng: mux: Add support for mux tables

Message ID 1469516671-19377-5-git-send-email-wens@csie.org (mailing list archive)
State Superseded
Delegated to: Stephen Boyd
Headers show

Commit Message

Chen-Yu Tsai July 26, 2016, 7:04 a.m. UTC
Some clock muxes have holes, i.e. invalid or unconnected inputs,
between parent mux values.

Add support for specifying a mux table to map clock parents to
mux values.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
---
 drivers/clk/sunxi-ng/ccu_mux.c | 12 ++++++++++++
 drivers/clk/sunxi-ng/ccu_mux.h | 12 ++++++++++--
 2 files changed, 22 insertions(+), 2 deletions(-)

Comments

Jean-Francois Moine July 26, 2016, 5:43 p.m. UTC | #1
On Tue, 26 Jul 2016 15:04:26 +0800
Chen-Yu Tsai <wens@csie.org> wrote:

> Some clock muxes have holes, i.e. invalid or unconnected inputs,
> between parent mux values.
> 
> Add support for specifying a mux table to map clock parents to
> mux values.

Putting empty strings in the holes should work. No?
Ex:

static const char * const csi_mclk_parents[] =
	{ "pll-video0", "pll-video1", "", "", "", "osc24M" };
Maxime Ripard July 27, 2016, 6:48 a.m. UTC | #2
On Tue, Jul 26, 2016 at 03:04:26PM +0800, Chen-Yu Tsai wrote:
> Some clock muxes have holes, i.e. invalid or unconnected inputs,
> between parent mux values.
> 
> Add support for specifying a mux table to map clock parents to
> mux values.
> 
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
> ---
>  drivers/clk/sunxi-ng/ccu_mux.c | 12 ++++++++++++
>  drivers/clk/sunxi-ng/ccu_mux.h | 12 ++++++++++--
>  2 files changed, 22 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
> index 1329b9ab481e..68b32f168a74 100644
> --- a/drivers/clk/sunxi-ng/ccu_mux.c
> +++ b/drivers/clk/sunxi-ng/ccu_mux.c
> @@ -107,6 +107,15 @@ u8 ccu_mux_helper_get_parent(struct ccu_common *common,
>  	parent = reg >> cm->shift;
>  	parent &= (1 << cm->width) - 1;
>  
> +	if (cm->table) {
> +		int num_parents = clk_hw_get_num_parents(&common->hw);
> +		int i;
> +
> +		for (i = 0; i < num_parents; i++)
> +			if (cm->table[i] == parent)
> +				return i;
> +	}
> +
>  	return parent;
>  }
>  
> @@ -117,6 +126,9 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
>  	unsigned long flags;
>  	u32 reg;
>  
> +	if (cm->table)
> +		index = cm->table[index];
> +
>  	spin_lock_irqsave(common->lock, flags);
>  
>  	reg = readl(common->base + common->reg);
> diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
> index d35ce5e93840..f0078de78712 100644
> --- a/drivers/clk/sunxi-ng/ccu_mux.h
> +++ b/drivers/clk/sunxi-ng/ccu_mux.h
> @@ -6,8 +6,9 @@
>  #include "ccu_common.h"
>  
>  struct ccu_mux_internal {
> -	u8	shift;
> -	u8	width;
> +	u8		shift;
> +	u8		width;
> +	const u8	*table;
>  
>  	struct {
>  		u8	index;
> @@ -21,6 +22,13 @@ struct ccu_mux_internal {
>  	} variable_prediv;
>  };
>  
> +#define SUNXI_CLK_MUX_TABLE(_shift, _width, _table)	\
> +	{						\
> +		.shift	= _shift,			\
> +		.width	= _width,			\
> +		.table	= _table,			\
> +	}
> +

I basically had the exact same patch done a few days ago :)

This is in my A64 serie, together with some cleanup on that macro that
is not consistent with the other internal structures.

Maxime
Maxime Ripard July 27, 2016, 6:59 a.m. UTC | #3
On Tue, Jul 26, 2016 at 07:43:06PM +0200, Jean-Francois Moine wrote:
> On Tue, 26 Jul 2016 15:04:26 +0800
> Chen-Yu Tsai <wens@csie.org> wrote:
> 
> > Some clock muxes have holes, i.e. invalid or unconnected inputs,
> > between parent mux values.
> > 
> > Add support for specifying a mux table to map clock parents to
> > mux values.
> 
> Putting empty strings in the holes should work. No?
> Ex:
> 
> static const char * const csi_mclk_parents[] =
> 	{ "pll-video0", "pll-video1", "", "", "", "osc24M" };

Not really. The clock would be declared as orphan, while it's really
not.

Parenting functions would also not work as expected,
clk_hw_get_parent_by_index being the obvious example, in that case
returning the empty string for an invalid parent, while it should
really return NULL.

Maxime
Jean-Francois Moine July 27, 2016, 7:18 a.m. UTC | #4
On Wed, 27 Jul 2016 08:59:34 +0200
Maxime Ripard <maxime.ripard@free-electrons.com> wrote:

> On Tue, Jul 26, 2016 at 07:43:06PM +0200, Jean-Francois Moine wrote:
> > On Tue, 26 Jul 2016 15:04:26 +0800
> > Chen-Yu Tsai <wens@csie.org> wrote:
> > 
> > > Some clock muxes have holes, i.e. invalid or unconnected inputs,
> > > between parent mux values.
> > > 
> > > Add support for specifying a mux table to map clock parents to
> > > mux values.
> > 
> > Putting empty strings in the holes should work. No?
> > Ex:
> > 
> > static const char * const csi_mclk_parents[] =
> > 	{ "pll-video0", "pll-video1", "", "", "", "osc24M" };
> 
> Not really. The clock would be declared as orphan, while it's really
> not.
> 
> Parenting functions would also not work as expected,
> clk_hw_get_parent_by_index being the obvious example, in that case
> returning the empty string for an invalid parent, while it should
> really return NULL.

I don't see why the clock should be orphan.
Then, when a parent is "", clk_hw_get_parent_by_index() returns NULL.
Chen-Yu Tsai July 27, 2016, 7:30 a.m. UTC | #5
On Wed, Jul 27, 2016 at 3:18 PM, Jean-Francois Moine <moinejf@free.fr> wrote:
> On Wed, 27 Jul 2016 08:59:34 +0200
> Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
>
>> On Tue, Jul 26, 2016 at 07:43:06PM +0200, Jean-Francois Moine wrote:
>> > On Tue, 26 Jul 2016 15:04:26 +0800
>> > Chen-Yu Tsai <wens@csie.org> wrote:
>> >
>> > > Some clock muxes have holes, i.e. invalid or unconnected inputs,
>> > > between parent mux values.
>> > >
>> > > Add support for specifying a mux table to map clock parents to
>> > > mux values.
>> >
>> > Putting empty strings in the holes should work. No?
>> > Ex:
>> >
>> > static const char * const csi_mclk_parents[] =
>> >     { "pll-video0", "pll-video1", "", "", "", "osc24M" };
>>
>> Not really. The clock would be declared as orphan, while it's really
>> not.
>>
>> Parenting functions would also not work as expected,
>> clk_hw_get_parent_by_index being the obvious example, in that case
>> returning the empty string for an invalid parent, while it should
>> really return NULL.
>
> I don't see why the clock should be orphan.
> Then, when a parent is "", clk_hw_get_parent_by_index() returns NULL.

There's no requirement for parent clk indexes to match the actual
register value, is there?

ChenYu
--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Maxime Ripard July 27, 2016, 7:40 a.m. UTC | #6
On Wed, Jul 27, 2016 at 09:18:27AM +0200, Jean-Francois Moine wrote:
> On Wed, 27 Jul 2016 08:59:34 +0200
> Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> 
> > On Tue, Jul 26, 2016 at 07:43:06PM +0200, Jean-Francois Moine wrote:
> > > On Tue, 26 Jul 2016 15:04:26 +0800
> > > Chen-Yu Tsai <wens@csie.org> wrote:
> > > 
> > > > Some clock muxes have holes, i.e. invalid or unconnected inputs,
> > > > between parent mux values.
> > > > 
> > > > Add support for specifying a mux table to map clock parents to
> > > > mux values.
> > > 
> > > Putting empty strings in the holes should work. No?
> > > Ex:
> > > 
> > > static const char * const csi_mclk_parents[] =
> > > 	{ "pll-video0", "pll-video1", "", "", "", "osc24M" };
> > 
> > Not really. The clock would be declared as orphan, while it's really
> > not.
> > 
> > Parenting functions would also not work as expected,
> > clk_hw_get_parent_by_index being the obvious example, in that case
> > returning the empty string for an invalid parent, while it should
> > really return NULL.
> 
> I don't see why the clock should be orphan.
> Then, when a parent is "", clk_hw_get_parent_by_index() returns NULL.

Why? It should return NULL when there's no parent, while you
explicitly registered a parent.

Maxime
Jean-Francois Moine July 27, 2016, 8:36 a.m. UTC | #7
On Wed, 27 Jul 2016 09:40:20 +0200
Maxime Ripard <maxime.ripard@free-electrons.com> wrote:

> > > Parenting functions would also not work as expected,
> > > clk_hw_get_parent_by_index being the obvious example, in that case
> > > returning the empty string for an invalid parent, while it should
> > > really return NULL.
> > 
> > I don't see why the clock should be orphan.
> > Then, when a parent is "", clk_hw_get_parent_by_index() returns NULL.
> 
> Why? It should return NULL when there's no parent, while you
> explicitly registered a parent.

"" is not an existing parent. It could be "none" / "dum" / "toto" / ...
with the same result: 'this index cannot be used in mux'.
Maxime Ripard July 28, 2016, 1:28 p.m. UTC | #8
On Wed, Jul 27, 2016 at 10:36:49AM +0200, Jean-Francois Moine wrote:
> On Wed, 27 Jul 2016 09:40:20 +0200
> Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> 
> > > > Parenting functions would also not work as expected,
> > > > clk_hw_get_parent_by_index being the obvious example, in that case
> > > > returning the empty string for an invalid parent, while it should
> > > > really return NULL.
> > > 
> > > I don't see why the clock should be orphan.
> > > Then, when a parent is "", clk_hw_get_parent_by_index() returns NULL.
> > 
> > Why? It should return NULL when there's no parent, while you
> > explicitly registered a parent.
> 
> "" is not an existing parent. It could be "none" / "dum" / "toto" / ...
> with the same result: 'this index cannot be used in mux'.

And the clock is marked as orphan, while it really isn't.
Jean-Francois Moine July 28, 2016, 2:23 p.m. UTC | #9
On Thu, 28 Jul 2016 15:28:42 +0200
Maxime Ripard <maxime.ripard@free-electrons.com> wrote:

> On Wed, Jul 27, 2016 at 10:36:49AM +0200, Jean-Francois Moine wrote:
> > On Wed, 27 Jul 2016 09:40:20 +0200
> > Maxime Ripard <maxime.ripard@free-electrons.com> wrote:
> > 
> > > > > Parenting functions would also not work as expected,
> > > > > clk_hw_get_parent_by_index being the obvious example, in that case
> > > > > returning the empty string for an invalid parent, while it should
> > > > > really return NULL.
> > > > 
> > > > I don't see why the clock should be orphan.
> > > > Then, when a parent is "", clk_hw_get_parent_by_index() returns NULL.
> > > 
> > > Why? It should return NULL when there's no parent, while you
> > > explicitly registered a parent.
> > 
> > "" is not an existing parent. It could be "none" / "dum" / "toto" / ...
> > with the same result: 'this index cannot be used in mux'.
> 
> And the clock is marked as orphan, while it really isn't.

Sorry for I don't follow you.

A clock is orphan when it has no parent. In our case, there are many
possible parents and, at startup time, the hardware or the boot sets
the mux to point to a real parent, with an index out of the usused
values.
Yes, the clock may be orphan, as the other clocks, but just the time
this real parent becomes visible.

So, how could such a clock stay marked as orphan?
diff mbox

Patch

diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index 1329b9ab481e..68b32f168a74 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -107,6 +107,15 @@  u8 ccu_mux_helper_get_parent(struct ccu_common *common,
 	parent = reg >> cm->shift;
 	parent &= (1 << cm->width) - 1;
 
+	if (cm->table) {
+		int num_parents = clk_hw_get_num_parents(&common->hw);
+		int i;
+
+		for (i = 0; i < num_parents; i++)
+			if (cm->table[i] == parent)
+				return i;
+	}
+
 	return parent;
 }
 
@@ -117,6 +126,9 @@  int ccu_mux_helper_set_parent(struct ccu_common *common,
 	unsigned long flags;
 	u32 reg;
 
+	if (cm->table)
+		index = cm->table[index];
+
 	spin_lock_irqsave(common->lock, flags);
 
 	reg = readl(common->base + common->reg);
diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
index d35ce5e93840..f0078de78712 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.h
+++ b/drivers/clk/sunxi-ng/ccu_mux.h
@@ -6,8 +6,9 @@ 
 #include "ccu_common.h"
 
 struct ccu_mux_internal {
-	u8	shift;
-	u8	width;
+	u8		shift;
+	u8		width;
+	const u8	*table;
 
 	struct {
 		u8	index;
@@ -21,6 +22,13 @@  struct ccu_mux_internal {
 	} variable_prediv;
 };
 
+#define SUNXI_CLK_MUX_TABLE(_shift, _width, _table)	\
+	{						\
+		.shift	= _shift,			\
+		.width	= _width,			\
+		.table	= _table,			\
+	}
+
 #define SUNXI_CLK_MUX(_shift, _width)	\
 	{					\
 		.shift	= _shift,		\