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