diff options
author | Alexander Shiyan <shc_work@mail.ru> | 2016-06-07 18:59:27 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-06-25 13:55:35 -0700 |
commit | 78adccac1ff9f485ccf427f337982799ce68738e (patch) | |
tree | efe6ffe3adeb7bf8590e50851752082fde5a96fc /drivers/tty | |
parent | c8246fefe2c995e128345614fb98b5ed5014318b (diff) |
serial: max310x: Assign port line automatically
This patch makes assignment of port line automatically,
so now user allow to use several MAX310X chips.
Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/serial/max310x.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 347f6e8dae39..9360801df3c4 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -32,7 +32,7 @@ #define MAX310X_NAME "max310x" #define MAX310X_MAJOR 204 #define MAX310X_MINOR 209 -#define MAX310X_UART_NR 4 +#define MAX310X_UART_NRMAX 16 /* MAX310X register definitions */ #define MAX310X_RHR_REG (0x00) /* RX FIFO */ @@ -279,9 +279,11 @@ static struct uart_driver max310x_uart = { .dev_name = "ttyMAX", .major = MAX310X_MAJOR, .minor = MAX310X_MINOR, - .nr = MAX310X_UART_NR, + .nr = MAX310X_UART_NRMAX, }; +static DECLARE_BITMAP(max310x_lines, MAX310X_UART_NRMAX); + static u8 max310x_port_read(struct uart_port *port, u8 reg) { struct max310x_port *s = dev_get_drvdata(port->dev); @@ -600,9 +602,7 @@ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen) unsigned int sts, ch, flag; if (unlikely(rxlen >= port->fifosize)) { - dev_warn_ratelimited(port->dev, - "Port %i: Possible RX FIFO overrun\n", - port->line); + dev_warn_ratelimited(port->dev, "Possible RX FIFO overrun\n"); port->icount.buf_overrun++; /* Ensure sanity of RX level */ rxlen = port->fifosize; @@ -1193,8 +1193,16 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, mutex_init(&s->mutex); for (i = 0; i < devtype->nr; i++) { + unsigned int line; + + line = find_first_zero_bit(max310x_lines, MAX310X_UART_NRMAX); + if (line == MAX310X_UART_NRMAX) { + ret = -ERANGE; + goto out_uart; + } + /* Initialize port data */ - s->p[i].port.line = i; + s->p[i].port.line = line; s->p[i].port.dev = dev; s->p[i].port.irq = irq; s->p[i].port.type = PORT_MAX310X; @@ -1220,8 +1228,15 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, INIT_WORK(&s->p[i].md_work, max310x_md_proc); /* Initialize queue for changing RS485 mode */ INIT_WORK(&s->p[i].rs_work, max310x_rs_proc); + /* Register port */ - uart_add_one_port(&max310x_uart, &s->p[i].port); + ret = uart_add_one_port(&max310x_uart, &s->p[i].port); + if (ret) { + s->p[i].port.dev = NULL; + goto out_uart; + } + set_bit(line, max310x_lines); + /* Go to suspend mode */ devtype->power(&s->p[i].port, 0); } @@ -1234,8 +1249,13 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, dev_err(dev, "Unable to reguest IRQ %i\n", irq); - for (i = 0; i < devtype->nr; i++) - uart_remove_one_port(&max310x_uart, &s->p[i].port); +out_uart: + for (i = 0; i < devtype->nr; i++) { + if (s->p[i].port.dev) { + uart_remove_one_port(&max310x_uart, &s->p[i].port); + clear_bit(s->p[i].port.line, max310x_lines); + } + } mutex_destroy(&s->mutex); @@ -1255,6 +1275,7 @@ static int max310x_remove(struct device *dev) cancel_work_sync(&s->p[i].md_work); cancel_work_sync(&s->p[i].rs_work); uart_remove_one_port(&max310x_uart, &s->p[i].port); + clear_bit(s->p[i].port.line, max310x_lines); s->devtype->power(&s->p[i].port, 0); } @@ -1347,6 +1368,8 @@ static int __init max310x_uart_init(void) { int ret; + bitmap_zero(max310x_lines, MAX310X_UART_NRMAX); + ret = uart_register_driver(&max310x_uart); if (ret) return ret; |