[PATCH] imx: power-domain: enable parent power domain
Patrick Wildt
patrick at blueri.se
Sun Jan 29 11:47:08 CET 2023
On Sun, Jan 29, 2023 at 05:00:15AM +0100, Marek Vasut wrote:
> On 1/29/23 04:28, Patrick Wildt wrote:
> > Am Sun, Jan 29, 2023 at 02:46:36AM +0100 schrieb Marek Vasut:
> > > On 1/28/23 23:14, Patrick Wildt wrote:
> > > > The PCIe power domains are dependant on each other, which is why
> > > > the device tree makes both PCIe controllers reference the PCIe1
> > > > power domain, which then depends on the PCIe2 power domain.
> > > >
> > > > Enabling the parent power domain used to be part of the driver,
> > > > but got partially lost in the rewrite. Add the enable call back
> > > > to be able to power up PCIe2.
> > > >
> > > > Signed-off-by: Patrick Wildt <patrick at blueri.se>
> > > > ---
> > > > drivers/power/domain/imx8m-power-domain.c | 3 +++
> > > > 1 file changed, 3 insertions(+)
> > > >
> > > > diff --git a/drivers/power/domain/imx8m-power-domain.c b/drivers/power/domain/imx8m-power-domain.c
> > > > index 145f6ec0cd..d8e9ce3291 100644
> > > > --- a/drivers/power/domain/imx8m-power-domain.c
> > > > +++ b/drivers/power/domain/imx8m-power-domain.c
> > > > @@ -330,6 +330,9 @@ static int imx8m_power_domain_on(struct power_domain *power_domain)
> > > > u32 pgc;
> > > > int ret;
> > > > + if (pdata->has_pd)
> > > > + power_domain_on(&pdata->pd);
> > > > +
> > > > if (pdata->clk.count) {
> > > > ret = clk_enable_bulk(&pdata->clk);
> > > > if (ret) {
> > >
> > > One problem with this patch is that it does not turn the power domain back
> > > OFF in imx8m_power_domain_off().
> >
> > That's not true. That function already turns the power domain off, it
> > just never enables them in the first place. The enabling was lost when
> > the code was rewritten to not use smcc but the disabling is still there:
> >
> > static int imx8m_power_domain_off(struct power_domain *power_domain)
> > {
> > (...)
> > if (pdata->has_pd)
> > power_domain_off(&pdata->pd);
> >
> > return 0;
> > (...)
> > }
>
> Doh, sorry, I did miss that one. Indeed, the imx power domain driver is not
> symmetrical now.
>
> > What might be missing though is error handling to turn the power domain
> > back off when enabling clocks/power up fails. In case this needs to be
> > fixed elsewhere, then maybe we need to *remove* the call to power_domain_
> > off().
> >
> > > However, the driver should not have to care about that. It is the uclass job
> > > to turn on any prerequisite power domains, which I believe happens in:
> > >
> > > drivers/power/domain/power-domain-uclass.c
> > > dev_power_domain_ctrl()
> > >
> > > However, I suspect the code fails to recurse through more than one level of
> > > power domains and therefore doesn't enable the power domains all the way up
> > > the power domain tree. I also think this would be the fix -- recurse in
> > > dev_power_domain_ctrl() if there are upstream domains to enable, enable them
> > > in that recursive call, and then enable the current power domain using
> > > power_domain_on() .
> > >
> > > Can you take a closer look at the uclass and the way it enables (or fail to)
> > > the upstream domains instead ?
> >
> > I guess one issue is that I was calling power_domain_on() directly instead of
> > dev_power_domain_on() in my PCIe driver.
>
> That sounds like a good idea.
>
> > And maybe I shouldn't even need to
> > have the PCIe driver call that one function anyway, maybe uclass is supposed
> > to turn on my PCIe controllers power domain automatically.
>
> device_probe() does call dev_power_domain_on(), so that sounds like a good
> idea too.
>
> > As you mentioned, there's no "parent handling" in dev_power_domain_ctrl().
> > Something like this could work, but I'm not sure that's better. Also I can't
> > judge if there are any other side-effects of this. Still feels a bit like a
> > layer violation
>
> How so ?
>
> > , but maybe it's the right thing to do.
> >
> > for (i = 0; i < count; i++) {
> > ret = power_domain_get_by_index(dev, &pd, i);
> > if (ret)
> > return ret;
> > if (on) {
> > ret = dev_power_domain_on(pd.dev);
> > if (!ret)
> > ret = power_domain_on(&pd);
> > } else {
> > ret = power_domain_off(&pd);
> > if (!ret)
> > ret = dev_power_domain_off(pd.dev);
> > }
> > }
> >
> > I'll give this a go after some sleep.
>
> I think this makes sense -- the domain should enable all its upstream
> domains first, before enabling itself.
>
> It might also make sense to remove the aforementioned power_domain_off()
> from imx8m-power-domain.c once the dev_power_domain_ctrl() is fixed.
Just tested, this diff works for me. Should I send it as a patch to the
list?
One thing that worries me is that there's no refcounting to make sure
that a parent that is used twice doesn't get disabled. That might be
something to follow-up on.
diff --git a/drivers/power/domain/power-domain-uclass.c b/drivers/power/domain/power-domain-uclass.c
index f6286c70c1..3b3caf6164 100644
--- a/drivers/power/domain/power-domain-uclass.c
+++ b/drivers/power/domain/power-domain-uclass.c
@@ -138,10 +138,15 @@ static int dev_power_domain_ctrl(struct udevice *dev, bool on)
ret = power_domain_get_by_index(dev, &pd, i);
if (ret)
return ret;
- if (on)
- ret = power_domain_on(&pd);
- else
+ if (on) {
+ ret = dev_power_domain_on(pd.dev);
+ if (!ret)
+ ret = power_domain_on(&pd);
+ } else {
ret = power_domain_off(&pd);
+ if (!ret)
+ ret = dev_power_domain_off(pd.dev);
+ }
}
/*
More information about the U-Boot
mailing list