Merge branch 'opp/genpd-pstate-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm
Pull Operating Performance Points (OPP) library changes for v4.18
from Viresh Kumar.
* 'opp/genpd-pstate-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm:
PM / OPP: Remove dev_pm_opp_{un}register_get_pstate_helper()
PM / OPP: Get performance state using genpd helper
PM / Domain: Implement of_genpd_opp_to_performance_state()
PM / Domain: Add support to parse domain's OPP table
PM / Domain: Add struct device to genpd
PM / OPP: Implement dev_pm_opp_get_of_node()
PM / OPP: Implement of_dev_pm_opp_find_required_opp()
PM / OPP: Implement dev_pm_opp_of_add_table_indexed()
PM / OPP: "opp-hz" is optional for power domains
PM / OPP: dt-bindings: Make "opp-hz" optional for power domains
PM / OPP: dt-bindings: Rename "required-opp" as "required-opps"
soc/tegra: pmc: Don't allocate struct tegra_powergate on stack
This commit is contained in:
+113
-14
@@ -10,6 +10,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_opp.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_qos.h>
|
||||
@@ -1691,6 +1692,9 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_initialize(&genpd->dev);
|
||||
dev_set_name(&genpd->dev, "%s", genpd->name);
|
||||
|
||||
mutex_lock(&gpd_list_lock);
|
||||
list_add(&genpd->gpd_list_node, &gpd_list);
|
||||
mutex_unlock(&gpd_list_lock);
|
||||
@@ -1887,14 +1891,33 @@ int of_genpd_add_provider_simple(struct device_node *np,
|
||||
|
||||
mutex_lock(&gpd_list_lock);
|
||||
|
||||
if (genpd_present(genpd)) {
|
||||
ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
|
||||
if (!ret) {
|
||||
genpd->provider = &np->fwnode;
|
||||
genpd->has_provider = true;
|
||||
if (!genpd_present(genpd))
|
||||
goto unlock;
|
||||
|
||||
genpd->dev.of_node = np;
|
||||
|
||||
/* Parse genpd OPP table */
|
||||
if (genpd->set_performance_state) {
|
||||
ret = dev_pm_opp_of_add_table(&genpd->dev);
|
||||
if (ret) {
|
||||
dev_err(&genpd->dev, "Failed to add OPP table: %d\n",
|
||||
ret);
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
|
||||
if (ret) {
|
||||
if (genpd->set_performance_state)
|
||||
dev_pm_opp_of_remove_table(&genpd->dev);
|
||||
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
genpd->provider = &np->fwnode;
|
||||
genpd->has_provider = true;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&gpd_list_lock);
|
||||
|
||||
return ret;
|
||||
@@ -1909,6 +1932,7 @@ EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple);
|
||||
int of_genpd_add_provider_onecell(struct device_node *np,
|
||||
struct genpd_onecell_data *data)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
unsigned int i;
|
||||
int ret = -EINVAL;
|
||||
|
||||
@@ -1921,13 +1945,27 @@ int of_genpd_add_provider_onecell(struct device_node *np,
|
||||
data->xlate = genpd_xlate_onecell;
|
||||
|
||||
for (i = 0; i < data->num_domains; i++) {
|
||||
if (!data->domains[i])
|
||||
genpd = data->domains[i];
|
||||
|
||||
if (!genpd)
|
||||
continue;
|
||||
if (!genpd_present(data->domains[i]))
|
||||
if (!genpd_present(genpd))
|
||||
goto error;
|
||||
|
||||
data->domains[i]->provider = &np->fwnode;
|
||||
data->domains[i]->has_provider = true;
|
||||
genpd->dev.of_node = np;
|
||||
|
||||
/* Parse genpd OPP table */
|
||||
if (genpd->set_performance_state) {
|
||||
ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i);
|
||||
if (ret) {
|
||||
dev_err(&genpd->dev, "Failed to add OPP table for index %d: %d\n",
|
||||
i, ret);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
genpd->provider = &np->fwnode;
|
||||
genpd->has_provider = true;
|
||||
}
|
||||
|
||||
ret = genpd_add_provider(np, data->xlate, data);
|
||||
@@ -1940,10 +1978,16 @@ int of_genpd_add_provider_onecell(struct device_node *np,
|
||||
|
||||
error:
|
||||
while (i--) {
|
||||
if (!data->domains[i])
|
||||
genpd = data->domains[i];
|
||||
|
||||
if (!genpd)
|
||||
continue;
|
||||
data->domains[i]->provider = NULL;
|
||||
data->domains[i]->has_provider = false;
|
||||
|
||||
genpd->provider = NULL;
|
||||
genpd->has_provider = false;
|
||||
|
||||
if (genpd->set_performance_state)
|
||||
dev_pm_opp_of_remove_table(&genpd->dev);
|
||||
}
|
||||
|
||||
mutex_unlock(&gpd_list_lock);
|
||||
@@ -1970,10 +2014,17 @@ void of_genpd_del_provider(struct device_node *np)
|
||||
* provider, set the 'has_provider' to false
|
||||
* so that the PM domain can be safely removed.
|
||||
*/
|
||||
list_for_each_entry(gpd, &gpd_list, gpd_list_node)
|
||||
if (gpd->provider == &np->fwnode)
|
||||
list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
|
||||
if (gpd->provider == &np->fwnode) {
|
||||
gpd->has_provider = false;
|
||||
|
||||
if (!gpd->set_performance_state)
|
||||
continue;
|
||||
|
||||
dev_pm_opp_of_remove_table(&gpd->dev);
|
||||
}
|
||||
}
|
||||
|
||||
list_del(&cp->link);
|
||||
of_node_put(cp->node);
|
||||
kfree(cp);
|
||||
@@ -2346,6 +2397,54 @@ int of_genpd_parse_idle_states(struct device_node *dn,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_genpd_parse_idle_states);
|
||||
|
||||
/**
|
||||
* of_genpd_opp_to_performance_state- Gets performance state of device's
|
||||
* power domain corresponding to a DT node's "required-opps" property.
|
||||
*
|
||||
* @dev: Device for which the performance-state needs to be found.
|
||||
* @opp_node: DT node where the "required-opps" property is present. This can be
|
||||
* the device node itself (if it doesn't have an OPP table) or a node
|
||||
* within the OPP table of a device (if device has an OPP table).
|
||||
* @state: Pointer to return performance state.
|
||||
*
|
||||
* Returns performance state corresponding to the "required-opps" property of
|
||||
* a DT node. This calls platform specific genpd->opp_to_performance_state()
|
||||
* callback to translate power domain OPP to performance state.
|
||||
*
|
||||
* Returns performance state on success and 0 on failure.
|
||||
*/
|
||||
unsigned int of_genpd_opp_to_performance_state(struct device *dev,
|
||||
struct device_node *opp_node)
|
||||
{
|
||||
struct generic_pm_domain *genpd;
|
||||
struct dev_pm_opp *opp;
|
||||
int state = 0;
|
||||
|
||||
genpd = dev_to_genpd(dev);
|
||||
if (IS_ERR(genpd))
|
||||
return 0;
|
||||
|
||||
if (unlikely(!genpd->set_performance_state))
|
||||
return 0;
|
||||
|
||||
genpd_lock(genpd);
|
||||
|
||||
opp = of_dev_pm_opp_find_required_opp(&genpd->dev, opp_node);
|
||||
if (IS_ERR(opp)) {
|
||||
state = PTR_ERR(opp);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
state = genpd->opp_to_performance_state(genpd, opp);
|
||||
dev_pm_opp_put(opp);
|
||||
|
||||
unlock:
|
||||
genpd_unlock(genpd);
|
||||
|
||||
return state;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_genpd_opp_to_performance_state);
|
||||
|
||||
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user