From: Andy Shevchenko <andriy.shevche...@linux.intel.com>

Backport:
 - Upstream-Status: Pending.
 
[https://bitbucket.org/andy-shev/linux/commits/31b40497a96e5f44fd0bea6cb30000ae2fd1cc27?at=master]

Set up RxD or CTS pin as wake source and switch the driver to use it.

Signed-off-by: Andy Shevchenko <andriy.shevche...@linux.intel.com>
---
 drivers/tty/serial/8250/8250_dw.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/tty/serial/8250/8250_dw.c 
b/drivers/tty/serial/8250/8250_dw.c
index 4ffd160..6c0c49a 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -14,6 +14,7 @@
  * raised, the LCR needs to be rewritten and the uart status register read.
  */
 #include <linux/device.h>
+#include <linux/gpio/consumer.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/serial_8250.h>
@@ -21,7 +22,9 @@
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/clk.h>
@@ -327,6 +330,7 @@ static int dw8250_probe(struct platform_device *pdev)
        int irq = platform_get_irq(pdev, 0);
        struct uart_port *p = &uart.port;
        struct dw8250_data *data;
+       struct gpio_desc *wake;
        int err;
        u32 val;
 
@@ -465,6 +469,26 @@ static int dw8250_probe(struct platform_device *pdev)
                uart.dma = &data->dma;
        }
 
+       /* Set up RxD or CTS pin as wake source */
+       wake = gpiod_get(&pdev->dev, "rx", GPIOD_IN);
+       if (IS_ERR(wake))
+               wake = gpiod_get(&pdev->dev, "cts", GPIOD_IN);
+       if (!IS_ERR(wake)) {
+               irq = gpiod_to_irq(wake);
+               if (irq >= 0) {
+                       device_init_wakeup(&pdev->dev, true);
+                       err = dev_pm_set_dedicated_wake_irq(&pdev->dev, irq);
+                       if (err) {
+                               dev_warn(&pdev->dev,
+                                        "Can't set dedicated wake IRQ: %d\n",
+                                        err);
+                       } else {
+                               irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
+                       }
+               }
+               gpiod_put(wake);
+       }
+
        data->line = serial8250_register_8250_port(&uart);
        if (data->line < 0) {
                err = data->line;
@@ -502,6 +526,9 @@ static int dw8250_remove(struct platform_device *pdev)
 
        pm_runtime_get_sync(&pdev->dev);
 
+       dev_pm_clear_wake_irq(&pdev->dev);
+       device_init_wakeup(&pdev->dev, false);
+
        serial8250_unregister_port(data->line);
 
        if (!IS_ERR(data->rst))
@@ -544,6 +571,8 @@ static int dw8250_runtime_suspend(struct device *dev)
 {
        struct dw8250_data *data = dev_get_drvdata(dev);
 
+       pinctrl_pm_select_sleep_state(dev);
+
        if (!IS_ERR(data->clk))
                clk_disable_unprepare(data->clk);
 
@@ -556,6 +585,7 @@ static int dw8250_runtime_suspend(struct device *dev)
 static int dw8250_runtime_resume(struct device *dev)
 {
        struct dw8250_data *data = dev_get_drvdata(dev);
+       struct uart_8250_port *up = serial8250_get_port(data->line);
 
        if (!IS_ERR(data->pclk))
                clk_prepare_enable(data->pclk);
@@ -563,6 +593,15 @@ static int dw8250_runtime_resume(struct device *dev)
        if (!IS_ERR(data->clk))
                clk_prepare_enable(data->clk);
 
+       pinctrl_pm_select_default_state(dev);
+
+       /* Restore context */
+       serial8250_do_restore_context(&up->port);
+
+       /*
+        *  TODO: Check if it needs more than it's done in
+        *  serial8250_console_restore()
+        */
        return 0;
 }
 #endif
-- 
1.9.1

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to