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 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





[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