diff options
author | Fugang Duan <fugang.duan@nxp.com> | 2017-12-14 17:52:50 +0800 |
---|---|---|
committer | Leonard Crestez <leonard.crestez@nxp.com> | 2018-08-24 12:41:33 +0300 |
commit | 623fce9131f228c10073b89d801f9797bdbd3474 (patch) | |
tree | 8ea8718b6b8166a1902bc3eec832fd1cb8546b7b /drivers/tty/serial | |
parent | 80e14d7f008b661ecc2aae64e3dc80dd8b7eb93e (diff) |
MLK-17218 tty: serial: imx: add lock for register save/restore
The driver save/restore registers in system suspend/resume noirq stage
to support no_console_suspend in power lost case.
In noirq stage with no_console_suspend, .imx_console_write() _maybe_
called to print out log_buf message in .printk() or console_unlock()
called by other drivers.
It should add port.lock to protect the registers save/restore in noirq
stage since .imx_console_write() also access them.
Reported-by: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r-- | drivers/tty/serial/imx.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 45cfd2f28819..348a3f169070 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -2268,9 +2268,12 @@ static int serial_imx_remove(struct platform_device *pdev) static void serial_imx_restore_context(struct imx_port *sport) { + unsigned long flags = 0; + if (!sport->context_saved) return; + spin_lock_irqsave(&sport->port.lock, flags); writel(sport->saved_reg[4], sport->port.membase + UFCR); writel(sport->saved_reg[5], sport->port.membase + UESC); writel(sport->saved_reg[6], sport->port.membase + UTIM); @@ -2282,11 +2285,15 @@ static void serial_imx_restore_context(struct imx_port *sport) writel(sport->saved_reg[2], sport->port.membase + UCR3); writel(sport->saved_reg[3], sport->port.membase + UCR4); sport->context_saved = false; + spin_unlock_irqrestore(&sport->port.lock, flags); } static void serial_imx_save_context(struct imx_port *sport) { + unsigned long flags = 0; + /* Save necessary regs */ + spin_lock_irqsave(&sport->port.lock, flags); sport->saved_reg[0] = readl(sport->port.membase + UCR1); sport->saved_reg[1] = readl(sport->port.membase + UCR2); sport->saved_reg[2] = readl(sport->port.membase + UCR3); @@ -2298,6 +2305,10 @@ static void serial_imx_save_context(struct imx_port *sport) sport->saved_reg[8] = readl(sport->port.membase + UBMR); sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS); sport->context_saved = true; + + if (uart_console(&sport->port) && sport->port.sysrq) + sport->saved_reg[0] |= UCR1_RRDYEN; + spin_unlock_irqrestore(&sport->port.lock, flags); } static void serial_imx_enable_wakeup(struct imx_port *sport, bool on) |