Skip to content

Commit 90bb6bd

Browse files
Shenwei Wanggregkh
authored andcommitted
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. Because added the dev_pm_ops, the old suspend/resume callbacks under platform_driver will not be called any more. Changed their prototypes and moved those two callbacks into dev_pm_ops too. Signed-off-by: Shenwei Wang <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent e70e69b commit 90bb6bd

File tree

1 file changed

+94
-32
lines changed

1 file changed

+94
-32
lines changed

drivers/tty/serial/imx.c

Lines changed: 94 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ struct imx_port {
216216
unsigned int tx_bytes;
217217
unsigned int dma_tx_nents;
218218
wait_queue_head_t dma_wait;
219+
unsigned int saved_reg[10];
219220
};
220221

221222
struct imx_port_ucrs {
@@ -1815,36 +1816,6 @@ static struct uart_driver imx_reg = {
18151816
.cons = IMX_CONSOLE,
18161817
};
18171818

1818-
static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
1819-
{
1820-
struct imx_port *sport = platform_get_drvdata(dev);
1821-
unsigned int val;
1822-
1823-
/* enable wakeup from i.MX UART */
1824-
val = readl(sport->port.membase + UCR3);
1825-
val |= UCR3_AWAKEN;
1826-
writel(val, sport->port.membase + UCR3);
1827-
1828-
uart_suspend_port(&imx_reg, &sport->port);
1829-
1830-
return 0;
1831-
}
1832-
1833-
static int serial_imx_resume(struct platform_device *dev)
1834-
{
1835-
struct imx_port *sport = platform_get_drvdata(dev);
1836-
unsigned int val;
1837-
1838-
/* disable wakeup from i.MX UART */
1839-
val = readl(sport->port.membase + UCR3);
1840-
val &= ~UCR3_AWAKEN;
1841-
writel(val, sport->port.membase + UCR3);
1842-
1843-
uart_resume_port(&imx_reg, &sport->port);
1844-
1845-
return 0;
1846-
}
1847-
18481819
#ifdef CONFIG_OF
18491820
/*
18501821
* This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
@@ -2009,16 +1980,107 @@ static int serial_imx_remove(struct platform_device *pdev)
20091980
return uart_remove_one_port(&imx_reg, &sport->port);
20101981
}
20111982

1983+
static int imx_serial_port_suspend_noirq(struct device *dev)
1984+
{
1985+
struct platform_device *pdev = to_platform_device(dev);
1986+
struct imx_port *sport = platform_get_drvdata(pdev);
1987+
int ret;
1988+
1989+
ret = clk_enable(sport->clk_ipg);
1990+
if (ret)
1991+
return ret;
1992+
1993+
/* Save necessary regs */
1994+
sport->saved_reg[0] = readl(sport->port.membase + UCR1);
1995+
sport->saved_reg[1] = readl(sport->port.membase + UCR2);
1996+
sport->saved_reg[2] = readl(sport->port.membase + UCR3);
1997+
sport->saved_reg[3] = readl(sport->port.membase + UCR4);
1998+
sport->saved_reg[4] = readl(sport->port.membase + UFCR);
1999+
sport->saved_reg[5] = readl(sport->port.membase + UESC);
2000+
sport->saved_reg[6] = readl(sport->port.membase + UTIM);
2001+
sport->saved_reg[7] = readl(sport->port.membase + UBIR);
2002+
sport->saved_reg[8] = readl(sport->port.membase + UBMR);
2003+
sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS);
2004+
2005+
clk_disable(sport->clk_ipg);
2006+
2007+
return 0;
2008+
}
2009+
2010+
static int imx_serial_port_resume_noirq(struct device *dev)
2011+
{
2012+
struct platform_device *pdev = to_platform_device(dev);
2013+
struct imx_port *sport = platform_get_drvdata(pdev);
2014+
int ret;
2015+
2016+
ret = clk_enable(sport->clk_ipg);
2017+
if (ret)
2018+
return ret;
2019+
2020+
writel(sport->saved_reg[4], sport->port.membase + UFCR);
2021+
writel(sport->saved_reg[5], sport->port.membase + UESC);
2022+
writel(sport->saved_reg[6], sport->port.membase + UTIM);
2023+
writel(sport->saved_reg[7], sport->port.membase + UBIR);
2024+
writel(sport->saved_reg[8], sport->port.membase + UBMR);
2025+
writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS);
2026+
writel(sport->saved_reg[0], sport->port.membase + UCR1);
2027+
writel(sport->saved_reg[1] | UCR2_SRST, sport->port.membase + UCR2);
2028+
writel(sport->saved_reg[2], sport->port.membase + UCR3);
2029+
writel(sport->saved_reg[3], sport->port.membase + UCR4);
2030+
2031+
clk_disable(sport->clk_ipg);
2032+
2033+
return 0;
2034+
}
2035+
2036+
static int imx_serial_port_suspend(struct device *dev)
2037+
{
2038+
struct platform_device *pdev = to_platform_device(dev);
2039+
struct imx_port *sport = platform_get_drvdata(pdev);
2040+
unsigned int val;
2041+
2042+
/* enable wakeup from i.MX UART */
2043+
val = readl(sport->port.membase + UCR3);
2044+
val |= UCR3_AWAKEN;
2045+
writel(val, sport->port.membase + UCR3);
2046+
2047+
uart_suspend_port(&imx_reg, &sport->port);
2048+
2049+
return 0;
2050+
}
2051+
2052+
static int imx_serial_port_resume(struct device *dev)
2053+
{
2054+
struct platform_device *pdev = to_platform_device(dev);
2055+
struct imx_port *sport = platform_get_drvdata(pdev);
2056+
unsigned int val;
2057+
2058+
/* disable wakeup from i.MX UART */
2059+
val = readl(sport->port.membase + UCR3);
2060+
val &= ~UCR3_AWAKEN;
2061+
writel(val, sport->port.membase + UCR3);
2062+
2063+
uart_resume_port(&imx_reg, &sport->port);
2064+
2065+
return 0;
2066+
}
2067+
2068+
static const struct dev_pm_ops imx_serial_port_pm_ops = {
2069+
.suspend_noirq = imx_serial_port_suspend_noirq,
2070+
.resume_noirq = imx_serial_port_resume_noirq,
2071+
.suspend = imx_serial_port_suspend,
2072+
.resume = imx_serial_port_resume,
2073+
};
2074+
20122075
static struct platform_driver serial_imx_driver = {
20132076
.probe = serial_imx_probe,
20142077
.remove = serial_imx_remove,
20152078

2016-
.suspend = serial_imx_suspend,
2017-
.resume = serial_imx_resume,
20182079
.id_table = imx_uart_devtype,
20192080
.driver = {
20202081
.name = "imx-uart",
20212082
.of_match_table = imx_uart_dt_ids,
2083+
.pm = &imx_serial_port_pm_ops,
20222084
},
20232085
};
20242086

0 commit comments

Comments
 (0)