[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