aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-10-01 19:41:29 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-10-01 19:41:29 -0400
commit2dc3c72cd0a3ea85b8b7ae469904cfc24af1de60 (patch)
treef86f376dabe37631eea57ca81c7403820fccefe8 /drivers/base
parent08895a8b6b06ed2323cd97a36ee40a116b3db8ed (diff)
parenteefdee07074db61764408583a23e96cf60d5a0a7 (diff)
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
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/power/domain.c430
1 files changed, 352 insertions, 78 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index a1f2aff33997..e023066e4215 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -45,7 +45,7 @@ static DEFINE_MUTEX(gpd_list_lock);
45 * and checks that the PM domain pointer is a real generic PM domain. 45 * and checks that the PM domain pointer is a real generic PM domain.
46 * Any failure results in NULL being returned. 46 * Any failure results in NULL being returned.
47 */ 47 */
48struct generic_pm_domain *pm_genpd_lookup_dev(struct device *dev) 48static struct generic_pm_domain *genpd_lookup_dev(struct device *dev)
49{ 49{
50 struct generic_pm_domain *genpd = NULL, *gpd; 50 struct generic_pm_domain *genpd = NULL, *gpd;
51 51
@@ -586,7 +586,7 @@ static int __init genpd_poweroff_unused(void)
586} 586}
587late_initcall(genpd_poweroff_unused); 587late_initcall(genpd_poweroff_unused);
588 588
589#ifdef CONFIG_PM_SLEEP 589#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM_GENERIC_DOMAINS_OF)
590 590
591/** 591/**
592 * pm_genpd_present - Check if the given PM domain has been initialized. 592 * 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)
606 return false; 606 return false;
607} 607}
608 608
609#endif
610
611#ifdef CONFIG_PM_SLEEP
612
609static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd, 613static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
610 struct device *dev) 614 struct device *dev)
611{ 615{
@@ -613,9 +617,8 @@ static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
613} 617}
614 618
615/** 619/**
616 * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its masters. 620 * genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
617 * @genpd: PM domain to power off, if possible. 621 * @genpd: PM domain to power off, if possible.
618 * @timed: True if latency measurements are allowed.
619 * 622 *
620 * Check if the given PM domain can be powered off (during system suspend or 623 * Check if the given PM domain can be powered off (during system suspend or
621 * hibernation) and do that if so. Also, in that case propagate to its masters. 624 * 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,
625 * executed sequentially, so it is guaranteed that it will never run twice in 628 * executed sequentially, so it is guaranteed that it will never run twice in
626 * parallel). 629 * parallel).
627 */ 630 */
628static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd, 631static void genpd_sync_poweroff(struct generic_pm_domain *genpd)
629 bool timed)
630{ 632{
631 struct gpd_link *link; 633 struct gpd_link *link;
632 634
@@ -639,28 +641,26 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd,
639 641
640 /* Choose the deepest state when suspending */ 642 /* Choose the deepest state when suspending */
641 genpd->state_idx = genpd->state_count - 1; 643 genpd->state_idx = genpd->state_count - 1;
642 genpd_power_off(genpd, timed); 644 genpd_power_off(genpd, false);
643 645
644 genpd->status = GPD_STATE_POWER_OFF; 646 genpd->status = GPD_STATE_POWER_OFF;
645 647
646 list_for_each_entry(link, &genpd->slave_links, slave_node) { 648 list_for_each_entry(link, &genpd->slave_links, slave_node) {
647 genpd_sd_counter_dec(link->master); 649 genpd_sd_counter_dec(link->master);
648 pm_genpd_sync_poweroff(link->master, timed); 650 genpd_sync_poweroff(link->master);
649 } 651 }
650} 652}
651 653
652/** 654/**
653 * pm_genpd_sync_poweron - Synchronously power on a PM domain and its masters. 655 * genpd_sync_poweron - Synchronously power on a PM domain and its masters.
654 * @genpd: PM domain to power on. 656 * @genpd: PM domain to power on.
655 * @timed: True if latency measurements are allowed.
656 * 657 *
657 * This function is only called in "noirq" and "syscore" stages of system power 658 * This function is only called in "noirq" and "syscore" stages of system power
658 * transitions, so it need not acquire locks (all of the "noirq" callbacks are 659 * transitions, so it need not acquire locks (all of the "noirq" callbacks are
659 * executed sequentially, so it is guaranteed that it will never run twice in 660 * executed sequentially, so it is guaranteed that it will never run twice in
660 * parallel). 661 * parallel).
661 */ 662 */
662static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd, 663static void genpd_sync_poweron(struct generic_pm_domain *genpd)
663 bool timed)
664{ 664{
665 struct gpd_link *link; 665 struct gpd_link *link;
666 666
@@ -668,11 +668,11 @@ static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd,
668 return; 668 return;
669 669
670 list_for_each_entry(link, &genpd->slave_links, slave_node) { 670 list_for_each_entry(link, &genpd->slave_links, slave_node) {
671 pm_genpd_sync_poweron(link->master, timed); 671 genpd_sync_poweron(link->master);
672 genpd_sd_counter_inc(link->master); 672 genpd_sd_counter_inc(link->master);
673 } 673 }
674 674
675 genpd_power_on(genpd, timed); 675 genpd_power_on(genpd, false);
676 676
677 genpd->status = GPD_STATE_ACTIVE; 677 genpd->status = GPD_STATE_ACTIVE;
678} 678}
@@ -784,7 +784,7 @@ static int pm_genpd_suspend_noirq(struct device *dev)
784 * the same PM domain, so it is not necessary to use locking here. 784 * the same PM domain, so it is not necessary to use locking here.
785 */ 785 */
786 genpd->suspended_count++; 786 genpd->suspended_count++;
787 pm_genpd_sync_poweroff(genpd, true); 787 genpd_sync_poweroff(genpd);
788 788
789 return 0; 789 return 0;
790} 790}
@@ -814,7 +814,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
814 * guaranteed that this function will never run twice in parallel for 814 * guaranteed that this function will never run twice in parallel for
815 * the same PM domain, so it is not necessary to use locking here. 815 * the same PM domain, so it is not necessary to use locking here.
816 */ 816 */
817 pm_genpd_sync_poweron(genpd, true); 817 genpd_sync_poweron(genpd);
818 genpd->suspended_count--; 818 genpd->suspended_count--;
819 819
820 if (genpd->dev_ops.stop && genpd->dev_ops.start) 820 if (genpd->dev_ops.stop && genpd->dev_ops.start)
@@ -902,12 +902,12 @@ static int pm_genpd_restore_noirq(struct device *dev)
902 if (genpd->suspended_count++ == 0) 902 if (genpd->suspended_count++ == 0)
903 /* 903 /*
904 * The boot kernel might put the domain into arbitrary state, 904 * The boot kernel might put the domain into arbitrary state,
905 * so make it appear as powered off to pm_genpd_sync_poweron(), 905 * so make it appear as powered off to genpd_sync_poweron(),
906 * so that it tries to power it on in case it was really off. 906 * so that it tries to power it on in case it was really off.
907 */ 907 */
908 genpd->status = GPD_STATE_POWER_OFF; 908 genpd->status = GPD_STATE_POWER_OFF;
909 909
910 pm_genpd_sync_poweron(genpd, true); 910 genpd_sync_poweron(genpd);
911 911
912 if (genpd->dev_ops.stop && genpd->dev_ops.start) 912 if (genpd->dev_ops.stop && genpd->dev_ops.start)
913 ret = pm_runtime_force_resume(dev); 913 ret = pm_runtime_force_resume(dev);
@@ -962,9 +962,9 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
962 962
963 if (suspend) { 963 if (suspend) {
964 genpd->suspended_count++; 964 genpd->suspended_count++;
965 pm_genpd_sync_poweroff(genpd, false); 965 genpd_sync_poweroff(genpd);
966 } else { 966 } else {
967 pm_genpd_sync_poweron(genpd, false); 967 genpd_sync_poweron(genpd);
968 genpd->suspended_count--; 968 genpd->suspended_count--;
969 } 969 }
970} 970}
@@ -1056,14 +1056,8 @@ static void genpd_free_dev_data(struct device *dev,
1056 dev_pm_put_subsys_data(dev); 1056 dev_pm_put_subsys_data(dev);
1057} 1057}
1058 1058
1059/** 1059static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
1060 * __pm_genpd_add_device - Add a device to an I/O PM domain. 1060 struct gpd_timing_data *td)
1061 * @genpd: PM domain to add the device to.
1062 * @dev: Device to be added.
1063 * @td: Set of PM QoS timing parameters to attach to the device.
1064 */
1065int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
1066 struct gpd_timing_data *td)
1067{ 1061{
1068 struct generic_pm_domain_data *gpd_data; 1062 struct generic_pm_domain_data *gpd_data;
1069 int ret = 0; 1063 int ret = 0;
@@ -1103,15 +1097,28 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
1103 1097
1104 return ret; 1098 return ret;
1105} 1099}
1106EXPORT_SYMBOL_GPL(__pm_genpd_add_device);
1107 1100
1108/** 1101/**
1109 * pm_genpd_remove_device - Remove a device from an I/O PM domain. 1102 * __pm_genpd_add_device - Add a device to an I/O PM domain.
1110 * @genpd: PM domain to remove the device from. 1103 * @genpd: PM domain to add the device to.
1111 * @dev: Device to be removed. 1104 * @dev: Device to be added.
1105 * @td: Set of PM QoS timing parameters to attach to the device.
1112 */ 1106 */
1113int pm_genpd_remove_device(struct generic_pm_domain *genpd, 1107int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
1114 struct device *dev) 1108 struct gpd_timing_data *td)
1109{
1110 int ret;
1111
1112 mutex_lock(&gpd_list_lock);
1113 ret = genpd_add_device(genpd, dev, td);
1114 mutex_unlock(&gpd_list_lock);
1115
1116 return ret;
1117}
1118EXPORT_SYMBOL_GPL(__pm_genpd_add_device);
1119
1120static int genpd_remove_device(struct generic_pm_domain *genpd,
1121 struct device *dev)
1115{ 1122{
1116 struct generic_pm_domain_data *gpd_data; 1123 struct generic_pm_domain_data *gpd_data;
1117 struct pm_domain_data *pdd; 1124 struct pm_domain_data *pdd;
@@ -1119,10 +1126,6 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
1119 1126
1120 dev_dbg(dev, "%s()\n", __func__); 1127 dev_dbg(dev, "%s()\n", __func__);
1121 1128
1122 if (!genpd || genpd != pm_genpd_lookup_dev(dev))
1123 return -EINVAL;
1124
1125 /* The above validation also means we have existing domain_data. */
1126 pdd = dev->power.subsys_data->domain_data; 1129 pdd = dev->power.subsys_data->domain_data;
1127 gpd_data = to_gpd_data(pdd); 1130 gpd_data = to_gpd_data(pdd);
1128 dev_pm_qos_remove_notifier(dev, &gpd_data->nb); 1131 dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
@@ -1154,15 +1157,24 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
1154 1157
1155 return ret; 1158 return ret;
1156} 1159}
1157EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
1158 1160
1159/** 1161/**
1160 * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain. 1162 * pm_genpd_remove_device - Remove a device from an I/O PM domain.
1161 * @genpd: Master PM domain to add the subdomain to. 1163 * @genpd: PM domain to remove the device from.
1162 * @subdomain: Subdomain to be added. 1164 * @dev: Device to be removed.
1163 */ 1165 */
1164int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, 1166int pm_genpd_remove_device(struct generic_pm_domain *genpd,
1165 struct generic_pm_domain *subdomain) 1167 struct device *dev)
1168{
1169 if (!genpd || genpd != genpd_lookup_dev(dev))
1170 return -EINVAL;
1171
1172 return genpd_remove_device(genpd, dev);
1173}
1174EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
1175
1176static int genpd_add_subdomain(struct generic_pm_domain *genpd,
1177 struct generic_pm_domain *subdomain)
1166{ 1178{
1167 struct gpd_link *link, *itr; 1179 struct gpd_link *link, *itr;
1168 int ret = 0; 1180 int ret = 0;
@@ -1205,6 +1217,23 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
1205 kfree(link); 1217 kfree(link);
1206 return ret; 1218 return ret;
1207} 1219}
1220
1221/**
1222 * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
1223 * @genpd: Master PM domain to add the subdomain to.
1224 * @subdomain: Subdomain to be added.
1225 */
1226int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
1227 struct generic_pm_domain *subdomain)
1228{
1229 int ret;
1230
1231 mutex_lock(&gpd_list_lock);
1232 ret = genpd_add_subdomain(genpd, subdomain);
1233 mutex_unlock(&gpd_list_lock);
1234
1235 return ret;
1236}
1208EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain); 1237EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
1209 1238
1210/** 1239/**
@@ -1278,27 +1307,17 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
1278 genpd->device_count = 0; 1307 genpd->device_count = 0;
1279 genpd->max_off_time_ns = -1; 1308 genpd->max_off_time_ns = -1;
1280 genpd->max_off_time_changed = true; 1309 genpd->max_off_time_changed = true;
1310 genpd->provider = NULL;
1311 genpd->has_provider = false;
1281 genpd->domain.ops.runtime_suspend = genpd_runtime_suspend; 1312 genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
1282 genpd->domain.ops.runtime_resume = genpd_runtime_resume; 1313 genpd->domain.ops.runtime_resume = genpd_runtime_resume;
1283 genpd->domain.ops.prepare = pm_genpd_prepare; 1314 genpd->domain.ops.prepare = pm_genpd_prepare;
1284 genpd->domain.ops.suspend = pm_generic_suspend;
1285 genpd->domain.ops.suspend_late = pm_generic_suspend_late;
1286 genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq; 1315 genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq;
1287 genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq; 1316 genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
1288 genpd->domain.ops.resume_early = pm_generic_resume_early;
1289 genpd->domain.ops.resume = pm_generic_resume;
1290 genpd->domain.ops.freeze = pm_generic_freeze;
1291 genpd->domain.ops.freeze_late = pm_generic_freeze_late;
1292 genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq; 1317 genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
1293 genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq; 1318 genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
1294 genpd->domain.ops.thaw_early = pm_generic_thaw_early;
1295 genpd->domain.ops.thaw = pm_generic_thaw;
1296 genpd->domain.ops.poweroff = pm_generic_poweroff;
1297 genpd->domain.ops.poweroff_late = pm_generic_poweroff_late;
1298 genpd->domain.ops.poweroff_noirq = pm_genpd_suspend_noirq; 1319 genpd->domain.ops.poweroff_noirq = pm_genpd_suspend_noirq;
1299 genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq; 1320 genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
1300 genpd->domain.ops.restore_early = pm_generic_restore_early;
1301 genpd->domain.ops.restore = pm_generic_restore;
1302 genpd->domain.ops.complete = pm_genpd_complete; 1321 genpd->domain.ops.complete = pm_genpd_complete;
1303 1322
1304 if (genpd->flags & GENPD_FLAG_PM_CLK) { 1323 if (genpd->flags & GENPD_FLAG_PM_CLK) {
@@ -1328,7 +1347,71 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
1328} 1347}
1329EXPORT_SYMBOL_GPL(pm_genpd_init); 1348EXPORT_SYMBOL_GPL(pm_genpd_init);
1330 1349
1350static int genpd_remove(struct generic_pm_domain *genpd)
1351{
1352 struct gpd_link *l, *link;
1353
1354 if (IS_ERR_OR_NULL(genpd))
1355 return -EINVAL;
1356
1357 mutex_lock(&genpd->lock);
1358
1359 if (genpd->has_provider) {
1360 mutex_unlock(&genpd->lock);
1361 pr_err("Provider present, unable to remove %s\n", genpd->name);
1362 return -EBUSY;
1363 }
1364
1365 if (!list_empty(&genpd->master_links) || genpd->device_count) {
1366 mutex_unlock(&genpd->lock);
1367 pr_err("%s: unable to remove %s\n", __func__, genpd->name);
1368 return -EBUSY;
1369 }
1370
1371 list_for_each_entry_safe(link, l, &genpd->slave_links, slave_node) {
1372 list_del(&link->master_node);
1373 list_del(&link->slave_node);
1374 kfree(link);
1375 }
1376
1377 list_del(&genpd->gpd_list_node);
1378 mutex_unlock(&genpd->lock);
1379 cancel_work_sync(&genpd->power_off_work);
1380 pr_debug("%s: removed %s\n", __func__, genpd->name);
1381
1382 return 0;
1383}
1384
1385/**
1386 * pm_genpd_remove - Remove a generic I/O PM domain
1387 * @genpd: Pointer to PM domain that is to be removed.
1388 *
1389 * To remove the PM domain, this function:
1390 * - Removes the PM domain as a subdomain to any parent domains,
1391 * if it was added.
1392 * - Removes the PM domain from the list of registered PM domains.
1393 *
1394 * The PM domain will only be removed, if the associated provider has
1395 * been removed, it is not a parent to any other PM domain and has no
1396 * devices associated with it.
1397 */
1398int pm_genpd_remove(struct generic_pm_domain *genpd)
1399{
1400 int ret;
1401
1402 mutex_lock(&gpd_list_lock);
1403 ret = genpd_remove(genpd);
1404 mutex_unlock(&gpd_list_lock);
1405
1406 return ret;
1407}
1408EXPORT_SYMBOL_GPL(pm_genpd_remove);
1409
1331#ifdef CONFIG_PM_GENERIC_DOMAINS_OF 1410#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
1411
1412typedef struct generic_pm_domain *(*genpd_xlate_t)(struct of_phandle_args *args,
1413 void *data);
1414
1332/* 1415/*
1333 * Device Tree based PM domain providers. 1416 * Device Tree based PM domain providers.
1334 * 1417 *
@@ -1340,8 +1423,8 @@ EXPORT_SYMBOL_GPL(pm_genpd_init);
1340 * maps a PM domain specifier retrieved from the device tree to a PM domain. 1423 * maps a PM domain specifier retrieved from the device tree to a PM domain.
1341 * 1424 *
1342 * Two simple mapping functions have been provided for convenience: 1425 * Two simple mapping functions have been provided for convenience:
1343 * - __of_genpd_xlate_simple() for 1:1 device tree node to PM domain mapping. 1426 * - genpd_xlate_simple() for 1:1 device tree node to PM domain mapping.
1344 * - __of_genpd_xlate_onecell() for mapping of multiple PM domains per node by 1427 * - genpd_xlate_onecell() for mapping of multiple PM domains per node by
1345 * index. 1428 * index.
1346 */ 1429 */
1347 1430
@@ -1366,7 +1449,7 @@ static LIST_HEAD(of_genpd_providers);
1366static DEFINE_MUTEX(of_genpd_mutex); 1449static DEFINE_MUTEX(of_genpd_mutex);
1367 1450
1368/** 1451/**
1369 * __of_genpd_xlate_simple() - Xlate function for direct node-domain mapping 1452 * genpd_xlate_simple() - Xlate function for direct node-domain mapping
1370 * @genpdspec: OF phandle args to map into a PM domain 1453 * @genpdspec: OF phandle args to map into a PM domain
1371 * @data: xlate function private data - pointer to struct generic_pm_domain 1454 * @data: xlate function private data - pointer to struct generic_pm_domain
1372 * 1455 *
@@ -1374,7 +1457,7 @@ static DEFINE_MUTEX(of_genpd_mutex);
1374 * have their own device tree nodes. The private data of xlate function needs 1457 * have their own device tree nodes. The private data of xlate function needs
1375 * to be a valid pointer to struct generic_pm_domain. 1458 * to be a valid pointer to struct generic_pm_domain.
1376 */ 1459 */
1377struct generic_pm_domain *__of_genpd_xlate_simple( 1460static struct generic_pm_domain *genpd_xlate_simple(
1378 struct of_phandle_args *genpdspec, 1461 struct of_phandle_args *genpdspec,
1379 void *data) 1462 void *data)
1380{ 1463{
@@ -1382,10 +1465,9 @@ struct generic_pm_domain *__of_genpd_xlate_simple(
1382 return ERR_PTR(-EINVAL); 1465 return ERR_PTR(-EINVAL);
1383 return data; 1466 return data;
1384} 1467}
1385EXPORT_SYMBOL_GPL(__of_genpd_xlate_simple);
1386 1468
1387/** 1469/**
1388 * __of_genpd_xlate_onecell() - Xlate function using a single index. 1470 * genpd_xlate_onecell() - Xlate function using a single index.
1389 * @genpdspec: OF phandle args to map into a PM domain 1471 * @genpdspec: OF phandle args to map into a PM domain
1390 * @data: xlate function private data - pointer to struct genpd_onecell_data 1472 * @data: xlate function private data - pointer to struct genpd_onecell_data
1391 * 1473 *
@@ -1394,7 +1476,7 @@ EXPORT_SYMBOL_GPL(__of_genpd_xlate_simple);
1394 * A single cell is used as an index into an array of PM domains specified in 1476 * A single cell is used as an index into an array of PM domains specified in
1395 * the genpd_onecell_data struct when registering the provider. 1477 * the genpd_onecell_data struct when registering the provider.
1396 */ 1478 */
1397struct generic_pm_domain *__of_genpd_xlate_onecell( 1479static struct generic_pm_domain *genpd_xlate_onecell(
1398 struct of_phandle_args *genpdspec, 1480 struct of_phandle_args *genpdspec,
1399 void *data) 1481 void *data)
1400{ 1482{
@@ -1414,16 +1496,15 @@ struct generic_pm_domain *__of_genpd_xlate_onecell(
1414 1496
1415 return genpd_data->domains[idx]; 1497 return genpd_data->domains[idx];
1416} 1498}
1417EXPORT_SYMBOL_GPL(__of_genpd_xlate_onecell);
1418 1499
1419/** 1500/**
1420 * __of_genpd_add_provider() - Register a PM domain provider for a node 1501 * genpd_add_provider() - Register a PM domain provider for a node
1421 * @np: Device node pointer associated with the PM domain provider. 1502 * @np: Device node pointer associated with the PM domain provider.
1422 * @xlate: Callback for decoding PM domain from phandle arguments. 1503 * @xlate: Callback for decoding PM domain from phandle arguments.
1423 * @data: Context pointer for @xlate callback. 1504 * @data: Context pointer for @xlate callback.
1424 */ 1505 */
1425int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate, 1506static int genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
1426 void *data) 1507 void *data)
1427{ 1508{
1428 struct of_genpd_provider *cp; 1509 struct of_genpd_provider *cp;
1429 1510
@@ -1442,7 +1523,83 @@ int __of_genpd_add_provider(struct device_node *np, genpd_xlate_t xlate,
1442 1523
1443 return 0; 1524 return 0;
1444} 1525}
1445EXPORT_SYMBOL_GPL(__of_genpd_add_provider); 1526
1527/**
1528 * of_genpd_add_provider_simple() - Register a simple PM domain provider
1529 * @np: Device node pointer associated with the PM domain provider.
1530 * @genpd: Pointer to PM domain associated with the PM domain provider.
1531 */
1532int of_genpd_add_provider_simple(struct device_node *np,
1533 struct generic_pm_domain *genpd)
1534{
1535 int ret = -EINVAL;
1536
1537 if (!np || !genpd)
1538 return -EINVAL;
1539
1540 mutex_lock(&gpd_list_lock);
1541
1542 if (pm_genpd_present(genpd))
1543 ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
1544
1545 if (!ret) {
1546 genpd->provider = &np->fwnode;
1547 genpd->has_provider = true;
1548 }
1549
1550 mutex_unlock(&gpd_list_lock);
1551
1552 return ret;
1553}
1554EXPORT_SYMBOL_GPL(of_genpd_add_provider_simple);
1555
1556/**
1557 * of_genpd_add_provider_onecell() - Register a onecell PM domain provider
1558 * @np: Device node pointer associated with the PM domain provider.
1559 * @data: Pointer to the data associated with the PM domain provider.
1560 */
1561int of_genpd_add_provider_onecell(struct device_node *np,
1562 struct genpd_onecell_data *data)
1563{
1564 unsigned int i;
1565 int ret = -EINVAL;
1566
1567 if (!np || !data)
1568 return -EINVAL;
1569
1570 mutex_lock(&gpd_list_lock);
1571
1572 for (i = 0; i < data->num_domains; i++) {
1573 if (!data->domains[i])
1574 continue;
1575 if (!pm_genpd_present(data->domains[i]))
1576 goto error;
1577
1578 data->domains[i]->provider = &np->fwnode;
1579 data->domains[i]->has_provider = true;
1580 }
1581
1582 ret = genpd_add_provider(np, genpd_xlate_onecell, data);
1583 if (ret < 0)
1584 goto error;
1585
1586 mutex_unlock(&gpd_list_lock);
1587
1588 return 0;
1589
1590error:
1591 while (i--) {
1592 if (!data->domains[i])
1593 continue;
1594 data->domains[i]->provider = NULL;
1595 data->domains[i]->has_provider = false;
1596 }
1597
1598 mutex_unlock(&gpd_list_lock);
1599
1600 return ret;
1601}
1602EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);
1446 1603
1447/** 1604/**
1448 * of_genpd_del_provider() - Remove a previously registered PM domain provider 1605 * of_genpd_del_provider() - Remove a previously registered PM domain provider
@@ -1451,10 +1608,21 @@ EXPORT_SYMBOL_GPL(__of_genpd_add_provider);
1451void of_genpd_del_provider(struct device_node *np) 1608void of_genpd_del_provider(struct device_node *np)
1452{ 1609{
1453 struct of_genpd_provider *cp; 1610 struct of_genpd_provider *cp;
1611 struct generic_pm_domain *gpd;
1454 1612
1613 mutex_lock(&gpd_list_lock);
1455 mutex_lock(&of_genpd_mutex); 1614 mutex_lock(&of_genpd_mutex);
1456 list_for_each_entry(cp, &of_genpd_providers, link) { 1615 list_for_each_entry(cp, &of_genpd_providers, link) {
1457 if (cp->node == np) { 1616 if (cp->node == np) {
1617 /*
1618 * For each PM domain associated with the
1619 * provider, set the 'has_provider' to false
1620 * so that the PM domain can be safely removed.
1621 */
1622 list_for_each_entry(gpd, &gpd_list, gpd_list_node)
1623 if (gpd->provider == &np->fwnode)
1624 gpd->has_provider = false;
1625
1458 list_del(&cp->link); 1626 list_del(&cp->link);
1459 of_node_put(cp->node); 1627 of_node_put(cp->node);
1460 kfree(cp); 1628 kfree(cp);
@@ -1462,11 +1630,12 @@ void of_genpd_del_provider(struct device_node *np)
1462 } 1630 }
1463 } 1631 }
1464 mutex_unlock(&of_genpd_mutex); 1632 mutex_unlock(&of_genpd_mutex);
1633 mutex_unlock(&gpd_list_lock);
1465} 1634}
1466EXPORT_SYMBOL_GPL(of_genpd_del_provider); 1635EXPORT_SYMBOL_GPL(of_genpd_del_provider);
1467 1636
1468/** 1637/**
1469 * of_genpd_get_from_provider() - Look-up PM domain 1638 * genpd_get_from_provider() - Look-up PM domain
1470 * @genpdspec: OF phandle args to use for look-up 1639 * @genpdspec: OF phandle args to use for look-up
1471 * 1640 *
1472 * Looks for a PM domain provider under the node specified by @genpdspec and if 1641 * 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);
1476 * Returns a valid pointer to struct generic_pm_domain on success or ERR_PTR() 1645 * Returns a valid pointer to struct generic_pm_domain on success or ERR_PTR()
1477 * on failure. 1646 * on failure.
1478 */ 1647 */
1479struct generic_pm_domain *of_genpd_get_from_provider( 1648static struct generic_pm_domain *genpd_get_from_provider(
1480 struct of_phandle_args *genpdspec) 1649 struct of_phandle_args *genpdspec)
1481{ 1650{
1482 struct generic_pm_domain *genpd = ERR_PTR(-ENOENT); 1651 struct generic_pm_domain *genpd = ERR_PTR(-ENOENT);
@@ -1499,7 +1668,109 @@ struct generic_pm_domain *of_genpd_get_from_provider(
1499 1668
1500 return genpd; 1669 return genpd;
1501} 1670}
1502EXPORT_SYMBOL_GPL(of_genpd_get_from_provider); 1671
1672/**
1673 * of_genpd_add_device() - Add a device to an I/O PM domain
1674 * @genpdspec: OF phandle args to use for look-up PM domain
1675 * @dev: Device to be added.
1676 *
1677 * Looks-up an I/O PM domain based upon phandle args provided and adds
1678 * the device to the PM domain. Returns a negative error code on failure.
1679 */
1680int of_genpd_add_device(struct of_phandle_args *genpdspec, struct device *dev)
1681{
1682 struct generic_pm_domain *genpd;
1683 int ret;
1684
1685 mutex_lock(&gpd_list_lock);
1686
1687 genpd = genpd_get_from_provider(genpdspec);
1688 if (IS_ERR(genpd)) {
1689 ret = PTR_ERR(genpd);
1690 goto out;
1691 }
1692
1693 ret = genpd_add_device(genpd, dev, NULL);
1694
1695out:
1696 mutex_unlock(&gpd_list_lock);
1697
1698 return ret;
1699}
1700EXPORT_SYMBOL_GPL(of_genpd_add_device);
1701
1702/**
1703 * of_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
1704 * @parent_spec: OF phandle args to use for parent PM domain look-up
1705 * @subdomain_spec: OF phandle args to use for subdomain look-up
1706 *
1707 * Looks-up a parent PM domain and subdomain based upon phandle args
1708 * provided and adds the subdomain to the parent PM domain. Returns a
1709 * negative error code on failure.
1710 */
1711int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
1712 struct of_phandle_args *subdomain_spec)
1713{
1714 struct generic_pm_domain *parent, *subdomain;
1715 int ret;
1716
1717 mutex_lock(&gpd_list_lock);
1718
1719 parent = genpd_get_from_provider(parent_spec);
1720 if (IS_ERR(parent)) {
1721 ret = PTR_ERR(parent);
1722 goto out;
1723 }
1724
1725 subdomain = genpd_get_from_provider(subdomain_spec);
1726 if (IS_ERR(subdomain)) {
1727 ret = PTR_ERR(subdomain);
1728 goto out;
1729 }
1730
1731 ret = genpd_add_subdomain(parent, subdomain);
1732
1733out:
1734 mutex_unlock(&gpd_list_lock);
1735
1736 return ret;
1737}
1738EXPORT_SYMBOL_GPL(of_genpd_add_subdomain);
1739
1740/**
1741 * of_genpd_remove_last - Remove the last PM domain registered for a provider
1742 * @provider: Pointer to device structure associated with provider
1743 *
1744 * Find the last PM domain that was added by a particular provider and
1745 * remove this PM domain from the list of PM domains. The provider is
1746 * identified by the 'provider' device structure that is passed. The PM
1747 * domain will only be removed, if the provider associated with domain
1748 * has been removed.
1749 *
1750 * Returns a valid pointer to struct generic_pm_domain on success or
1751 * ERR_PTR() on failure.
1752 */
1753struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
1754{
1755 struct generic_pm_domain *gpd, *genpd = ERR_PTR(-ENOENT);
1756 int ret;
1757
1758 if (IS_ERR_OR_NULL(np))
1759 return ERR_PTR(-EINVAL);
1760
1761 mutex_lock(&gpd_list_lock);
1762 list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
1763 if (gpd->provider == &np->fwnode) {
1764 ret = genpd_remove(gpd);
1765 genpd = ret ? ERR_PTR(ret) : gpd;
1766 break;
1767 }
1768 }
1769 mutex_unlock(&gpd_list_lock);
1770
1771 return genpd;
1772}
1773EXPORT_SYMBOL_GPL(of_genpd_remove_last);
1503 1774
1504/** 1775/**
1505 * genpd_dev_pm_detach - Detach a device from its PM domain. 1776 * 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)
1515 unsigned int i; 1786 unsigned int i;
1516 int ret = 0; 1787 int ret = 0;
1517 1788
1518 pd = pm_genpd_lookup_dev(dev); 1789 pd = dev_to_genpd(dev);
1519 if (!pd) 1790 if (IS_ERR(pd))
1520 return; 1791 return;
1521 1792
1522 dev_dbg(dev, "removing from PM domain %s\n", pd->name); 1793 dev_dbg(dev, "removing from PM domain %s\n", pd->name);
1523 1794
1524 for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { 1795 for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
1525 ret = pm_genpd_remove_device(pd, dev); 1796 ret = genpd_remove_device(pd, dev);
1526 if (ret != -EAGAIN) 1797 if (ret != -EAGAIN)
1527 break; 1798 break;
1528 1799
@@ -1596,9 +1867,11 @@ int genpd_dev_pm_attach(struct device *dev)
1596 return -ENOENT; 1867 return -ENOENT;
1597 } 1868 }
1598 1869
1599 pd = of_genpd_get_from_provider(&pd_args); 1870 mutex_lock(&gpd_list_lock);
1871 pd = genpd_get_from_provider(&pd_args);
1600 of_node_put(pd_args.np); 1872 of_node_put(pd_args.np);
1601 if (IS_ERR(pd)) { 1873 if (IS_ERR(pd)) {
1874 mutex_unlock(&gpd_list_lock);
1602 dev_dbg(dev, "%s() failed to find PM domain: %ld\n", 1875 dev_dbg(dev, "%s() failed to find PM domain: %ld\n",
1603 __func__, PTR_ERR(pd)); 1876 __func__, PTR_ERR(pd));
1604 return -EPROBE_DEFER; 1877 return -EPROBE_DEFER;
@@ -1607,13 +1880,14 @@ int genpd_dev_pm_attach(struct device *dev)
1607 dev_dbg(dev, "adding to PM domain %s\n", pd->name); 1880 dev_dbg(dev, "adding to PM domain %s\n", pd->name);
1608 1881
1609 for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { 1882 for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) {
1610 ret = pm_genpd_add_device(pd, dev); 1883 ret = genpd_add_device(pd, dev, NULL);
1611 if (ret != -EAGAIN) 1884 if (ret != -EAGAIN)
1612 break; 1885 break;
1613 1886
1614 mdelay(i); 1887 mdelay(i);
1615 cond_resched(); 1888 cond_resched();
1616 } 1889 }
1890 mutex_unlock(&gpd_list_lock);
1617 1891
1618 if (ret < 0) { 1892 if (ret < 0) {
1619 dev_err(dev, "failed to add to PM domain %s: %d", 1893 dev_err(dev, "failed to add to PM domain %s: %d",
@@ -1636,7 +1910,7 @@ EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
1636 1910
1637/*** debugfs support ***/ 1911/*** debugfs support ***/
1638 1912
1639#ifdef CONFIG_PM_ADVANCED_DEBUG 1913#ifdef CONFIG_DEBUG_FS
1640#include <linux/pm.h> 1914#include <linux/pm.h>
1641#include <linux/device.h> 1915#include <linux/device.h>
1642#include <linux/debugfs.h> 1916#include <linux/debugfs.h>
@@ -1784,4 +2058,4 @@ static void __exit pm_genpd_debug_exit(void)
1784 debugfs_remove_recursive(pm_genpd_debugfs_dir); 2058 debugfs_remove_recursive(pm_genpd_debugfs_dir);
1785} 2059}
1786__exitcall(pm_genpd_debug_exit); 2060__exitcall(pm_genpd_debug_exit);
1787#endif /* CONFIG_PM_ADVANCED_DEBUG */ 2061#endif /* CONFIG_DEBUG_FS */