Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47d85ec2 authored by Tony Lindgren's avatar Tony Lindgren
Browse files

Merge tag 'for_3.7-omap_device' of...

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.
parents 55d512e2 9634c8dd
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ extern struct dev_pm_domain omap_device_pm_domain;
 * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM
 * @_state: one of OMAP_DEVICE_STATE_* (see above)
 * @flags: device flags
 * @_driver_status: one of BUS_NOTIFY_*_DRIVER from <linux/device.h>
 *
 * Integrates omap_hwmod data into Linux platform_device.
 *
@@ -73,6 +74,7 @@ struct omap_device {
	struct omap_device_pm_latency	*pm_lats;
	u32				dev_wakeup_lat;
	u32				_dev_wakeup_lat_limit;
	unsigned long			_driver_status;
	u8				pm_lats_cnt;
	s8				pm_lat_level;
	u8				hwmods_cnt;
+51 −5
Original line number Diff line number Diff line
@@ -385,17 +385,21 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
				      unsigned long event, void *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omap_device *od;

	switch (event) {
	case BUS_NOTIFY_ADD_DEVICE:
		if (pdev->dev.of_node)
			omap_device_build_from_dt(pdev);
		break;

	case BUS_NOTIFY_DEL_DEVICE:
		if (pdev->archdata.od)
			omap_device_delete(pdev->archdata.od);
		break;
	case BUS_NOTIFY_ADD_DEVICE:
		if (pdev->dev.of_node)
			omap_device_build_from_dt(pdev);
		/* fall through */
	default:
		od = to_omap_device(pdev);
		if (od)
			od->_driver_status = event;
	}

	return NOTIFY_DONE;
@@ -752,6 +756,10 @@ static int _od_suspend_noirq(struct device *dev)
	struct omap_device *od = to_omap_device(pdev);
	int ret;

	/* Don't attempt late suspend on a driver that is not bound */
	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER)
		return 0;

	ret = pm_generic_suspend_noirq(dev);

	if (!ret && !pm_runtime_status_suspended(dev)) {
@@ -1125,3 +1133,41 @@ static int __init omap_device_init(void)
	return 0;
}
core_initcall(omap_device_init);

/**
 * omap_device_late_idle - idle devices without drivers
 * @dev: struct device * associated with omap_device
 * @data: unused
 *
 * Check the driver bound status of this device, and idle it
 * if there is no driver attached.
 */
static int __init omap_device_late_idle(struct device *dev, void *data)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct omap_device *od = to_omap_device(pdev);

	if (!od)
		return 0;

	/*
	 * If omap_device state is enabled, but has no driver bound,
	 * idle it.
	 */
	if (od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) {
		if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
			dev_warn(dev, "%s: enabled but no driver.  Idling\n",
				 __func__);
			omap_device_idle(pdev);
		}
	}

	return 0;
}

static int __init omap_device_late_init(void)
{
	bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
	return 0;
}
late_initcall(omap_device_late_init);