serial: sh-sci: Require a device per port mapping.
[~shefty/rdma-dev.git] / drivers / serial / sh-sci.c
index 5b3e9769ca2101fc8645a4ef6c1e5835412f0594..3fd1577a162fa829aaec90616697eda762b698df 100644 (file)
@@ -47,7 +47,6 @@
 #include <linux/clk.h>
 #include <linux/ctype.h>
 #include <linux/err.h>
-#include <linux/list.h>
 #include <linux/dmaengine.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
@@ -83,8 +82,6 @@ struct sci_port {
        /* Function clock */
        struct clk              *fclk;
 
-       struct list_head        node;
-
        struct dma_chan                 *chan_tx;
        struct dma_chan                 *chan_rx;
 
@@ -105,16 +102,14 @@ struct sci_port {
        struct timer_list               rx_timer;
        unsigned int                    rx_timeout;
 #endif
-};
 
-struct sh_sci_priv {
-       spinlock_t lock;
-       struct list_head ports;
-       struct notifier_block clk_nb;
+       struct notifier_block           freq_transition;
 };
 
 /* Function prototypes */
+static void sci_start_tx(struct uart_port *port);
 static void sci_stop_tx(struct uart_port *port);
+static void sci_start_rx(struct uart_port *port);
 
 #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
 
@@ -827,17 +822,17 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
 static int sci_notifier(struct notifier_block *self,
                        unsigned long phase, void *p)
 {
-       struct sh_sci_priv *priv = container_of(self,
-                                               struct sh_sci_priv, clk_nb);
        struct sci_port *sci_port;
        unsigned long flags;
 
+       sci_port = container_of(self, struct sci_port, freq_transition);
+
        if ((phase == CPUFREQ_POSTCHANGE) ||
            (phase == CPUFREQ_RESUMECHANGE)) {
-               spin_lock_irqsave(&priv->lock, flags);
-               list_for_each_entry(sci_port, &priv->ports, node)
-                       sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
-               spin_unlock_irqrestore(&priv->lock, flags);
+               struct uart_port *port = &sci_port->port;
+               spin_lock_irqsave(&port->lock, flags);
+               port->uartclk = clk_get_rate(sci_port->iclk);
+               spin_unlock_irqrestore(&port->lock, flags);
        }
 
        return NOTIFY_OK;
@@ -1025,9 +1020,6 @@ static void sci_dma_rx_complete(void *arg)
        schedule_work(&s->work_rx);
 }
 
-static void sci_start_rx(struct uart_port *port);
-static void sci_start_tx(struct uart_port *port);
-
 static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
 {
        struct dma_chan *chan = s->chan_rx;
@@ -1874,24 +1866,18 @@ static struct uart_driver sci_uart_driver = {
        .cons           = SCI_CONSOLE,
 };
 
-
 static int sci_remove(struct platform_device *dev)
 {
-       struct sh_sci_priv *priv = platform_get_drvdata(dev);
-       struct sci_port *p;
-       unsigned long flags;
+       struct sci_port *port = platform_get_drvdata(dev);
 
-       cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
+       cpufreq_unregister_notifier(&port->freq_transition,
+                                   CPUFREQ_TRANSITION_NOTIFIER);
 
-       spin_lock_irqsave(&priv->lock, flags);
-       list_for_each_entry(p, &priv->ports, node) {
-               uart_remove_one_port(&sci_uart_driver, &p->port);
-               clk_put(p->iclk);
-               clk_put(p->fclk);
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
+       uart_remove_one_port(&sci_uart_driver, &port->port);
+
+       clk_put(port->iclk);
+       clk_put(port->fclk);
 
-       kfree(priv);
        return 0;
 }
 
@@ -1900,8 +1886,6 @@ static int __devinit sci_probe_single(struct platform_device *dev,
                                      struct plat_sci_port *p,
                                      struct sci_port *sciport)
 {
-       struct sh_sci_priv *priv = platform_get_drvdata(dev);
-       unsigned long flags;
        int ret;
 
        /* Sanity check */
@@ -1918,17 +1902,7 @@ static int __devinit sci_probe_single(struct platform_device *dev,
        if (ret)
                return ret;
 
-       ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
-       if (ret)
-               return ret;
-
-       INIT_LIST_HEAD(&sciport->node);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       list_add(&sciport->node, &priv->ports);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       return 0;
+       return uart_add_one_port(&sci_uart_driver, &sciport->port);
 }
 
 /*
@@ -1940,46 +1914,38 @@ static int __devinit sci_probe_single(struct platform_device *dev,
 static int __devinit sci_probe(struct platform_device *dev)
 {
        struct plat_sci_port *p = dev->dev.platform_data;
-       struct sh_sci_priv *priv;
-       int i, ret = -EINVAL;
+       struct sci_port *sp = &sci_ports[dev->id];
+       int ret = -EINVAL;
 
 #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
        if (is_early_platform_device(dev)) {
-               if (dev->id == -1)
-                       return -ENOTSUPP;
                early_serial_console.index = dev->id;
                early_serial_console.data = &early_serial_port.port;
+
                sci_init_single(NULL, &early_serial_port, dev->id, p);
+
                serial_console_setup(&early_serial_console, early_serial_buf);
+
                if (!strstr(early_serial_buf, "keep"))
                        early_serial_console.flags |= CON_BOOT;
+
                register_console(&early_serial_console);
                return 0;
        }
 #endif
 
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
+       platform_set_drvdata(dev, sp);
 
-       INIT_LIST_HEAD(&priv->ports);
-       spin_lock_init(&priv->lock);
-       platform_set_drvdata(dev, priv);
+       ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]);
+       if (ret)
+               goto err_unreg;
 
-       priv->clk_nb.notifier_call = sci_notifier;
-       cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
+       sp->freq_transition.notifier_call = sci_notifier;
 
-       if (dev->id != -1) {
-               ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]);
-               if (ret)
-                       goto err_unreg;
-       } else {
-               for (i = 0; p && p->flags != 0; p++, i++) {
-                       ret = sci_probe_single(dev, i, p, &sci_ports[i]);
-                       if (ret)
-                               goto err_unreg;
-               }
-       }
+       ret = cpufreq_register_notifier(&sp->freq_transition,
+                                       CPUFREQ_TRANSITION_NOTIFIER);
+       if (unlikely(ret < 0))
+               goto err_unreg;
 
 #ifdef CONFIG_SH_STANDARD_BIOS
        sh_bios_gdb_detach();
@@ -1994,28 +1960,20 @@ err_unreg:
 
 static int sci_suspend(struct device *dev)
 {
-       struct sh_sci_priv *priv = dev_get_drvdata(dev);
-       struct sci_port *p;
-       unsigned long flags;
+       struct sci_port *sport = dev_get_drvdata(dev);
 
-       spin_lock_irqsave(&priv->lock, flags);
-       list_for_each_entry(p, &priv->ports, node)
-               uart_suspend_port(&sci_uart_driver, &p->port);
-       spin_unlock_irqrestore(&priv->lock, flags);
+       if (sport)
+               uart_suspend_port(&sci_uart_driver, &sport->port);
 
        return 0;
 }
 
 static int sci_resume(struct device *dev)
 {
-       struct sh_sci_priv *priv = dev_get_drvdata(dev);
-       struct sci_port *p;
-       unsigned long flags;
+       struct sci_port *sport = dev_get_drvdata(dev);
 
-       spin_lock_irqsave(&priv->lock, flags);
-       list_for_each_entry(p, &priv->ports, node)
-               uart_resume_port(&sci_uart_driver, &p->port);
-       spin_unlock_irqrestore(&priv->lock, flags);
+       if (sport)
+               uart_resume_port(&sci_uart_driver, &sport->port);
 
        return 0;
 }