mirror of https://gitee.com/openkylin/linux.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 <jan.kundrat@cesnet.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8031358635
commit
78be70c824
|
@ -685,9 +685,10 @@ static void max310x_handle_tx(struct uart_port *port)
|
||||||
uart_write_wakeup(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;
|
struct uart_port *port = &s->p[portno].port;
|
||||||
|
irqreturn_t res = IRQ_NONE;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
unsigned int ists, lsr, rxlen;
|
unsigned int ists, lsr, rxlen;
|
||||||
|
@ -698,6 +699,8 @@ static void max310x_port_irq(struct max310x_port *s, int portno)
|
||||||
if (!ists && !rxlen)
|
if (!ists && !rxlen)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
res = IRQ_HANDLED;
|
||||||
|
|
||||||
if (ists & MAX310X_IRQ_CTS_BIT) {
|
if (ists & MAX310X_IRQ_CTS_BIT) {
|
||||||
lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
lsr = max310x_port_read(port, MAX310X_LSR_IRQSTS_REG);
|
||||||
uart_handle_cts_change(port,
|
uart_handle_cts_change(port,
|
||||||
|
@ -711,11 +714,13 @@ static void max310x_port_irq(struct max310x_port *s, int portno)
|
||||||
mutex_unlock(&s->mutex);
|
mutex_unlock(&s->mutex);
|
||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t max310x_ist(int irq, void *dev_id)
|
static irqreturn_t max310x_ist(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct max310x_port *s = (struct max310x_port *)dev_id;
|
struct max310x_port *s = (struct max310x_port *)dev_id;
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
if (s->devtype->nr > 1) {
|
if (s->devtype->nr > 1) {
|
||||||
do {
|
do {
|
||||||
|
@ -726,12 +731,15 @@ static irqreturn_t max310x_ist(int irq, void *dev_id)
|
||||||
val = ((1 << s->devtype->nr) - 1) & ~val;
|
val = ((1 << s->devtype->nr) - 1) & ~val;
|
||||||
if (!val)
|
if (!val)
|
||||||
break;
|
break;
|
||||||
max310x_port_irq(s, fls(val) - 1);
|
if (max310x_port_irq(s, fls(val) - 1) == IRQ_HANDLED)
|
||||||
|
handled = true;
|
||||||
} while (1);
|
} while (1);
|
||||||
} else
|
} else {
|
||||||
max310x_port_irq(s, 0);
|
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)
|
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 */
|
/* Setup interrupt */
|
||||||
ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
|
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)
|
if (!ret)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue