dm: pci: Add APIs to find next capability and extended capability
authorBin Meng <bmeng.cn@gmail.com>
Mon, 15 Oct 2018 09:21:21 +0000 (02:21 -0700)
committerSimon Glass <sjg@chromium.org>
Wed, 14 Nov 2018 17:16:28 +0000 (09:16 -0800)
This introduces two new APIs dm_pci_find_next_capability() and
dm_pci_find_next_ext_capability() to get PCI capability address
and PCI express extended capability address for a given PCI device
starting from a given offset.

Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/pci/pci-uclass.c
include/pci.h

index da49c96ed5e365a3acb3298ca69b83dbb923288c..0c52337f33a2315a435109638f09aa4783f2b3ab 100644 (file)
@@ -1344,26 +1344,14 @@ void *dm_pci_map_bar(struct udevice *dev, int bar, int flags)
        return dm_pci_bus_to_virt(dev, pci_bus_addr, flags, 0, MAP_NOCACHE);
 }
 
-int dm_pci_find_capability(struct udevice *dev, int cap)
+static int _dm_pci_find_next_capability(struct udevice *dev, u8 pos, int cap)
 {
-       u16 status;
-       u8 header_type;
        int ttl = PCI_FIND_CAP_TTL;
        u8 id;
        u16 ent;
-       u8 pos;
-
-       dm_pci_read_config16(dev, PCI_STATUS, &status);
-       if (!(status & PCI_STATUS_CAP_LIST))
-               return 0;
-
-       dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
-       if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
-               pos = PCI_CB_CAPABILITY_LIST;
-       else
-               pos = PCI_CAPABILITY_LIST;
 
        dm_pci_read_config8(dev, pos, &pos);
+
        while (ttl--) {
                if (pos < PCI_STD_HEADER_SIZEOF)
                        break;
@@ -1381,7 +1369,32 @@ int dm_pci_find_capability(struct udevice *dev, int cap)
        return 0;
 }
 
-int dm_pci_find_ext_capability(struct udevice *dev, int cap)
+int dm_pci_find_next_capability(struct udevice *dev, u8 start, int cap)
+{
+       return _dm_pci_find_next_capability(dev, start + PCI_CAP_LIST_NEXT,
+                                           cap);
+}
+
+int dm_pci_find_capability(struct udevice *dev, int cap)
+{
+       u16 status;
+       u8 header_type;
+       u8 pos;
+
+       dm_pci_read_config16(dev, PCI_STATUS, &status);
+       if (!(status & PCI_STATUS_CAP_LIST))
+               return 0;
+
+       dm_pci_read_config8(dev, PCI_HEADER_TYPE, &header_type);
+       if ((header_type & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
+               pos = PCI_CB_CAPABILITY_LIST;
+       else
+               pos = PCI_CAPABILITY_LIST;
+
+       return _dm_pci_find_next_capability(dev, pos, cap);
+}
+
+int dm_pci_find_next_ext_capability(struct udevice *dev, int start, int cap)
 {
        u32 header;
        int ttl;
@@ -1390,6 +1403,9 @@ int dm_pci_find_ext_capability(struct udevice *dev, int cap)
        /* minimum 8 bytes per capability */
        ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
 
+       if (start)
+               pos = start;
+
        dm_pci_read_config32(dev, pos, &header);
        /*
         * If we have no capabilities, this is indicated by cap ID,
@@ -1412,6 +1428,11 @@ int dm_pci_find_ext_capability(struct udevice *dev, int cap)
        return 0;
 }
 
+int dm_pci_find_ext_capability(struct udevice *dev, int cap)
+{
+       return dm_pci_find_next_ext_capability(dev, 0, cap);
+}
+
 UCLASS_DRIVER(pci) = {
        .id             = UCLASS_PCI,
        .name           = "pci",
index 938a8390cbfca66f8ca7683801f83a220c3a3e7b..785d7d28b7e44c3500587624665349dcae90c493 100644 (file)
@@ -1312,6 +1312,29 @@ pci_addr_t dm_pci_phys_to_bus(struct udevice *dev, phys_addr_t addr,
  */
 void *dm_pci_map_bar(struct udevice *dev, int bar, int flags);
 
+/**
+ * dm_pci_find_next_capability() - find a capability starting from an offset
+ *
+ * Tell if a device supports a given PCI capability. Returns the
+ * address of the requested capability structure within the device's
+ * PCI configuration space or 0 in case the device does not support it.
+ *
+ * Possible values for @cap:
+ *
+ *  %PCI_CAP_ID_MSI    Message Signalled Interrupts
+ *  %PCI_CAP_ID_PCIX   PCI-X
+ *  %PCI_CAP_ID_EXP    PCI Express
+ *  %PCI_CAP_ID_MSIX   MSI-X
+ *
+ * See PCI_CAP_ID_xxx for the complete capability ID codes.
+ *
+ * @dev:       PCI device to query
+ * @start:     offset to start from
+ * @cap:       capability code
+ * @return:    capability address or 0 if not supported
+ */
+int dm_pci_find_next_capability(struct udevice *dev, u8 start, int cap);
+
 /**
  * dm_pci_find_capability() - find a capability
  *
@@ -1334,6 +1357,31 @@ void *dm_pci_map_bar(struct udevice *dev, int bar, int flags);
  */
 int dm_pci_find_capability(struct udevice *dev, int cap);
 
+/**
+ * dm_pci_find_next_ext_capability() - find an extended capability
+ *                                    starting from an offset
+ *
+ * Tell if a device supports a given PCI express extended capability.
+ * Returns the address of the requested extended capability structure
+ * within the device's PCI configuration space or 0 in case the device
+ * does not support it.
+ *
+ * Possible values for @cap:
+ *
+ *  %PCI_EXT_CAP_ID_ERR        Advanced Error Reporting
+ *  %PCI_EXT_CAP_ID_VC Virtual Channel
+ *  %PCI_EXT_CAP_ID_DSN        Device Serial Number
+ *  %PCI_EXT_CAP_ID_PWR        Power Budgeting
+ *
+ * See PCI_EXT_CAP_ID_xxx for the complete extended capability ID codes.
+ *
+ * @dev:       PCI device to query
+ * @start:     offset to start from
+ * @cap:       extended capability code
+ * @return:    extended capability address or 0 if not supported
+ */
+int dm_pci_find_next_ext_capability(struct udevice *dev, int start, int cap);
+
 /**
  * dm_pci_find_ext_capability() - find an extended capability
  *