aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Belloni <alexandre.belloni@free-electrons.com>2017-02-03 17:53:16 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-02-10 09:10:16 -0500
commit6a5f0e2f9352accf857f683518bd3cc6ef6ae6c6 (patch)
tree426c7d1b4398cbf2b516a0728eed5c791bb1e269
parent424d79183af07fbcb8059f9e86efc9ff8b346c75 (diff)
tty/serial: atmel: ensure state is restored after suspending
When going to suspend, the UART registers may be lost because the power to VDDcore is cut. This is not an issue in the normal case but when no_console_suspend is used, we need to restore the registers in order to get a functional console. Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Reviewed-by: Nicolas Ferre <nicolas.ferre@microchip.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/serial/atmel_serial.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index fabbe76203bb..8d2cec0f03c2 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -175,6 +175,17 @@ struct atmel_uart_port {
175 unsigned int pending_status; 175 unsigned int pending_status;
176 spinlock_t lock_suspended; 176 spinlock_t lock_suspended;
177 177
178 struct {
179 u32 cr;
180 u32 mr;
181 u32 imr;
182 u32 brgr;
183 u32 rtor;
184 u32 ttgr;
185 u32 fmr;
186 u32 fimr;
187 } cache;
188
178 int (*prepare_rx)(struct uart_port *port); 189 int (*prepare_rx)(struct uart_port *port);
179 int (*prepare_tx)(struct uart_port *port); 190 int (*prepare_tx)(struct uart_port *port);
180 void (*schedule_rx)(struct uart_port *port); 191 void (*schedule_rx)(struct uart_port *port);
@@ -2659,6 +2670,20 @@ static int atmel_serial_suspend(struct platform_device *pdev,
2659 cpu_relax(); 2670 cpu_relax();
2660 } 2671 }
2661 2672
2673 if (atmel_is_console_port(port) && !console_suspend_enabled) {
2674 /* Cache register values as we won't get a full shutdown/startup
2675 * cycle
2676 */
2677 atmel_port->cache.mr = atmel_uart_readl(port, ATMEL_US_MR);
2678 atmel_port->cache.imr = atmel_uart_readl(port, ATMEL_US_IMR);
2679 atmel_port->cache.brgr = atmel_uart_readl(port, ATMEL_US_BRGR);
2680 atmel_port->cache.rtor = atmel_uart_readl(port,
2681 atmel_port->rtor);
2682 atmel_port->cache.ttgr = atmel_uart_readl(port, ATMEL_US_TTGR);
2683 atmel_port->cache.fmr = atmel_uart_readl(port, ATMEL_US_FMR);
2684 atmel_port->cache.fimr = atmel_uart_readl(port, ATMEL_US_FIMR);
2685 }
2686
2662 /* we can not wake up if we're running on slow clock */ 2687 /* we can not wake up if we're running on slow clock */
2663 atmel_port->may_wakeup = device_may_wakeup(&pdev->dev); 2688 atmel_port->may_wakeup = device_may_wakeup(&pdev->dev);
2664 if (atmel_serial_clk_will_stop()) { 2689 if (atmel_serial_clk_will_stop()) {
@@ -2681,6 +2706,25 @@ static int atmel_serial_resume(struct platform_device *pdev)
2681 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); 2706 struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
2682 unsigned long flags; 2707 unsigned long flags;
2683 2708
2709 if (atmel_is_console_port(port) && !console_suspend_enabled) {
2710 atmel_uart_writel(port, ATMEL_US_MR, atmel_port->cache.mr);
2711 atmel_uart_writel(port, ATMEL_US_IER, atmel_port->cache.imr);
2712 atmel_uart_writel(port, ATMEL_US_BRGR, atmel_port->cache.brgr);
2713 atmel_uart_writel(port, atmel_port->rtor,
2714 atmel_port->cache.rtor);
2715 atmel_uart_writel(port, ATMEL_US_TTGR, atmel_port->cache.ttgr);
2716
2717 if (atmel_port->fifo_size) {
2718 atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_FIFOEN |
2719 ATMEL_US_RXFCLR | ATMEL_US_TXFLCLR);
2720 atmel_uart_writel(port, ATMEL_US_FMR,
2721 atmel_port->cache.fmr);
2722 atmel_uart_writel(port, ATMEL_US_FIER,
2723 atmel_port->cache.fimr);
2724 }
2725 atmel_start_rx(port);
2726 }
2727
2684 spin_lock_irqsave(&atmel_port->lock_suspended, flags); 2728 spin_lock_irqsave(&atmel_port->lock_suspended, flags);
2685 if (atmel_port->pending) { 2729 if (atmel_port->pending) {
2686 atmel_handle_receive(port, atmel_port->pending); 2730 atmel_handle_receive(port, atmel_port->pending);