summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Shiyan <shc_work@mail.ru>2016-06-07 18:59:27 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-06-25 23:55:35 +0300
commit78adccac1ff9f485ccf427f337982799ce68738e (patch)
treeefe6ffe3adeb7bf8590e50851752082fde5a96fc
parentc8246fefe2c995e128345614fb98b5ed5014318b (diff)
downloadlinux-78adccac1ff9f485ccf427f337982799ce68738e.tar.xz
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>
-rw-r--r--drivers/tty/serial/max310x.c41
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;