Skip to content

Commit 92a511a

Browse files
thierryredingjwrdegoede
authored andcommitted
fbdev/simplefb: Add support for generic power-domains
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. v2: - remove unnecessary call to simplefb_detach_genpds() since that's already done automatically by devres - fix crash if power-domains property is missing in DT Signed-off-by: Thierry Reding <[email protected]> Reviewed-by: Hans de Goede <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 8ddfc01 commit 92a511a

File tree

1 file changed

+93
-0
lines changed

1 file changed

+93
-0
lines changed

drivers/video/fbdev/simplefb.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/of_clk.h>
2626
#include <linux/of_platform.h>
2727
#include <linux/parser.h>
28+
#include <linux/pm_domain.h>
2829
#include <linux/regulator/consumer.h>
2930

3031
static const struct fb_fix_screeninfo simplefb_fix = {
@@ -78,6 +79,11 @@ struct simplefb_par {
7879
unsigned int clk_count;
7980
struct clk **clks;
8081
#endif
82+
#if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS
83+
unsigned int num_genpds;
84+
struct device **genpds;
85+
struct device_link **genpd_links;
86+
#endif
8187
#if defined CONFIG_OF && defined CONFIG_REGULATOR
8288
bool regulators_enabled;
8389
u32 regulator_count;
@@ -432,6 +438,89 @@ static void simplefb_regulators_enable(struct simplefb_par *par,
432438
static void simplefb_regulators_destroy(struct simplefb_par *par) { }
433439
#endif
434440

441+
#if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS
442+
static void simplefb_detach_genpds(void *res)
443+
{
444+
struct simplefb_par *par = res;
445+
unsigned int i = par->num_genpds;
446+
447+
if (par->num_genpds <= 1)
448+
return;
449+
450+
while (i--) {
451+
if (par->genpd_links[i])
452+
device_link_del(par->genpd_links[i]);
453+
454+
if (!IS_ERR_OR_NULL(par->genpds[i]))
455+
dev_pm_domain_detach(par->genpds[i], true);
456+
}
457+
}
458+
459+
static int simplefb_attach_genpds(struct simplefb_par *par,
460+
struct platform_device *pdev)
461+
{
462+
struct device *dev = &pdev->dev;
463+
unsigned int i;
464+
int err;
465+
466+
err = of_count_phandle_with_args(dev->of_node, "power-domains",
467+
"#power-domain-cells");
468+
if (err < 0) {
469+
dev_info(dev, "failed to parse power-domains: %d\n", err);
470+
return err;
471+
}
472+
473+
par->num_genpds = err;
474+
475+
/*
476+
* Single power-domain devices are handled by the driver core, so
477+
* nothing to do here.
478+
*/
479+
if (par->num_genpds <= 1)
480+
return 0;
481+
482+
par->genpds = devm_kcalloc(dev, par->num_genpds, sizeof(*par->genpds),
483+
GFP_KERNEL);
484+
if (!par->genpds)
485+
return -ENOMEM;
486+
487+
par->genpd_links = devm_kcalloc(dev, par->num_genpds,
488+
sizeof(*par->genpd_links),
489+
GFP_KERNEL);
490+
if (!par->genpd_links)
491+
return -ENOMEM;
492+
493+
for (i = 0; i < par->num_genpds; i++) {
494+
par->genpds[i] = dev_pm_domain_attach_by_id(dev, i);
495+
if (IS_ERR(par->genpds[i])) {
496+
err = PTR_ERR(par->genpds[i]);
497+
if (err == -EPROBE_DEFER) {
498+
simplefb_detach_genpds(par);
499+
return err;
500+
}
501+
502+
dev_warn(dev, "failed to attach domain %u: %d\n", i, err);
503+
continue;
504+
}
505+
506+
par->genpd_links[i] = device_link_add(dev, par->genpds[i],
507+
DL_FLAG_STATELESS |
508+
DL_FLAG_PM_RUNTIME |
509+
DL_FLAG_RPM_ACTIVE);
510+
if (!par->genpd_links[i])
511+
dev_warn(dev, "failed to link power-domain %u\n", i);
512+
}
513+
514+
return devm_add_action_or_reset(dev, simplefb_detach_genpds, par);
515+
}
516+
#else
517+
static int simplefb_attach_genpds(struct simplefb_par *par,
518+
struct platform_device *pdev)
519+
{
520+
return 0;
521+
}
522+
#endif
523+
435524
static int simplefb_probe(struct platform_device *pdev)
436525
{
437526
int ret;
@@ -518,6 +607,10 @@ static int simplefb_probe(struct platform_device *pdev)
518607
if (ret < 0)
519608
goto error_clocks;
520609

610+
ret = simplefb_attach_genpds(par, pdev);
611+
if (ret < 0)
612+
goto error_regulators;
613+
521614
simplefb_clocks_enable(par, pdev);
522615
simplefb_regulators_enable(par, pdev);
523616

0 commit comments

Comments
 (0)