Subject: [PATCH 3/3] clk: shmobile: Add R8A7790 clocks support

From: [email-masked] (Laurent Pinchart)
Date: Wed, 06 Nov 2013 13:45:04 +0100

Hi Magnus,

(CC'ing Grant Likely)

On Wednesday 06 November 2013 17:19:48 Magnus Damm wrote:
> On Wed, Nov 6, 2013 at 8:47 AM, Laurent Pinchart wrote:
> > On Tuesday 05 November 2013 16:56:40 Magnus Damm wrote:
> >> On Tue, Oct 29, 2013 at 11:55 PM, Laurent Pinchart wrote:
> >> > The R8A7790 has several clocks that are too custom to be supported in a
> >> > generic driver. Those clocks can be divided in two categories:
> >> > 
> >> > - Fixed rate clocks with multiplier and divisor set according to boot
> >> >   mode configuration
> >> > 
> >> > - Custom divider clocks with SoC-specific divider values
> >> > 
> >> > This driver supports both.
> >> > 
> >> > Signed-off-by: Laurent Pinchart
> >> > <[email-masked]>
> >> > ---
> >> > 
> >> > +void __init r8a7790_clocks_init(u32 mode)
> >> > +{
> >> > +       cpg_mode = mode;
> >> > +
> >> > +       of_clk_init(NULL);
> >> > +}
> >> 
> >> Hi Laurent,
> >> 
> >> Thanks a lot for your efforts on this. In general I think it all looks
> >> good,
> >
> > Thank you.
> > 
> >> I have however one question regarding the "probe" interface between the
> >> SoC code in arch/arm/mach-shmobile and drivers/clk. The code above in
> >> r8a7790_clocks_init() looks a bit spaghetti-style to me, perhaps it is
> >> possible to make it cleaner somehow?
> > 
> > Isn't it just a loop ? :-) The clocks handled by this driver are
> > "special", they need to be initialized manually.
> 
> Spaghetti-O's? =) I agree that some special handling is needed.
> 
> >> I realize that you need some way to read out the mode pin setting, and
> >> that is currently provided by the SoC code in arch/arm/mach-shmobile/.
> >> Today it seems that you instead of letting the drivers/clk/ code call SoC
> >> code to get the mode pin setting (and add a SoC link dependency) you
> >> simply feed the settings to the clk code from the SoC code using the
> >> parameter to r8a7790_clocks_init(). This direction seems good to me. I'm
> >> however not too keen on the current symbol dependency in the "other"
> >> direction.
> >> 
> >> If possible I'd like to keep the interface between the SoC code and the
> >> driver code to "standard" driver model functions. For instance, using
> >> of_clk_init(NULL) from the SoC code seems like a pretty good standard
> >> interface - without any link time dependencies. So with the current code,
> >> the r8a7790_clocks_init() function somehow goes against this no-symbol-
> >> dependency preference that I happen to have. =)
> >> 
> >> Would it for instance be possible let the SoC code read out the mode pin
> >> setting, and then pass the current setting using the argument of
> >> of_clk_init() to select different dividers? That way the symbol
> >> dependency goes away. Or maybe it becomes too verbose?
> > 
> > The of_clk_init() argument is an array of struct of_device_id that is used
> > by the clock core to match device tree nodes. I don't really see how you
> > would like to use it to pass the boot mode pins state to the driver.
> 
> Yeah, it seems that interface isn't such a good match. Thanks.
> 
> > There is currently no dedicated API (at least to my knowledge) to pass
> > clock configuration information between arch/arm and drivers/clk. Here's
> > a couple of methods that can be used.
> > 
> > - Call a drivers/clk function from platform code with the clock
> > configuration information and store that information in a driver global
> > variable for later use (this is the method currently used by this patch).
> > 
> > - Call a platform code function from driver code to read the
> > configuration. This is pretty similar to the above, with a dependency in
> > the other direction.
> > 
> > - Read the value directly from the hardware in the clock driver. This
> > doesn't feel really right, as that's not the job of the clock driver. In
> > a more general case this solution might not always be possible, as
> > reading the configuration might require access to resources not available
> > to drivers.
> > 
> > - Create a standard API for this purpose. It might be overengineering.
> > 
> > - Use AUXDATA filled by platform code.
> > 
> > There might be other solutions I haven't thought of. I went for the first
> > method as there's already 8 other clock drivers that expose an
> > initialization function to platform code. I might just have copied a
> > mistake though.
>
> Thanks for listing these. I have come across another option:
> 
> Use of_update_property() and of_property_read_u32() to pass using a
> property, see below.
> 
> > Mike, do you have an opinion on this ? In a nutshell, the code clocks are
> > fixed factor but their factor depend on a boot mode configuration. The
> > configuration value is thus needed when instantiating the clocks. It can
> > be read from a hardware register, outside of the clocks IP core.
> 
> Yeah, I too would be interested to hear what Mike thinks about this matter.
> 
> Please see below for a prototype patch on top of your code that shows
> the driver side of my DT property proposal. The omitted SoC side
> becomes slightly more complicated but that code can be shared between
> multiple R-Car SoCs so I think it should be acceptable size-wise.
> 
> With this patch applied the interface between the driver and the SoC
> code is a DT property (that needs documentation) and
> of_clk_init(NULL). No more evil link time symbol dependencies between
> arch/ and drivers/...

