Merge tag 'driver-core-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / tty / serial / of_serial.c
index 1f65e72..64f1bab 100644 (file)
@@ -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>
@@ -129,8 +130,15 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 
        port->dev = &ofdev->dev;
 
-       if (type == PORT_TEGRA)
+       switch (type) {
+       case PORT_TEGRA:
                port->handle_break = tegra_serial_handle_break;
+               break;
+
+       case PORT_RT2880:
+               port->iotype = UPIO_AU;
+               break;
+       }
 
        return 0;
 out:
@@ -158,7 +166,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
        if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
                return -EBUSY;
 
-       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (info == NULL)
                return -ENOMEM;
 
@@ -241,13 +249,48 @@ static int of_platform_serial_remove(struct platform_device *ofdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int of_serial_suspend(struct device *dev)
+#ifdef CONFIG_SERIAL_8250
+static void of_serial_suspend_8250(struct of_serial_info *info)
 {
-       struct of_serial_info *info = dev_get_drvdata(dev);
+       struct uart_8250_port *port8250 = serial8250_get_port(info->line);
+       struct uart_port *port = &port8250->port;
 
        serial8250_suspend_port(info->line);
-       if (info->clk)
+       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;
 }
@@ -256,10 +299,13 @@ static int of_serial_resume(struct device *dev)
 {
        struct of_serial_info *info = dev_get_drvdata(dev);
 
-       if (info->clk)
-               clk_prepare_enable(info->clk);
-
-       serial8250_resume_port(info->line);
+       switch (info->type) {
+       case PORT_8250 ... PORT_MAX_8250:
+               of_serial_resume_8250(info);
+               break;
+       default:
+               break;
+       }
 
        return 0;
 }
@@ -278,6 +324,7 @@ static struct of_device_id of_platform_serial_table[] = {
        { .compatible = "ns16850",  .data = (void *)PORT_16850, },
        { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
        { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },
+       { .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, },
        { .compatible = "altr,16550-FIFO32",
                .data = (void *)PORT_ALTR_16550_F32, },
        { .compatible = "altr,16550-FIFO64",
@@ -296,7 +343,6 @@ static struct platform_driver of_platform_serial_driver = {
        .driver = {
                .name = "of_serial",
                .of_match_table = of_platform_serial_table,
-               .pm = &of_serial_pm_ops,
        },
        .probe = of_platform_serial_probe,
        .remove = of_platform_serial_remove,