[PATCH 3/7] serial: max310x: Support IRQ sharing with other devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 drivers/tty/serial/max310x.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

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;
 
-- 
2.14.3


--
To unsubscribe from this list: send the line "unsubscribe linux-serial" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux