From: Jan Kundrát Date: Tue, 12 Dec 2017 15:17:59 +0000 (+0100) Subject: serial: max310x: Support IRQ sharing with other devices X-Git-Tag: v4.19~1692^2~27 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=78be70c8243ae6bfe8ca642dd19b2b411d4b466f;p=platform%2Fkernel%2Flinux-rpi.git 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 Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 828a2853bd4a..9e4e70f864ea 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -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;