Merge branch 'pm-domains'
* pm-domains: PM / Domains: Rename pm_genpd_sync_poweron|poweroff() PM / Domains: Don't measure latency of ->power_on|off() during system PM PM / Domains: Remove redundant system PM callbacks PM / Domains: Simplify detaching a device from its genpd PM / Domains: Allow holes in genpd_data.domains array PM / Domains: Add support for removing nested PM domains by provider PM / Domains: Add support for removing PM domains PM / Domains: Store the provider in the PM domain structure PM / Domains: Prepare for adding support to remove PM domains PM / Domains: Verify the PM domain is present when adding a provider PM / Domains: Don't expose xlate and provider helper functions PM / Domains: Don't expose generic_pm_domain structure to clients staging: board: Remove calls to of_genpd_get_from_provider() ARM: EXYNOS: Remove calls to of_genpd_get_from_provider() PM / Domains: Add new helper functions for device-tree PM / Domains: Always enable debugfs support if available
This commit is contained in:
commit
2dc3c72cd0
|
@ -45,7 +45,7 @@ static DEFINE_MUTEX(gpd_list_lock);
|
||||||
* and checks that the PM domain pointer is a real generic PM domain.
|
* and checks that the PM domain pointer is a real generic PM domain.
|
||||||
* Any failure results in NULL being returned.
|
* Any failure results in NULL being returned.
|
||||||
*/
|
*/
|
||||||
struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
|
static struct generic_pm_domain *genpd_lookup_dev(struct device *dev)
|
||||||
{
|
{
|
||||||
struct generic_pm_domain *genpd = NULL, *gpd;
|
struct generic_pm_domain *genpd = NULL, *gpd;
|
||||||
|
|
||||||
|
@ -586,7 +586,7 @@ static int __init genpd_poweroff_unused(void)
|
||||||
}
|
}
|
||||||
late_initcall(genpd_poweroff_unused);
|
late_initcall(genpd_poweroff_unused);
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_GENERIC_DOMAINS_OF)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pm_genpd_present - Check if the given PM domain has been initialized.
|
* pm_genpd_present - Check if the given PM domain has been initialized.
|
||||||
|
@ -606,6 +606,10 @@ static bool pm_genpd_present(const struct generic_pm_domain *genpd)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
|
||||||
static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
|
static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -613,9 +617,8 @@ static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pm_genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
|
* genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
|
||||||
* @genpd: PM domain to power off, if possible.
|
* @genpd: PM domain to power off, if possible.
|
||||||
* @timed: True if latency measurements are allowed.
|
|
||||||
*
|
*
|
||||||
* Check if the given PM domain can be powered off (during system suspend or
|
* Check if the given PM domain can be powered off (during system suspend or
|
||||||
* hibernation) and do that if so. Also, in that case propagate to its masters.
|
* hibernation) and do that if so. Also, in that case propagate to its masters.
|
||||||
|
@ -625,8 +628,7 @@ static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
|
||||||
* executed sequentially, so it is guaranteed that it will never run twice in
|
* executed sequentially, so it is guaranteed that it will never run twice in
|
||||||
* parallel).
|
* parallel).
|
||||||
*/
|
*/
|
||||||
static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd,
|
static void genpd_sync_poweroff(struct generic_pm_domain *genpd)
|
||||||
bool timed)
|
|
||||||
{
|
{
|
||||||
struct gpd_link *link;
|
struct gpd_link *link;
|
||||||
|
|
||||||
|
@ -639,28 +641,26 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd,
|
||||||
|
|
||||||
/* Choose the deepest state when suspending */
|
/* Choose the deepest state when suspending */
|
||||||
genpd->state_idx = genpd->state_count - 1;
|
genpd->state_idx = genpd->state_count - 1;
|
||||||
genpd_power_off(genpd, timed);
|
genpd_power_off(genpd, false);
|
||||||
|
|
||||||
genpd->status = GPD_STATE_POWER_OFF;
|
genpd->status = GPD_STATE_POWER_OFF;
|
||||||
|
|
||||||
list_for_each_entry(link, &genpd->slave_links, slave_node) {
|
list_for_each_entry(link, &genpd->slave_links, slave_node) {
|
||||||
genpd_sd_counter_dec(link->master);
|
genpd_sd_counter_dec(link->master);
|
||||||
pm_genpd_sync_poweroff(link->master, timed);
|
genpd_sync_poweroff(link->master);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters.
|
* genpd_sync_poweron - Synchronously power on a PM domain and its masters.
|
||||||
* @genpd: PM domain to power on.
|
* @genpd: PM domain to power on.
|
||||||
* @timed: True if latency measurements are allowed.
|
|
||||||
*
|
*
|
||||||
* This function is only called in "noirq" and "syscore" stages of system power
|
* This function is only called in "noirq" and "syscore" stages of system power
|
||||||
* transitions, so it need not acquire locks (all of the "noirq" callbacks are
|
* transitions, so it need not acquire locks (all of the "noirq" callbacks are
|
||||||
* executed sequentially, so it is guaranteed that it will never run twice in
|
* executed sequentially, so it is guaranteed that it will never run twice in
|
||||||
* parallel).
|
* parallel).
|
||||||
*/
|
*/
|
||||||
static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd,
|
static void genpd_sync_poweron(struct generic_pm_domain *genpd)
|
||||||
bool timed)
|
|
||||||
{
|
{
|
||||||
struct gpd_link *link;
|
struct gpd_link *link;
|
||||||
|
|
||||||
|
@ -668,11 +668,11 @@ static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
list_for_each_entry(link, &genpd->slave_links, slave_node) {
|
list_for_each_entry(link, &genpd->slave_links, slave_node) {
|
||||||
pm_genpd_sync_poweron(link->master, timed);
|
genpd_sync_poweron(link->master);
|
||||||
genpd_sd_counter_inc(link->master);
|
genpd_sd_counter_inc(link->master);
|
||||||
}
|
}
|
||||||
|
|
||||||
genpd_power_on(genpd, timed);
|
genpd_power_on(genpd, false);
|
||||||
|
|
||||||
genpd->status = GPD_STATE_ACTIVE;
|
genpd->status = GPD_STATE_ACTIVE;
|
||||||
}
|
}
|
||||||
|
@ -784,7 +784,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
|
||||||
* the same PM domain, so it is not necessary to use locking here.
|
* the same PM domain, so it is not necessary to use locking here.
|
||||||
*/
|
*/
|
||||||
genpd->suspended_count++;
|
genpd->suspended_count++;
|
||||||
pm_genpd_sync_poweroff(genpd, true);
|
genpd_sync_poweroff(genpd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -814,7 +814,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
|
||||||
* guaranteed that this function will never run twice in parallel for
|
* guaranteed that this function will never run twice in parallel for
|
||||||
* the same PM domain, so it is not necessary to use locking here.
|
* the same PM domain, so it is not necessary to use locking here.
|
||||||
*/
|
*/
|
||||||
pm_genpd_sync_poweron(genpd, true);
|
genpd_sync_poweron(genpd);
|
||||||
genpd->suspended_count--;
|
genpd->suspended_count--;
|
||||||
|
|
||||||
if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
||||||
|
@ -902,12 +902,12 @@ static int pm_genpd_restore_noirq(struct device *dev)
|
||||||
if (genpd->suspended_count++ == 0)
|
if (genpd->suspended_count++ == 0)
|
||||||
/*
|
/*
|
||||||
* The boot kernel might put the domain into arbitrary state,
|
* The boot kernel might put the domain into arbitrary state,
|
||||||
* so make it appear as powered off to pm_genpd_sync_poweron(),
|
* so make it appear as powered off to genpd_sync_poweron(),
|
||||||
* so that it tries to power it on in case it was really off.
|
* so that it tries to power it on in case it was really off.
|
||||||
*/
|
*/
|
||||||
genpd->status = GPD_STATE_POWER_OFF;
|
genpd->status = GPD_STATE_POWER_OFF;
|
||||||
|
|
||||||
pm_genpd_sync_poweron(genpd, true);
|
genpd_sync_poweron(genpd);
|
||||||
|
|
||||||
if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
if (genpd->dev_ops.stop && genpd->dev_ops.start)
|
||||||
ret = pm_runtime_force_resume(dev);
|
ret = pm_runtime_force_resume(dev);
|
||||||
|
@ -962,9 +962,9 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
|
||||||
|
|
||||||
if (suspend) {
|
if (suspend) {
|
||||||
genpd->suspended_count++;
|
genpd->suspended_count++;
|
||||||
pm_genpd_sync_poweroff(genpd, false);
|
genpd_sync_poweroff(genpd);
|
||||||
} else {
|
} else {
|
||||||
pm_genpd_sync_poweron(genpd, false);
|
genpd_sync_poweron(genpd);
|
||||||
genpd->suspended_count--;
|
genpd->suspended_count--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1056,14 +1056,8 @@ static void genpd_free_dev_data(struct device *dev,
|
||||||
dev_pm_put_subsys_data(dev);
|
dev_pm_put_subsys_data(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
|
||||||
* __pm_genpd_add_device - Add a device to an I/O PM domain.
|
struct gpd_timing_data *td)
|
||||||
* @genpd: PM domain to add the device to.
|
|
||||||
* @dev: Device to be added.
|
|
||||||
* @td: Set of PM QoS timing parameters to attach to the device.
|
|
||||||
*/
|
|
||||||
int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
|
|
||||||
struct gpd_timing_data *td)
|
|
||||||
{
|
{
|
||||||
struct generic_pm_domain_data *gpd_data;
|
struct generic_pm_domain_data *gpd_data;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -1103,15 +1097,28 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__pm_genpd_add_device);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pm_genpd_remove_device - Remove a device from an I/O PM domain.
|
* __pm_genpd_add_device - Add a device to an I/O PM domain.
|
||||||
* @genpd: PM domain to remove the device from.
|
* @genpd: PM domain to add the device to.
|
||||||
* @dev: Device to be removed.
|
* @dev: Device to be added.
|
||||||
|
* @td: Set of PM QoS timing parameters to attach to the device.
|
||||||
*/
|
*/
|
||||||
int pm_genpd_remove_device(struct generic_pm_domain *genpd,
|
int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
|
||||||
struct device *dev)
|
struct gpd_timing_data *td)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&gpd_list_lock);
|
||||||
|
ret = genpd_add_device(genpd, dev, td);
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(__pm_genpd_add_device);
|
||||||
|
|
||||||
|
static int genpd_remove_device(struct generic_pm_domain *genpd,
|
||||||
|
struct device *dev)
|
||||||
{
|
{
|
||||||
struct generic_pm_domain_data *gpd_data;
|
struct generic_pm_domain_data *gpd_data;
|
||||||
struct pm_domain_data *pdd;
|
struct pm_domain_data *pdd;
|
||||||
|
@ -1119,10 +1126,6 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
|
||||||
|
|
||||||
dev_dbg(dev, "%s()\n", __func__);
|
dev_dbg(dev, "%s()\n", __func__);
|
||||||
|
|
||||||
if (!genpd || genpd != pm_genpd_lookup_dev(dev))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* The above validation also means we have existing domain_data. */
|
|
||||||
pdd = dev->power.subsys_data->domain_data;
|
pdd = dev->power.subsys_data->domain_data;
|
||||||
gpd_data = to_gpd_data(pdd);
|
gpd_data = to_gpd_data(pdd);
|
||||||
dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
|
dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
|
||||||
|
@ -1154,15 +1157,24 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
|
* pm_genpd_remove_device - Remove a device from an I/O PM domain.
|
||||||
* @genpd: Master PM domain to add the subdomain to.
|
* @genpd: PM domain to remove the device from.
|
||||||
* @subdomain: Subdomain to be added.
|
* @dev: Device to be removed.
|
||||||
*/
|
*/
|
||||||
int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
|
int pm_genpd_remove_device(struct generic_pm_domain *genpd,
|
||||||
struct generic_pm_domain *subdomain)
|
struct device *dev)
|
||||||
|
{
|
||||||
|
if (!genpd || genpd != genpd_lookup_dev(dev))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return genpd_remove_device(genpd, dev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
|
||||||
|
|
||||||
|
static int genpd_add_subdomain(struct generic_pm_domain *genpd,
|
||||||
|
struct generic_pm_domain *subdomain)
|
||||||
{
|
{
|
||||||
struct gpd_link *link, *itr;
|
struct gpd_link *link, *itr;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
@ -1205,6 +1217,23 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
|
||||||
kfree(link);
|
kfree(link);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
|
||||||
|
* @genpd: Master PM domain to add the subdomain to.
|
||||||
|
* @subdomain: Subdomain to be added.
|
||||||
|
*/
|
||||||
|
int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
|
||||||
|
struct generic_pm_domain *subdomain)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&gpd_list_lock);
|
||||||
|
ret = genpd_add_subdomain(genpd, subdomain);
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
|
EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1278,27 +1307,17 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
||||||
genpd->device_count = 0;
|
genpd->device_count = 0;
|
||||||
genpd->max_off_time_ns = -1;
|
genpd->max_off_time_ns = -1;
|
||||||
genpd->max_off_time_changed = true;
|
genpd->max_off_time_changed = true;
|
||||||
|
genpd->provider = NULL;
|
||||||
|
genpd->has_provider = false;
|
||||||
genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
|
genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
|
||||||
genpd->domain.ops.runtime_resume = genpd_runtime_resume;
|
genpd->domain.ops.runtime_resume = genpd_runtime_resume;
|
||||||
genpd->domain.ops.prepare = pm_genpd_prepare;
|
genpd->domain.ops.prepare = pm_genpd_prepare;
|
||||||
genpd->domain.ops.suspend = pm_generic_suspend;
|
|
||||||
genpd->domain.ops.suspend_late = pm_generic_suspend_late;
|
|
||||||
genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq;
|
genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq;
|
||||||
genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
|
genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
|
||||||
genpd->domain.ops.resume_early = pm_generic_resume_early;
|
|
||||||
genpd->domain.ops.resume = pm_generic_resume;
|
|
||||||
genpd->domain.ops.freeze = pm_generic_freeze;
|
|
||||||
genpd->domain.ops.freeze_late = pm_generic_freeze_late;
|
|
||||||
genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
|
genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
|
||||||
genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
|
genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
|
||||||
genpd->domain.ops.thaw_early = pm_generic_thaw_early;
|
|
||||||
genpd->domain.ops.thaw = pm_generic_thaw;
|
|
||||||
genpd->domain.ops.poweroff = pm_generic_poweroff;
|
|
||||||
genpd->domain.ops.poweroff_late = pm_generic_poweroff_late;
|
|
||||||
genpd->domain.ops.poweroff_noirq = pm_genpd_suspend_noirq;
|
genpd->domain.ops.poweroff_noirq = pm_genpd_suspend_noirq;
|
||||||
genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
|
genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
|
||||||
genpd->domain.ops.restore_early = pm_generic_restore_early;
|
|
||||||
genpd->domain.ops.restore = pm_generic_restore;
|
|
||||||
genpd->domain.ops.complete = pm_genpd_complete;
|
genpd->domain.ops.complete = pm_genpd_complete;
|
||||||
|
|
||||||
if (genpd->flags & GENPD_FLAG_PM_CLK) {
|
if (genpd->flags & GENPD_FLAG_PM_CLK) {
|
||||||
|
@ -1328,7 +1347,71 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(pm_genpd_init);
|
EXPORT_SYMBOL_GPL(pm_genpd_init);
|
||||||
|
|
||||||
|
static int genpd_remove(struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
struct gpd_link *l, *link;
|
||||||
|
|
||||||
|
if (IS_ERR_OR_NULL(genpd))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&genpd->lock);
|
||||||
|
|
||||||
|
if (genpd->has_provider) {
|
||||||
|
mutex_unlock(&genpd->lock);
|
||||||
|
pr_err("Provider present, unable to remove %s\n", genpd->name);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!list_empty(&genpd->master_links) || genpd->device_count) {
|
||||||
|
mutex_unlock(&genpd->lock);
|
||||||
|
pr_err("%s: unable to remove %s\n", __func__, genpd->name);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry_safe(link, l, &genpd->slave_links, slave_node) {
|
||||||
|
list_del(&link->master_node);
|
||||||
|
list_del(&link->slave_node);
|
||||||
|
kfree(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_del(&genpd->gpd_list_node);
|
||||||
|
mutex_unlock(&genpd->lock);
|
||||||
|
cancel_work_sync(&genpd->power_off_work);
|
||||||
|
pr_debug("%s: removed %s\n", __func__, genpd->name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pm_genpd_remove - Remove a generic I/O PM domain
|
||||||
|
* @genpd: Pointer to PM domain that is to be removed.
|
||||||
|
*
|
||||||
|
* To remove the PM domain, this function:
|
||||||
|
* - Removes the PM domain as a subdomain to any parent domains,
|
||||||
|
* if it was added.
|
||||||
|
* - Removes the PM domain from the list of registered PM domains.
|
||||||
|
*
|
||||||
|
* The PM domain will only be removed, if the associated provider has
|
||||||
|
* been removed, it is not a parent to any other PM domain and has no
|
||||||
|
* devices associated with it.
|
||||||
|
*/
|
||||||
|
int pm_genpd_remove(struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&gpd_list_lock);
|
||||||
|
ret = genpd_remove(genpd);
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pm_genpd_remove);
|
||||||
|
|
||||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||||
|
|
||||||
|
typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
|
||||||
|
void *data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Device Tree based PM domain providers.
|
* Device Tree based PM domain providers.
|
||||||
*
|
*
|
||||||
|
@ -1340,8 +1423,8 @@ EXPORT_SYMBOL_GPL(pm_genpd_init);
|
||||||
* maps a PM domain specifier retrieved from the device tree to a PM domain.
|
* maps a PM domain specifier retrieved from the device tree to a PM domain.
|
||||||
*
|
*
|
||||||
* Two simple mapping functions have been provided for convenience:
|
* Two simple mapping functions have been provided for convenience:
|
||||||
* - __of_genpd_xlate_simple() for 1:1 device tree node to PM domain mapping.
|
* - genpd_xlate_simple() for 1:1 device tree node to PM domain mapping.
|
||||||
* - __of_genpd_xlate_onecell() for mapping of multiple PM domains per node by
|
* - genpd_xlate_onecell() for mapping of multiple PM domains per node by
|
||||||
* index.
|
* index.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1366,7 +1449,7 @@ static LIST_HEAD(of_genpd_providers);
|
||||||
static DEFINE_MUTEX(of_genpd_mutex);
|
static DEFINE_MUTEX(of_genpd_mutex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __of_genpd_xlate_simple() - Xlate function for direct node-domain mapping
|
* genpd_xlate_simple() - Xlate function for direct node-domain mapping
|
||||||
* @genpdspec: OF phandle args to map into a PM domain
|
* @genpdspec: OF phandle args to map into a PM domain
|
||||||
* @data: xlate function private data - pointer to struct generic_pm_domain
|
* @data: xlate function private data - pointer to struct generic_pm_domain
|
||||||
*
|
*
|
||||||
|
@ -1374,7 +1457,7 @@ static DEFINE_MUTEX(of_genpd_mutex);
|
||||||
* have their own device tree nodes. The private data of xlate function needs
|
* have their own device tree nodes. The private data of xlate function needs
|
||||||
* to be a valid pointer to struct generic_pm_domain.
|
* to be a valid pointer to struct generic_pm_domain.
|
||||||
*/
|
*/
|
||||||
struct generic_pm_domain *__of_genpd_xlate_simple(
|
static struct generic_pm_domain *genpd_xlate_simple(
|
||||||
struct of_phandle_args *genpdspec,
|
struct of_phandle_args *genpdspec,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
|
@ -1382,10 +1465,9 @@ struct generic_pm_domain *__of_genpd_xlate_simple(
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__of_genpd_xlate_simple);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __of_genpd_xlate_onecell() - Xlate function using a single index.
|
* genpd_xlate_onecell() - Xlate function using a single index.
|
||||||
* @genpdspec: OF phandle args to map into a PM domain
|
* @genpdspec: OF phandle args to map into a PM domain
|
||||||
* @data: xlate function private data - pointer to struct genpd_onecell_data
|
* @data: xlate function private data - pointer to struct genpd_onecell_data
|
||||||
*
|
*
|
||||||
|
@ -1394,7 +1476,7 @@ EXPORT_SYMBOL_GPL(__of_genpd_xlate_simple);
|
||||||
* A single cell is used as an index into an array of PM domains specified in
|
* A single cell is used as an index into an array of PM domains specified in
|
||||||
* the genpd_onecell_data struct when registering the provider.
|
* the genpd_onecell_data struct when registering the provider.
|
||||||
*/
|
*/
|
||||||
struct generic_pm_domain *__of_genpd_xlate_onecell(
|
static struct generic_pm_domain *genpd_xlate_onecell(
|
||||||
struct of_phandle_args *genpdspec,
|
struct of_phandle_args *genpdspec,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
|
@ -1414,16 +1496,15 @@ struct generic_pm_domain *__of_genpd_xlate_onecell(
|
||||||
|
|
||||||
return genpd_data->domains[idx];
|
return genpd_data->domains[idx];
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__of_genpd_xlate_onecell);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __of_genpd_add_provider() - Register a PM domain provider for a node
|
* genpd_add_provider() - Register a PM domain provider for a node
|
||||||
* @np: Device node pointer associated with the PM domain provider.
|
* @np: Device node pointer associated with the PM domain provider.
|
||||||
* @xlate: Callback for decoding PM domain from phandle arguments.
|
* @xlate: Callback for decoding PM domain from phandle arguments.
|
||||||
* @data: Context pointer for @xlate callback.
|
* @data: Context pointer for @xlate callback.
|
||||||
*/
|
*/
|
||||||
int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
|
static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct of_genpd_provider *cp;
|
struct of_genpd_provider *cp;
|
||||||
|
|
||||||
|
@ -1442,7 +1523,83 @@ int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__of_genpd_add_provider);
|
|
||||||
|
/**
|
||||||
|
* of_genpd_add_provider_simple() - Register a simple PM domain provider
|
||||||
|
* @np: Device node pointer associated with the PM domain provider.
|
||||||
|
* @genpd: Pointer to PM domain associated with the PM domain provider.
|
||||||
|
*/
|
||||||
|
int of_genpd_add_provider_simple(struct device_node *np,
|
||||||
|
struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
|
if (!np || !genpd)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&gpd_list_lock);
|
||||||
|
|
||||||
|
if (pm_genpd_present(genpd))
|
||||||
|
ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
genpd->provider = &np->fwnode;
|
||||||
|
genpd->has_provider = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* of_genpd_add_provider_onecell() - Register a onecell PM domain provider
|
||||||
|
* @np: Device node pointer associated with the PM domain provider.
|
||||||
|
* @data: Pointer to the data associated with the PM domain provider.
|
||||||
|
*/
|
||||||
|
int of_genpd_add_provider_onecell(struct device_node *np,
|
||||||
|
struct genpd_onecell_data *data)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
|
if (!np || !data)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&gpd_list_lock);
|
||||||
|
|
||||||
|
for (i = 0; i < data->num_domains; i++) {
|
||||||
|
if (!data->domains[i])
|
||||||
|
continue;
|
||||||
|
if (!pm_genpd_present(data->domains[i]))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
data->domains[i]->provider = &np->fwnode;
|
||||||
|
data->domains[i]->has_provider = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = genpd_add_provider(np, genpd_xlate_onecell, data);
|
||||||
|
if (ret < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
while (i--) {
|
||||||
|
if (!data->domains[i])
|
||||||
|
continue;
|
||||||
|
data->domains[i]->provider = NULL;
|
||||||
|
data->domains[i]->has_provider = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* of_genpd_del_provider() - Remove a previously registered PM domain provider
|
* of_genpd_del_provider() - Remove a previously registered PM domain provider
|
||||||
|
@ -1451,10 +1608,21 @@ EXPORT_SYMBOL_GPL(__of_genpd_add_provider);
|
||||||
void of_genpd_del_provider(struct device_node *np)
|
void of_genpd_del_provider(struct device_node *np)
|
||||||
{
|
{
|
||||||
struct of_genpd_provider *cp;
|
struct of_genpd_provider *cp;
|
||||||
|
struct generic_pm_domain *gpd;
|
||||||
|
|
||||||
|
mutex_lock(&gpd_list_lock);
|
||||||
mutex_lock(&of_genpd_mutex);
|
mutex_lock(&of_genpd_mutex);
|
||||||
list_for_each_entry(cp, &of_genpd_providers, link) {
|
list_for_each_entry(cp, &of_genpd_providers, link) {
|
||||||
if (cp->node == np) {
|
if (cp->node == np) {
|
||||||
|
/*
|
||||||
|
* For each PM domain associated with the
|
||||||
|
* 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)
|
||||||
|
gpd->has_provider = false;
|
||||||
|
|
||||||
list_del(&cp->link);
|
list_del(&cp->link);
|
||||||
of_node_put(cp->node);
|
of_node_put(cp->node);
|
||||||
kfree(cp);
|
kfree(cp);
|
||||||
|
@ -1462,11 +1630,12 @@ void of_genpd_del_provider(struct device_node *np)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&of_genpd_mutex);
|
mutex_unlock(&of_genpd_mutex);
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(of_genpd_del_provider);
|
EXPORT_SYMBOL_GPL(of_genpd_del_provider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* of_genpd_get_from_provider() - Look-up PM domain
|
* genpd_get_from_provider() - Look-up PM domain
|
||||||
* @genpdspec: OF phandle args to use for look-up
|
* @genpdspec: OF phandle args to use for look-up
|
||||||
*
|
*
|
||||||
* Looks for a PM domain provider under the node specified by @genpdspec and if
|
* Looks for a PM domain provider under the node specified by @genpdspec and if
|
||||||
|
@ -1476,7 +1645,7 @@ EXPORT_SYMBOL_GPL(of_genpd_del_provider);
|
||||||
* Returns a valid pointer to struct generic_pm_domain on success or ERR_PTR()
|
* Returns a valid pointer to struct generic_pm_domain on success or ERR_PTR()
|
||||||
* on failure.
|
* on failure.
|
||||||
*/
|
*/
|
||||||
struct generic_pm_domain *of_genpd_get_from_provider(
|
static struct generic_pm_domain *genpd_get_from_provider(
|
||||||
struct of_phandle_args *genpdspec)
|
struct of_phandle_args *genpdspec)
|
||||||
{
|
{
|
||||||
struct generic_pm_domain *genpd = ERR_PTR(-ENOENT);
|
struct generic_pm_domain *genpd = ERR_PTR(-ENOENT);
|
||||||
|
@ -1499,7 +1668,109 @@ struct generic_pm_domain *of_genpd_get_from_provider(
|
||||||
|
|
||||||
return genpd;
|
return genpd;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(of_genpd_get_from_provider);
|
|
||||||
|
/**
|
||||||
|
* of_genpd_add_device() - Add a device to an I/O PM domain
|
||||||
|
* @genpdspec: OF phandle args to use for look-up PM domain
|
||||||
|
* @dev: Device to be added.
|
||||||
|
*
|
||||||
|
* Looks-up an I/O PM domain based upon phandle args provided and adds
|
||||||
|
* the device to the PM domain. Returns a negative error code on failure.
|
||||||
|
*/
|
||||||
|
int of_genpd_add_device(struct of_phandle_args *genpdspec, struct device *dev)
|
||||||
|
{
|
||||||
|
struct generic_pm_domain *genpd;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&gpd_list_lock);
|
||||||
|
|
||||||
|
genpd = genpd_get_from_provider(genpdspec);
|
||||||
|
if (IS_ERR(genpd)) {
|
||||||
|
ret = PTR_ERR(genpd);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = genpd_add_device(genpd, dev, NULL);
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(of_genpd_add_device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* of_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
|
||||||
|
* @parent_spec: OF phandle args to use for parent PM domain look-up
|
||||||
|
* @subdomain_spec: OF phandle args to use for subdomain look-up
|
||||||
|
*
|
||||||
|
* Looks-up a parent PM domain and subdomain based upon phandle args
|
||||||
|
* provided and adds the subdomain to the parent PM domain. Returns a
|
||||||
|
* negative error code on failure.
|
||||||
|
*/
|
||||||
|
int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
|
||||||
|
struct of_phandle_args *subdomain_spec)
|
||||||
|
{
|
||||||
|
struct generic_pm_domain *parent, *subdomain;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mutex_lock(&gpd_list_lock);
|
||||||
|
|
||||||
|
parent = genpd_get_from_provider(parent_spec);
|
||||||
|
if (IS_ERR(parent)) {
|
||||||
|
ret = PTR_ERR(parent);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
subdomain = genpd_get_from_provider(subdomain_spec);
|
||||||
|
if (IS_ERR(subdomain)) {
|
||||||
|
ret = PTR_ERR(subdomain);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = genpd_add_subdomain(parent, subdomain);
|
||||||
|
|
||||||
|
out:
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(of_genpd_add_subdomain);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* of_genpd_remove_last - Remove the last PM domain registered for a provider
|
||||||
|
* @provider: Pointer to device structure associated with provider
|
||||||
|
*
|
||||||
|
* Find the last PM domain that was added by a particular provider and
|
||||||
|
* remove this PM domain from the list of PM domains. The provider is
|
||||||
|
* identified by the 'provider' device structure that is passed. The PM
|
||||||
|
* domain will only be removed, if the provider associated with domain
|
||||||
|
* has been removed.
|
||||||
|
*
|
||||||
|
* Returns a valid pointer to struct generic_pm_domain on success or
|
||||||
|
* ERR_PTR() on failure.
|
||||||
|
*/
|
||||||
|
struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
|
||||||
|
{
|
||||||
|
struct generic_pm_domain *gpd, *genpd = ERR_PTR(-ENOENT);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (IS_ERR_OR_NULL(np))
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
mutex_lock(&gpd_list_lock);
|
||||||
|
list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
|
||||||
|
if (gpd->provider == &np->fwnode) {
|
||||||
|
ret = genpd_remove(gpd);
|
||||||
|
genpd = ret ? ERR_PTR(ret) : gpd;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
|
return genpd;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(of_genpd_remove_last);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* genpd_dev_pm_detach - Detach a device from its PM domain.
|
* genpd_dev_pm_detach - Detach a device from its PM domain.
|
||||||
|
@ -1515,14 +1786,14 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
pd = pm_genpd_lookup_dev(dev);
|
pd = dev_to_genpd(dev);
|
||||||
if (!pd)
|
if (IS_ERR(pd))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dev_dbg(dev, "removing from PM domain %s\n", pd->name);
|
dev_dbg(dev, "removing from PM domain %s\n", pd->name);
|
||||||
|
|
||||||
for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
|
for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
|
||||||
ret = pm_genpd_remove_device(pd, dev);
|
ret = genpd_remove_device(pd, dev);
|
||||||
if (ret != -EAGAIN)
|
if (ret != -EAGAIN)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1596,9 +1867,11 @@ int genpd_dev_pm_attach(struct device *dev)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
pd = of_genpd_get_from_provider(&pd_args);
|
mutex_lock(&gpd_list_lock);
|
||||||
|
pd = genpd_get_from_provider(&pd_args);
|
||||||
of_node_put(pd_args.np);
|
of_node_put(pd_args.np);
|
||||||
if (IS_ERR(pd)) {
|
if (IS_ERR(pd)) {
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
|
dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
|
||||||
__func__, PTR_ERR(pd));
|
__func__, PTR_ERR(pd));
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
|
@ -1607,13 +1880,14 @@ int genpd_dev_pm_attach(struct device *dev)
|
||||||
dev_dbg(dev, "adding to PM domain %s\n", pd->name);
|
dev_dbg(dev, "adding to PM domain %s\n", pd->name);
|
||||||
|
|
||||||
for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
|
for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
|
||||||
ret = pm_genpd_add_device(pd, dev);
|
ret = genpd_add_device(pd, dev, NULL);
|
||||||
if (ret != -EAGAIN)
|
if (ret != -EAGAIN)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
mdelay(i);
|
mdelay(i);
|
||||||
cond_resched();
|
cond_resched();
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&gpd_list_lock);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "failed to add to PM domain %s: %d",
|
dev_err(dev, "failed to add to PM domain %s: %d",
|
||||||
|
@ -1636,7 +1910,7 @@ EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
|
||||||
|
|
||||||
/*** debugfs support ***/
|
/*** debugfs support ***/
|
||||||
|
|
||||||
#ifdef CONFIG_PM_ADVANCED_DEBUG
|
#ifdef CONFIG_DEBUG_FS
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
@ -1784,4 +2058,4 @@ static void __exit pm_genpd_debug_exit(void)
|
||||||
debugfs_remove_recursive(pm_genpd_debugfs_dir);
|
debugfs_remove_recursive(pm_genpd_debugfs_dir);
|
||||||
}
|
}
|
||||||
__exitcall(pm_genpd_debug_exit);
|
__exitcall(pm_genpd_debug_exit);
|
||||||
#endif /* CONFIG_PM_ADVANCED_DEBUG */
|
#endif /* CONFIG_DEBUG_FS */
|
||||||
|
|
|
@ -215,29 +215,22 @@ static __init int exynos4_pm_init_power_domain(void)
|
||||||
|
|
||||||
/* Assign the child power domains to their parents */
|
/* Assign the child power domains to their parents */
|
||||||
for_each_matching_node(np, exynos_pm_domain_of_match) {
|
for_each_matching_node(np, exynos_pm_domain_of_match) {
|
||||||
struct generic_pm_domain *child_domain, *parent_domain;
|
struct of_phandle_args child, parent;
|
||||||
struct of_phandle_args args;
|
|
||||||
|
|
||||||
args.np = np;
|
child.np = np;
|
||||||
args.args_count = 0;
|
child.args_count = 0;
|
||||||
child_domain = of_genpd_get_from_provider(&args);
|
|
||||||
if (IS_ERR(child_domain))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (of_parse_phandle_with_args(np, "power-domains",
|
if (of_parse_phandle_with_args(np, "power-domains",
|
||||||
"#power-domain-cells", 0, &args) != 0)
|
"#power-domain-cells", 0,
|
||||||
|
&parent) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
parent_domain = of_genpd_get_from_provider(&args);
|
if (of_genpd_add_subdomain(&parent, &child))
|
||||||
if (IS_ERR(parent_domain))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (pm_genpd_add_subdomain(parent_domain, child_domain))
|
|
||||||
pr_warn("%s failed to add subdomain: %s\n",
|
pr_warn("%s failed to add subdomain: %s\n",
|
||||||
parent_domain->name, child_domain->name);
|
parent.np->name, child.np->name);
|
||||||
else
|
else
|
||||||
pr_info("%s has as child subdomain: %s.\n",
|
pr_info("%s has as child subdomain: %s.\n",
|
||||||
parent_domain->name, child_domain->name);
|
parent.np->name, child.np->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -140,7 +140,6 @@ static int board_staging_add_dev_domain(struct platform_device *pdev,
|
||||||
const char *domain)
|
const char *domain)
|
||||||
{
|
{
|
||||||
struct of_phandle_args pd_args;
|
struct of_phandle_args pd_args;
|
||||||
struct generic_pm_domain *pd;
|
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
|
||||||
np = of_find_node_by_path(domain);
|
np = of_find_node_by_path(domain);
|
||||||
|
@ -151,14 +150,8 @@ static int board_staging_add_dev_domain(struct platform_device *pdev,
|
||||||
|
|
||||||
pd_args.np = np;
|
pd_args.np = np;
|
||||||
pd_args.args_count = 0;
|
pd_args.args_count = 0;
|
||||||
pd = of_genpd_get_from_provider(&pd_args);
|
|
||||||
if (IS_ERR(pd)) {
|
|
||||||
pr_err("Cannot find genpd %s (%ld)\n", domain, PTR_ERR(pd));
|
|
||||||
return PTR_ERR(pd);
|
|
||||||
}
|
|
||||||
pr_debug("Found genpd %s for device %s\n", pd->name, pdev->name);
|
|
||||||
|
|
||||||
return pm_genpd_add_device(pd, &pdev->dev);
|
return of_genpd_add_device(&pd_args, &pdev->dev);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline int board_staging_add_dev_domain(struct platform_device *pdev,
|
static inline int board_staging_add_dev_domain(struct platform_device *pdev,
|
||||||
|
|
|
@ -51,6 +51,8 @@ struct generic_pm_domain {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
struct dev_power_governor *gov;
|
struct dev_power_governor *gov;
|
||||||
struct work_struct power_off_work;
|
struct work_struct power_off_work;
|
||||||
|
struct fwnode_handle *provider; /* Identity of the domain provider */
|
||||||
|
bool has_provider;
|
||||||
const char *name;
|
const char *name;
|
||||||
atomic_t sd_count; /* Number of subdomains with power "on" */
|
atomic_t sd_count; /* Number of subdomains with power "on" */
|
||||||
enum gpd_status status; /* Current state of the domain */
|
enum gpd_status status; /* Current state of the domain */
|
||||||
|
@ -116,7 +118,6 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
|
||||||
return to_gpd_data(dev->power.subsys_data->domain_data);
|
return to_gpd_data(dev->power.subsys_data->domain_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev);
|
|
||||||
extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
|
extern int __pm_genpd_add_device(struct generic_pm_domain *genpd,
|
||||||
struct device *dev,
|
struct device *dev,
|
||||||
struct gpd_timing_data *td);
|
struct gpd_timing_data *td);
|
||||||
|
@ -129,6 +130,7 @@ extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
|
||||||
struct generic_pm_domain *target);
|
struct generic_pm_domain *target);
|
||||||
extern int pm_genpd_init(struct generic_pm_domain *genpd,
|
extern int pm_genpd_init(struct generic_pm_domain *genpd,
|
||||||
struct dev_power_governor *gov, bool is_off);
|
struct dev_power_governor *gov, bool is_off);
|
||||||
|
extern int pm_genpd_remove(struct generic_pm_domain *genpd);
|
||||||
|
|
||||||
extern struct dev_power_governor simple_qos_governor;
|
extern struct dev_power_governor simple_qos_governor;
|
||||||
extern struct dev_power_governor pm_domain_always_on_gov;
|
extern struct dev_power_governor pm_domain_always_on_gov;
|
||||||
|
@ -138,10 +140,6 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
|
||||||
{
|
{
|
||||||
return ERR_PTR(-ENOSYS);
|
return ERR_PTR(-ENOSYS);
|
||||||
}
|
}
|
||||||
static inline struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
|
static inline int __pm_genpd_add_device(struct generic_pm_domain *genpd,
|
||||||
struct device *dev,
|
struct device *dev,
|
||||||
struct gpd_timing_data *td)
|
struct gpd_timing_data *td)
|
||||||
|
@ -168,6 +166,10 @@ static inline int pm_genpd_init(struct generic_pm_domain *genpd,
|
||||||
{
|
{
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
static inline int pm_genpd_remove(struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
return -ENOTSUPP;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
|
static inline int pm_genpd_add_device(struct generic_pm_domain *genpd,
|
||||||
|
@ -192,57 +194,57 @@ struct genpd_onecell_data {
|
||||||
unsigned int num_domains;
|
unsigned int num_domains;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||||
int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
|
int of_genpd_add_provider_simple(struct device_node *np,
|
||||||
void *data);
|
struct generic_pm_domain *genpd);
|
||||||
|
int of_genpd_add_provider_onecell(struct device_node *np,
|
||||||
|
struct genpd_onecell_data *data);
|
||||||
void of_genpd_del_provider(struct device_node *np);
|
void of_genpd_del_provider(struct device_node *np);
|
||||||
struct generic_pm_domain *of_genpd_get_from_provider(
|
extern int of_genpd_add_device(struct of_phandle_args *args,
|
||||||
struct of_phandle_args *genpdspec);
|
struct device *dev);
|
||||||
|
extern int of_genpd_add_subdomain(struct of_phandle_args *parent,
|
||||||
struct generic_pm_domain *__of_genpd_xlate_simple(
|
struct of_phandle_args *new_subdomain);
|
||||||
struct of_phandle_args *genpdspec,
|
extern struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
|
||||||
void *data);
|
|
||||||
struct generic_pm_domain *__of_genpd_xlate_onecell(
|
|
||||||
struct of_phandle_args *genpdspec,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
int genpd_dev_pm_attach(struct device *dev);
|
int genpd_dev_pm_attach(struct device *dev);
|
||||||
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
|
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
|
||||||
static inline int __of_genpd_add_provider(struct device_node *np,
|
static inline int of_genpd_add_provider_simple(struct device_node *np,
|
||||||
genpd_xlate_t xlate, void *data)
|
struct generic_pm_domain *genpd)
|
||||||
{
|
{
|
||||||
return 0;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int of_genpd_add_provider_onecell(struct device_node *np,
|
||||||
|
struct genpd_onecell_data *data)
|
||||||
|
{
|
||||||
|
return -ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void of_genpd_del_provider(struct device_node *np) {}
|
static inline void of_genpd_del_provider(struct device_node *np) {}
|
||||||
|
|
||||||
static inline struct generic_pm_domain *of_genpd_get_from_provider(
|
static inline int of_genpd_add_device(struct of_phandle_args *args,
|
||||||
struct of_phandle_args *genpdspec)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
return NULL;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __of_genpd_xlate_simple NULL
|
static inline int of_genpd_add_subdomain(struct of_phandle_args *parent,
|
||||||
#define __of_genpd_xlate_onecell NULL
|
struct of_phandle_args *new_subdomain)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int genpd_dev_pm_attach(struct device *dev)
|
static inline int genpd_dev_pm_attach(struct device *dev)
|
||||||
{
|
{
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
|
|
||||||
|
|
||||||
static inline int of_genpd_add_provider_simple(struct device_node *np,
|
static inline
|
||||||
struct generic_pm_domain *genpd)
|
struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
|
||||||
{
|
{
|
||||||
return __of_genpd_add_provider(np, __of_genpd_xlate_simple, genpd);
|
return ERR_PTR(-ENOTSUPP);
|
||||||
}
|
|
||||||
static inline int of_genpd_add_provider_onecell(struct device_node *np,
|
|
||||||
struct genpd_onecell_data *data)
|
|
||||||
{
|
|
||||||
return __of_genpd_add_provider(np, __of_genpd_xlate_onecell, data);
|
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
extern int dev_pm_domain_attach(struct device *dev, bool power_on);
|
extern int dev_pm_domain_attach(struct device *dev, bool power_on);
|
||||||
|
|
Loading…
Reference in New Issue