Commit b0819465 authored by Bing Fan's avatar Bing Fan Committed by Greg Kroah-Hartman
Browse files

arm pl011 serial: support multi-irq request



In order to make pl011 work better, multiple interrupts are
required, such as TXIM, RXIM, RTIM, error interrupt(FE/PE/BE/OE);
at the same time, pl011 to GIC does not merge the interrupt
lines(each serial-interrupt corresponding to different GIC hardware
interrupt), so need to enable and request multiple gic interrupt
numbers in the driver.

Signed-off-by: default avatarBing Fan <tombinfan@tencent.com>
Link: https://lore.kernel.org/r/1625103512-30182-1-git-send-email-hptsfb@gmail.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8d479237
Loading
Loading
Loading
Loading
+31 −3
Original line number Diff line number Diff line
@@ -1777,11 +1777,39 @@ static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
	}
}

static void pl011_release_irq(struct uart_amba_port *uap, unsigned int max_cnt)
{
	struct amba_device *amba_dev = container_of(uap->port.dev, struct amba_device, dev);
	int i;

	for (i = 0; i < max_cnt; i++)
		if (amba_dev->irq[i])
			free_irq(amba_dev->irq[i], uap);
}

static int pl011_allocate_irq(struct uart_amba_port *uap)
{
	int ret = 0;
	int i;
	unsigned int virq;
	struct amba_device *amba_dev = container_of(uap->port.dev, struct amba_device, dev);

	pl011_write(uap->im, uap, REG_IMSC);

	return request_irq(uap->port.irq, pl011_int, IRQF_SHARED, "uart-pl011", uap);
	for (i = 0; i < AMBA_NR_IRQS; i++) {
		virq = amba_dev->irq[i];
		if (virq == 0)
			break;

		ret = request_irq(virq, pl011_int, IRQF_SHARED, dev_name(&amba_dev->dev), uap);
		if (ret) {
			dev_err(uap->port.dev, "request %u interrupt failed\n", virq);
			pl011_release_irq(uap, i - 1);
			break;
		}
	}

	return ret;
}

/*
@@ -1953,7 +1981,7 @@ static void pl011_shutdown(struct uart_port *port)
	if ((port->rs485.flags & SER_RS485_ENABLED) && uap->rs485_tx_started)
		pl011_rs485_tx_stop(uap);

	free_irq(uap->port.irq, uap);
	pl011_release_irq(uap, AMBA_NR_IRQS);

	pl011_disable_uart(uap);

@@ -1983,7 +2011,7 @@ static void sbsa_uart_shutdown(struct uart_port *port)

	pl011_disable_interrupts(uap);

	free_irq(uap->port.irq, uap);
	pl011_release_irq(uap, AMBA_NR_IRQS);

	if (uap->port.ops->flush_buffer)
		uap->port.ops->flush_buffer(port);