[PATCH 2/2] fbdev/simplefb: Add support for generic power-domains
Robert Foss
rfoss at kernel.org
Wed Oct 18 12:18:19 UTC 2023
On Wed, Oct 18, 2023 at 12:35 PM Robert Foss <rfoss at kernel.org> wrote:
>
> On Wed, Oct 11, 2023 at 4:38 PM Thierry Reding <thierry.reding at gmail.com> wrote:
> >
> > From: Thierry Reding <treding at nvidia.com>
> >
> > The simple-framebuffer device tree bindings document the power-domains
> > property, so make sure that simplefb supports it. This ensures that the
> > power domains remain enabled as long as simplefb is active.
> >
> > Signed-off-by: Thierry Reding <treding at nvidia.com>
> > ---
> > drivers/video/fbdev/simplefb.c | 93 +++++++++++++++++++++++++++++++++-
> > 1 file changed, 91 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
> > index 18025f34fde7..e69fb0ad2d54 100644
> > --- a/drivers/video/fbdev/simplefb.c
> > +++ b/drivers/video/fbdev/simplefb.c
> > @@ -25,6 +25,7 @@
> > #include <linux/of_clk.h>
> > #include <linux/of_platform.h>
> > #include <linux/parser.h>
> > +#include <linux/pm_domain.h>
> > #include <linux/regulator/consumer.h>
> >
> > static const struct fb_fix_screeninfo simplefb_fix = {
> > @@ -78,6 +79,11 @@ struct simplefb_par {
> > unsigned int clk_count;
> > struct clk **clks;
> > #endif
> > +#if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS
> > + unsigned int num_genpds;
> > + struct device **genpds;
> > + struct device_link **genpd_links;
> > +#endif
> > #if defined CONFIG_OF && defined CONFIG_REGULATOR
> > bool regulators_enabled;
> > u32 regulator_count;
> > @@ -432,6 +438,83 @@ static void simplefb_regulators_enable(struct simplefb_par *par,
> > static void simplefb_regulators_destroy(struct simplefb_par *par) { }
> > #endif
> >
> > +#if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS
> > +static void simplefb_detach_genpds(void *res)
> > +{
> > + struct simplefb_par *par = res;
> > + unsigned int i = par->num_genpds;
> > +
> > + if (par->num_genpds <= 1)
> > + return;
> > +
> > + while (i--) {
> > + if (par->genpd_links[i])
> > + device_link_del(par->genpd_links[i]);
> > +
> > + if (!IS_ERR_OR_NULL(par->genpds[i]))
> > + dev_pm_domain_detach(par->genpds[i], true);
> > + }
> > +}
> > +
> > +static int simplefb_attach_genpd(struct simplefb_par *par,
> > + struct platform_device *pdev)
> > +{
> > + struct device *dev = &pdev->dev;
> > + unsigned int i;
> > + int err;
> > +
> > + par->num_genpds = of_count_phandle_with_args(dev->of_node,
> > + "power-domains",
> > + "#power-domain-cells");
> > + /*
> > + * Single power-domain devices are handled by the driver core, so
> > + * nothing to do here.
> > + */
> > + if (par->num_genpds <= 1)
> > + return 0;
> > +
> > + par->genpds = devm_kcalloc(dev, par->num_genpds, sizeof(*par->genpds),
> > + GFP_KERNEL);
> > + if (!par->genpds)
> > + return -ENOMEM;
> > +
> > + par->genpd_links = devm_kcalloc(dev, par->num_genpds,
> > + sizeof(*par->genpd_links),
> > + GFP_KERNEL);
> > + if (!par->genpd_links)
> > + return -ENOMEM;
> > +
> > + for (i = 0; i < par->num_genpds; i++) {
> > + par->genpds[i] = dev_pm_domain_attach_by_id(dev, i);
> > + if (IS_ERR(par->genpds[i])) {
> > + err = PTR_ERR(par->genpds[i]);
> > + if (err == -EPROBE_DEFER) {
> > + simplefb_detach_genpds(par);
> > + return err;
> > + }
> > +
> > + dev_warn(dev, "failed to attach domain %u: %d\n", i, err);
> > + continue;
> > + }
> > +
> > + par->genpd_links[i] = device_link_add(dev, par->genpds[i],
> > + DL_FLAG_STATELESS |
> > + DL_FLAG_PM_RUNTIME |
> > + DL_FLAG_RPM_ACTIVE);
> > + if (!par->genpd_links[i])
> > + dev_warn(dev, "failed to link power-domain %u\n", i);
> > + }
> > +
> > + return devm_add_action_or_reset(dev, simplefb_detach_genpds, par);
> > +}
> > +#else
> > +static int simplefb_attach_genpd(struct simplefb_par *par,
> > + struct platform_device *pdev)
> > +{
> > + return 0;
> > +}
> > +#endif
> > +
> > static int simplefb_probe(struct platform_device *pdev)
> > {
> > int ret;
> > @@ -518,6 +601,10 @@ static int simplefb_probe(struct platform_device *pdev)
> > if (ret < 0)
> > goto error_clocks;
> >
> > + ret = simplefb_attach_genpd(par, pdev);
> > + if (ret < 0)
> > + goto error_regulators;
> > +
> > simplefb_clocks_enable(par, pdev);
> > simplefb_regulators_enable(par, pdev);
> >
> > @@ -534,18 +621,20 @@ static int simplefb_probe(struct platform_device *pdev)
> > ret = devm_aperture_acquire_for_platform_device(pdev, par->base, par->size);
> > if (ret) {
> > dev_err(&pdev->dev, "Unable to acquire aperture: %d\n", ret);
> > - goto error_regulators;
> > + goto error_genpds;
> > }
> > ret = register_framebuffer(info);
> > if (ret < 0) {
> > dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
> > - goto error_regulators;
> > + goto error_genpds;
> > }
> >
> > dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
> >
> > return 0;
> >
> > +error_genpds:
> > + simplefb_detach_genpds(par);
> > error_regulators:
> > simplefb_regulators_destroy(par);
>
> I saw an error on a rhel9.3 kernel build, it may or may not be hit on
> an upstream build.
>
> drivers/video/fbdev/simplefb.c: In function 'simplefb_probe':
> drivers/video/fbdev/simplefb.c:650:1: warning: label
> 'error_regulators' defined but not used [-Wunused-label]
> 650 | error_regulators:
> | ^~~~~~~~~~~~~~~~
>
>
Scratch that. After applying on an upstream build, it builds cleanly.
More information about the dri-devel
mailing list