RE: [PATCH v3 3/4] clk: renesas: rzg2l: Add support to handle coupled clocks

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

 



Hi Geert,

Thanks for the feedback.

> Subject: Re: [PATCH v3 3/4] clk: renesas: rzg2l: Add support to handle
> coupled clocks
> 
> Hi Biju,
> 
> On Sun, Aug 15, 2021 at 12:30 PM Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
> wrote:
> > The AXI and CHI clocks use the same register bit for controlling clock
> > output. Add a new clock type for coupled clocks, which sets the
> > CPG_CLKON_ETH.CLK[01]_ON bit when at least one clock is enabled, and
> > clears the bit only when both clocks are disabled.
> >
> > Signed-off-by: Biju Das <biju.das.jz@xxxxxxxxxxxxxx>
> > Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
> > ---
> > v2->v3:
> >  * Reworked as per Geert's suggestion
> >  * Added enabled flag to track the status of clock, if it is coupled
> >    with another clock
> >  * Introduced siblings pointer which points to the other coupled
> >    clock
> >  * coupled clock linking is done during module clk register.
> >  * rzg2l_mod_clock_is_enabled function returns soft state of the
> >    module clocks, if it is coupled with another clock
> >  * Updated the commit header
> 
> Thanks for the update!
> 
> > --- a/drivers/clk/renesas/rzg2l-cpg.c
> > +++ b/drivers/clk/renesas/rzg2l-cpg.c
> > @@ -392,11 +396,35 @@ static int rzg2l_mod_clock_endisable(struct
> > clk_hw *hw, bool enable)
> >
> >  static int rzg2l_mod_clock_enable(struct clk_hw *hw)  {
> > +       struct mstp_clock *clock = to_mod_clock(hw);
> > +       struct mstp_clock *siblings = clock->siblings;
> > +
> > +       if (siblings) {
> > +               if (siblings->enabled) {
> > +                       clock->enabled = true;
> > +                       return 0;
> > +               }
> > +
> > +               clock->enabled = true;
> 
> clock->enabled is set to true regardless of the if condition.
> This also needs locking, in case both clocks are changed concurrently:

Agreed. It needs locking.

> 
>     spin_lock_irqsave(&priv->rmw_lock, flags);
>     enabled = siblings->enabled;
>     clock->enabled = true;
>     spin_unlock_irqrestore(&priv->rmw_lock, flags);
>     if (enabled)
>             return 0;
> 
> > +       }
> > +
> >         return rzg2l_mod_clock_endisable(hw, true);  }
> >
> >  static void rzg2l_mod_clock_disable(struct clk_hw *hw)  {
> > +       struct mstp_clock *clock = to_mod_clock(hw);
> > +       struct mstp_clock *siblings = clock->siblings;
> > +
> > +       if (siblings) {
> > +               if (siblings->enabled) {
> > +                       clock->enabled = false;
> > +                       return;
> > +               }
> > +
> > +               clock->enabled = false;
> 
> Likewise.
OK.

> 
> > +       }
> > +
> >         rzg2l_mod_clock_endisable(hw, false);  }
> >
> > @@ -412,6 +440,9 @@ static int rzg2l_mod_clock_is_enabled(struct clk_hw
> *hw)
> >                 return 1;
> >         }
> >
> > +       if (clock->siblings)
> > +               return clock->enabled;
> > +
> >         value = readl(priv->base + CLK_MON_R(clock->off));
> >
> >         return !(value & bitmask);
> > @@ -423,11 +454,33 @@ static const struct clk_ops rzg2l_mod_clock_ops =
> {
> >         .is_enabled = rzg2l_mod_clock_is_enabled,  };
> >
> > +static struct mstp_clock
> > +*rzg2l_cpg_get_sibling_clk(struct mstp_clock *clock,
> > +                          struct rzg2l_cpg_priv *priv) {
> > +       struct mstp_clock *sibl_clk = NULL;
> 
> clk?
> It's only a sibling when the condition inside the loop is true.

OK, will declare "clk" inside for loop to limit the scope.

> 
> > +       struct clk_hw *hw;
> > +       unsigned int i;
> > +
> > +       for (i = 0; i < priv->num_mod_clks; i++) {
> > +               if (priv->clks[priv->num_core_clks + i] == ERR_PTR(-
> ENOENT))
> > +                       continue;
> > +
> > +               hw = __clk_get_hw(priv->clks[priv->num_core_clks + i]);
> > +               sibl_clk = to_mod_clock(hw);
> > +               if (clock->off == sibl_clk->off && clock->bit ==
> sibl_clk->bit)
> > +                       break;
> > +       }
> > +
> > +       return sibl_clk;
> > +}
> > +
> >  static void __init
> >  rzg2l_cpg_register_mod_clk(const struct rzg2l_mod_clk *mod,
> >                            const struct rzg2l_cpg_info *info,
> >                            struct rzg2l_cpg_priv *priv)  {
> > +       struct mstp_clock *sibling_clock = NULL;
> >         struct mstp_clock *clock = NULL;
> >         struct device *dev = priv->dev;
> >         unsigned int id = mod->id;
> > @@ -484,6 +537,15 @@ rzg2l_cpg_register_mod_clk(const struct
> > rzg2l_mod_clk *mod,
> >
> >         dev_dbg(dev, "Module clock %pC at %lu Hz\n", clk,
> clk_get_rate(clk));
> >         priv->clks[id] = clk;
> > +
> > +       if (mod->is_coupled) {
> > +               sibling_clock = rzg2l_cpg_get_sibling_clk(clock, priv);
> > +               if (sibling_clock) {
> > +                       clock->siblings = sibling_clock;
> > +                       sibling_clock->siblings = clock;
> > +               }
> 
> You forgot to initialize mstp_clock.enabled to match the current hardware
> state.

OK. will initialize mstp_clock.enabled to match the current hardware state.

Cheers,
Biju

> 
> > +       }
> > +
> >         return;
> >
> >  fail:
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-
> m68k.org
> 
> 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]     [Linux Samsung SOC]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]

  Powered by Linux