[PATCH 1/1] Serial: imx: add dev_pm_ops to support suspend to ram/disk

Shenwei Wang Shenwei.Wang at freescale.com
Wed Jul 22 11:11:17 PDT 2015


Kind PING.

> -----Original Message-----
> From: linux-arm-kernel [mailto:linux-arm-kernel-bounces at lists.infradead.org] On
> Behalf Of Shenwei Wang
> Sent: 2015年7月17日 15:30
> To: gregkh at linuxfoundation.org
> Cc: linux-arm-kernel at lists.infradead.org; linux-serial at vger.kernel.org
> Subject: [PATCH 1/1] Serial: imx: add dev_pm_ops to support suspend to ram/disk
> 
> When system goes into low power states like SUSPEND_MEM and HIBERNATION,
> the hardware IP block may be powered off to reduce the power consumption.
> This power down may cause problems on some imx platforms, because the
> hardware settings are reset to its power on default values which may differ from
> the ones when it power off. This patch added the dev_pm_ops and implemented
> two callbacks: suspend_noirq and resume_noirq, which will save the necessory
> hardware parameters right before power down and recover them before system
> uses the hardware.
> 
> Signed-off-by: Shenwei Wang <shenwei.wang at freescale.com>
> ---
>  drivers/tty/serial/imx.c | 54
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 54 insertions(+)
> 
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index
> c8cfa06..acaaa68 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -216,6 +216,7 @@ struct imx_port {
>  	unsigned int		tx_bytes;
>  	unsigned int		dma_tx_nents;
>  	wait_queue_head_t	dma_wait;
> +	unsigned int            saved_reg[10];
>  };
> 
>  struct imx_port_ucrs {
> @@ -1986,6 +1987,58 @@ static int serial_imx_remove(struct platform_device
> *pdev)
>  	return uart_remove_one_port(&imx_reg, &sport->port);  }
> 
> +static int imx_serial_port_suspend_noirq(struct device *dev) {
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct imx_port *sport = platform_get_drvdata(pdev);
> +
> +	/* Save necessary regs */
> +	clk_enable(sport->clk_ipg);
> +	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);
> +	sport->saved_reg[3] = readl(sport->port.membase + UCR4);
> +	sport->saved_reg[4] = readl(sport->port.membase + UFCR);
> +	sport->saved_reg[5] = readl(sport->port.membase + UESC);
> +	sport->saved_reg[6] = readl(sport->port.membase + UTIM);
> +	sport->saved_reg[7] = readl(sport->port.membase + UBIR);
> +	sport->saved_reg[8] = readl(sport->port.membase + UBMR);
> +	sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS);
> +	clk_disable(sport->clk_ipg);
> +
> +	pr_debug("0x%p (%d)\r\n", sport->port.membase, sport->port.line);
> +
> +	return 0;
> +}
> +
> +static int imx_serial_port_resume_noirq(struct device *dev) {
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct imx_port *sport = platform_get_drvdata(pdev);
> +
> +	clk_enable(sport->clk_ipg);
> +	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);
> +	writel(sport->saved_reg[7], sport->port.membase + UBIR);
> +	writel(sport->saved_reg[8], sport->port.membase + UBMR);
> +	writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS);
> +	writel(sport->saved_reg[0], sport->port.membase + UCR1);
> +	writel(sport->saved_reg[1] | 0x1, sport->port.membase + UCR2);
> +	writel(sport->saved_reg[2], sport->port.membase + UCR3);
> +	writel(sport->saved_reg[3], sport->port.membase + UCR4);
> +	clk_disable(sport->clk_ipg);
> +
> +	pr_debug("0x%p (%d)\r\n", sport->port.membase, sport->port.line);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops imx_serial_port_pm_ops = {
> +	.suspend_noirq = imx_serial_port_suspend_noirq,
> +	.resume_noirq = imx_serial_port_resume_noirq, };
> +
>  static struct platform_driver serial_imx_driver = {
>  	.probe		= serial_imx_probe,
>  	.remove		= serial_imx_remove,
> @@ -1996,6 +2049,7 @@ static struct platform_driver serial_imx_driver = {
>  	.driver		= {
>  		.name	= "imx-uart",
>  		.of_match_table = imx_uart_dt_ids,
> +		.pm	= &imx_serial_port_pm_ops,
>  	},
>  };
> 
> --
> 2.5.0.rc2
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


More information about the linux-arm-kernel mailing list