diff options
author | Tony Lindgren <tony@atomide.com> | 2012-09-13 00:17:56 -0400 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2012-09-13 00:17:56 -0400 |
commit | 47d85ec2a23552fd3d8b56778a23a5a843c5b9b1 (patch) | |
tree | 7db2cdf6272f93f1c44e736a1e968eb322316fc5 /arch | |
parent | 55d512e245bc7699a8800e23df1a24195dd08217 (diff) | |
parent | 9634c8dd6a729406e89aed4e29470e3ffb3cd060 (diff) |
Merge tag 'for_3.7-omap_device' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-omap-pm into devel-omap-device
Updates for omap_device layer for v3.7.
Allows omap_device layer to keep track of driver bound status in order
to make more intelligent decisions about idling unused devices.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap_device.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-omap/omap_device.c | 56 |
2 files changed, 53 insertions, 5 deletions
diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index 4327b2c90c3..e7259c0d33e 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h | |||
@@ -60,6 +60,7 @@ extern struct dev_pm_domain omap_device_pm_domain; | |||
60 | * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM | 60 | * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM |
61 | * @_state: one of OMAP_DEVICE_STATE_* (see above) | 61 | * @_state: one of OMAP_DEVICE_STATE_* (see above) |
62 | * @flags: device flags | 62 | * @flags: device flags |
63 | * @_driver_status: one of BUS_NOTIFY_*_DRIVER from <linux/device.h> | ||
63 | * | 64 | * |
64 | * Integrates omap_hwmod data into Linux platform_device. | 65 | * Integrates omap_hwmod data into Linux platform_device. |
65 | * | 66 | * |
@@ -73,6 +74,7 @@ struct omap_device { | |||
73 | struct omap_device_pm_latency *pm_lats; | 74 | struct omap_device_pm_latency *pm_lats; |
74 | u32 dev_wakeup_lat; | 75 | u32 dev_wakeup_lat; |
75 | u32 _dev_wakeup_lat_limit; | 76 | u32 _dev_wakeup_lat_limit; |
77 | unsigned long _driver_status; | ||
76 | u8 pm_lats_cnt; | 78 | u8 pm_lats_cnt; |
77 | s8 pm_lat_level; | 79 | s8 pm_lat_level; |
78 | u8 hwmods_cnt; | 80 | u8 hwmods_cnt; |
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index c490240bb82..0f519829e79 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c | |||
@@ -385,17 +385,21 @@ static int _omap_device_notifier_call(struct notifier_block *nb, | |||
385 | unsigned long event, void *dev) | 385 | unsigned long event, void *dev) |
386 | { | 386 | { |
387 | struct platform_device *pdev = to_platform_device(dev); | 387 | struct platform_device *pdev = to_platform_device(dev); |
388 | struct omap_device *od; | ||
388 | 389 | ||
389 | switch (event) { | 390 | switch (event) { |
390 | case BUS_NOTIFY_ADD_DEVICE: | ||
391 | if (pdev->dev.of_node) | ||
392 | omap_device_build_from_dt(pdev); | ||
393 | break; | ||
394 | |||
395 | case BUS_NOTIFY_DEL_DEVICE: | 391 | case BUS_NOTIFY_DEL_DEVICE: |
396 | if (pdev->archdata.od) | 392 | if (pdev->archdata.od) |
397 | omap_device_delete(pdev->archdata.od); | 393 | omap_device_delete(pdev->archdata.od); |
398 | break; | 394 | break; |
395 | case BUS_NOTIFY_ADD_DEVICE: | ||
396 | if (pdev->dev.of_node) | ||
397 | omap_device_build_from_dt(pdev); | ||
398 | /* fall through */ | ||
399 | default: | ||
400 | od = to_omap_device(pdev); | ||
401 | if (od) | ||
402 | od->_driver_status = event; | ||
399 | } | 403 | } |
400 | 404 | ||
401 | return NOTIFY_DONE; | 405 | return NOTIFY_DONE; |
@@ -752,6 +756,10 @@ static int _od_suspend_noirq(struct device *dev) | |||
752 | struct omap_device *od = to_omap_device(pdev); | 756 | struct omap_device *od = to_omap_device(pdev); |
753 | int ret; | 757 | int ret; |
754 | 758 | ||
759 | /* Don't attempt late suspend on a driver that is not bound */ | ||
760 | if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) | ||
761 | return 0; | ||
762 | |||
755 | ret = pm_generic_suspend_noirq(dev); | 763 | ret = pm_generic_suspend_noirq(dev); |
756 | 764 | ||
757 | if (!ret && !pm_runtime_status_suspended(dev)) { | 765 | if (!ret && !pm_runtime_status_suspended(dev)) { |
@@ -1125,3 +1133,41 @@ static int __init omap_device_init(void) | |||
1125 | return 0; | 1133 | return 0; |
1126 | } | 1134 | } |
1127 | core_initcall(omap_device_init); | 1135 | core_initcall(omap_device_init); |
1136 | |||
1137 | /** | ||
1138 | * omap_device_late_idle - idle devices without drivers | ||
1139 | * @dev: struct device * associated with omap_device | ||
1140 | * @data: unused | ||
1141 | * | ||
1142 | * Check the driver bound status of this device, and idle it | ||
1143 | * if there is no driver attached. | ||
1144 | */ | ||
1145 | static int __init omap_device_late_idle(struct device *dev, void *data) | ||
1146 | { | ||
1147 | struct platform_device *pdev = to_platform_device(dev); | ||
1148 | struct omap_device *od = to_omap_device(pdev); | ||
1149 | |||
1150 | if (!od) | ||
1151 | return 0; | ||
1152 | |||
1153 | /* | ||
1154 | * If omap_device state is enabled, but has no driver bound, | ||
1155 | * idle it. | ||
1156 | */ | ||
1157 | if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) { | ||
1158 | if (od->_state == OMAP_DEVICE_STATE_ENABLED) { | ||
1159 | dev_warn(dev, "%s: enabled but no driver. Idling\n", | ||
1160 | __func__); | ||
1161 | omap_device_idle(pdev); | ||
1162 | } | ||
1163 | } | ||
1164 | |||
1165 | return 0; | ||
1166 | } | ||
1167 | |||
1168 | static int __init omap_device_late_init(void) | ||
1169 | { | ||
1170 | bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle); | ||
1171 | return 0; | ||
1172 | } | ||
1173 | late_initcall(omap_device_late_init); | ||