[U-Boot] [PATCH 1/2][V2] pci: Add function to find an extended capability

Bin Meng
2015-07-10T08:38:48Z

On Fri, Jul 10, 2015 at 11:35 AM, Minghuan Lian
<Minghuan.Lian@freescale.com> wrote:
> PCIe extends device's configuration space to 4k and provides
> extended capability. The patch adds function to find them.
> The code is ported from Linux PCIe driver.
>
> Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
> ---
> Change log:
> v2-v1:
> 1. add a descriptor of pci_find_next_ext_capability
> 2. fix a typo
>
> drivers/pci/pci.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> include/pci.h | 41 +++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 94 insertions(+)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 157491c..df50b48 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -526,3 +526,56 @@ int pci_find_cap(struct pci_controller *hose, pci_dev_t dev, int pos, int cap)
> }
> return 0;
> }
> +
> +/**
> + * pci_find_next_ext_capability - Find an extended capability
> + *
> + * Returns the address of the next matching extended capability structure
> + * within the device's PCI configuration space or 0 if the device does
> + * not support it. Some capabilities can occur several times, e.g., the
> + * vendor-specific capability, and this provides a way to find them all.
> + */
> +int pci_find_next_ext_capability(struct pci_controller *hose, pci_dev_t dev,
> + int start, int cap)
> +{
> + u32 header;
> + int ttl, pos = PCI_CFG_SPACE_SIZE;
> +
> + /* minimum 8 bytes per capability */
> + ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
> +
> + if (start)
> + pos = start;
> +
> + pci_hose_read_config_dword(hose, dev, pos, &header);
> + if (header == 0xffffffff || header == 0)
> + return 0;
> +
> + while (ttl-- > 0) {
> + if (PCI_EXT_CAP_ID(header) == cap && pos != start)
> + return pos;
> +
> + pos = PCI_EXT_CAP_NEXT(header);
> + if (pos < PCI_CFG_SPACE_SIZE)
> + break;
> +
> + pci_hose_read_config_dword(hose, dev, pos, &header);
> + if (header == 0xffffffff || header == 0)
> + break;
> + }
> +
> + return 0;
> +}
> +
> +/**
> + * pci_hose_find_ext_capability - Find an extended capability
> + *
> + * Returns the address of the requested extended capability structure
> + * within the device's PCI configuration space or 0 if the device does
> + * not support it.
> + */
> +int pci_hose_find_ext_capability(struct pci_controller *hose, pci_dev_t dev,
> + int cap)
> +{
> + return pci_find_next_ext_capability(hose, dev, 0, cap);
> +}
> diff --git a/include/pci.h b/include/pci.h
> index 07b1e9a..2f88714 100644
> --- a/include/pci.h
> +++ b/include/pci.h
> @@ -11,6 +11,9 @@
> #ifndef _PCI_H
> #define _PCI_H
>
> +#define PCI_CFG_SPACE_SIZE 256
> +#define PCI_CFG_SPACE_EXP_SIZE 4096
> +
> /*
> * Under PCI, each device has 256 bytes of configuration address space,
> * of which the first 64 bytes are standardized as follows:
> @@ -413,6 +416,39 @@
> #define PCI_FIND_CAP_TTL 0x48
> #define CAP_START_POS 0x40
>
> +/* Extended Capabilities (PCI-X 2.0 and Express) */
> +#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
> +#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf)
> +#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc)
> +
> +#define PCI_EXT_CAP_ID_ERR 0x01 /* Advanced Error Reporting */
> +#define PCI_EXT_CAP_ID_VC 0x02 /* Virtual Channel Capability */
> +#define PCI_EXT_CAP_ID_DSN 0x03 /* Device Serial Number */
> +#define PCI_EXT_CAP_ID_PWR 0x04 /* Power Budgeting */
> +#define PCI_EXT_CAP_ID_RCLD 0x05 /* Root Complex Link Declaration */
> +#define PCI_EXT_CAP_ID_RCILC 0x06 /* Root Complex Internal Link Control */
> +#define PCI_EXT_CAP_ID_RCEC 0x07 /* Root Complex Event Collector */
> +#define PCI_EXT_CAP_ID_MFVC 0x08 /* Multi-Function VC Capability */
> +#define PCI_EXT_CAP_ID_VC9 0x09 /* same as _VC */
> +#define PCI_EXT_CAP_ID_RCRB 0x0A /* Root Complex RB? */
> +#define PCI_EXT_CAP_ID_VNDR 0x0B /* Vendor-Specific */
> +#define PCI_EXT_CAP_ID_CAC 0x0C /* Config Access - obsolete */
> +#define PCI_EXT_CAP_ID_ACS 0x0D /* Access Control Services */
> +#define PCI_EXT_CAP_ID_ARI 0x0E /* Alternate Routing ID */
> +#define PCI_EXT_CAP_ID_ATS 0x0F /* Address Translation Services */
> +#define PCI_EXT_CAP_ID_SRIOV 0x10 /* Single Root I/O Virtualization */
> +#define PCI_EXT_CAP_ID_MRIOV 0x11 /* Multi Root I/O Virtualization */
> +#define PCI_EXT_CAP_ID_MCAST 0x12 /* Multicast */
> +#define PCI_EXT_CAP_ID_PRI 0x13 /* Page Request Interface */
> +#define PCI_EXT_CAP_ID_AMD_XXX 0x14 /* Reserved for AMD */
> +#define PCI_EXT_CAP_ID_REBAR 0x15 /* Resizable BAR */
> +#define PCI_EXT_CAP_ID_DPA 0x16 /* Dynamic Power Allocation */
> +#define PCI_EXT_CAP_ID_TPH 0x17 /* TPH Requester */
> +#define PCI_EXT_CAP_ID_LTR 0x18 /* Latency Tolerance Reporting */
> +#define PCI_EXT_CAP_ID_SECPCI 0x19 /* Secondary PCIe Capability */
> +#define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */
> +#define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */
> +
> /* Include the ID list */
>
> #include <pci_ids.h>
> @@ -674,6 +710,11 @@ extern int pci_hose_find_cap_start(struct pci_controller *hose, pci_dev_t dev,
> extern int pci_find_cap(struct pci_controller *hose, pci_dev_t dev, int pos,
> int cap);
>
> +int pci_find_next_ext_capability(struct pci_controller *hose,
> + pci_dev_t dev, int start, int cap);
> +int pci_hose_find_ext_capability(struct pci_controller *hose,
> + pci_dev_t dev, int cap);
> +
> #ifdef CONFIG_PCI_FIXUP_DEV
> extern void board_pci_fixup_dev(struct pci_controller *hose, pci_dev_t dev,
> unsigned short vendor,
> --

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>