From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751517AbdBFLKk (ORCPT ); Mon, 6 Feb 2017 06:10:40 -0500 Received: from mail-lf0-f67.google.com ([209.85.215.67]:35224 "EHLO mail-lf0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750950AbdBFLKj (ORCPT ); Mon, 6 Feb 2017 06:10:39 -0500 Subject: Re: [PATCH] tty/serial: atmel: ensure state is restored after suspending To: Alexandre Belloni References: <20170203225316.10466-1-alexandre.belloni@free-electrons.com> Cc: Greg Kroah-Hartman , Nicolas Ferre , linux-arm-kernel@lists.infradead.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org From: Richard Genoud Message-ID: <55a39641-87d4-4f61-11fa-54c8904ac40d@gmail.com> Date: Mon, 6 Feb 2017 12:10:34 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.6.0 MIME-Version: 1.0 In-Reply-To: <20170203225316.10466-1-alexandre.belloni@free-electrons.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Alexandre, On 03/02/2017 23:53, Alexandre Belloni wrote: > 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 > --- > drivers/tty/serial/atmel_serial.c | 44 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 44 insertions(+) > > diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c > index 168b10cad47b..22e0a73c0cb7 100644 > --- a/drivers/tty/serial/atmel_serial.c > +++ b/drivers/tty/serial/atmel_serial.c > @@ -175,6 +175,17 @@ struct atmel_uart_port { > unsigned int pending_status; > spinlock_t lock_suspended; > > + struct { > + u32 cr; > + u32 mr; > + u32 imr; > + u32 brgr; > + u32 rtor; > + u32 ttgr; > + u32 fmr; > + u32 fimr; > + } cache; > + As struct cache is only used in suspend()/resume() we could add: #ifdef CONFIG_PM / #endif to remove it from atmel_uart_port when PM is not selected. Even if I'm not a big fan of ifdefs, the suspend code is already compiled out with #ifdef CONFIG_PM, so, at least, it would be consistent. > int (*prepare_rx)(struct uart_port *port); > int (*prepare_tx)(struct uart_port *port); > void (*schedule_rx)(struct uart_port *port); > @@ -2649,6 +2660,20 @@ static int atmel_serial_suspend(struct platform_device *pdev, > cpu_relax(); > } > > + if (atmel_is_console_port(port) && !console_suspend_enabled) { > + /* Cache register values as we won't get a full shutdown/startup > + * cycle > + */ > + atmel_port->cache.mr = atmel_uart_readl(port, ATMEL_US_MR); > + atmel_port->cache.imr = atmel_uart_readl(port, ATMEL_US_IMR); > + atmel_port->cache.brgr = atmel_uart_readl(port, ATMEL_US_BRGR); > + atmel_port->cache.rtor = atmel_uart_readl(port, > + atmel_port->rtor); > + atmel_port->cache.ttgr = atmel_uart_readl(port, ATMEL_US_TTGR); > + atmel_port->cache.fmr = atmel_uart_readl(port, ATMEL_US_FMR); > + atmel_port->cache.fimr = atmel_uart_readl(port, ATMEL_US_FIMR); > + } > + > /* we can not wake up if we're running on slow clock */ > atmel_port->may_wakeup = device_may_wakeup(&pdev->dev); > if (atmel_serial_clk_will_stop()) { > @@ -2671,6 +2696,25 @@ static int atmel_serial_resume(struct platform_device *pdev) > struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); > unsigned long flags; > > + if (atmel_is_console_port(port) && !console_suspend_enabled) { > + atmel_uart_writel(port, ATMEL_US_MR, atmel_port->cache.mr); > + atmel_uart_writel(port, ATMEL_US_IER, atmel_port->cache.imr); > + atmel_uart_writel(port, ATMEL_US_BRGR, atmel_port->cache.brgr); > + atmel_uart_writel(port, atmel_port->rtor, > + atmel_port->cache.rtor); > + atmel_uart_writel(port, ATMEL_US_TTGR, atmel_port->cache.ttgr); > + > + if (atmel_port->fifo_size) { > + atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_FIFOEN | > + ATMEL_US_RXFCLR | ATMEL_US_TXFLCLR); > + atmel_uart_writel(port, ATMEL_US_FMR, > + atmel_port->cache.fmr); > + atmel_uart_writel(port, ATMEL_US_FIER, > + atmel_port->cache.fimr); > + } > + atmel_start_rx(port); > + } > + > spin_lock_irqsave(&atmel_port->lock_suspended, flags); > if (atmel_port->pending) { > atmel_handle_receive(port, atmel_port->pending); > Thanks ! Richard.