On Mon, Dec 30, 2024 at 05:22:56PM -0800, Stephen Boyd wrote: > Quoting Miquel Raynal (2024-12-23 10:43:13) > > Hi Maxime, > > > > On 17/12/2024 at 13:47:53 +01, Maxime Ripard <mripard@xxxxxxxxxx> wrote: > > > > > On Thu, Nov 21, 2024 at 06:41:14PM +0100, Miquel Raynal wrote: > > >> There are mainly two ways to change a clock frequency. > > > > > > There's much more than that :) > > > > "mainly" > > > > Or maybe I should have added "on purpose". > > > > > > > > Off the top of my head, setting/clearing a min/max rate and changing the > > > parent might also result in a rate change. > > > > > > And then, the firmware might get involved too. > > > > > >> The active way requires calling ->set_rate() in order to ask "on > > >> purpose" for a frequency change. Otherwise, a clock can passively see > > >> its frequency being updated depending on upstream clock frequency > > >> changes. In most cases it is fine to just accept the new upstream > > >> frequency - which by definition will have an impact on downstream > > >> frequencies if we do not recalculate internal divisors. But there are > > >> cases where, upon an upstream frequency change, we would like to > > >> maintain a specific rate. > > > > > > Why is clk_set_rate_exclusive not enough? > > > > I am trying to protect these rate changes from subtree walks, I don't > > see where setting an exclusive rate would have an effect? But I might be > > overlooking something, definitely. > > > > ... > > > > >> @@ -2272,7 +2271,13 @@ static void clk_calc_subtree(struct clk_core *core) > > >> { > > >> struct clk_core *child; > > >> > > >> - core->new_rate = clk_recalc(core, core->parent->new_rate); > > >> + if (core->flags & CLK_NO_RATE_CHANGE_DURING_PROPAGATION) { > > >> + core->new_rate = clk_determine(core, core->rate); > > >> + if (!core->new_rate) > > >> + core->new_rate = clk_recalc(core, core->parent->new_rate); > > >> + } else { > > >> + core->new_rate = clk_recalc(core, core->parent->new_rate); > > >> + } > > > > > > Sorry, it's not clear to me how it works. How will the parent clocks > > > will get notified to adjust their dividers in that scenario? Also, what > > > if they can't? > > > > The idea is: if the flag is set, instead of accepting the new upstream > > rate and recalculate the downstream rate based on a previously set > > divider value, we change our divider value to match the same frequency > > as before. But if we cannot, then we just keep the old way. > > > > The exclusive rate code could support this if it doesn't already do so. > If you call clk_set_rate_exclusive(child, <constant rate>) followed by > clk_set_rate(parent, <new rate>) the core code should try to keep the > child at the constant rate, or fail the clk_set_rate() call on the > parent. It should be possible to confirm this with some KUnit tests for > clk_set_rate_exclusive(). Similarly, if another child, child_B, of the > parent changes the parent rate, we should speculate the new rate of the > child_A that's protected and fail if we can't maintain the rate. We need > to start generating a list of clks that we operate a rate change on to > support this though, because right now we rely on the stack to track the > clks that we change the rate of. > > Initially we thought that we could do this with clk notifiers. That may > work here, but I suspect it will be clunky to get working because clk > notifiers operate on struct clk. I think notifiers are great for customers, but not really adequate for the clock drivers tree. Indeed, you can only react to a (sub)tree configuration using notifiers, but you can't affect it to try something new that would be a better fit. Like, if we have a PLL A, with two child clocks that are dividers. B is initially (exclusively) set to freq X, and then you want to set C to 2X. The best thing to do is to set A to 2X, and double B's divider. It's simple enough, but we have no way to try to negociate that at the moment. Maxime
Attachment:
signature.asc
Description: PGP signature