aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/serial/sh-sci.c125
1 files changed, 72 insertions, 53 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 17fa7f17bbe..e9b350c58ba 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