diff --git a/arch/x86/core/early_serial.c b/arch/x86/core/early_serial.c index 027c88c1a61..0c102300a51 100644 --- a/arch/x86/core/early_serial.c +++ b/arch/x86/core/early_serial.c @@ -88,7 +88,7 @@ void z_x86_early_serial_init(void) { #if defined(DEVICE_MMIO_IS_IN_RAM) && !defined(CONFIG_UART_NS16550_ACCESS_IOPORT) #ifdef X86_SOC_EARLY_SERIAL_PCIDEV - struct pcie_mbar mbar; + struct pcie_bar mbar; pcie_get_mbar(X86_SOC_EARLY_SERIAL_PCIDEV, 0, &mbar); pcie_set_cmd(X86_SOC_EARLY_SERIAL_PCIDEV, PCIE_CONF_CMDSTAT_MEM, true); device_map(&mmio, mbar.phys_addr, mbar.size, K_MEM_CACHE_NONE); diff --git a/doc/kernel/drivers/index.rst b/doc/kernel/drivers/index.rst index ebade5ca5a3..fe8c64d9534 100644 --- a/doc/kernel/drivers/index.rst +++ b/doc/kernel/drivers/index.rst @@ -606,7 +606,7 @@ may be used directly: void some_init_code(...) { ... - struct pcie_mbar mbar; + struct pcie_bar mbar; bool bar_found = pcie_get_mbar(bdf, index, &mbar); device_map(DEVICE_MMIO_RAM_PTR(dev), mbar.phys_addr, mbar.size, K_MEM_CACHE_NONE); diff --git a/drivers/ethernet/eth_e1000.c b/drivers/ethernet/eth_e1000.c index 8cfb4ea39b6..83036ab37b9 100644 --- a/drivers/ethernet/eth_e1000.c +++ b/drivers/ethernet/eth_e1000.c @@ -238,7 +238,7 @@ int e1000_probe(const struct device *ddev) const pcie_bdf_t bdf = PCIE_BDF(0, 3, 0); struct e1000_dev *dev = ddev->data; uint32_t ral, rah; - struct pcie_mbar mbar; + struct pcie_bar mbar; if (!pcie_probe(bdf, PCIE_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_I82540EM))) { diff --git a/drivers/i2c/i2c_dw.c b/drivers/i2c/i2c_dw.c index 7a6cfbceb7c..95982e84a45 100644 --- a/drivers/i2c/i2c_dw.c +++ b/drivers/i2c/i2c_dw.c @@ -849,7 +849,7 @@ static int i2c_dw_initialize(const struct device *dev) #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) if (rom->pcie) { - struct pcie_mbar mbar; + struct pcie_bar mbar; if (!pcie_probe(rom->pcie_bdf, rom->pcie_id)) { return -EINVAL; diff --git a/drivers/pcie/host/msi.c b/drivers/pcie/host/msi.c index ddb35296ee9..d948a216554 100644 --- a/drivers/pcie/host/msi.c +++ b/drivers/pcie/host/msi.c @@ -84,7 +84,7 @@ static bool map_msix_table_entries(pcie_bdf_t bdf, { uint32_t table_offset; uint8_t table_bir; - struct pcie_mbar bar; + struct pcie_bar bar; uintptr_t mapped_table; int i; diff --git a/drivers/pcie/host/pcie.c b/drivers/pcie/host/pcie.c index 68855b35b52..91d06a40a83 100644 --- a/drivers/pcie/host/pcie.c +++ b/drivers/pcie/host/pcie.c @@ -103,9 +103,19 @@ uint32_t pcie_get_ext_cap(pcie_bdf_t bdf, uint32_t cap_id) return reg; } -bool pcie_get_mbar(pcie_bdf_t bdf, - unsigned int bar_index, - struct pcie_mbar *mbar) +/** + * @brief Get the BAR at a specific BAR index + * + * @param bdf the PCI(e) endpoint + * @param bar_index 0-based BAR index + * @param bar Pointer to struct pcie_bar + * @param io true for I/O BARs, false otherwise + * @return true if the BAR was found and is valid, false otherwise + */ +static bool pcie_get_bar(pcie_bdf_t bdf, + unsigned int bar_index, + struct pcie_bar *bar, + bool io) { uint32_t reg = bar_index + PCIE_CONF_BAR0; #ifdef CONFIG_PCIE_CONTROLLER @@ -128,8 +138,7 @@ bool pcie_get_mbar(pcie_bdf_t bdf, phys_addr = pcie_conf_read(bdf, reg); #ifndef CONFIG_PCIE_CONTROLLER - if (PCIE_CONF_BAR_IO(phys_addr)) { - /* Discard I/O bars */ + if ((PCIE_CONF_BAR_MEM(phys_addr) && io) || (PCIE_CONF_BAR_IO(phys_addr) && !io)) { return false; } #endif @@ -183,20 +192,36 @@ bool pcie_get_mbar(pcie_bdf_t bdf, PCIE_CONF_BAR_MEM(phys_addr) ? PCIE_CONF_BAR_ADDR(phys_addr) : PCIE_CONF_BAR_IO_ADDR(phys_addr), - &mbar->phys_addr)) { + &bar->phys_addr)) { return false; } #else - mbar->phys_addr = PCIE_CONF_BAR_ADDR(phys_addr); + bar->phys_addr = PCIE_CONF_BAR_ADDR(phys_addr); #endif /* CONFIG_PCIE_CONTROLLER */ - mbar->size = size & ~(size-1); + bar->size = size & ~(size-1); return true; } -bool pcie_probe_mbar(pcie_bdf_t bdf, - unsigned int index, - struct pcie_mbar *mbar) +/** + * @brief Probe the nth BAR assigned to an endpoint. + * + * A PCI(e) endpoint has 0 or more BARs. This function + * allows the caller to enumerate them by calling with index=0..n. + * Value of n has to be below 6, as there is a maximum of 6 BARs. The indices + * are order-preserving with respect to the endpoint BARs: e.g., index 0 + * will return the lowest-numbered BAR on the endpoint. + * + * @param bdf the PCI(e) endpoint + * @param index (0-based) index + * @param bar Pointer to struct pcie_bar + * @param io true for I/O BARs, false otherwise + * @return true if the BAR was found and is valid, false otherwise + */ +static bool pcie_probe_bar(pcie_bdf_t bdf, + unsigned int index, + struct pcie_bar *bar, + bool io) { uint32_t reg; @@ -213,7 +238,35 @@ bool pcie_probe_mbar(pcie_bdf_t bdf, return false; } - return pcie_get_mbar(bdf, reg - PCIE_CONF_BAR0, mbar); + return pcie_get_bar(bdf, reg - PCIE_CONF_BAR0, bar, io); +} + +bool pcie_get_mbar(pcie_bdf_t bdf, + unsigned int bar_index, + struct pcie_bar *mbar) +{ + return pcie_get_bar(bdf, bar_index, mbar, false); +} + +bool pcie_probe_mbar(pcie_bdf_t bdf, + unsigned int index, + struct pcie_bar *mbar) +{ + return pcie_probe_bar(bdf, index, mbar, false); +} + +bool pcie_get_iobar(pcie_bdf_t bdf, + unsigned int bar_index, + struct pcie_bar *iobar) +{ + return pcie_get_bar(bdf, bar_index, iobar, true); +} + +bool pcie_probe_iobar(pcie_bdf_t bdf, + unsigned int index, + struct pcie_bar *iobar) +{ + return pcie_probe_bar(bdf, index, iobar, true); } #ifndef CONFIG_PCIE_CONTROLLER diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index 10b4efb6729..45e325db9ec 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -333,7 +333,7 @@ static int uart_ns16550_configure(const struct device *dev, #ifndef CONFIG_UART_NS16550_ACCESS_IOPORT #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) if (dev_cfg->pcie) { - struct pcie_mbar mbar; + struct pcie_bar mbar; if (!pcie_probe(dev_cfg->pcie_bdf, dev_cfg->pcie_id)) { ret = -EINVAL; diff --git a/drivers/virtualization/virt_ivshmem.c b/drivers/virtualization/virt_ivshmem.c index 3c10f154e31..3bc06d8409e 100644 --- a/drivers/virtualization/virt_ivshmem.c +++ b/drivers/virtualization/virt_ivshmem.c @@ -108,7 +108,7 @@ static const struct ivshmem_reg no_reg; static bool ivshmem_configure(const struct device *dev) { struct ivshmem *data = dev->data; - struct pcie_mbar mbar_regs, mbar_mem; + struct pcie_bar mbar_regs, mbar_mem; if (!pcie_get_mbar(data->bdf, IVSHMEM_PCIE_REG_BAR_IDX, &mbar_regs)) { #ifdef CONFIG_IVSHMEM_DOORBELL diff --git a/include/zephyr/drivers/pcie/pcie.h b/include/zephyr/drivers/pcie/pcie.h index 91e0579d056..a9741d3505b 100644 --- a/include/zephyr/drivers/pcie/pcie.h +++ b/include/zephyr/drivers/pcie/pcie.h @@ -36,7 +36,7 @@ typedef uint32_t pcie_bdf_t; */ typedef uint32_t pcie_id_t; -struct pcie_mbar { +struct pcie_bar { uintptr_t phys_addr; size_t size; }; @@ -91,18 +91,18 @@ extern bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id); * @brief Get the MBAR at a specific BAR index * @param bdf the PCI(e) endpoint * @param bar_index 0-based BAR index - * @param mbar Pointer to struct pcie_mbar + * @param mbar Pointer to struct pcie_bar * @return true if the mbar was found and is valid, false otherwise */ extern bool pcie_get_mbar(pcie_bdf_t bdf, unsigned int bar_index, - struct pcie_mbar *mbar); + struct pcie_bar *mbar); /** * @brief Probe the nth MMIO address assigned to an endpoint. * @param bdf the PCI(e) endpoint * @param index (0-based) index - * @param mbar Pointer to struct pcie_mbar + * @param mbar Pointer to struct pcie_bar * @return true if the mbar was found and is valid, false otherwise * * A PCI(e) endpoint has 0 or more memory-mapped regions. This function @@ -113,7 +113,35 @@ extern bool pcie_get_mbar(pcie_bdf_t bdf, */ extern bool pcie_probe_mbar(pcie_bdf_t bdf, unsigned int index, - struct pcie_mbar *mbar); + struct pcie_bar *mbar); + +/** + * @brief Get the I/O BAR at a specific BAR index + * @param bdf the PCI(e) endpoint + * @param bar_index 0-based BAR index + * @param iobar Pointer to struct pcie_bar + * @return true if the I/O BAR was found and is valid, false otherwise + */ +extern bool pcie_get_iobar(pcie_bdf_t bdf, + unsigned int bar_index, + struct pcie_bar *iobar); + +/** + * @brief Probe the nth I/O BAR address assigned to an endpoint. + * @param bdf the PCI(e) endpoint + * @param index (0-based) index + * @param iobar Pointer to struct pcie_bar + * @return true if the I/O BAR was found and is valid, false otherwise + * + * A PCI(e) endpoint has 0 or more I/O regions. This function + * allows the caller to enumerate them by calling with index=0..n. + * Value of n has to be below 6, as there is a maximum of 6 BARs. The indices + * are order-preserving with respect to the endpoint BARs: e.g., index 0 + * will return the lowest-numbered I/O BAR on the endpoint. + */ +extern bool pcie_probe_iobar(pcie_bdf_t bdf, + unsigned int index, + struct pcie_bar *iobar); /** * @brief Set or reset bits in the endpoint command/status register.