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)
#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);

View file

@ -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);

View file

@ -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))) {

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 (rom->pcie) {
struct pcie_mbar mbar;
struct pcie_bar mbar;
if (!pcie_probe(rom->pcie_bdf, rom->pcie_id)) {
return -EINVAL;

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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.