drivers/pcie: Change pcie_get_mbar() to return size and flags
currently pcie_get_mbar only returns the physical address. This changes the function to return the size of the mbar and the flags (IO Bar vs MEM BAR). Signed-off-by: Maximilian Bachmann <m.bachmann@acontis.com>
This commit is contained in:
parent
19c2f78495
commit
3c8e98cb39
7 changed files with 76 additions and 36 deletions
|
@ -79,15 +79,15 @@ int arch_printk_char_out(int c)
|
||||||
void z_x86_early_serial_init(void)
|
void z_x86_early_serial_init(void)
|
||||||
{
|
{
|
||||||
#if defined(DEVICE_MMIO_IS_IN_RAM) && !defined(UART_NS16550_ACCESS_IOPORT)
|
#if defined(DEVICE_MMIO_IS_IN_RAM) && !defined(UART_NS16550_ACCESS_IOPORT)
|
||||||
uintptr_t phys;
|
|
||||||
|
|
||||||
#ifdef X86_SOC_EARLY_SERIAL_PCIDEV
|
#ifdef X86_SOC_EARLY_SERIAL_PCIDEV
|
||||||
phys = pcie_get_mbar(X86_SOC_EARLY_SERIAL_PCIDEV, 0);
|
struct pcie_mbar 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);
|
||||||
#else
|
#else
|
||||||
phys = X86_SOC_EARLY_SERIAL_MMIO8_ADDR;
|
device_map(&mmio, X86_SOC_EARLY_SERIAL_MMIO8_ADDR, 0x1000, K_MEM_CACHE_NONE);
|
||||||
#endif
|
#endif
|
||||||
device_map(&mmio, phys, 0x1000, K_MEM_CACHE_NONE);
|
|
||||||
#endif /* DEVICE_MMIO_IS_IN_RAM */
|
#endif /* DEVICE_MMIO_IS_IN_RAM */
|
||||||
|
|
||||||
OUT(REG_IER, IER_DISABLE); /* Disable interrupts */
|
OUT(REG_IER, IER_DISABLE); /* Disable interrupts */
|
||||||
|
|
|
@ -584,10 +584,10 @@ may be used directly:
|
||||||
void some_init_code(...)
|
void some_init_code(...)
|
||||||
{
|
{
|
||||||
...
|
...
|
||||||
uintptr_t phys_addr = pcie_get_mbar(...);
|
struct pcie_mbar mbar;
|
||||||
size_t size = ...
|
bool bar_found = pcie_get_mbar(bdf, index, &mbar);
|
||||||
|
|
||||||
device_map(DEVICE_MMIO_RAM_PTR(dev), phys_addr, size, K_MEM_CACHE_NONE);
|
device_map(DEVICE_MMIO_RAM_PTR(dev), mbar.phys_addr, mbar.size, K_MEM_CACHE_NONE);
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -217,20 +217,18 @@ int e1000_probe(const struct device *device)
|
||||||
const pcie_bdf_t bdf = PCIE_BDF(0, 3, 0);
|
const pcie_bdf_t bdf = PCIE_BDF(0, 3, 0);
|
||||||
struct e1000_dev *dev = device->data;
|
struct e1000_dev *dev = device->data;
|
||||||
uint32_t ral, rah;
|
uint32_t ral, rah;
|
||||||
uintptr_t phys_addr;
|
struct pcie_mbar mbar;
|
||||||
size_t size;
|
|
||||||
|
|
||||||
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))) {
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
phys_addr = pcie_get_mbar(bdf, 0);
|
pcie_get_mbar(bdf, 0, &mbar);
|
||||||
pcie_set_cmd(bdf, PCIE_CONF_CMDSTAT_MEM |
|
pcie_set_cmd(bdf, PCIE_CONF_CMDSTAT_MEM |
|
||||||
PCIE_CONF_CMDSTAT_MASTER, true);
|
PCIE_CONF_CMDSTAT_MASTER, true);
|
||||||
size = KB(128); /* TODO: get from PCIe */
|
|
||||||
|
|
||||||
device_map(&dev->address, phys_addr, size,
|
device_map(&dev->address, mbar.phys_addr, mbar.size,
|
||||||
K_MEM_CACHE_NONE);
|
K_MEM_CACHE_NONE);
|
||||||
|
|
||||||
/* Setup TX descriptor */
|
/* Setup TX descriptor */
|
||||||
|
|
|
@ -611,17 +611,17 @@ static int i2c_dw_initialize(const struct device *dev)
|
||||||
|
|
||||||
#ifdef I2C_DW_PCIE_ENABLED
|
#ifdef I2C_DW_PCIE_ENABLED
|
||||||
if (rom->pcie) {
|
if (rom->pcie) {
|
||||||
uintptr_t mmio_phys_addr;
|
struct pcie_mbar mbar;
|
||||||
|
|
||||||
if (!pcie_probe(rom->pcie_bdf, rom->pcie_id)) {
|
if (!pcie_probe(rom->pcie_bdf, rom->pcie_id)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mmio_phys_addr = pcie_get_mbar(rom->pcie_bdf, 0);
|
pcie_get_mbar(rom->pcie_bdf, 0, &mbar);
|
||||||
pcie_set_cmd(rom->pcie_bdf, PCIE_CONF_CMDSTAT_MEM, true);
|
pcie_set_cmd(rom->pcie_bdf, PCIE_CONF_CMDSTAT_MEM, true);
|
||||||
|
|
||||||
device_map(DEVICE_MMIO_RAM_PTR(dev), mmio_phys_addr,
|
device_map(DEVICE_MMIO_RAM_PTR(dev), mbar.phys_addr,
|
||||||
0x1000, K_MEM_CACHE_NONE);
|
mbar.size, K_MEM_CACHE_NONE);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Intel Corporation
|
* Copyright (c) 2019 Intel Corporation
|
||||||
|
* Copyright (c) 2020 acontis technologies GmbH
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
@ -46,26 +47,57 @@ void pcie_set_cmd(pcie_bdf_t bdf, uint32_t bits, bool on)
|
||||||
pcie_conf_write(bdf, PCIE_CONF_CMDSTAT, cmdstat);
|
pcie_conf_write(bdf, PCIE_CONF_CMDSTAT, cmdstat);
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t pcie_get_mbar(pcie_bdf_t bdf, unsigned int index)
|
bool pcie_get_mbar(pcie_bdf_t bdf, unsigned int index, struct pcie_mbar *mbar)
|
||||||
{
|
{
|
||||||
uint32_t reg, bar;
|
bool valid_bar = false;
|
||||||
uintptr_t addr = PCIE_CONF_BAR_NONE;
|
uint32_t reg;
|
||||||
|
uintptr_t phys_addr = PCIE_CONF_BAR_NONE;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
reg = PCIE_CONF_BAR0;
|
for (reg = PCIE_CONF_BAR0; reg <= PCIE_CONF_BAR5; reg++) {
|
||||||
for (bar = 0; bar < index && reg <= PCIE_CONF_BAR5; bar++) {
|
uint32_t addr = pcie_conf_read(bdf, reg);
|
||||||
if (PCIE_CONF_BAR_64(pcie_conf_read(bdf, reg++))) {
|
|
||||||
|
/* skip useless bars and I/O Bars */
|
||||||
|
if (addr == 0xFFFFFFFFU || addr == 0x0U || PCIE_CONF_BAR_IO(addr)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
valid_bar = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PCIE_CONF_BAR_64(addr)) {
|
||||||
reg++;
|
reg++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bar == index) {
|
if (valid_bar) {
|
||||||
addr = pcie_conf_read(bdf, reg++);
|
phys_addr = pcie_conf_read(bdf, reg);
|
||||||
if (IS_ENABLED(CONFIG_64BIT) && PCIE_CONF_BAR_64(addr)) {
|
pcie_conf_write(bdf, reg, 0xFFFFFFFF);
|
||||||
addr |= ((uint64_t)pcie_conf_read(bdf, reg)) << 32;
|
size = pcie_conf_read(bdf, reg);
|
||||||
|
pcie_conf_write(bdf, reg, (uint32_t)phys_addr);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_64BIT) && PCIE_CONF_BAR_64(phys_addr)) {
|
||||||
|
reg++;
|
||||||
|
phys_addr |= ((uint64_t)pcie_conf_read(bdf, reg)) << 32;
|
||||||
|
pcie_conf_write(bdf, reg, 0xFFFFFFFF);
|
||||||
|
size |= ((uint64_t)pcie_conf_read(bdf, reg)) << 32;
|
||||||
|
pcie_conf_write(bdf, reg, (uint32_t)((uint64_t)phys_addr >> 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
size = PCIE_CONF_BAR_ADDR(size);
|
||||||
|
if (size) {
|
||||||
|
mbar->phys_addr = PCIE_CONF_BAR_ADDR(phys_addr);
|
||||||
|
mbar->size = size & ~(size-1);
|
||||||
|
} else {
|
||||||
|
valid_bar = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return PCIE_CONF_BAR_ADDR(addr);
|
return valid_bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The first bit is used to indicate whether the list of reserved interrupts
|
/* The first bit is used to indicate whether the list of reserved interrupts
|
||||||
|
|
|
@ -352,17 +352,17 @@ static int uart_ns16550_configure(const struct device *dev,
|
||||||
#ifndef UART_NS16550_ACCESS_IOPORT
|
#ifndef UART_NS16550_ACCESS_IOPORT
|
||||||
#ifdef UART_NS16550_PCIE_ENABLED
|
#ifdef UART_NS16550_PCIE_ENABLED
|
||||||
if (dev_cfg->pcie) {
|
if (dev_cfg->pcie) {
|
||||||
uintptr_t phys;
|
struct pcie_mbar 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;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
phys = pcie_get_mbar(dev_cfg->pcie_bdf, 0);
|
pcie_get_mbar(dev_cfg->pcie_bdf, 0, &mbar);
|
||||||
pcie_set_cmd(dev_cfg->pcie_bdf, PCIE_CONF_CMDSTAT_MEM, true);
|
pcie_set_cmd(dev_cfg->pcie_bdf, PCIE_CONF_CMDSTAT_MEM, true);
|
||||||
|
|
||||||
device_map(DEVICE_MMIO_RAM_PTR(dev), phys, 0x1000,
|
device_map(DEVICE_MMIO_RAM_PTR(dev), mbar.phys_addr, mbar.size,
|
||||||
K_MEM_CACHE_NONE);
|
K_MEM_CACHE_NONE);
|
||||||
} else
|
} else
|
||||||
#endif /* UART_NS16550_PCIE_ENABLED */
|
#endif /* UART_NS16550_PCIE_ENABLED */
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_
|
#ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_
|
||||||
#define ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_
|
#define ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
#include <dt-bindings/pcie/pcie.h>
|
#include <dt-bindings/pcie/pcie.h>
|
||||||
#include <zephyr/types.h>
|
#include <zephyr/types.h>
|
||||||
|
|
||||||
|
@ -35,6 +36,11 @@ typedef uint32_t pcie_bdf_t;
|
||||||
*/
|
*/
|
||||||
typedef uint32_t pcie_id_t;
|
typedef uint32_t pcie_id_t;
|
||||||
|
|
||||||
|
struct pcie_mbar {
|
||||||
|
uintptr_t phys_addr;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions are arch-, board-, or SoC-specific.
|
* These functions are arch-, board-, or SoC-specific.
|
||||||
*/
|
*/
|
||||||
|
@ -74,15 +80,19 @@ extern bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id);
|
||||||
* @brief Get the nth MMIO address assigned to an endpoint.
|
* @brief Get 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
|
||||||
* @return the address, or PCIE_CONF_BAR_NONE if nonexistent.
|
* @param mbar Pointer to struct pcie_mbar
|
||||||
|
* @return true if the mbar was found, 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
|
||||||
* allows the caller to enumerate them by calling with index=0..n. If
|
* allows the caller to enumerate them by calling with index=0..n. If
|
||||||
* PCIE_CONF_BAR_NONE is returned, there are no further regions. The indices
|
* false is returned, there are no further regions. The indices
|
||||||
* are order-preserving with respect to the endpoint BARs: e.g., index 0
|
* are order-preserving with respect to the endpoint BARs (skips useless bars
|
||||||
* will return the lowest-numbered memory BAR on the endpoint.
|
* and I/O Bars): e.g., index 0 will return the lowest-numbered valid memory BAR
|
||||||
|
* on the endpoint.
|
||||||
*/
|
*/
|
||||||
extern uintptr_t pcie_get_mbar(pcie_bdf_t bdf, unsigned int index);
|
extern bool pcie_get_mbar(pcie_bdf_t bdf,
|
||||||
|
unsigned int index,
|
||||||
|
struct pcie_mbar *mbar);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set or reset bits in the endpoint command/status register.
|
* @brief Set or reset bits in the endpoint command/status register.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue