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:
parent
f2af5fe731
commit
869c5d2e54
2 changed files with 47 additions and 7 deletions
|
@ -50,20 +50,51 @@ static void irq_config_func_@NUM@(struct device *dev)
|
||||||
{
|
{
|
||||||
ARG_UNUSED(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,
|
IRQ_CONNECT(DT_UART_NS16550_PORT_@NUM@_IRQ,
|
||||||
DT_UART_NS16550_PORT_@NUM@_IRQ_PRI,
|
DT_UART_NS16550_PORT_@NUM@_IRQ_PRI,
|
||||||
uart_ns16550_isr, DEVICE_GET(uart_ns16550_@NUM@),
|
uart_ns16550_isr, DEVICE_GET(uart_ns16550_@NUM@),
|
||||||
DT_UART_NS16550_PORT_@NUM@_IRQ_FLAGS);
|
DT_UART_NS16550_PORT_@NUM@_IRQ_FLAGS);
|
||||||
|
|
||||||
#ifdef UART_NS16550_PCIE_ENABLED
|
pcie_irq_enable(DT_UART_NS16550_PORT_@NUM@_BASE_ADDR,
|
||||||
if (DEV_CFG(dev)->pcie) {
|
DT_UART_NS16550_PORT_@NUM@_IRQ);
|
||||||
pcie_irq_enable(DT_UART_NS16550_PORT_@NUM@_BASE_ADDR,
|
|
||||||
DT_UART_NS16550_PORT_@NUM@_IRQ);
|
#endif
|
||||||
} else {
|
|
||||||
irq_enable(DT_UART_NS16550_PORT_@NUM@_IRQ);
|
|
||||||
}
|
|
||||||
#else
|
#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);
|
irq_enable(DT_UART_NS16550_PORT_@NUM@_IRQ);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,6 +7,15 @@
|
||||||
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PCIE_PCIE_H_
|
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PCIE_PCIE_H_
|
||||||
#define 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
|
* 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.
|
* coincidentally, this is same representation used in PCI configuration space.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue