|
@@ -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,
|