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

From: Lad, Prabhakar
Date: Mon Jun 10 2024 - 18:03:45 EST


Hi Geert,

Thank you for the review.

On Tue, Jun 4, 2024 at 5:01 PM Geert Uytterhoeven <geert@xxxxxxxxxxxxxx> wrote:
>
> 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"? ;-)
>
As this file basically uses core API for clock and reset, I worded the
commit as such.

> Looking at the structure, this looks like a family-specific clock driver?
Yes, as the CPG on RZ/V2H varies quite a bit compared to RZ/G2L I have
introduced a family-specific clock driver

> Will there be more RZ/V2H-alike SoCs?
>
I'm not sure about it tbh!

> > 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).
>
OK.

> > + 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.
>
OK, I will move it to the family section.

> > --- /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
>
I will drop it.

> > +
> > + 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?
>
I will add a check for it.

> > + 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?
>
Nope, I 'll drop this check.

>
> > 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.
>
>
Ok, I will store the indexes for CLK/CLKMON/RST/RSTMON regs.

> > +};
> > +
> > +#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?
>
To get the offsets for PLL CLK1/2. But I plan to drop these and get
the offset from conf instead.

Cheers,
Prabhakar