[linux-yocto] [PATCH 13/15] serial: 8250_dw: support serial console wakeup

Nilesh Bacchewar nilesh.bacchewar at intel.com
Thu Nov 17 15:06:29 PST 2016


From: Andy Shevchenko <andriy.shevchenko at 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.shevchenko at 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



More information about the linux-yocto mailing list