Re: [PATCH] clk: qcom: rcg2: Cache rate changes for parked RCGs

From: Stephen Boyd
Date: Tue Jan 11 2022 - 22:06:09 EST


Quoting Bjorn Andersson (2021-12-16 20:05:52)
> On Thu 16 Dec 19:45 CST 2021, Stephen Boyd wrote:
> > > >
> > > > >
> > > > > > So instead of saving the current_rate can we save the cfg register value
> > > > > > (or however many registers we need) to put back the frequency of the clk
> > > > > > to what we want on enable? The other thing is that we made recalc_rate()
> > > > > > work "seamlessly" here by stashing the frequency into the register but
> > > > > > leaving it uncommitted until enable. We may need to now look at the
> > > > > > software copy of the registers in the shared rcg recalc rate operation
> > > > > > to figure out what the frequency is.
> > > > > >
> > > > >
> > > > > I made an attempt at this, the problem I had was to come up within
> > > > > something sane for how to deal with set_rate on parked clocks; because
> > > > > we need to re-generate the register contents, without writing out the
> > > > > value - and that got messy.
> > > >
> > > > Looking back on the introduction of this code[1] I see that it's not
> > > > about the rate but more about the parent. i.e. we park the clk on the XO
> > > > parent but don't care about the m/n values or pre divider because it
> > > > doesn't really matter if the clk is running slowly. So nothing needs to
> > > > be saved except for the cfg register, and we can do that in software
> > > > with a single u32 instead of using a rate and looking it up and then
> > > > reprogramming the other values. We should be able to cache the register
> > > > content with an init clk_op.
> > > >
> > >
> > > So you're suggesting that, in clk_rcg2_shared_set_rate(), when the RCG
> > > is found to be disabled, I should write out M, N, D and calculate a new
> > > cfg value which I stash until the next enable?
> > >
> > > Looks a little bit messy, but I will give it a try.
> >
> > No. I don't see where clk_rcg2_shared_set_rate() needs to change.
> >
> > I'm suggesting we cache the config register on disable so it can be
> > restored on enable. Basically everything is the same except now we don't
> > write the cfg register and leave it dirty in the hardware. We need a
> > shared rcg version of recalc rate that looks at the shadow cfg register
> > instead of reading the hardware because we've changed the parent behind
> > the back of the framework and we want to make it look like nothing has
> > changed.
> >
>
> I see, that was my first attempt of an implementation as well.
>
> The problem I ran into right away was that i had something that did
> disable(), set_rate(), enable() and I would restore the wrong settings.
>
> So clk_rcg2_shared_set_rate() needs to update the stashed cfg value -
> and it needs to write out M, N and D if we're not caching those.
>
> > This is all based on my understanding that the problem is the RCG is
> > changing rate due to the gdsc turning on the clk for us. So we can't
> > leave anything dirty in the hardware and have to keep it in software.
> > I hope the change is minimal.
>
> That's my understanding as well.
>
>
> Looking more at the code I think it's possible that we get disable(),
> set_parent(), enable() as well; which if that's the case would result
> in the same problem, so I assume I need to tend to that as well.

Hopefully we can write the M, N, D and pre-divier values all the time
and avoid writing the parent selection register (the cfg one) when the
clk is off. It would mean that the "safe parent" of XO is getting
divided pretty heavily sometimes but I suspect it doesn't matter in
practice. When the clk is enabled in the kernel, we'll move the parent
over by making the cfg register have the right parent selectoin and then
the mnd and divider would already be what they're supposed to be in the
hardware. Does that work?