Re: [PATCH 3/4] clk: renesas: Add RZ/V2H CPG core wrapper driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Prabhakar,

Thanks for your patch!

On Fri, May 24, 2024 at 10:29 AM Prabhakar <prabhakar.csengg@xxxxxxxxx> wrote:
> From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
>
> Add CPG core helper wrapper driver for RZ/V2H SoC.

What is a "core helper wrapper"? ;-)

Looking at the structure, this looks like a family-specific clock driver?
Will there be more RZ/V2H-alike SoCs?

> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
> ---
>  drivers/clk/renesas/Kconfig     |   5 +
>  drivers/clk/renesas/Makefile    |   1 +
>  drivers/clk/renesas/rzv2h-cpg.c | 673 ++++++++++++++++++++++++++++++++
>  drivers/clk/renesas/rzv2h-cpg.h | 149 +++++++
>  4 files changed, 828 insertions(+)
>  create mode 100644 drivers/clk/renesas/rzv2h-cpg.c
>  create mode 100644 drivers/clk/renesas/rzv2h-cpg.h
>
> diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig
> index d252150402e8..254203c2cb2e 100644
> --- a/drivers/clk/renesas/Kconfig
> +++ b/drivers/clk/renesas/Kconfig
> @@ -40,6 +40,7 @@ config CLK_RENESAS
>         select CLK_R9A07G054 if ARCH_R9A07G054
>         select CLK_R9A08G045 if ARCH_R9A08G045
>         select CLK_R9A09G011 if ARCH_R9A09G011
> +       select CLK_R9A09G057 if ARCH_R9A09G057
>         select CLK_SH73A0 if ARCH_SH73A0
>
>  if CLK_RENESAS
> @@ -193,6 +194,10 @@ config CLK_R9A09G011
>         bool "RZ/V2M clock support" if COMPILE_TEST
>         select CLK_RZG2L
>
> +config CLK_R9A09G057
> +       bool "Renesas RZ/V2H(P) clock support" if COMPILE_TEST

Please drop "Renesas "
(few other symbols have it, I'll fix the remaining).

> +       select RESET_CONTROLLER
> +
>  config CLK_SH73A0
>         bool "SH-Mobile AG5 clock support" if COMPILE_TEST
>         select CLK_RENESAS_CPG_MSTP
> diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile
> index f7e18679c3b8..79cc7c4d77c6 100644
> --- a/drivers/clk/renesas/Makefile
> +++ b/drivers/clk/renesas/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_CLK_R9A07G044)           += r9a07g044-cpg.o
>  obj-$(CONFIG_CLK_R9A07G054)            += r9a07g044-cpg.o
>  obj-$(CONFIG_CLK_R9A08G045)            += r9a08g045-cpg.o
>  obj-$(CONFIG_CLK_R9A09G011)            += r9a09g011-cpg.o
> +obj-$(CONFIG_CLK_R9A09G057)            += rzv2h-cpg.o

If this is a family-specific clock driver, please use a separate Kconfig
symbol, like other families do, and move it ...

>  obj-$(CONFIG_CLK_SH73A0)               += clk-sh73a0.o
>
>  # Family

... here.

> --- /dev/null
> +++ b/drivers/clk/renesas/rzv2h-cpg.c

> +/**
> + * struct rzv2h_cpg_priv - Clock Pulse Generator Private Data
> + *
> + * @rcdev: Reset controller entity
> + * @dev: CPG device
> + * @base: CPG register block base address
> + * @rmw_lock: protects register accesses
> + * @clks: Array containing all Core and Module Clocks
> + * @num_core_clks: Number of Core Clocks in clks[]
> + * @num_mod_clks: Number of Module Clocks in clks[]
> + * @num_resets: Number of Module Resets in info->resets[]
> + * @info: Pointer to platform data
> + */
> +struct rzv2h_cpg_priv {
> +       struct reset_controller_dev rcdev;
> +       struct device *dev;
> +       void __iomem *base;
> +       spinlock_t rmw_lock;

Unused

> +
> +       struct clk **clks;
> +       unsigned int num_core_clks;
> +       unsigned int num_mod_clks;
> +       unsigned int num_resets;
> +
> +       const struct rzv2h_cpg_info *info;
> +};

> +static struct clk
> +*rzv2h_cpg_clk_src_twocell_get(struct of_phandle_args *clkspec,
> +                              void *data)
> +{
> +       unsigned int clkidx = clkspec->args[1];
> +       struct rzv2h_cpg_priv *priv = data;
> +       struct device *dev = priv->dev;
> +       const char *type;
> +       struct clk *clk;
> +
> +       switch (clkspec->args[0]) {
> +       case CPG_CORE:
> +               type = "core";
> +               clk = priv->clks[clkidx];

No range checking?

> +               break;
> +
> +       case CPG_MOD:
> +               type = "module";
> +               if (clkidx >= priv->num_mod_clks) {
> +                       dev_err(dev, "Invalid %s clock index %u\n", type,
> +                               clkidx);
> +                       return ERR_PTR(-EINVAL);
> +               }
> +               clk = priv->clks[priv->num_core_clks + clkidx];
> +               break;
> +
> +       default:
> +               dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]);
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       if (IS_ERR(clk))
> +               dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx,
> +                       PTR_ERR(clk));
> +       else
> +               dev_dbg(dev, "clock (%u, %u) is %pC at %lu Hz\n",
> +                       clkspec->args[0], clkspec->args[1], clk,
> +                       clk_get_rate(clk));
> +       return clk;
> +}

