Skip to content

Commit

Permalink
tty: serial: qcom_geni_serial: Wakeup over UART RX
Browse files Browse the repository at this point in the history
Add system wakeup capability over UART RX line for wakeup capable UART.
When system is suspended, RX line act as an interrupt to wakeup system
for any communication requests from peer.

Signed-off-by: Akash Asthana <akashast@codeaurora.org>
Link: https://lore.kernel.org/r/1570700803-17566-1-git-send-email-akashast@codeaurora.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Akash Asthana authored and Greg Kroah-Hartman committed Oct 10, 2019
1 parent 3e4aaea commit 8b7103f
Showing 1 changed file with 43 additions and 1 deletion.
44 changes: 43 additions & 1 deletion drivers/tty/serial/qcom_geni_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_wakeirq.h>
#include <linux/qcom-geni-se.h>
#include <linux/serial.h>
#include <linux/serial_core.h>
Expand Down Expand Up @@ -116,6 +117,7 @@ struct qcom_geni_serial_port {
bool brk;

unsigned int tx_remaining;
int wakeup_irq;
};

static const struct uart_ops qcom_geni_console_pops;
Expand Down Expand Up @@ -755,6 +757,15 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done,
uart_write_wakeup(uport);
}

static irqreturn_t qcom_geni_serial_wakeup_isr(int isr, void *dev)
{
struct uart_port *uport = dev;

pm_wakeup_event(uport->dev, 2000);

return IRQ_HANDLED;
}

static irqreturn_t qcom_geni_serial_isr(int isr, void *dev)
{
u32 m_irq_en;
Expand Down Expand Up @@ -1306,6 +1317,29 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
return ret;
}

if (!console) {
port->wakeup_irq = platform_get_irq(pdev, 1);
if (port->wakeup_irq < 0) {
dev_err(&pdev->dev, "Failed to get wakeup IRQ %d\n",
port->wakeup_irq);
} else {
irq_set_status_flags(port->wakeup_irq, IRQ_NOAUTOEN);
ret = devm_request_irq(uport->dev, port->wakeup_irq,
qcom_geni_serial_wakeup_isr,
IRQF_TRIGGER_FALLING, "uart_wakeup", uport);
if (ret) {
dev_err(uport->dev, "Failed to register wakeup IRQ ret %d\n",
ret);
return ret;
}

device_init_wakeup(&pdev->dev, true);
ret = dev_pm_set_wake_irq(&pdev->dev, port->wakeup_irq);
if (unlikely(ret))
dev_err(uport->dev, "%s:Failed to set IRQ wake:%d\n",
__func__, ret);
}
}
uport->private_data = drv;
platform_set_drvdata(pdev, port);
port->handle_rx = console ? handle_rx_console : handle_rx_uart;
Expand All @@ -1328,14 +1362,22 @@ static int __maybe_unused qcom_geni_serial_sys_suspend(struct device *dev)
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
struct uart_port *uport = &port->uport;

return uart_suspend_port(uport->private_data, uport);
uart_suspend_port(uport->private_data, uport);

if (port->wakeup_irq > 0)
enable_irq(port->wakeup_irq);

return 0;
}

static int __maybe_unused qcom_geni_serial_sys_resume(struct device *dev)
{
struct qcom_geni_serial_port *port = dev_get_drvdata(dev);
struct uart_port *uport = &port->uport;

if (port->wakeup_irq > 0)
disable_irq(port->wakeup_irq);

return uart_resume_port(uport->private_data, uport);
}

Expand Down

0 comments on commit 8b7103f

Please sign in to comment.