sh-sci: allow single port platform devices
Magnus Damm [Wed, 21 Jan 2009 15:13:50 +0000 (15:13 +0000)]
Allow registration of single port sh-sci platform devices.

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

drivers/serial/sh-sci.c

index 17fa7f1..e9b350c 100644 (file)
@@ -1221,6 +1221,70 @@ static int __devexit sci_remove(struct platform_device *dev)
        return 0;
 }
 
+static int __devinit sci_probe_single(struct platform_device *dev,
+                                     unsigned int index,
+                                     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 */
+       if (unlikely(index >= SCI_NPORTS)) {
+               dev_notice(&dev->dev, "Attempting to register port "
+                          "%d when only %d are available.\n",
+                          index+1, SCI_NPORTS);
+               dev_notice(&dev->dev, "Consider bumping "
+                          "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
+               return 0;
+       }
+
+       sciport->port.mapbase   = p->mapbase;
+
+       if (p->mapbase && !p->membase) {
+               if (p->flags & UPF_IOREMAP) {
+                       p->membase = ioremap_nocache(p->mapbase, 0x40);
+                       if (IS_ERR(p->membase))
+                               return PTR_ERR(p->membase);
+               } else {
+                       /*
+                        * For the simple (and majority of) cases
+                        * where we don't need to do any remapping,
+                        * just cast the cookie directly.
+                        */
+                       p->membase = (void __iomem *)p->mapbase;
+               }
+       }
+
+       sciport->port.membase   = p->membase;
+
+       sciport->port.irq       = p->irqs[SCIx_TXI_IRQ];
+       sciport->port.flags     = p->flags;
+       sciport->port.dev       = &dev->dev;
+
+       sciport->type           = sciport->port.type = p->type;
+
+       memcpy(&sciport->irqs, &p->irqs, sizeof(p->irqs));
+
+       ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
+
+       if (ret) {
+               if (p->flags & UPF_IOREMAP)
+                       iounmap(p->membase);
+
+               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;
+}
+
 /*
  * Register a set of serial devices attached to a platform device.  The
  * list is terminated with a zero flags entry, which means we expect
@@ -1232,7 +1296,6 @@ 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;
-       unsigned long flags;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -1247,60 +1310,16 @@ static int __devinit sci_probe(struct platform_device *dev)
        cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
 #endif
 
-       for (i = 0; p && p->flags != 0; p++, i++) {
-               struct sci_port *sciport = &sci_ports[i];
-
-               /* Sanity check */
-               if (unlikely(i == SCI_NPORTS)) {
-                       dev_notice(&dev->dev, "Attempting to register port "
-                                  "%d when only %d are available.\n",
-                                  i+1, SCI_NPORTS);
-                       dev_notice(&dev->dev, "Consider bumping "
-                                  "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n");
-                       break;
-               }
-
-               sciport->port.mapbase   = p->mapbase;
-
-               if (p->mapbase && !p->membase) {
-                       if (p->flags & UPF_IOREMAP) {
-                               p->membase = ioremap_nocache(p->mapbase, 0x40);
-                               if (IS_ERR(p->membase)) {
-                                       ret = PTR_ERR(p->membase);
-                                       goto err_unreg;
-                               }
-                       } else {
-                               /*
-                                * For the simple (and majority of) cases
-                                * where we don't need to do any remapping,
-                                * just cast the cookie directly.
-                                */
-                               p->membase = (void __iomem *)p->mapbase;
-                       }
-               }
-
-               sciport->port.membase   = p->membase;
-
-               sciport->port.irq       = p->irqs[SCIx_TXI_IRQ];
-               sciport->port.flags     = p->flags;
-               sciport->port.dev       = &dev->dev;
-
-               sciport->type           = sciport->port.type = p->type;
-
-               memcpy(&sciport->irqs, &p->irqs, sizeof(p->irqs));
-
-               ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
-
-               if (ret && (p->flags & UPF_IOREMAP)) {
-                       iounmap(p->membase);
+       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;
                }
-
-               INIT_LIST_HEAD(&sciport->node);
-
-               spin_lock_irqsave(&priv->lock, flags);
-               list_add(&sciport->node, &priv->ports);
-               spin_unlock_irqrestore(&priv->lock, flags);
        }
 
 #ifdef CONFIG_SH_STANDARD_BIOS