diff options
Diffstat (limited to 'arch/arm')
| -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 4327b2c90c3d..e7259c0d33ec 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 c490240bb82c..0f519829e795 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); | ||
