diff options
author | Jingchang Lu <jingchang.lu@freescale.com> | 2014-11-11 15:09:05 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-25 17:06:40 -0800 |
commit | 8ad3b1352693972b737607c7b9c89b56d45fea9b (patch) | |
tree | 97e18010e637f02ad4740511d8e43837d2b88e72 | |
parent | 261119f727a4c7cfc001eed0d94cea70e662433a (diff) | |
download | linux-8ad3b1352693972b737607c7b9c89b56d45fea9b.tar.gz linux-8ad3b1352693972b737607c7b9c89b56d45fea9b.tar.bz2 linux-8ad3b1352693972b737607c7b9c89b56d45fea9b.zip |
serial: of-serial: add PM suspend/resume support
This adds suspend/resume support for the of-serial driver
to provide power management support on devices attatched.
The handling may vary since not every of_serial device is
an 8250 port. Currently only 8250 port handling is added
in the suspend/resume function based on the type switch.
Signed-off-by: Jingchang Lu <jingchang.lu@freescale.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Tested-by: Joseph Lo <josephl@nvidia.com>
Reviewed-by: Peter Hurley <peter@hurleysoftware.com>
Tested-by: Florina Fainelli <f.fainelli@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/tty/serial/of_serial.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index 12c95cc64c00..58830bcddb7f 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -9,6 +9,7 @@ * 2 of the License, or (at your option) any later version. * */ +#include <linux/console.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/delay.h> @@ -247,6 +248,70 @@ static int of_platform_serial_remove(struct platform_device *ofdev) return 0; } +#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_SERIAL_8250 +static void of_serial_suspend_8250(struct of_serial_info *info) +{ + struct uart_8250_port *port8250 = serial8250_get_port(info->line); + struct uart_port *port = &port8250->port; + + serial8250_suspend_port(info->line); + if (info->clk && (!uart_console(port) || console_suspend_enabled)) + clk_disable_unprepare(info->clk); +} + +static void of_serial_resume_8250(struct of_serial_info *info) +{ + struct uart_8250_port *port8250 = serial8250_get_port(info->line); + struct uart_port *port = &port8250->port; + + if (info->clk && (!uart_console(port) || console_suspend_enabled)) + clk_prepare_enable(info->clk); + + serial8250_resume_port(info->line); +} +#else +static inline void of_serial_suspend_8250(struct of_serial_info *info) +{ +} + +static inline void of_serial_resume_8250(struct of_serial_info *info) +{ +} +#endif + +static int of_serial_suspend(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + switch (info->type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_suspend_8250(info); + break; + default: + break; + } + + return 0; +} + +static int of_serial_resume(struct device *dev) +{ + struct of_serial_info *info = dev_get_drvdata(dev); + + switch (info->type) { + case PORT_8250 ... PORT_MAX_8250: + of_serial_resume_8250(info); + break; + default: + break; + } + + return 0; +} +#endif +static SIMPLE_DEV_PM_OPS(of_serial_pm_ops, of_serial_suspend, of_serial_resume); + /* * A few common types, add more as needed. */ @@ -279,6 +344,7 @@ static struct platform_driver of_platform_serial_driver = { .name = "of_serial", .owner = THIS_MODULE, .of_match_table = of_platform_serial_table, + .pm = &of_serial_pm_ops, }, .probe = of_platform_serial_probe, .remove = of_platform_serial_remove, |