Skip to content

Commit

Permalink
PM: domains: Allow genpd providers to manage OPP tables directly by i…
Browse files Browse the repository at this point in the history
…ts FW

In some cases the OPP tables aren't specified in device tree, but rather
encoded in the FW. To allow a genpd provider to specify them dynamically
instead, let's add a new genpd flag, GENPD_FLAG_OPP_TABLE_FW.

Signed-off-by: Ulf Hansson <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Sudeep Holla <[email protected]>
  • Loading branch information
storulf authored and sudeep-holla committed Sep 21, 2023
1 parent 92b2028 commit 3dd9151
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
11 changes: 6 additions & 5 deletions drivers/base/power/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
#define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP)
#define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN)
#define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON)
#define genpd_is_opp_table_fw(genpd) (genpd->flags & GENPD_FLAG_OPP_TABLE_FW)

static inline bool irq_safe_dev_in_sleep_domain(struct device *dev,
const struct generic_pm_domain *genpd)
Expand Down Expand Up @@ -2328,7 +2329,7 @@ int of_genpd_add_provider_simple(struct device_node *np,
genpd->dev.of_node = np;

/* Parse genpd OPP table */
if (genpd->set_performance_state) {
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
ret = dev_pm_opp_of_add_table(&genpd->dev);
if (ret)
return dev_err_probe(&genpd->dev, ret, "Failed to add OPP table\n");
Expand All @@ -2343,7 +2344,7 @@ int of_genpd_add_provider_simple(struct device_node *np,

ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
if (ret) {
if (genpd->set_performance_state) {
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
dev_pm_opp_put_opp_table(genpd->opp_table);
dev_pm_opp_of_remove_table(&genpd->dev);
}
Expand Down Expand Up @@ -2387,7 +2388,7 @@ int of_genpd_add_provider_onecell(struct device_node *np,
genpd->dev.of_node = np;

/* Parse genpd OPP table */
if (genpd->set_performance_state) {
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i);
if (ret) {
dev_err_probe(&genpd->dev, ret,
Expand Down Expand Up @@ -2423,7 +2424,7 @@ int of_genpd_add_provider_onecell(struct device_node *np,
genpd->provider = NULL;
genpd->has_provider = false;

if (genpd->set_performance_state) {
if (!genpd_is_opp_table_fw(genpd) && genpd->set_performance_state) {
dev_pm_opp_put_opp_table(genpd->opp_table);
dev_pm_opp_of_remove_table(&genpd->dev);
}
Expand Down Expand Up @@ -2455,7 +2456,7 @@ void of_genpd_del_provider(struct device_node *np)
if (gpd->provider == &np->fwnode) {
gpd->has_provider = false;

if (!gpd->set_performance_state)
if (genpd_is_opp_table_fw(gpd) || !gpd->set_performance_state)
continue;

dev_pm_opp_put_opp_table(gpd->opp_table);
Expand Down
5 changes: 5 additions & 0 deletions include/linux/pm_domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
* GENPD_FLAG_MIN_RESIDENCY: Enable the genpd governor to consider its
* components' next wakeup when determining the
* optimal idle state.
*
* GENPD_FLAG_OPP_TABLE_FW: The genpd provider supports performance states,
* but its corresponding OPP tables are not
* described in DT, but are given directly by FW.
*/
#define GENPD_FLAG_PM_CLK (1U << 0)
#define GENPD_FLAG_IRQ_SAFE (1U << 1)
Expand All @@ -69,6 +73,7 @@
#define GENPD_FLAG_CPU_DOMAIN (1U << 4)
#define GENPD_FLAG_RPM_ALWAYS_ON (1U << 5)
#define GENPD_FLAG_MIN_RESIDENCY (1U << 6)
#define GENPD_FLAG_OPP_TABLE_FW (1U << 7)

enum gpd_status {
GENPD_STATE_ON = 0, /* PM domain is on */
Expand Down

0 comments on commit 3dd9151

Please sign in to comment.