Re: [PATCH v2 14/15] clk: sunxi-ng: Add H3 clocks

2016-06-28 Thread Maxime Ripard
On Mon, Jun 27, 2016 at 05:53:37PM -0700, Michael Turquette wrote:
> > > The nice thing about struct ccu_common is that you don't have to walk
> > > the list of clocks for each separate clock type like the above probe
> > > function does. I'm still thinking of the best way to solve this
> > > generically. Maybe add a .base member struct clk_hw? I dunno, and I've
> > > resisted the urge to add stuff to struct clk_hw in the past... But I
> > > really want to minimize this .probe as much as possible, and I do not
> > > want every clock provider driver to be forced to invent something like
> > > struct ccu_common every time.
> > 
> > We'd need a few more things (in this case) at least: the register
> > offset and a private field to store our flags.
> 
> A bit of mumbling to myself below:
> 
> Hmm, upon further reflection, walking the list of ccu clocks is rather
> identical to walking the list of each clock type, as I do in the gxbb
> driver, where ccu_common is the one and only clock type.
> 
> So that in itself is not a big deal and isn't a problem that needs
> solving.
> 
> What needs solving is a way to populate base addresses for each clock at
> runtime in a way that does not *force* you to invent something like
> ccu_common if you do not need it.
> 
> You would hit this issue if you broke your common gate or divider clocks
> out and did not wrap them in the ccu_common structure. I solved this by
> overloading the ->reg value of each of the common types as static data,
> and then did the following when registering them:
> 
>   /* Populate base address for gates */
>   for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++)
>   gxbb_clk_gates[i]->reg = clk_base +
>   (u64)gxbb_clk_gates[i]->reg;
> 
> Any thoughts on how to fix this for other common gate types that need
> their base addresses populated from an OF node at runtime?

One obvious way to work around it would be to allow to store a regmap
directly in the clk_hw structure, and then you'll only need to keep
the register offset in your clock type, which is fine (I think?).

> > > > diff --git a/include/dt-bindings/clock/sun8i-h3.h 
> > > > b/include/dt-bindings/clock/sun8i-h3.h
> > > > new file mode 100644
> > > > index ..96eced56e7a2
> > > > --- /dev/null
> > > > +++ b/include/dt-bindings/clock/sun8i-h3.h
> > > > @@ -0,0 +1,162 @@
> > > > +#ifndef _DT_BINDINGS_CLK_SUN8I_H3_H_
> > > > +#define _DT_BINDINGS_CLK_SUN8I_H3_H_
> > > > +
> > > > +#define CLK_PLL_CPUX   0
> > > > +#define CLK_PLL_AUDIO_BASE 1
> > > > +#define CLK_PLL_AUDIO  2
> > > > +#define CLK_PLL_AUDIO_2X   3
> > > > +#define CLK_PLL_AUDIO_4X   4
> > > 
> > > Are you sure you want to expose all of these clocks as part of the ABI?
> > > I exposed the bare minimum clocks for the gxbb driver in the DT shared
> > > header (we can always add more later) and kept the rest internal to the
> > > kernel source.
> > 
> > I thought about it, but that would require a third array with
> > basically the same clocks:
> > 
> >   * the ccu_common array to patch to set the lock and base pointers,
> >   * the list of clocks to register
> >   * the clk_hw_onecell_data to deal with the dt binding.
> 
> "the list of clocks to register" and "the clk_hw_onecell_data to deal
> with the dt binding" are the same array.
> 
> You only need two arrays:
> 
> 1) the ccu_common init data
> 2) the clk_hw_onecell_data array of clk_hw pointers that points to
> clk_hw statically defined in the ccu_common array

Ah, so you're still exposing them (anyone could be free to access of
the hidden clocks if it knows what value to use), but you're hiding
them (the ID is not public).

That could work, I'll change that.

Thanks!
Maxime

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


signature.asc
Description: PGP signature


Re: [PATCH v2 14/15] clk: sunxi-ng: Add H3 clocks

