Skip to content

Commit c016baf

Browse files
Rajendra Nayakrafaeljw
authored andcommitted
PM: domains: Add support for 'required-opps' to set default perf state
Some devices within power domains with performance states do not support DVFS, but still need to vote on a default/static state while they are active. They can express this using the 'required-opps' property in device tree, which points to the phandle of the OPP supported by the corresponding power-domains. Add support to parse this information from DT and then set the specified performance state during attach and drop it on detach. runtime suspend/resume callbacks already have logic to drop/set the vote as needed and should take care of dropping the default perf state vote on runtime suspend and restore it back on runtime resume. Signed-off-by: Rajendra Nayak <[email protected]> Reviewed-by: Ulf Hansson <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 020d86f commit c016baf

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

drivers/base/power/domain.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2598,6 +2598,12 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)
25982598

25992599
dev_dbg(dev, "removing from PM domain %s\n", pd->name);
26002600

2601+
/* Drop the default performance state */
2602+
if (dev_gpd_data(dev)->default_pstate) {
2603+
dev_pm_genpd_set_performance_state(dev, 0);
2604+
dev_gpd_data(dev)->default_pstate = 0;
2605+
}
2606+
26012607
for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
26022608
ret = genpd_remove_device(pd, dev);
26032609
if (ret != -EAGAIN)
@@ -2637,6 +2643,7 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
26372643
{
26382644
struct of_phandle_args pd_args;
26392645
struct generic_pm_domain *pd;
2646+
int pstate;
26402647
int ret;
26412648

26422649
ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
@@ -2675,10 +2682,29 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
26752682
genpd_unlock(pd);
26762683
}
26772684

2678-
if (ret)
2685+
if (ret) {
26792686
genpd_remove_device(pd, dev);
2687+
return -EPROBE_DEFER;
2688+
}
26802689

2681-
return ret ? -EPROBE_DEFER : 1;
2690+
/* Set the default performance state */
2691+
pstate = of_get_required_opp_performance_state(dev->of_node, index);
2692+
if (pstate < 0 && pstate != -ENODEV) {
2693+
ret = pstate;
2694+
goto err;
2695+
} else if (pstate > 0) {
2696+
ret = dev_pm_genpd_set_performance_state(dev, pstate);
2697+
if (ret)
2698+
goto err;
2699+
dev_gpd_data(dev)->default_pstate = pstate;
2700+
}
2701+
return 1;
2702+
2703+
err:
2704+
dev_err(dev, "failed to set required performance state for power-domain %s: %d\n",
2705+
pd->name, ret);
2706+
genpd_remove_device(pd, dev);
2707+
return ret;
26822708
}
26832709

26842710
/**

include/linux/pm_domain.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ struct generic_pm_domain_data {
198198
struct notifier_block *power_nb;
199199
int cpu;
200200
unsigned int performance_state;
201+
unsigned int default_pstate;
201202
unsigned int rpm_pstate;
202203
ktime_t next_wakeup;
203204
void *data;

0 commit comments

Comments
 (0)