drivers: pcie: reintroduce support for I/O BARs

Reintroduce support for accessing I/O BARs which was removed in
43d84147d9.

Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
This commit is contained in:
Henrik Brix Andersen 2022-10-21 10:23:42 +02:00 committed by Christopher Friedt
commit 3c99a1e015
9 changed files with 105 additions and 24 deletions

View file

@ -88,7 +88,7 @@ void z_x86_early_serial_init(void)
{ {
#if defined(DEVICE_MMIO_IS_IN_RAM) && !defined(CONFIG_UART_NS16550_ACCESS_IOPORT) #if defined(DEVICE_MMIO_IS_IN_RAM) && !defined(CONFIG_UART_NS16550_ACCESS_IOPORT)
#ifdef X86_SOC_EARLY_SERIAL_PCIDEV #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_get_mbar(X86_SOC_EARLY_SERIAL_PCIDEV, 0, &mbar);
pcie_set_cmd(X86_SOC_EARLY_SERIAL_PCIDEV, PCIE_CONF_CMDSTAT_MEM, true); 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); device_map(&mmio, mbar.phys_addr, mbar.size, K_MEM_CACHE_NONE);

View file

@ -606,7 +606,7 @@ may be used directly:
void some_init_code(...) void some_init_code(...)
{ {
... ...
struct pcie_mbar mbar; struct pcie_bar mbar;
bool bar_found = pcie_get_mbar(bdf, index, &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); device_map(DEVICE_MMIO_RAM_PTR(dev), mbar.phys_addr, mbar.size, K_MEM_CACHE_NONE);

View file

@ -238,7 +238,7 @@ int e1000_probe(const struct device *ddev)
const pcie_bdf_t bdf = PCIE_BDF(0, 3, 0); const pcie_bdf_t bdf = PCIE_BDF(0, 3, 0);
struct e1000_dev *dev = ddev->data; struct e1000_dev *dev = ddev->data;
uint32_t ral, rah; uint32_t ral, rah;
struct pcie_mbar mbar; struct pcie_bar mbar;
if (!pcie_probe(bdf, PCIE_ID(PCI_VENDOR_ID_INTEL, if (!pcie_probe(bdf, PCIE_ID(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_I82540EM))) { PCI_DEVICE_ID_I82540EM))) {

View file

@ -849,7 +849,7 @@ static int i2c_dw_initialize(const struct device *dev)
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie)
if (rom->pcie) { if (rom->pcie) {
struct pcie_mbar mbar; struct pcie_bar mbar;
if (!pcie_probe(rom->pcie_bdf, rom->pcie_id)) { if (!pcie_probe(rom->pcie_bdf, rom->pcie_id)) {
return -EINVAL; return -EINVAL;

View file

@ -84,7 +84,7 @@ static bool map_msix_table_entries(pcie_bdf_t bdf,
{ {
uint32_t table_offset; uint32_t table_offset;
uint8_t table_bir; uint8_t table_bir;
struct pcie_mbar bar; struct pcie_bar bar;
uintptr_t mapped_table; uintptr_t mapped_table;
int i; int i;

View file

@ -103,9 +103,19 @@ uint32_t pcie_get_ext_cap(pcie_bdf_t bdf, uint32_t cap_id)
return reg; return reg;
} }
bool pcie_get_mbar(pcie_bdf_t bdf, /**
* @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, unsigned int bar_index,
struct pcie_mbar *mbar) struct pcie_bar *bar,
bool io)
{ {
uint32_t reg = bar_index + PCIE_CONF_BAR0; uint32_t reg = bar_index + PCIE_CONF_BAR0;
#ifdef CONFIG_PCIE_CONTROLLER #ifdef CONFIG_PCIE_CONTROLLER
@ -128,8 +138,7 @@ bool pcie_get_mbar(pcie_bdf_t bdf,
phys_addr = pcie_conf_read(bdf, reg); phys_addr = pcie_conf_read(bdf, reg);
#ifndef CONFIG_PCIE_CONTROLLER #ifndef CONFIG_PCIE_CONTROLLER
if (PCIE_CONF_BAR_IO(phys_addr)) { if ((PCIE_CONF_BAR_MEM(phys_addr) && io) || (PCIE_CONF_BAR_IO(phys_addr) && !io)) {
/* Discard I/O bars */
return false; return false;
} }
#endif #endif
@ -183,20 +192,36 @@ bool pcie_get_mbar(pcie_bdf_t bdf,
PCIE_CONF_BAR_MEM(phys_addr) ? PCIE_CONF_BAR_MEM(phys_addr) ?
PCIE_CONF_BAR_ADDR(phys_addr) PCIE_CONF_BAR_ADDR(phys_addr)
: PCIE_CONF_BAR_IO_ADDR(phys_addr), : PCIE_CONF_BAR_IO_ADDR(phys_addr),
&mbar->phys_addr)) { &bar->phys_addr)) {
return false; return false;
} }
#else #else
mbar->phys_addr = PCIE_CONF_BAR_ADDR(phys_addr); bar->phys_addr = PCIE_CONF_BAR_ADDR(phys_addr);
#endif /* CONFIG_PCIE_CONTROLLER */ #endif /* CONFIG_PCIE_CONTROLLER */
mbar->size = size & ~(size-1); bar->size = size & ~(size-1);
return true; return true;
} }
bool pcie_probe_mbar(pcie_bdf_t bdf, /**
* @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, unsigned int index,
struct pcie_mbar *mbar) struct pcie_bar *bar,
bool io)
{ {
uint32_t reg; uint32_t reg;
@ -213,7 +238,35 @@ bool pcie_probe_mbar(pcie_bdf_t bdf,
return false; 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 #ifndef CONFIG_PCIE_CONTROLLER

View file

@ -333,7 +333,7 @@ static int uart_ns16550_configure(const struct device *dev,
#ifndef CONFIG_UART_NS16550_ACCESS_IOPORT #ifndef CONFIG_UART_NS16550_ACCESS_IOPORT
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie)
if (dev_cfg->pcie) { if (dev_cfg->pcie) {
struct pcie_mbar mbar; struct pcie_bar mbar;
if (!pcie_probe(dev_cfg->pcie_bdf, dev_cfg->pcie_id)) { if (!pcie_probe(dev_cfg->pcie_bdf, dev_cfg->pcie_id)) {
ret = -EINVAL; ret = -EINVAL;

View file

@ -108,7 +108,7 @@ static const struct ivshmem_reg no_reg;
static bool ivshmem_configure(const struct device *dev) static bool ivshmem_configure(const struct device *dev)
{ {
struct ivshmem *data = dev->data; 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)) { if (!pcie_get_mbar(data->bdf, IVSHMEM_PCIE_REG_BAR_IDX, &mbar_regs)) {
#ifdef CONFIG_IVSHMEM_DOORBELL #ifdef CONFIG_IVSHMEM_DOORBELL

View file

@ -36,7 +36,7 @@ typedef uint32_t pcie_bdf_t;
*/ */
typedef uint32_t pcie_id_t; typedef uint32_t pcie_id_t;
struct pcie_mbar { struct pcie_bar {
uintptr_t phys_addr; uintptr_t phys_addr;
size_t size; 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 * @brief Get the MBAR at a specific BAR index
* @param bdf the PCI(e) endpoint * @param bdf the PCI(e) endpoint
* @param bar_index 0-based BAR index * @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 * @return true if the mbar was found and is valid, false otherwise
*/ */
extern bool pcie_get_mbar(pcie_bdf_t bdf, extern bool pcie_get_mbar(pcie_bdf_t bdf,
unsigned int bar_index, unsigned int bar_index,
struct pcie_mbar *mbar); struct pcie_bar *mbar);
/** /**
* @brief Probe the nth MMIO address assigned to an endpoint. * @brief Probe the nth MMIO address assigned to an endpoint.
* @param bdf the PCI(e) endpoint * @param bdf the PCI(e) endpoint
* @param index (0-based) index * @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 * @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 * 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, extern bool pcie_probe_mbar(pcie_bdf_t bdf,
unsigned int index, 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. * @brief Set or reset bits in the endpoint command/status register.