aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/serial/uartlite.c99
1 files changed, 65 insertions, 34 deletions
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c
index 10e0da97811e..c00a627ef89e 100644
--- a/drivers/serial/uartlite.c
+++ b/drivers/serial/uartlite.c
@@ -413,59 +413,90 @@ static struct uart_driver ulite_uart_driver = {
413#endif 413#endif
414}; 414};
415 415
416static int __devinit ulite_probe(struct platform_device *pdev) 416static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
417{ 417{
418 struct resource *res, *res2;
419 struct uart_port *port; 418 struct uart_port *port;
419 int rc;
420 420
421 if (pdev->id < 0 || pdev->id >= ULITE_NR_UARTS) 421 /* if id = -1; then scan for a free id and use that */
422 if (id < 0) {
423 for (id = 0; id < ULITE_NR_UARTS; id++)
424 if (ulite_ports[id].mapbase == 0)
425 break;
426 }
427 if (id < 0 || id >= ULITE_NR_UARTS) {
428 dev_err(dev, "%s%i too large\n", ULITE_NAME, id);
422 return -EINVAL; 429 return -EINVAL;
430 }
423 431
424 if (ulite_ports[pdev->id].membase) 432 if (ulite_ports[id].mapbase) {
433 dev_err(dev, "cannot assign to %s%i; it is already in use\n",
434 ULITE_NAME, id);
425 return -EBUSY; 435 return -EBUSY;
436 }
426 437
427 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 438 port = &ulite_ports[id];
428 if (!res)
429 return -ENODEV;
430 439
431 res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 440 spin_lock_init(&port->lock);
432 if (!res2) 441 port->fifosize = 16;
433 return -ENODEV; 442 port->regshift = 2;
443 port->iotype = UPIO_MEM;
444 port->iobase = 1; /* mark port in use */
445 port->mapbase = base;
446 port->membase = NULL;
447 port->ops = &ulite_ops;
448 port->irq = irq;
449 port->flags = UPF_BOOT_AUTOCONF;
450 port->dev = dev;
451 port->type = PORT_UNKNOWN;
452 port->line = id;
453
454 dev_set_drvdata(dev, port);
455
456 /* Register the port */
457 rc = uart_add_one_port(&ulite_uart_driver, port);
458 if (rc) {
459 dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc);
460 port->mapbase = 0;
461 dev_set_drvdata(dev, NULL);
462 return rc;
463 }
434 464
435 port = &ulite_ports[pdev->id]; 465 return 0;
466}
436 467
437 port->fifosize = 16; 468static int __devinit ulite_release(struct device *dev)
438 port->regshift = 2; 469{
439 port->iotype = UPIO_MEM; 470 struct uart_port *port = dev_get_drvdata(dev);
440 port->iobase = 1; /* mark port in use */ 471 int rc = 0;
441 port->mapbase = res->start;
442 port->membase = NULL;
443 port->ops = &ulite_ops;
444 port->irq = res2->start;
445 port->flags = UPF_BOOT_AUTOCONF;
446 port->dev = &pdev->dev;
447 port->type = PORT_UNKNOWN;
448 port->line = pdev->id;
449 472
450 uart_add_one_port(&ulite_uart_driver, port); 473 if (port) {
451 platform_set_drvdata(pdev, port); 474 rc = uart_remove_one_port(&ulite_uart_driver, port);
475 dev_set_drvdata(dev, NULL);
476 port->mapbase = 0;
477 }
452 478
453 return 0; 479 return rc;
454} 480}
455 481
456static int ulite_remove(struct platform_device *pdev) 482static int __devinit ulite_probe(struct platform_device *pdev)
457{ 483{
458 struct uart_port *port = platform_get_drvdata(pdev); 484 struct resource *res, *res2;
459 485
460 platform_set_drvdata(pdev, NULL); 486 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
487 if (!res)
488 return -ENODEV;
461 489
462 if (port) 490 res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
463 uart_remove_one_port(&ulite_uart_driver, port); 491 if (!res2)
492 return -ENODEV;
464 493
465 /* mark port as free */ 494 return ulite_assign(&pdev->dev, pdev->id, res->start, res2->start);
466 port->membase = NULL; 495}
467 496
468 return 0; 497static int ulite_remove(struct platform_device *pdev)
498{
499 return ulite_release(&pdev->dev);
469} 500}
470 501
471static struct platform_driver ulite_platform_driver = { 502static struct platform_driver ulite_platform_driver = {