[RFC] driver wakeup: wakeup property in device tree

Message ID 1395132984-10860-1-git-send-email-sanjay.rawat@linaro.org
State New
Headers show

Commit Message

Sanjay Singh Rawat March 18, 2014, 8:56 a.m.
To configure the devices as wakeup sources, currently drivers make explicit calls
to device wakeup functions. This patch tries to automate the wakeup configuration
with the help of device tree.

In this approach, we parse the device node and if the node is having the wakeup
property, the driver will be configured as wakeup source. We don't have to make
explicit call to wakeup functions in the drivers init part. Also using this, to set
a device as wakeup source, we just need to rebuild the device tree with wakeup
property set in the dt node.

Signed-off-by: Sanjay Singh Rawat <sanjay.rawat@linaro.org>
---
 drivers/base/dd.c |   31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

Patch

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 0605176..ec72c73 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -23,6 +23,7 @@ 
 #include <linux/kthread.h>
 #include <linux/wait.h>
 #include <linux/async.h>
+#include <linux/of.h>
 #include <linux/pm_runtime.h>
 #include <linux/pinctrl/devinfo.h>
 
@@ -262,6 +263,31 @@  EXPORT_SYMBOL_GPL(device_bind_driver);
 static atomic_t probe_count = ATOMIC_INIT(0);
 static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
 
+void driver_configure_wakeup(struct device *dev, bool set)
+{
+	if(dev->of_node) {
+		const int *can_wakeup;
+		u32 val;
+
+		can_wakeup = of_get_property(dev->of_node, "wakeup", NULL);
+		if(!can_wakeup)
+			return;
+
+		if(set) {
+			val = be32_to_cpu(*can_wakeup);
+			if(val == 1) {
+				val = device_init_wakeup(dev, true);
+				if(val)
+					printk(KERN_ERR "failed to configure
+						(%s) as wakeup source\n", dev_name(dev));
+				dev_dbg(dev, "configured as wakeup source\n");
+			}
+		}
+		else
+			device_init_wakeup(dev, false);
+	}
+}
+
 static int really_probe(struct device *dev, struct device_driver *drv)
 {
 	int ret = 0;
@@ -292,6 +318,7 @@  static int really_probe(struct device *dev, struct device_driver *drv)
 		ret = drv->probe(dev);
 		if (ret)
 			goto probe_failed;
+		driver_configure_wakeup(dev, true);
 	}
 
 	driver_bound(dev);
@@ -503,8 +530,10 @@  static void __device_release_driver(struct device *dev)
 
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
-		else if (drv->remove)
+		else if (drv->remove) {
 			drv->remove(dev);
+			driver_configure_wakeup(dev, false);
+		}
 		devres_release_all(dev);
 		dev->driver = NULL;
 		dev_set_drvdata(dev, NULL);