Message ID | 20240308000432.32369-1-semen.protsenko@linaro.org |
---|---|
State | New |
Headers | show |
Series | clk: Propagate clk_set_rate() if CLK_SET_PARENT_RATE present | expand |
On Thu, Mar 7, 2024 at 6:04 PM Sam Protsenko <semen.protsenko@linaro.org> wrote: > > Sometimes clocks provided to a consumer might not have .set_rate > operation (like gate or mux clocks), but have CLK_SET_PARENT_RATE flag > set. In that case it's usually possible to find a parent up the tree > which is capable of setting the rate (div, pll, etc). Implement a simple > lookup procedure for such cases, to traverse the clock tree until > .set_rate capable parent is found, and use that parent to actually > change the rate. The search will stop once the first .set_rate capable > clock is found, which is usually enough to handle most cases. > > Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org> > --- Hi Lukasz, Sean, Tom, If this patch looks good to you and there are no outstanding comments, can you please apply it? It's needed as a part of eMMC enablement for E850-96 board, as eMMC gate (leaf) clock is specified as ciu clock in dts, which requires further clock rate change propagation up to divider clock. Thanks! > drivers/clk/clk-uclass.c | 16 ++++++++++++++-- > 1 file changed, 14 insertions(+), 2 deletions(-) > > diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c > index ed6e60bc4841..755f05f34669 100644 > --- a/drivers/clk/clk-uclass.c > +++ b/drivers/clk/clk-uclass.c > @@ -571,8 +571,20 @@ ulong clk_set_rate(struct clk *clk, ulong rate) > return 0; > ops = clk_dev_ops(clk->dev); > > - if (!ops->set_rate) > - return -ENOSYS; > + /* Try to find parents which can set rate */ > + while (!ops->set_rate) { > + struct clk *parent; > + > + if (!(clk->flags & CLK_SET_RATE_PARENT)) > + return -ENOSYS; > + > + parent = clk_get_parent(clk); > + if (IS_ERR_OR_NULL(parent) || !clk_valid(parent)) > + return -ENODEV; > + > + clk = parent; > + ops = clk_dev_ops(clk->dev); > + } > > /* get private clock struct used for cache */ > clk_get_priv(clk, &clkp); > -- > 2.39.2 >
On 3/20/2024 2:42 AM, Sam Protsenko wrote: > On Thu, Mar 7, 2024 at 6:04 PM Sam Protsenko <semen.protsenko@linaro.org> wrote: >> Sometimes clocks provided to a consumer might not have .set_rate >> operation (like gate or mux clocks), but have CLK_SET_PARENT_RATE flag >> set. In that case it's usually possible to find a parent up the tree >> which is capable of setting the rate (div, pll, etc). Implement a simple >> lookup procedure for such cases, to traverse the clock tree until >> .set_rate capable parent is found, and use that parent to actually >> change the rate. The search will stop once the first .set_rate capable >> clock is found, which is usually enough to handle most cases. >> >> Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org> >> --- > Hi Lukasz, Sean, Tom, > > If this patch looks good to you and there are no outstanding comments, > can you please apply it? It's needed as a part of eMMC enablement for > E850-96 board, as eMMC gate (leaf) clock is specified as ciu clock in > dts, which requires further clock rate change propagation up to > divider clock. > > Thanks! Please be patient. The release cycle is quite long. My patch set for HiSilicon clk framework has been ignored for ~2months already. > >> drivers/clk/clk-uclass.c | 16 ++++++++++++++-- >> 1 file changed, 14 insertions(+), 2 deletions(-) >> >> diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c >> index ed6e60bc4841..755f05f34669 100644 >> --- a/drivers/clk/clk-uclass.c >> +++ b/drivers/clk/clk-uclass.c >> @@ -571,8 +571,20 @@ ulong clk_set_rate(struct clk *clk, ulong rate) >> return 0; >> ops = clk_dev_ops(clk->dev); >> >> - if (!ops->set_rate) >> - return -ENOSYS; >> + /* Try to find parents which can set rate */ >> + while (!ops->set_rate) { >> + struct clk *parent; >> + >> + if (!(clk->flags & CLK_SET_RATE_PARENT)) >> + return -ENOSYS; >> + >> + parent = clk_get_parent(clk); >> + if (IS_ERR_OR_NULL(parent) || !clk_valid(parent)) >> + return -ENODEV; >> + >> + clk = parent; >> + ops = clk_dev_ops(clk->dev); >> + } >> >> /* get private clock struct used for cache */ >> clk_get_priv(clk, &clkp); >> -- >> 2.39.2 >>
On 3/20/24 10:02, Yang Xiwen wrote: > On 3/20/2024 2:42 AM, Sam Protsenko wrote: >> On Thu, Mar 7, 2024 at 6:04 PM Sam Protsenko <semen.protsenko@linaro.org> wrote: >>> Sometimes clocks provided to a consumer might not have .set_rate >>> operation (like gate or mux clocks), but have CLK_SET_PARENT_RATE flag >>> set. In that case it's usually possible to find a parent up the tree >>> which is capable of setting the rate (div, pll, etc). Implement a simple >>> lookup procedure for such cases, to traverse the clock tree until >>> .set_rate capable parent is found, and use that parent to actually >>> change the rate. The search will stop once the first .set_rate capable >>> clock is found, which is usually enough to handle most cases. >>> >>> Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org> >>> --- >> Hi Lukasz, Sean, Tom, >> >> If this patch looks good to you and there are no outstanding comments, >> can you please apply it? It's needed as a part of eMMC enablement for >> E850-96 board, as eMMC gate (leaf) clock is specified as ciu clock in >> dts, which requires further clock rate change propagation up to >> divider clock. >> >> Thanks! > > > Please be patient. The release cycle is quite long. My patch set for HiSilicon clk framework has been ignored for ~2months already. Sorry, I've been busy IRL recently. I will try to review patches in the backlog, but it might be a few more weeks. --Sean
On 3/7/24 19:04, Sam Protsenko wrote: > Sometimes clocks provided to a consumer might not have .set_rate > operation (like gate or mux clocks), but have CLK_SET_PARENT_RATE flag > set. In that case it's usually possible to find a parent up the tree > which is capable of setting the rate (div, pll, etc). Implement a simple > lookup procedure for such cases, to traverse the clock tree until > .set_rate capable parent is found, and use that parent to actually > change the rate. The search will stop once the first .set_rate capable > clock is found, which is usually enough to handle most cases. > > Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org> > --- > drivers/clk/clk-uclass.c | 16 ++++++++++++++-- > 1 file changed, 14 insertions(+), 2 deletions(-) > > diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c > index ed6e60bc4841..755f05f34669 100644 > --- a/drivers/clk/clk-uclass.c > +++ b/drivers/clk/clk-uclass.c > @@ -571,8 +571,20 @@ ulong clk_set_rate(struct clk *clk, ulong rate) > return 0; > ops = clk_dev_ops(clk->dev); > > - if (!ops->set_rate) > - return -ENOSYS; > + /* Try to find parents which can set rate */ > + while (!ops->set_rate) { > + struct clk *parent; > + > + if (!(clk->flags & CLK_SET_RATE_PARENT)) > + return -ENOSYS; > + > + parent = clk_get_parent(clk); > + if (IS_ERR_OR_NULL(parent) || !clk_valid(parent)) > + return -ENODEV; > + > + clk = parent; > + ops = clk_dev_ops(clk->dev); > + } > > /* get private clock struct used for cache */ > clk_get_priv(clk, &clkp); Can you give an example of where this is needed? --Sean
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index ed6e60bc4841..755f05f34669 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -571,8 +571,20 @@ ulong clk_set_rate(struct clk *clk, ulong rate) return 0; ops = clk_dev_ops(clk->dev); - if (!ops->set_rate) - return -ENOSYS; + /* Try to find parents which can set rate */ + while (!ops->set_rate) { + struct clk *parent; + + if (!(clk->flags & CLK_SET_RATE_PARENT)) + return -ENOSYS; + + parent = clk_get_parent(clk); + if (IS_ERR_OR_NULL(parent) || !clk_valid(parent)) + return -ENODEV; + + clk = parent; + ops = clk_dev_ops(clk->dev); + } /* get private clock struct used for cache */ clk_get_priv(clk, &clkp);
Sometimes clocks provided to a consumer might not have .set_rate operation (like gate or mux clocks), but have CLK_SET_PARENT_RATE flag set. In that case it's usually possible to find a parent up the tree which is capable of setting the rate (div, pll, etc). Implement a simple lookup procedure for such cases, to traverse the clock tree until .set_rate capable parent is found, and use that parent to actually change the rate. The search will stop once the first .set_rate capable clock is found, which is usually enough to handle most cases. Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org> --- drivers/clk/clk-uclass.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)