Re: [PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-23 Thread Maxime Ripard
On Mon, Aug 08, 2016 at 06:21:45PM +0100, Andre Przywara wrote:
> The Allwinner H3 SoC introduced bus clock gates with potentially
> different parents per clock gate register. The H3 driver chose to
> hardcode the actual parent clock relation in the code.
> Add a new driver (which has the potential to drive the H3 and also
> the simple clock gates as well) which uses the power of DT to describe
> this relationship in an elegant and flexible way.
> Using one subnode for every parent clock we get away with a single
> DT compatible match, which can be used as a fallback value in the
> actual DTs without the need to add specific compatible strings to the
> code.  This avoids adding a new driver or function for every new SoC.
> 
> Signed-off-by: Andre Przywara 
> Acked-by: Jean-Francois Moine 
> ---
>  drivers/clk/sunxi/Makefile  |   1 +
>  drivers/clk/sunxi/clk-multi-gates.c | 105 
> 

Aside from my initial objections (that I still have),
drivers/clk/sunxi is in maintainance-only mode, we won't merge any new
drivers there.

Maxime

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


signature.asc
Description: PGP signature


Re: [PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-23 Thread Maxime Ripard
On Mon, Aug 08, 2016 at 06:21:45PM +0100, Andre Przywara wrote:
> The Allwinner H3 SoC introduced bus clock gates with potentially
> different parents per clock gate register. The H3 driver chose to
> hardcode the actual parent clock relation in the code.
> Add a new driver (which has the potential to drive the H3 and also
> the simple clock gates as well) which uses the power of DT to describe
> this relationship in an elegant and flexible way.
> Using one subnode for every parent clock we get away with a single
> DT compatible match, which can be used as a fallback value in the
> actual DTs without the need to add specific compatible strings to the
> code.  This avoids adding a new driver or function for every new SoC.
> 
> Signed-off-by: Andre Przywara 
> Acked-by: Jean-Francois Moine 
> ---
>  drivers/clk/sunxi/Makefile  |   1 +
>  drivers/clk/sunxi/clk-multi-gates.c | 105 
> 

Aside from my initial objections (that I still have),
drivers/clk/sunxi is in maintainance-only mode, we won't merge any new
drivers there.

Maxime

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


signature.asc
Description: PGP signature


Re: [linux-sunxi] Re: [PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-09 Thread Jean-Francois Moine
On Tue, 9 Aug 2016 18:02:47 +0800
Chen-Yu Tsai  wrote:

> > The 'parent's of the bus gates are of no interest.
> > They are supposed to be (no clear documentation) apb1, apb2, ahb1 and
> > ahb2, but, as you well noticed in the patch 5/7, these clocks are fixed
> > and have no gate. Some of them are parents of real clocks, but they
> > don't bring anything to the bus gates of the other clocks.
> 
> Yes they are. Some devices, such as UARTs and I2C controllers, need
> to get the clock rate of the gate and calculate the proper internal
> divider.

You are right, the clocks of some subsystems have only a gate, but
these are exceptions.

Look at an ordinary clock, say the mmc0 of the H3.
There is a "bus" gate (see below) in the CCU register 0x60, bit 8, and
the "clock" gate in the CCU register 0x88, bit 31.

The 'simple-gates' says that the "bus gate" is child of ahb1 (in all
sunxi versions, the one prior to 'simple-gate', in the 'simple-gate',
in 'sunxi-ng', and now in André's patch).

But, where do you see a hardware relation between the mmc0 clock and
the ahb1 clock?

> > As I wrote previously, the simplest is to ungate/gate the clocks in
> > both the bus and clock registers on clk_prepare/unprepare.
> > Then, your 'multi-bus-gates' would be simply a generic 'multi-gates'.
> 
> This is somewhat misleading. What "clock" registers are you referring
> to? There are no "bus" registers. The reason we call them "bus clock
> gates" is because they are mashed together, instead of having clearly
> separated registers for each AHB/APB bus.
> 
> And if you want just a generic clock gates driver, we already have
> the "simple-gates" driver.

Maybe I used the wrong words.

The "clock" register is the one which defines the parameters of the
clock (parents, mul/div factors, gate). For the H3 mmc0, it is the
CCU register 0x60.

The "bus" register is one of the so-called "Bus Clock Gating Register"s.
For the H3 mmc0, it is the CCU register 0x88.   

-- 
Ken ar c'hentañ | ** Breizh ha Linux atav! **
Jef |   http://moinejf.free.fr/


Re: [linux-sunxi] Re: [PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-09 Thread Jean-Francois Moine
On Tue, 9 Aug 2016 18:02:47 +0800
Chen-Yu Tsai  wrote:

> > The 'parent's of the bus gates are of no interest.
> > They are supposed to be (no clear documentation) apb1, apb2, ahb1 and
> > ahb2, but, as you well noticed in the patch 5/7, these clocks are fixed
> > and have no gate. Some of them are parents of real clocks, but they
> > don't bring anything to the bus gates of the other clocks.
> 
> Yes they are. Some devices, such as UARTs and I2C controllers, need
> to get the clock rate of the gate and calculate the proper internal
> divider.

You are right, the clocks of some subsystems have only a gate, but
these are exceptions.

Look at an ordinary clock, say the mmc0 of the H3.
There is a "bus" gate (see below) in the CCU register 0x60, bit 8, and
the "clock" gate in the CCU register 0x88, bit 31.

The 'simple-gates' says that the "bus gate" is child of ahb1 (in all
sunxi versions, the one prior to 'simple-gate', in the 'simple-gate',
in 'sunxi-ng', and now in André's patch).

But, where do you see a hardware relation between the mmc0 clock and
the ahb1 clock?

> > As I wrote previously, the simplest is to ungate/gate the clocks in
> > both the bus and clock registers on clk_prepare/unprepare.
> > Then, your 'multi-bus-gates' would be simply a generic 'multi-gates'.
> 
> This is somewhat misleading. What "clock" registers are you referring
> to? There are no "bus" registers. The reason we call them "bus clock
> gates" is because they are mashed together, instead of having clearly
> separated registers for each AHB/APB bus.
> 
> And if you want just a generic clock gates driver, we already have
> the "simple-gates" driver.

Maybe I used the wrong words.

The "clock" register is the one which defines the parameters of the
clock (parents, mul/div factors, gate). For the H3 mmc0, it is the
CCU register 0x60.

The "bus" register is one of the so-called "Bus Clock Gating Register"s.
For the H3 mmc0, it is the CCU register 0x88.   

-- 
Ken ar c'hentañ | ** Breizh ha Linux atav! **
Jef |   http://moinejf.free.fr/


Re: [linux-sunxi] Re: [PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-09 Thread Chen-Yu Tsai
On Tue, Aug 9, 2016 at 2:15 AM, Jean-Francois Moine  wrote:
> On Mon,  8 Aug 2016 18:21:45 +0100
> Andre Przywara  wrote:
>
>> The Allwinner H3 SoC introduced bus clock gates with potentially
>> different parents per clock gate register. The H3 driver chose to
>> hardcode the actual parent clock relation in the code.
>> Add a new driver (which has the potential to drive the H3 and also
>> the simple clock gates as well) which uses the power of DT to describe
>> this relationship in an elegant and flexible way.
>> Using one subnode for every parent clock we get away with a single
>> DT compatible match, which can be used as a fallback value in the
>> actual DTs without the need to add specific compatible strings to the
>> code.  This avoids adding a new driver or function for every new SoC.
>
> The 'parent's of the bus gates are of no interest.
> They are supposed to be (no clear documentation) apb1, apb2, ahb1 and
> ahb2, but, as you well noticed in the patch 5/7, these clocks are fixed
> and have no gate. Some of them are parents of real clocks, but they
> don't bring anything to the bus gates of the other clocks.

Yes they are. Some devices, such as UARTs and I2C controllers, need
to get the clock rate of the gate and calculate the proper internal
divider.

> As I wrote previously, the simplest is to ungate/gate the clocks in
> both the bus and clock registers on clk_prepare/unprepare.
> Then, your 'multi-bus-gates' would be simply a generic 'multi-gates'.

This is somewhat misleading. What "clock" registers are you referring
to? There are no "bus" registers. The reason we call them "bus clock
gates" is because they are mashed together, instead of having clearly
separated registers for each AHB/APB bus.

And if you want just a generic clock gates driver, we already have
the "simple-gates" driver.

Regards
ChenYu


Re: [linux-sunxi] Re: [PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-09 Thread Chen-Yu Tsai
On Tue, Aug 9, 2016 at 2:15 AM, Jean-Francois Moine  wrote:
> On Mon,  8 Aug 2016 18:21:45 +0100
> Andre Przywara  wrote:
>
>> The Allwinner H3 SoC introduced bus clock gates with potentially
>> different parents per clock gate register. The H3 driver chose to
>> hardcode the actual parent clock relation in the code.
>> Add a new driver (which has the potential to drive the H3 and also
>> the simple clock gates as well) which uses the power of DT to describe
>> this relationship in an elegant and flexible way.
>> Using one subnode for every parent clock we get away with a single
>> DT compatible match, which can be used as a fallback value in the
>> actual DTs without the need to add specific compatible strings to the
>> code.  This avoids adding a new driver or function for every new SoC.
>
> The 'parent's of the bus gates are of no interest.
> They are supposed to be (no clear documentation) apb1, apb2, ahb1 and
> ahb2, but, as you well noticed in the patch 5/7, these clocks are fixed
> and have no gate. Some of them are parents of real clocks, but they
> don't bring anything to the bus gates of the other clocks.

Yes they are. Some devices, such as UARTs and I2C controllers, need
to get the clock rate of the gate and calculate the proper internal
divider.

> As I wrote previously, the simplest is to ungate/gate the clocks in
> both the bus and clock registers on clk_prepare/unprepare.
> Then, your 'multi-bus-gates' would be simply a generic 'multi-gates'.

This is somewhat misleading. What "clock" registers are you referring
to? There are no "bus" registers. The reason we call them "bus clock
gates" is because they are mashed together, instead of having clearly
separated registers for each AHB/APB bus.

And if you want just a generic clock gates driver, we already have
the "simple-gates" driver.

Regards
ChenYu


Re: [PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-08 Thread Jean-Francois Moine
On Mon,  8 Aug 2016 18:21:45 +0100
Andre Przywara  wrote:

> The Allwinner H3 SoC introduced bus clock gates with potentially
> different parents per clock gate register. The H3 driver chose to
> hardcode the actual parent clock relation in the code.
> Add a new driver (which has the potential to drive the H3 and also
> the simple clock gates as well) which uses the power of DT to describe
> this relationship in an elegant and flexible way.
> Using one subnode for every parent clock we get away with a single
> DT compatible match, which can be used as a fallback value in the
> actual DTs without the need to add specific compatible strings to the
> code.  This avoids adding a new driver or function for every new SoC.

The 'parent's of the bus gates are of no interest.
They are supposed to be (no clear documentation) apb1, apb2, ahb1 and
ahb2, but, as you well noticed in the patch 5/7, these clocks are fixed
and have no gate. Some of them are parents of real clocks, but they
don't bring anything to the bus gates of the other clocks.

As I wrote previously, the simplest is to ungate/gate the clocks in
both the bus and clock registers on clk_prepare/unprepare.
Then, your 'multi-bus-gates' would be simply a generic 'multi-gates'.

-- 
Ken ar c'hentañ | ** Breizh ha Linux atav! **
Jef |   http://moinejf.free.fr/


Re: [PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-08 Thread Jean-Francois Moine
On Mon,  8 Aug 2016 18:21:45 +0100
Andre Przywara  wrote:

> The Allwinner H3 SoC introduced bus clock gates with potentially
> different parents per clock gate register. The H3 driver chose to
> hardcode the actual parent clock relation in the code.
> Add a new driver (which has the potential to drive the H3 and also
> the simple clock gates as well) which uses the power of DT to describe
> this relationship in an elegant and flexible way.
> Using one subnode for every parent clock we get away with a single
> DT compatible match, which can be used as a fallback value in the
> actual DTs without the need to add specific compatible strings to the
> code.  This avoids adding a new driver or function for every new SoC.

The 'parent's of the bus gates are of no interest.
They are supposed to be (no clear documentation) apb1, apb2, ahb1 and
ahb2, but, as you well noticed in the patch 5/7, these clocks are fixed
and have no gate. Some of them are parents of real clocks, but they
don't bring anything to the bus gates of the other clocks.

As I wrote previously, the simplest is to ungate/gate the clocks in
both the bus and clock registers on clk_prepare/unprepare.
Then, your 'multi-bus-gates' would be simply a generic 'multi-gates'.

-- 
Ken ar c'hentañ | ** Breizh ha Linux atav! **
Jef |   http://moinejf.free.fr/


[PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-08 Thread Andre Przywara
The Allwinner H3 SoC introduced bus clock gates with potentially
different parents per clock gate register. The H3 driver chose to
hardcode the actual parent clock relation in the code.
Add a new driver (which has the potential to drive the H3 and also
the simple clock gates as well) which uses the power of DT to describe
this relationship in an elegant and flexible way.
Using one subnode for every parent clock we get away with a single
DT compatible match, which can be used as a fallback value in the
actual DTs without the need to add specific compatible strings to the
code.  This avoids adding a new driver or function for every new SoC.

Signed-off-by: Andre Przywara 
Acked-by: Jean-Francois Moine 
---
 drivers/clk/sunxi/Makefile  |   1 +
 drivers/clk/sunxi/clk-multi-gates.c | 105 
 2 files changed, 106 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk-multi-gates.c

diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 39d2044..caf2bf6 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -14,6 +14,7 @@ obj-y += clk-simple-gates.o
 obj-y += clk-sun4i-display.o
 obj-y += clk-sun4i-pll3.o
 obj-y += clk-sun4i-tcon-ch1.o
+obj-y += clk-multi-gates.o
 obj-y += clk-sun8i-bus-gates.o
 obj-y += clk-sun8i-mbus.o
 obj-y += clk-sun9i-core.o
diff --git a/drivers/clk/sunxi/clk-multi-gates.c 
b/drivers/clk/sunxi/clk-multi-gates.c
new file mode 100644
index 000..76e715a
--- /dev/null
+++ b/drivers/clk/sunxi/clk-multi-gates.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * Based on clk-sun8i-bus-gates.c, which is:
+ *  Copyright (C) 2015 Jens Kuske 
+ * Based on clk-simple-gates.c, which is:
+ *  Copyright 2015 Maxime Ripard 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static DEFINE_SPINLOCK(gates_lock);
+
+static void __init sunxi_parse_parent(struct device_node *node,
+ struct clk_onecell_data *clk_data,
+ void __iomem *reg)
+{
+   const char *parent = of_clk_get_parent_name(node, 0);
+   const char *clk_name;
+   struct property *prop;
+   struct clk *clk;
+   const __be32 *p;
+   int index, i = 0;
+
+   of_property_for_each_u32(node, "clock-indices", prop, p, index) {
+   of_property_read_string_index(node, "clock-output-names",
+ i, _name);
+
+   clk = clk_register_gate(NULL, clk_name, parent, 0,
+   reg + 4 * (index / 32), index % 32,
+   0, _lock);
+   i++;
+   if (IS_ERR(clk)) {
+   pr_warn("could not register gate clock \"%s\"\n",
+   clk_name);
+   continue;
+   }
+   if (clk_data->clks[index])
+   pr_warn("bus-gate clock %s: index #%d already 
registered as %s\n",
+   clk_name, index, "?");
+   else
+   clk_data->clks[index] = clk;
+   }
+}
+
+static void __init sunxi_multi_bus_gates_init(struct device_node *node)
+{
+   struct clk_onecell_data *clk_data;
+   struct device_node *child;
+   struct property *prop;
+   struct resource res;
+   void __iomem *reg;
+   const __be32 *p;
+   int number = 0;
+   int index;
+
+   reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+   if (IS_ERR(reg))
+   return;
+
+   clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+   if (!clk_data)
+   goto err_unmap;
+
+   for_each_child_of_node(node, child)
+   of_property_for_each_u32(child, "clock-indices", prop, p, index)
+   number = max(number, index);
+
+   clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL);
+   if (!clk_data->clks)
+   goto err_free_data;
+
+   for_each_child_of_node(node, child)
+   sunxi_parse_parent(child, clk_data, reg);
+
+   clk_data->clk_num = number + 1;
+   if (of_clk_add_provider(node, of_clk_src_onecell_get, clk_data))
+   pr_err("registering bus-gate clock %s failed\n", node->name);
+
+   return;
+
+err_free_data:
+   

[PATCH v4 3/7] clk: sunxi: add generic multi-parent bus clock gates driver

2016-08-08 Thread Andre Przywara
The Allwinner H3 SoC introduced bus clock gates with potentially
different parents per clock gate register. The H3 driver chose to
hardcode the actual parent clock relation in the code.
Add a new driver (which has the potential to drive the H3 and also
the simple clock gates as well) which uses the power of DT to describe
this relationship in an elegant and flexible way.
Using one subnode for every parent clock we get away with a single
DT compatible match, which can be used as a fallback value in the
actual DTs without the need to add specific compatible strings to the
code.  This avoids adding a new driver or function for every new SoC.

Signed-off-by: Andre Przywara 
Acked-by: Jean-Francois Moine 
---
 drivers/clk/sunxi/Makefile  |   1 +
 drivers/clk/sunxi/clk-multi-gates.c | 105 
 2 files changed, 106 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk-multi-gates.c

diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 39d2044..caf2bf6 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -14,6 +14,7 @@ obj-y += clk-simple-gates.o
 obj-y += clk-sun4i-display.o
 obj-y += clk-sun4i-pll3.o
 obj-y += clk-sun4i-tcon-ch1.o
+obj-y += clk-multi-gates.o
 obj-y += clk-sun8i-bus-gates.o
 obj-y += clk-sun8i-mbus.o
 obj-y += clk-sun9i-core.o
diff --git a/drivers/clk/sunxi/clk-multi-gates.c 
b/drivers/clk/sunxi/clk-multi-gates.c
new file mode 100644
index 000..76e715a
--- /dev/null
+++ b/drivers/clk/sunxi/clk-multi-gates.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * Based on clk-sun8i-bus-gates.c, which is:
+ *  Copyright (C) 2015 Jens Kuske 
+ * Based on clk-simple-gates.c, which is:
+ *  Copyright 2015 Maxime Ripard 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static DEFINE_SPINLOCK(gates_lock);
+
+static void __init sunxi_parse_parent(struct device_node *node,
+ struct clk_onecell_data *clk_data,
+ void __iomem *reg)
+{
+   const char *parent = of_clk_get_parent_name(node, 0);
+   const char *clk_name;
+   struct property *prop;
+   struct clk *clk;
+   const __be32 *p;
+   int index, i = 0;
+
+   of_property_for_each_u32(node, "clock-indices", prop, p, index) {
+   of_property_read_string_index(node, "clock-output-names",
+ i, _name);
+
+   clk = clk_register_gate(NULL, clk_name, parent, 0,
+   reg + 4 * (index / 32), index % 32,
+   0, _lock);
+   i++;
+   if (IS_ERR(clk)) {
+   pr_warn("could not register gate clock \"%s\"\n",
+   clk_name);
+   continue;
+   }
+   if (clk_data->clks[index])
+   pr_warn("bus-gate clock %s: index #%d already 
registered as %s\n",
+   clk_name, index, "?");
+   else
+   clk_data->clks[index] = clk;
+   }
+}
+
+static void __init sunxi_multi_bus_gates_init(struct device_node *node)
+{
+   struct clk_onecell_data *clk_data;
+   struct device_node *child;
+   struct property *prop;
+   struct resource res;
+   void __iomem *reg;
+   const __be32 *p;
+   int number = 0;
+   int index;
+
+   reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+   if (IS_ERR(reg))
+   return;
+
+   clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+   if (!clk_data)
+   goto err_unmap;
+
+   for_each_child_of_node(node, child)
+   of_property_for_each_u32(child, "clock-indices", prop, p, index)
+   number = max(number, index);
+
+   clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL);
+   if (!clk_data->clks)
+   goto err_free_data;
+
+   for_each_child_of_node(node, child)
+   sunxi_parse_parent(child, clk_data, reg);
+
+   clk_data->clk_num = number + 1;
+   if (of_clk_add_provider(node, of_clk_src_onecell_get, clk_data))
+   pr_err("registering bus-gate clock %s failed\n", node->name);
+
+   return;
+
+err_free_data:
+   kfree(clk_data);
+err_unmap:
+   iounmap(reg);
+   of_address_to_resource(node, 0, );
+