diff options
author | Nicolas Ferre <nicolas.ferre@atmel.com> | 2011-10-12 12:06:59 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-10-18 19:42:07 -0400 |
commit | 4cbf9f4864bd4fb2e64d555aacb93c24478e4e8d (patch) | |
tree | 80d85d123ee482dfa2b3881f5a0f3cf755c29416 | |
parent | 588edbf3b8948d94a52da5d6b45c9bb7307d1f01 (diff) |
tty/serial: atmel_serial: auto-enumerate ports
If no platform data provided to enumerate ports, use a bit field
to choose port number and check if port is already initialized.
Use this mechanism for both console and plain serial ports.
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/tty/serial/atmel_serial.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index bb723542ad24..10743297a001 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -157,6 +157,7 @@ struct atmel_uart_port { | |||
157 | }; | 157 | }; |
158 | 158 | ||
159 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; | 159 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; |
160 | static unsigned long atmel_ports_in_use; | ||
160 | 161 | ||
161 | #ifdef SUPPORT_SYSRQ | 162 | #ifdef SUPPORT_SYSRQ |
162 | static struct console atmel_console; | 163 | static struct console atmel_console; |
@@ -1423,7 +1424,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1423 | port->flags = UPF_BOOT_AUTOCONF; | 1424 | port->flags = UPF_BOOT_AUTOCONF; |
1424 | port->ops = &atmel_pops; | 1425 | port->ops = &atmel_pops; |
1425 | port->fifosize = 1; | 1426 | port->fifosize = 1; |
1426 | port->line = pdata->num; | ||
1427 | port->dev = &pdev->dev; | 1427 | port->dev = &pdev->dev; |
1428 | port->mapbase = pdev->resource[0].start; | 1428 | port->mapbase = pdev->resource[0].start; |
1429 | port->irq = pdev->resource[1].start; | 1429 | port->irq = pdev->resource[1].start; |
@@ -1613,10 +1613,15 @@ static struct console atmel_console = { | |||
1613 | static int __init atmel_console_init(void) | 1613 | static int __init atmel_console_init(void) |
1614 | { | 1614 | { |
1615 | if (atmel_default_console_device) { | 1615 | if (atmel_default_console_device) { |
1616 | add_preferred_console(ATMEL_DEVICENAME, | 1616 | int id = atmel_default_console_device->id; |
1617 | atmel_default_console_device->id, NULL); | 1617 | struct atmel_uart_port *port = &atmel_ports[id]; |
1618 | atmel_init_port(&atmel_ports[atmel_default_console_device->id], | 1618 | |
1619 | atmel_default_console_device); | 1619 | set_bit(id, &atmel_ports_in_use); |
1620 | port->backup_imr = 0; | ||
1621 | port->uart.line = id; | ||
1622 | |||
1623 | add_preferred_console(ATMEL_DEVICENAME, id, NULL); | ||
1624 | atmel_init_port(port, atmel_default_console_device); | ||
1620 | register_console(&atmel_console); | 1625 | register_console(&atmel_console); |
1621 | } | 1626 | } |
1622 | 1627 | ||
@@ -1715,12 +1720,33 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) | |||
1715 | struct atmel_uart_port *port; | 1720 | struct atmel_uart_port *port; |
1716 | struct atmel_uart_data *pdata = pdev->dev.platform_data; | 1721 | struct atmel_uart_data *pdata = pdev->dev.platform_data; |
1717 | void *data; | 1722 | void *data; |
1718 | int ret; | 1723 | int ret = -ENODEV; |
1719 | 1724 | ||
1720 | BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); | 1725 | BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); |
1721 | 1726 | ||
1722 | port = &atmel_ports[pdata->num]; | 1727 | if (pdata) |
1728 | ret = pdata->num; | ||
1729 | |||
1730 | if (ret < 0) | ||
1731 | /* port id not found in platform data: | ||
1732 | * auto-enumerate it */ | ||
1733 | ret = find_first_zero_bit(&atmel_ports_in_use, | ||
1734 | sizeof(atmel_ports_in_use)); | ||
1735 | |||
1736 | if (ret > ATMEL_MAX_UART) { | ||
1737 | ret = -ENODEV; | ||
1738 | goto err; | ||
1739 | } | ||
1740 | |||
1741 | if (test_and_set_bit(ret, &atmel_ports_in_use)) { | ||
1742 | /* port already in use */ | ||
1743 | ret = -EBUSY; | ||
1744 | goto err; | ||
1745 | } | ||
1746 | |||
1747 | port = &atmel_ports[ret]; | ||
1723 | port->backup_imr = 0; | 1748 | port->backup_imr = 0; |
1749 | port->uart.line = ret; | ||
1724 | 1750 | ||
1725 | atmel_init_port(port, pdev); | 1751 | atmel_init_port(port, pdev); |
1726 | 1752 | ||
@@ -1766,7 +1792,7 @@ err_alloc_ring: | |||
1766 | clk_put(port->clk); | 1792 | clk_put(port->clk); |
1767 | port->clk = NULL; | 1793 | port->clk = NULL; |
1768 | } | 1794 | } |
1769 | 1795 | err: | |
1770 | return ret; | 1796 | return ret; |
1771 | } | 1797 | } |
1772 | 1798 | ||
@@ -1786,6 +1812,8 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) | |||
1786 | 1812 | ||
1787 | /* "port" is allocated statically, so we shouldn't free it */ | 1813 | /* "port" is allocated statically, so we shouldn't free it */ |
1788 | 1814 | ||
1815 | clear_bit(port->line, &atmel_ports_in_use); | ||
1816 | |||
1789 | clk_put(atmel_port->clk); | 1817 | clk_put(atmel_port->clk); |
1790 | 1818 | ||
1791 | return ret; | 1819 | return ret; |