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 (1) 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(-)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0605176..df680f0 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) + dev_err(dev, "failed to configure + as wakeup source\n"); + 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);