diff options
-rw-r--r-- | drivers/serial/sh-sci.c | 125 |
1 files changed, 72 insertions, 53 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 17fa7f17bbe3..e9b350c58ba8 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -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 |