From 99c2279abfb228baa6b7ff3c3cf52bc57a216fd9 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Fri, 2 Jul 2021 16:40:49 +0200 Subject: [PATCH] pci: add Extended PCI(e) capability offset get Extend the PCIe API to find Extended Capabilities in the PCI Express Extended Capabilities located in Configuration Space at offsets 256 or greater. Note: the Root Complex Register Block is not supported Signed-off-by: Neil Armstrong --- drivers/pcie/host/pcie.c | 25 +++++++++++++++++++++++++ include/drivers/pcie/pcie.h | 24 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/drivers/pcie/host/pcie.c b/drivers/pcie/host/pcie.c index acb73288759..62022a6b89c 100644 --- a/drivers/pcie/host/pcie.c +++ b/drivers/pcie/host/pcie.c @@ -71,6 +71,31 @@ uint32_t pcie_get_cap(pcie_bdf_t bdf, uint32_t cap_id) return reg; } +uint32_t pcie_get_ext_cap(pcie_bdf_t bdf, uint32_t cap_id) +{ + unsigned int reg = PCIE_CONF_EXT_CAPPTR; /* Start at end of the PCI configuration space */ + uint32_t data; + + while (reg) { + data = pcie_conf_read(bdf, reg); + if (!data || data == 0xffffffff) { + return 0; + } + + if (PCIE_CONF_EXT_CAP_ID(data) == cap_id) { + break; + } + + reg = PCIE_CONF_EXT_CAP_NEXT(data) >> 2; + + if (reg < PCIE_CONF_EXT_CAPPTR) { + return 0; + } + } + + return reg; +} + bool pcie_get_mbar(pcie_bdf_t bdf, unsigned int bar_index, struct pcie_mbar *mbar) diff --git a/include/drivers/pcie/pcie.h b/include/drivers/pcie/pcie.h index 327702af6f0..0a9e0bd6223 100644 --- a/include/drivers/pcie/pcie.h +++ b/include/drivers/pcie/pcie.h @@ -167,6 +167,15 @@ extern void pcie_irq_enable(pcie_bdf_t bdf, unsigned int irq); */ extern uint32_t pcie_get_cap(pcie_bdf_t bdf, uint32_t cap_id); +/** + * @brief Find an Extended PCI(e) capability in an endpoint's configuration space. + * + * @param bdf the PCI endpoint to examine + * @param cap_id the capability ID of interest + * @return the index of the configuration word, or 0 if no capability. + */ +extern uint32_t pcie_get_ext_cap(pcie_bdf_t bdf, uint32_t cap_id); + /* * Configuration word 13 contains the head of the capabilities list. */ @@ -182,6 +191,21 @@ extern uint32_t pcie_get_cap(pcie_bdf_t bdf, uint32_t cap_id); #define PCIE_CONF_CAP_ID(w) ((w) & 0xFFU) #define PCIE_CONF_CAP_NEXT(w) (((w) >> 10) & 0x3FU) +/* + * The extended PCI Express capabilies lies at the end of the PCI configuration space + */ + +#define PCIE_CONF_EXT_CAPPTR 64U + +/* + * The first word of every capability contains an extended capability identifier, + * and a link to the next capability (or 0) in the extended configuration space. + */ + +#define PCIE_CONF_EXT_CAP_ID(w) ((w) & 0xFFFFU) +#define PCIE_CONF_EXT_CAP_VER(w) (((w) >> 16) & 0xFU) +#define PCIE_CONF_EXT_CAP_NEXT(w) (((w) >> 20) & 0xFFFU) + /* * Configuration word 0 aligns directly with pcie_id_t. */