| From dfd1cc0d1f8680ba3c405fb479f4e65aba2c679c Mon Sep 17 00:00:00 2001 |
| From: Geert Uytterhoeven <geert+renesas@glider.be> |
| Date: Mon, 5 Mar 2018 18:17:40 +0100 |
| Subject: [PATCH 1262/1795] serial: sh-sci: Add support for dynamic instances |
| |
| On DT platforms, the sh-sci driver requires the presence of "serialN" |
| aliases in DT, from which instance IDs are derived. If a DT alias is |
| missing, the drivers fails to probe the corresponding serial port. |
| |
| This becomes cumbersome when considering DT overlays, as currently |
| there is no upstream support for dynamically updating the /aliases node |
| in DT. Furthermore, even in the presence of such support, hardcoded |
| instance IDs in independent overlays are prone to conflicts. |
| |
| Hence add support for dynamic instance IDs, to be used in the absence of |
| a DT alias. This makes serial ports behave similar to I2C and SPI |
| buses, which already support dynamic instances. |
| |
| Ports in use are tracked using a simple bitmask of type unsigned long, |
| which is sufficient to handle all current hardware (max. 18 ports). |
| The maximum number of serial ports is still fixed, and configurable |
| through Kconfig. Range validation is done through both Kconfig and a |
| compile-time check. |
| |
| Due to the fixed maximum number of serial ports, dynamic and static |
| instances share the same ID space. Static instances added later are |
| rejected when conflicting with dynamic instances registered earlier. |
| |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| (cherry picked from commit 7678f4c20fa7670fcc23e2537a26543c5c6a7772) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> |
| --- |
| drivers/tty/serial/Kconfig | 2 ++ |
| drivers/tty/serial/sh-sci.c | 8 ++++++++ |
| 2 files changed, 10 insertions(+) |
| |
| diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig |
| index 3682fd3e960c..76005dc5f624 100644 |
| --- a/drivers/tty/serial/Kconfig |
| +++ b/drivers/tty/serial/Kconfig |
| @@ -762,6 +762,8 @@ config SERIAL_SH_SCI |
| |
| config SERIAL_SH_SCI_NR_UARTS |
| int "Maximum number of SCI(F) serial ports" if EXPERT |
| + range 1 64 if 64BIT |
| + range 1 32 if !64BIT |
| depends on SERIAL_SH_SCI |
| default "3" if H8300 |
| default "10" if SUPERH |
| diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c |
| index 2051a5309851..59fac9761e9c 100644 |
| --- a/drivers/tty/serial/sh-sci.c |
| +++ b/drivers/tty/serial/sh-sci.c |
| @@ -160,6 +160,7 @@ struct sci_port { |
| #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS |
| |
| static struct sci_port sci_ports[SCI_NPORTS]; |
| +static unsigned long sci_ports_in_use; |
| static struct uart_driver sci_uart_driver; |
| |
| static inline struct sci_port * |
| @@ -3024,6 +3025,7 @@ static int sci_remove(struct platform_device *dev) |
| { |
| struct sci_port *port = platform_get_drvdata(dev); |
| |
| + sci_ports_in_use &= ~BIT(port->port.line); |
| uart_remove_one_port(&sci_uart_driver, &port->port); |
| |
| sci_cleanup_single(port); |
| @@ -3105,6 +3107,8 @@ static struct plat_sci_port *sci_parse_dt(struct platform_device *pdev, |
| |
| /* Get the line number from the aliases node. */ |
| id = of_alias_get_id(np, "serial"); |
| + if (id < 0 && ~sci_ports_in_use) |
| + id = ffz(sci_ports_in_use); |
| if (id < 0) { |
| dev_err(&pdev->dev, "failed to get alias id (%d)\n", id); |
| return NULL; |
| @@ -3139,6 +3143,9 @@ static int sci_probe_single(struct platform_device *dev, |
| dev_notice(&dev->dev, "Consider bumping CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); |
| return -EINVAL; |
| } |
| + BUILD_BUG_ON(SCI_NPORTS > sizeof(sci_ports_in_use) * 8); |
| + if (sci_ports_in_use & BIT(index)) |
| + return -EBUSY; |
| |
| mutex_lock(&sci_uart_registration_lock); |
| if (!sci_uart_driver.state) { |
| @@ -3237,6 +3244,7 @@ static int sci_probe(struct platform_device *dev) |
| sh_bios_gdb_detach(); |
| #endif |
| |
| + sci_ports_in_use |= BIT(dev_id); |
| return 0; |
| } |
| |
| -- |
| 2.19.0 |
| |