summaryrefslogtreecommitdiff
path: root/drivers/tty/serial/mvebu-uart.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-05 16:55:56 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-05 16:55:56 -0700
commita22e48cf317d22a4326dc19e906e6b5f4f92e94e (patch)
treee3573ec1f96c50e52efe8717d9a99f249c4a65cf /drivers/tty/serial/mvebu-uart.c
parentec064d3c6b40697fd72f4b1eeabbf293b7947a04 (diff)
parent4b4ecd9cb853c14913a3726cfcc60ccda1d2924a (diff)
Merge tag 'tty-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial updates from Greg KH: "Here is the big tty/serial driver update for 4.18-rc1. There's nothing major here, just lots of serial driver updates. Full details are in the shortlog, nothing anything specific to call out here. All have been in linux-next for a while with no reported issues" * tag 'tty-4.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (55 commits) vt: Perform safe console erase only once serial: imx: disable UCR4_OREN on shutdown serial: imx: drop CTS/RTS handling from shutdown tty: fix typo in ASYNCB_FOURPORT comment serial: samsung: check DMA engine capabilities before using DMA mode tty: Fix data race in tty_insert_flip_string_fixed_flag tty: serial: msm_geni_serial: Fix TX infinite loop serial: 8250_dw: Fix runtime PM handling serial: 8250: omap: Fix idling of clocks for unused uarts tty: serial: drop ATH79 specific SoC symbols serial: 8250: Add missing rxtrig_bytes on Altera 16550 UART serial/aspeed-vuart: fix a couple mod_timer() calls serial: sh-sci: Use spin_{try}lock_irqsave instead of open coding version serial: 8250_of: Add IO space support tty/serial: atmel: use port->name as name in request_irq() serial: imx: dma_unmap_sg buffers on shutdown serial: imx: cleanup imx_uart_disable_dma() tty: serial: qcom_geni_serial: Add early console support tty: serial: qcom_geni_serial: Return IRQ_NONE for spurious interrupts tty: serial: qcom_geni_serial: Use iowrite32_rep to write to FIFO ...
Diffstat (limited to 'drivers/tty/serial/mvebu-uart.c')
-rw-r--r--drivers/tty/serial/mvebu-uart.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c
index f503fab1e268..d04b5eeea3c6 100644
--- a/drivers/tty/serial/mvebu-uart.c
+++ b/drivers/tty/serial/mvebu-uart.c
@@ -71,6 +71,8 @@
#define UART_BRDV 0x10
#define BRDV_BAUD_MASK 0x3FF
+#define UART_OSAMP 0x14
+
#define MVEBU_NR_UARTS 2
#define MVEBU_UART_TYPE "mvebu-uart"
@@ -108,6 +110,17 @@ struct mvebu_uart_driver_data {
struct uart_flags flags;
};
+/* Saved registers during suspend */
+struct mvebu_uart_pm_regs {
+ unsigned int rbr;
+ unsigned int tsh;
+ unsigned int ctrl;
+ unsigned int intr;
+ unsigned int stat;
+ unsigned int brdv;
+ unsigned int osamp;
+};
+
/* MVEBU UART driver structure */
struct mvebu_uart {
struct uart_port *port;
@@ -115,6 +128,9 @@ struct mvebu_uart {
int irq[UART_IRQ_COUNT];
unsigned char __iomem *nb;
struct mvebu_uart_driver_data *data;
+#if defined(CONFIG_PM)
+ struct mvebu_uart_pm_regs pm_regs;
+#endif /* CONFIG_PM */
};
static struct mvebu_uart *to_mvuart(struct uart_port *port)
@@ -718,6 +734,51 @@ static struct uart_driver mvebu_uart_driver = {
#endif
};
+#if defined(CONFIG_PM)
+static int mvebu_uart_suspend(struct device *dev)
+{
+ struct mvebu_uart *mvuart = dev_get_drvdata(dev);
+ struct uart_port *port = mvuart->port;
+
+ uart_suspend_port(&mvebu_uart_driver, port);
+
+ mvuart->pm_regs.rbr = readl(port->membase + UART_RBR(port));
+ mvuart->pm_regs.tsh = readl(port->membase + UART_TSH(port));
+ mvuart->pm_regs.ctrl = readl(port->membase + UART_CTRL(port));
+ mvuart->pm_regs.intr = readl(port->membase + UART_INTR(port));
+ mvuart->pm_regs.stat = readl(port->membase + UART_STAT);
+ mvuart->pm_regs.brdv = readl(port->membase + UART_BRDV);
+ mvuart->pm_regs.osamp = readl(port->membase + UART_OSAMP);
+
+ device_set_wakeup_enable(dev, true);
+
+ return 0;
+}
+
+static int mvebu_uart_resume(struct device *dev)
+{
+ struct mvebu_uart *mvuart = dev_get_drvdata(dev);
+ struct uart_port *port = mvuart->port;
+
+ writel(mvuart->pm_regs.rbr, port->membase + UART_RBR(port));
+ writel(mvuart->pm_regs.tsh, port->membase + UART_TSH(port));
+ writel(mvuart->pm_regs.ctrl, port->membase + UART_CTRL(port));
+ writel(mvuart->pm_regs.intr, port->membase + UART_INTR(port));
+ writel(mvuart->pm_regs.stat, port->membase + UART_STAT);
+ writel(mvuart->pm_regs.brdv, port->membase + UART_BRDV);
+ writel(mvuart->pm_regs.osamp, port->membase + UART_OSAMP);
+
+ uart_resume_port(&mvebu_uart_driver, port);
+
+ return 0;
+}
+
+static const struct dev_pm_ops mvebu_uart_pm_ops = {
+ .suspend = mvebu_uart_suspend,
+ .resume = mvebu_uart_resume,
+};
+#endif /* CONFIG_PM */
+
static const struct of_device_id mvebu_uart_of_match[];
/* Counter to keep track of each UART port id when not using CONFIG_OF */
@@ -891,6 +952,9 @@ static struct platform_driver mvebu_uart_platform_driver = {
.name = "mvebu-uart",
.of_match_table = of_match_ptr(mvebu_uart_of_match),
.suppress_bind_attrs = true,
+#if defined(CONFIG_PM)
+ .pm = &mvebu_uart_pm_ops,
+#endif /* CONFIG_PM */
},
};