drivers/uart_ns16550: enable auto IRQ detection for PCI(e) endpoints

If a UART is configured with IRQ == PCIE_IRQ_DETECT, then use the
pcie_wired_irq() to determine the IRQ at runtime, and install the
handler using the dynamic interrupt mechanism.

Signed-off-by: Charles E. Youse <charles.youse@intel.com>
This commit is contained in:
Charles E. Youse 2019-05-02 14:22:00 -07:00 committed by Anas Nashif
commit 869c5d2e54
2 changed files with 47 additions and 7 deletions

View file

@ -50,20 +50,51 @@ static void irq_config_func_@NUM@(struct device *dev)
{
ARG_UNUSED(dev);
#if DT_UART_NS16550_PORT_@NUM@_PCIE
#if DT_UART_NS16550_PORT_@NUM@_IRQ == PCIE_IRQ_DETECT
/* PCI(e) with auto IRQ detection */
BUILD_ASSERT_MSG(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS),
"NS16550 PCI auto-IRQ needs CONFIG_DYNAMIC_INTERRUPTS");
unsigned int irq;
irq = pcie_wired_irq(DT_UART_NS16550_PORT_@NUM@_BASE_ADDR);
if (irq == PCIE_CONF_INTR_IRQ_NONE) return;
irq_connect_dynamic(irq,
DT_UART_NS16550_PORT_@NUM@_IRQ_PRI,
uart_ns16550_isr,
DEVICE_GET(uart_ns16550_@NUM@),
DT_UART_NS16550_PORT_@NUM@_IRQ_FLAGS);
pcie_irq_enable(DT_UART_NS16550_PORT_@NUM@_BASE_ADDR, irq);
#else
/* PCI(e) with fixed or MSI IRQ */
IRQ_CONNECT(DT_UART_NS16550_PORT_@NUM@_IRQ,
DT_UART_NS16550_PORT_@NUM@_IRQ_PRI,
uart_ns16550_isr, DEVICE_GET(uart_ns16550_@NUM@),
DT_UART_NS16550_PORT_@NUM@_IRQ_FLAGS);
#ifdef UART_NS16550_PCIE_ENABLED
if (DEV_CFG(dev)->pcie) {
pcie_irq_enable(DT_UART_NS16550_PORT_@NUM@_BASE_ADDR,
DT_UART_NS16550_PORT_@NUM@_IRQ);
} else {
irq_enable(DT_UART_NS16550_PORT_@NUM@_IRQ);
}
pcie_irq_enable(DT_UART_NS16550_PORT_@NUM@_BASE_ADDR,
DT_UART_NS16550_PORT_@NUM@_IRQ);
#endif
#else
/* not PCI(e) */
IRQ_CONNECT(DT_UART_NS16550_PORT_@NUM@_IRQ,
DT_UART_NS16550_PORT_@NUM@_IRQ_PRI,
uart_ns16550_isr, DEVICE_GET(uart_ns16550_@NUM@),
DT_UART_NS16550_PORT_@NUM@_IRQ_FLAGS);
irq_enable(DT_UART_NS16550_PORT_@NUM@_IRQ);
#endif
}
#endif

View file

@ -7,6 +7,15 @@
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PCIE_PCIE_H_
#define ZEPHYR_INCLUDE_DT_BINDINGS_PCIE_PCIE_H_
/*
* Set the device's IRQ (in devicetree, or whatever) to PCIE_IRQ_DETECT
* if the device doesn't support MSI and we don't/can't know the wired IRQ
* allocated by the firmware ahead of time. Use of this functionality will
* generally also require CONFIG_DYNAMIC_INTERRUPTS.
*/
#define PCIE_IRQ_DETECT 0xFFFFFFFU
/*
* We represent a PCI device ID as [31:16] device ID, [15:0] vendor ID. Not
* coincidentally, this is same representation used in PCI configuration space.