Skip to content
Permalink
Browse files

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>
  • Loading branch information...
Charles E. Youse authored and nashif committed May 2, 2019
1 parent f2af5fe commit 869c5d2e54967a8dde25359708353df8d50ebfae
Showing with 47 additions and 7 deletions.
  1. +38 −7 drivers/serial/uart_ns16550_port_x.h
  2. +9 −0 include/dt-bindings/pcie/pcie.h
@@ -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
@@ -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.

0 comments on commit 869c5d2

Please sign in to comment.
You can’t perform that action at this time.