2016-06-26 Thread Maxime Ripard
Hi Mike,

On Fri, Jun 24, 2016 at 05:28:37PM -0700, Michael Turquette wrote:
> Hi Maxime,
> 
> Nice series! Looks really great to me. :-)

Great :)

> Quoting Maxime Ripard (2016-06-07 13:41:53)
> > +static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux",
> > +"osc24M", 0x000,
> > +8, 5,  /* N */
> > +4, 2,  /* K */
> > +0, 2,  /* M */
> > +16, 2, /* P */
> > +BIT(31),   /* gate */
> > +BIT(28),   /* lock */
> > +0);
> 
> I'm more of a fan of expanding the struct with designated initializers
> versus macro use, but that's only personal preference.

Chen-Yu was very much in favour of having everything defined by
macros, I didn't care that much either, so I guess he wins :)

> > +static const char * const ahb2_parents[] = { "ahb1" , "pll-periph0" };
> > +static struct ccu_mux ahb2_clk = {
> > +   .mux= {
> > +   .shift  = 0,
> > +   .width  = 1,
> > +
> > +   .fixed_prediv   = {
> > +   .index  = 1,
> > +   .div= 2,
> > +   },
> > +   },
> > +
> > +   .common = {
> > +   .reg= 0x05c,
> > +   .features   = CCU_FEATURE_FIXED_PREDIV,
> > +   .hw.init= SUNXI_HW_INIT_PARENTS("ahb2",
> > +   ahb2_parents,
> 
> Note that it's possible to initialize the parent strings here if you
> prefer:
> 
>   .hw.init = &(struct clk_init_data){
>  .parent_names = (const char *[]){ "ahb1",
>"pll-periph0" };
>
> Similar to the above, no big deal, just an observation.

A significant bunch of our clocks have the same parent list. Passing
the parent array allows to reuse the same arrays for those, so I'd
really like that over having VA_ARGS based macros (and that would put
the list of parents at the end of the declaration, which seems weird).
 
> > +static struct ccu_common *sun8i_h3_ccu_clks[] = {
> > +   [CLK_PLL_CPUX]  = &pll_cpux_clk.common,
> > +   [CLK_PLL_AUDIO_BASE]= &pll_audio_base_clk.common,
> > +   [CLK_PLL_AUDIO] = &pll_audio_clk.common,
> 
> OK, it looks like you followed the qcom clk driver approach here, which
> is a nice way to do things. However, as Stephen alluded to in his
> response to the cover letter, the clk_hw_* api's are an even more
> friendly interface for clock providers. For example, check out the gxbb
> clk driver probe:
> 
>   static int gxbb_clkc_probe(struct platform_device *pdev)
>   {
>   void __iomem *clk_base;
>   int ret, clkid, i;
>   struct device *dev = &pdev->dev;
>   
>   /*  Generic clocks and PLLs */
>   clk_base = of_iomap(dev->of_node, 0);
>   if (!clk_base) {
>   pr_err("%s: Unable to map clk base\n", __func__);
>   return -ENXIO;
>   }
>   
>   /* Populate base address for PLLs */
>   for (i = 0; i < ARRAY_SIZE(gxbb_clk_plls); i++)
>   gxbb_clk_plls[i]->base = clk_base;
>   
>   /* Populate base address for MPLLs */
>   for (i = 0; i < ARRAY_SIZE(gxbb_clk_mplls); i++)
>   gxbb_clk_mplls[i]->base = clk_base;
> 
>   ...
> 
>   /*
>* register all clks
>*/
>   for (clkid = 0; clkid < NR_CLKS; clkid++) {
>   ret = devm_clk_hw_register(dev, 
> gxbb_hw_onecell_data.hws[clkid]);
>   if (ret)
>   goto iounmap;
>   }

Ok, I'll move the fixed factor clocks out of the common list, and
initialize the clk_hw_onedata_cell structure to register it.

> The nice thing about struct ccu_common is that you don't have to walk
> the list of clocks for each separate clock type like the above probe
> function does. I'm still thinking of the best way to solve this
> generically. Maybe add a .base member struct clk_hw? I dunno, and I've
> resisted the urge to add stuff to struct clk_hw in the past... But I
> really want to minimize this .probe as much as possible, and I do not
> want every clock provider driver to be forced to invent something like
> struct ccu_common every time.

We'd need a few more things (in this case) at least: the register
offset and a private field to store our flags.

> Anyways, that is not a blocker for your implementation to be merged,
> but Stephen's question in patch #4 got me thinking about this
> again...
> 
> The real nice part is the call to devm_clk_hw_register. That

Re: [PATCH v2 14/15] clk: sunxi-ng: Add H3 clocks

2016-06-24 Thread Michael Turquette
Hi Maxime,

Nice series! Looks really great to me. :-)

Quoting Maxime Ripard (2016-06-07 13:41:53)
> +static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux",
> +"osc24M", 0x000,
> +8, 5,  /* N */
> +4, 2,  /* K */
> +0, 2,  /* M */
> +16, 2, /* P */
> +BIT(31),   /* gate */
> +BIT(28),   /* lock */
> +0);

I'm more of a fan of expanding the struct with designated initializers
versus macro use, but that's only personal preference.

> +static const char * const ahb2_parents[] = { "ahb1" , "pll-periph0" };
> +static struct ccu_mux ahb2_clk = {
> +   .mux= {
> +   .shift  = 0,
> +   .width  = 1,
> +
> +   .fixed_prediv   = {
> +   .index  = 1,
> +   .div= 2,
> +   },
> +   },
> +
> +   .common = {
> +   .reg= 0x05c,
> +   .features   = CCU_FEATURE_FIXED_PREDIV,
> +   .hw.init= SUNXI_HW_INIT_PARENTS("ahb2",
> +   ahb2_parents,

Note that it's possible to initialize the parent strings here if you
prefer:

.hw.init = &(struct clk_init_data){
   .parent_names = (const char *[]){ "ahb1",
 "pll-periph0" };

Similar to the above, no big deal, just an observation.

> +static struct ccu_common *sun8i_h3_ccu_clks[] = {
> +   [CLK_PLL_CPUX]  = &pll_cpux_clk.common,
> +   [CLK_PLL_AUDIO_BASE]= &pll_audio_base_clk.common,
> +   [CLK_PLL_AUDIO] = &pll_audio_clk.common,

OK, it looks like you followed the qcom clk driver approach here, which
is a nice way to do things. However, as Stephen alluded to in his
response to the cover letter, the clk_hw_* api's are an even more
friendly interface for clock providers. For example, check out the gxbb
clk driver probe:

static int gxbb_clkc_probe(struct platform_device *pdev)
{
void __iomem *clk_base;
int ret, clkid, i;
struct device *dev = &pdev->dev;

/*  Generic clocks and PLLs */
clk_base = of_iomap(dev->of_node, 0);
if (!clk_base) {
pr_err("%s: Unable to map clk base\n", __func__);
return -ENXIO;
}

/* Populate base address for PLLs */
for (i = 0; i < ARRAY_SIZE(gxbb_clk_plls); i++)
gxbb_clk_plls[i]->base = clk_base;

/* Populate base address for MPLLs */
for (i = 0; i < ARRAY_SIZE(gxbb_clk_mplls); i++)
gxbb_clk_mplls[i]->base = clk_base;

...

/*
 * register all clks
 */
for (clkid = 0; clkid < NR_CLKS; clkid++) {
ret = devm_clk_hw_register(dev, 
gxbb_hw_onecell_data.hws[clkid]);
if (ret)
goto iounmap;
}

The nice thing about struct ccu_common is that you don't have to walk
the list of clocks for each separate clock type like the above probe
function does. I'm still thinking of the best way to solve this
generically. Maybe add a .base member struct clk_hw? I dunno, and I've
resisted the urge to add stuff to struct clk_hw in the past... But I
really want to minimize this .probe as much as possible, and I do not
want every clock provider driver to be forced to invent something like
struct ccu_common every time. Anyways, that is not a blocker for your
implementation to be merged, but Stephen's question in patch #4 got me
thinking about this again...

The real nice part is the call to devm_clk_hw_register. That uses the
new clk_hw_* apis and struct clk_hw_onecell_data, which is initialized
statically like so:

static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
.hws = {
[CLKID_SYS_PLL]  = &gxbb_sys_pll.hw,
[CLKID_CPUCLK]= &gxbb_cpu_clk.hw,
...
},
.num = NR_CLKS,
};

Unfortunately I believe it impossible to replace NR_CLKS with some
ARRAY_SIZE stuff because C. As Stephen mentioned, please use this method
instead.

> diff --git a/include/dt-bindings/clock/sun8i-h3.h 
> b/include/dt-bindings/clock/sun8i-h3.h
> new file mode 100644
> index ..96eced56e7a2
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun8i-h3.h
> @@ -0,0 +1,162 @@
> +#ifndef _DT_BINDINGS_CLK_SUN8I_H3_H_
> +#define _DT_BINDINGS_CLK_

Re: [PATCH v2 14/15] clk: sunxi-ng: Add H3 clocks

2016-06-09 Thread Jean-Francois Moine
On Tue,  7 Jun 2016 22:41:53 +0200
Maxime Ripard  wrote:

> Add the list of clocks and resets found in the H3 CCU.
> 
> Signed-off-by: Maxime Ripard 
> 
> ---
> Changes from v1:
>   - Only build the H3 clocks description when MACH_SUN8I is set
> ---
>  drivers/clk/sunxi-ng/Makefile|   2 +
>  drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 703 
> +++
>  include/dt-bindings/clock/sun8i-h3.h | 162 
>  include/dt-bindings/reset/sun8i-h3.h | 103 +
>  4 files changed, 970 insertions(+)
>  create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
>  create mode 100644 include/dt-bindings/clock/sun8i-h3.h
>  create mode 100644 include/dt-bindings/reset/sun8i-h3.h
> 
> diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
> index ddcf456df719..cafabf0e8060 100644
> --- a/drivers/clk/sunxi-ng/Makefile
> +++ b/drivers/clk/sunxi-ng/Makefile
> @@ -13,3 +13,5 @@ obj-y += ccu_nkm.o
>  obj-y += ccu_nkmp.o
>  obj-y += ccu_nm.o
>  obj-y += ccu_phase.o
> +
> +obj-$(CONFIG_MACH_SUN8I) += ccu-sun8i-h3.o
> diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c 
> b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
> new file mode 100644
> index ..41102ac020d9
> --- /dev/null
> +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
[snip]
> +static const struct sunxi_ccu_desc sun8i_h3_ccu_desc = {
> + .clks   = sun8i_h3_ccu_clks,
> + .num_clks   = ARRAY_SIZE(sun8i_h3_ccu_clks),
> +
> + .resets = sun8i_h3_ccu_resets,
> + .num_resets = ARRAY_SIZE(sun8i_h3_ccu_resets),
> +};
> +
> +#define SUN8I_H3_PLL2_REG0x008

SUN8I_H3_PLL_AUDIO_REG would be clearer.

This definition could go near the audio PLL description with some
comments.

> +
> +static void __init sun8i_h3_ccu_setup(struct device_node *node)
> +{
> + void __iomem *reg;
> + u32 val;
> +
> + reg = of_io_request_and_map(node, 0, of_node_full_name(node));
> + if (IS_ERR(reg)) {
> + pr_err("%s: Could not map the clock registers\n",
> +of_node_full_name(node));
> + return;
> + }
> +
> + /* Force the PLL2-1x divider to 4 */
> + val = readl(reg + SUN8I_H3_PLL2_REG);
> + val &= ~GENMASK(4, 0);
> + writel(val | 3, reg + SUN8I_H3_PLL2_REG);
> +
> + sunxi_ccu_probe(node, reg, &sun8i_h3_ccu_desc);
> +}
> +CLK_OF_DECLARE(sun8i_h3_ccu, "allwinner,sun8i-h3-ccu",
> +sun8i_h3_ccu_setup);
> diff --git a/include/dt-bindings/clock/sun8i-h3.h 
> b/include/dt-bindings/clock/sun8i-h3.h
> new file mode 100644
> index ..96eced56e7a2
> --- /dev/null
> +++ b/include/dt-bindings/clock/sun8i-h3.h
[snip]

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


[PATCH v2 14/15] clk: sunxi-ng: Add H3 clocks

2016-06-07 Thread Maxime Ripard
Add the list of clocks and resets found in the H3 CCU.

Signed-off-by: Maxime Ripard 

---
Changes from v1:
  - Only build the H3 clocks description when MACH_SUN8I is set
---
 drivers/clk/sunxi-ng/Makefile|   2 +
 drivers/clk/sunxi-ng/ccu-sun8i-h3.c  | 703 +++
 include/dt-bindings/clock/sun8i-h3.h | 162 
 include/dt-bindings/reset/sun8i-h3.h | 103 +
 4 files changed, 970 insertions(+)
 create mode 100644 drivers/clk/sunxi-ng/ccu-sun8i-h3.c
 create mode 100644 include/dt-bindings/clock/sun8i-h3.h
 create mode 100644 include/dt-bindings/reset/sun8i-h3.h

diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile
index ddcf456df719..cafabf0e8060 100644
--- a/drivers/clk/sunxi-ng/Makefile
+++ b/drivers/clk/sunxi-ng/Makefile
@@ -13,3 +13,5 @@ obj-y += ccu_nkm.o
 obj-y += ccu_nkmp.o
 obj-y += ccu_nm.o
 obj-y += ccu_phase.o
+
+obj-$(CONFIG_MACH_SUN8I) += ccu-sun8i-h3.o
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c 
b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
new file mode 100644
index ..41102ac020d9
--- /dev/null
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -0,0 +1,703 @@
+/*
+ * Copyright (c) 2016 Maxime Ripard. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_fixed_factor.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_mult.h"
+#include "ccu_nk.h"
+#include "ccu_nkm.h"
+#include "ccu_nkmp.h"
+#include "ccu_nm.h"
+#include "ccu_phase.h"
+
+static SUNXI_CCU_NKMP_WITH_GATE_LOCK(pll_cpux_clk, "pll-cpux",
+"osc24M", 0x000,
+8, 5,  /* N */
+4, 2,  /* K */
+0, 2,  /* M */
+16, 2, /* P */
+BIT(31),   /* gate */
+BIT(28),   /* lock */
+0);
+
+static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
+  "osc24M", 0x008,
+  8, 7,/* N */
+  0, 5,/* M */
+  BIT(31), /* gate */
+  BIT(28), /* lock */
+  0);
+
+/* We hardcode the divider to 4 for now */
+static SUNXI_CCU_FIXED_FACTOR(pll_audio_clk, "pll-audio",
+ "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
+static SUNXI_CCU_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x",
+ "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT);
+static SUNXI_CCU_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x",
+ "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT);
+static SUNXI_CCU_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x",
+ "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video_clk, "pll-video",
+   "osc24M", 0x0010,
+   8, 7,   /* N */
+   0, 4,   /* M */
+   BIT(24),/* frac enable */
+   BIT(25),/* frac select */
+   27000,  /* frac rate 0 */
+   29700,  /* frac rate 1 */
+   BIT(31),/* gate */
+   BIT(28),/* lock */
+   0);
+
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve",
+   "osc24M", 0x0018,
+   8, 7,   /* N */
+   0, 4,   /* M */
+   BIT(24),/* frac enable */
+   BIT(25),/* frac select */
+   27000,  /* frac rate 0 */
+   29700,  /* frac rate 1 */
+   BIT(31),/* gate */
+   BIT(28),/* lock */
+   0);
+
+static SU