serial: max310x: Support IRQ sharing with other devices

According to my chip's datasheet [1], the IRQ output is an open
collector pin which is suitable for sharing with other chips. The chip
also has a register which indicates which UART performed a change and
the driver checks that register already, so we have everything what is
needed to effectively share the IRQ GPIO.

[1] https://datasheets.maximintegrated.com/en/ds/MAX14830.pdf

Signed-off-by: Jan Kundrát <jan.kundrat@cesnet.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Jan Kundrát 2017-12-12 16:17:59 +01:00 committed by Greg Kroah-Hartman
parent 8031358635
commit 78be70c824
1 changed files with 14 additions and 6 deletions

View File

@ -685,9 +685,10 @@ static void max310x_handle_tx(struct uart_port *port)
uart_write_wakeup(port);
}
static void max310x_port_irq(struct max310x_port *s, int portno)
static irqreturn_t max310x_port_irq(struct max310x_port *s, int portno)
{
struct uart_port *port = &s->p[portno].port;
irqreturn_t res = IRQ_NONE;
do {
unsigned int ists, lsr, rxlen;
@ -698,6 +699,8 @@ static void max310x_port_irq(struct max310x_port *s, int portno)
if (!ists && !rxlen)
break;
res = IRQ_HANDLED;
if (ists & MAX310X_IRQ_CTS_BIT) {
lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
uart_handle_cts_change(port,
@ -711,11 +714,13 @@ static void max310x_port_irq(struct max310x_port *s, int portno)
mutex_unlock(&s->mutex);
}
} while (1);
return res;
}
static irqreturn_t max310x_ist(int irq, void *dev_id)
{
struct max310x_port *s = (struct max310x_port *)dev_id;
bool handled = false;
if (s->devtype->nr > 1) {
do {
@ -726,12 +731,15 @@ static irqreturn_t max310x_ist(int irq, void *dev_id)
val = ((1 << s->devtype->nr) - 1) & ~val;
if (!val)
break;
max310x_port_irq(s, fls(val) - 1);
if (max310x_port_irq(s, fls(val) - 1) == IRQ_HANDLED)
handled = true;
} while (1);
} else
max310x_port_irq(s, 0);
} else {
if (max310x_port_irq(s, 0) == IRQ_HANDLED)
handled = true;
}
return IRQ_HANDLED;
return IRQ_RETVAL(handled);
}
static void max310x_wq_proc(struct work_struct *ws)
@ -1239,7 +1247,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
/* Setup interrupt */
ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
IRQF_ONESHOT, dev_name(dev), s);
IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), s);
if (!ret)
return 0;