Skip to contentSkip to conversation

Serial: imx: add dev_pm_ops to support suspend to ram/disk

PATCH Superseded Shenwei Wang 2 participants 4 messages Jul 17, 2015 – Jul 24, 2015

Subsystems (2)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

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.

---
 drivers/tty/serial/imx.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
drivers/tty/serial/imx.c +54 -0
index c8cfa06..acaaa68 100644
@@ -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,
 	},
 };
 
Signature · 1 line
2.5.0.rc2
#1 lore raw

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

Kind PING.

Quoted 108 lines

-----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.

---
 drivers/tty/serial/imx.c | 54
++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
drivers/tty/serial/imx.c index renamed from drivers/tty/serial/imx.c +0 -0

c8cfa06..acaaa68 100644

drivers/tty/serial/imx.c +51 -1
@@ -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

maintainer
#2 lore raw

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

In reply to Shenwei Wang
Quoted 41 lines · Shenwei Wang

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.

---
 drivers/tty/serial/imx.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)
drivers/tty/serial/imx.c +11 -0
index c8cfa06..acaaa68 100644
@@ -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);

drivers/tty/serial/imx.c static int serial_imx_remove(struct platform_device *pdev) · line 2009

Quoted 10 lines
drivers/tty/serial/imx.c +10 -0
+	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);

You have a struct device, please use dev_dbg() instead.

Quoted 13 lines
drivers/tty/serial/imx.c +13 -0
+
+	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);

drivers/tty/serial/imx.c static int serial_imx_remove(struct platform_device *pdev) · line 2032

Quoted 10 lines
drivers/tty/serial/imx.c +10 -0
+	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);

Same here, please use dev_dbg()

#3 lore raw

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

Quoted 8 lines

-----Original Message-----
From: Greg KH [mailto:gregkh at linuxfoundation.org]
Sent: 2015?7?23? 19:37
To: Wang Shenwei-B38339
Cc: linux-serial at vger.kernel.org; linux-arm-kernel at lists.infradead.org
Subject: Re: [PATCH 1/1] Serial: imx: add dev_pm_ops to support suspend to ram/disk

Quoted 11 lines

drivers/tty/serial/imx.c static int serial_imx_remove(struct platform_device *pdev) · line 2009

Quoted 9 lines
drivers/tty/serial/imx.c +9 -0
+	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);

You have a struct device, please use dev_dbg() instead.

Adopted in PATCH v2.

Quoted 12 lines

drivers/tty/serial/imx.c static int serial_imx_remove(struct platform_device *pdev) · line 2032

Quoted 10 lines
drivers/tty/serial/imx.c +9 -0
+
+	return 0;
+}
+
+	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);

Same here, please use dev_dbg()

Adopted in PATCH v2.

Thanks,
Shenwei