Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78be70c8 authored by Jan Kundrát's avatar Jan Kundrát Committed by Greg Kroah-Hartman
Browse files

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: default avatarJan Kundrát <jan.kundrat@cesnet.cz>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 80313586
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -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;