This feels a bit like a DT abuse to me. I'm not strongly opposed to this 
approach, but I would need an ack from Mike and Grant before implementing it.

>  drivers/clk/shmobile/clk-r8a7790.c |   15 ++++++---------
>  include/linux/clk/shmobile.h       |   19 -------------------
>  2 files changed, 6 insertions(+), 28 deletions(-)
> 
> --- 0018/drivers/clk/shmobile/clk-r8a7790.c
> +++ work/drivers/clk/shmobile/clk-r8a7790.c     2013-11-06
> 16:59:59.000000000 +0 900
> @@ -12,7 +12,6 @@
> 
>  #include <linux/clk-provider.h>
>  #include <linux/clkdev.h>
> -#include <linux/clk/shmobile.h>
>  #include <linux/init.h>
>  #include <linux/kernel.h>
>  #include <linux/of.h>
> @@ -70,8 +69,6 @@ static const struct clk_div_table cpg_sd
>         { 10, 36 }, { 11, 48 }, { 12, 10 }, {  0,  0 },
>  };
> 
> -static u32 cpg_mode __initdata;
> -
>  #define CPG_SDCKCR                     0x00000074
> 
>  static void __init r8a7790_cpg_clocks_init(struct device_node *np)
> @ -80,6 +77,12 @@ static void __init r8a7790_cpg_clocks_in
>         struct r8a7790_cpg *cpg;
>         struct clk **clks;
>         unsigned int i;
> +       u32 cpg_mode;
> +
> +       if (of_property_read_u32(node, "cpg-mode", &cpg_mode)) {
> +               pr_err("%s: failed to determine CPG mode\n", __func__);
> +               return;
> +       }
> 
>         cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
>         clks = kzalloc(CPG_NUM_CLOCKS * sizeof(*clks), GFP_KERNEL);
> @ -168,9 +171,3 @@ static void __init r8a7790_cpg_clocks_in
>  CLK_OF_DECLARE(r8a7790_cpg_clks, "renesas,r8a7790-cpg-clocks",
>                r8a7790_cpg_clocks_init);
> 
> -void __init r8a7790_clocks_init(u32 mode)
> -{
> -       cpg_mode = mode;
> -
> -       of_clk_init(NULL);
> -}
> --- 0018/include/linux/clk/shmobile.h
> +++ /dev/null   2013-06-03 21:41:10.638032047 +0900
> @@ -1,19 +0,0 @@
> -/*
> - * Copyright 2013 Ideas On Board SPRL
> - *
> - * Contact: Laurent Pinchart <[email-masked]>
> - *
> - * 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.
> - */
> -
> -#ifndef __LINUX_CLK_SHMOBILE_H_
> -#define __LINUX_CLK_SHMOBILE_H_
> -
> -#include <linux/types.h>
> -
> -void r8a7790_clocks_init(u32 mode);
> -
> -#endif

-- 
Regards,

Laurent Pinchart