> +static void __init
> +rzv2h_cpg_register_mod_clk(const struct rzv2h_mod_clk *mod,
> +                          const struct rzv2h_cpg_info *info,
> +                          struct rzv2h_cpg_priv *priv)
> +{
> +       struct mstp_clock *clock = NULL;
> +       struct device *dev = priv->dev;
> +       unsigned int id = mod->id;
> +       struct clk_init_data init;
> +       struct clk *parent, *clk;
> +       const char *parent_name;
> +       unsigned int i;
> +
> +       WARN_DEBUG(id < priv->num_core_clks);
> +       WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks);
> +       WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
> +       WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
> +
> +       if (!mod->name) {
> +               /* Skip NULLified clock */
> +               return;
> +       }

Do you have NULLified clocks?


> new file mode 100644
> index 000000000000..689c123d01c5
> --- /dev/null
> +++ b/drivers/clk/renesas/rzv2h-cpg.h

> +/**
> + * struct rzv2h_mod_clk - Module Clocks definitions
> + *
> + * @name: handle between common and hardware-specific interfaces
> + * @id: clock index in array containing all Core and Module Clocks
> + * @parent: id of parent clock
> + * @off: register offset

control register offset

> + * @bit: ON/MON bit

> + * @monoff: monitor register offset
> + * @monbit: monitor bit
> + */
> +struct rzv2h_mod_clk {
> +       const char *name;
> +       unsigned int id;
> +       unsigned int parent;
> +       u16 off;
> +       u8 bit;

Perhaps name them ctrl{off,bit}?

However, as all CPG_CLKONn registers are contiguous, storing
the register index (u8) might be better than the register offset (u16)?

> +       u16 monoff;
> +       u8 monbit;

Likewise for the CPG_CLKMONx registers...

> +};
> +
> +#define DEF_MOD_BASE(_name, _id, _parent, _off, _bit, _monoff, _monbit)        \
> +       { \
> +               .name = _name, \
> +               .id = MOD_CLK_BASE + (_id), \
> +               .parent = (_parent), \
> +               .off = (_off), \
> +               .bit = (_bit), \
> +               .monoff = (_monoff), \
> +               .monbit = (_monbit), \
> +       }
> +
> +#define DEF_MOD(_name, _id, _parent, _off, _bit, _monoff, _monbit)     \
> +       DEF_MOD_BASE(_name, _id, _parent, _off, _bit, _monoff, _monbit)
> +
> +/**
> + * struct rzv2h_reset - Reset definitions
> + *
> + * @off: reset register offset
> + * @bit: reset bit
> + * @monoff: monitor register offset
> + * @monbit: monitor bit
> + */
> +struct rzv2h_reset {
> +       u16 resoff;
> +       u8 resbit;
> +       u16 monoff;
> +       u8 monbit;

... and the CPG_RSTx and CPG_RSTMONx registers.


> +};
> +
> +#define DEF_RST(_id, _resoff, _resbit, _monoff, _monbit)       \
> +       [_id] = { \
> +               .resoff = (_resoff), \
> +               .resbit = (_resbit), \
> +               .monoff = (_monoff), \
> +               .monbit = (_monbit) \
> +       }
> +
> +/**
> + * struct rzv2h_cpg_info - SoC-specific CPG Description
> + *
> + * @core_clks: Array of Core Clock definitions
> + * @num_core_clks: Number of entries in core_clks[]
> + * @num_total_core_clks: Total number of Core Clocks (exported + internal)
> + *
> + * @mod_clks: Array of Module Clock definitions
> + * @num_mod_clks: Number of entries in mod_clks[]
> + * @num_hw_mod_clks: Number of Module Clocks supported by the hardware
> + *
> + * @resets: Array of Module Reset definitions
> + * @num_resets: Number of entries in resets[]
> + *
> + * @crit_mod_clks: Array with Module Clock IDs of critical clocks that
> + *                 should not be disabled without a knowledgeable driver
> + * @num_crit_mod_clks: Number of entries in crit_mod_clks[]
> + * @pll_get_clk1_offset: Function pointer to get PLL CLK1 offset
> + * @pll_get_clk2_offset: Function pointer to get PLL CLK2 offset
> + */
> +struct rzv2h_cpg_info {

> +       /* function pointers for PLL information */
> +       int (*pll_get_clk1_offset)(int clk);
> +       int (*pll_get_clk2_offset)(int clk);

Why are these function pointers?

> +};
> +
> +#endif /* __RENESAS_RZV2H_CPG_H__ */

Gr{oetje,eeting}s,

                        Geert


--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds





[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]


  Powered by Linux