summaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ext-caps.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci-ext-caps.h')
-rw-r--r--drivers/usb/host/xhci-ext-caps.h87
1 files changed, 32 insertions, 55 deletions
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h
index 9fe3225e6c61..e0244fb3903d 100644
--- a/drivers/usb/host/xhci-ext-caps.h
+++ b/drivers/usb/host/xhci-ext-caps.h
@@ -91,66 +91,43 @@
#include <linux/io.h>
/**
- * Return the next extended capability pointer register.
- *
- * @base PCI register base address.
- *
- * @ext_offset Offset of the 32-bit register that contains the extended
- * capabilites pointer. If searching for the first extended capability, pass
- * in XHCI_HCC_PARAMS_OFFSET. If searching for the next extended capability,
- * pass in the offset of the current extended capability register.
- *
- * Returns 0 if there is no next extended capability register or returns the register offset
- * from the PCI registers base address.
- */
-static inline int xhci_find_next_cap_offset(void __iomem *base, int ext_offset)
-{
- u32 next;
-
- next = readl(base + ext_offset);
-
- if (ext_offset == XHCI_HCC_PARAMS_OFFSET) {
- /* Find the first extended capability */
- next = XHCI_HCC_EXT_CAPS(next);
- ext_offset = 0;
- } else {
- /* Find the next extended capability */
- next = XHCI_EXT_CAPS_NEXT(next);
- }
-
- if (!next)
- return 0;
- /*
- * Address calculation from offset of extended capabilities
- * (or HCCPARAMS) register - see section 5.3.6 and section 7.
- */
- return ext_offset + (next << 2);
-}
-
-/**
* Find the offset of the extended capabilities with capability ID id.
*
- * @base PCI MMIO registers base address.
- * @ext_offset Offset from base of the first extended capability to look at,
- * or the address of HCCPARAMS.
- * @id Extended capability ID to search for.
+ * @base PCI MMIO registers base address.
+ * @start address at which to start looking, (0 or HCC_PARAMS to start at
+ * beginning of list)
+ * @id Extended capability ID to search for.
*
- * This uses an arbitrary limit of XHCI_MAX_EXT_CAPS extended capabilities
- * to make sure that the list doesn't contain a loop.
+ * Returns the offset of the next matching extended capability structure.
+ * Some capabilities can occur several times, e.g., the XHCI_EXT_CAPS_PROTOCOL,
+ * and this provides a way to find them all.
*/
-static inline int xhci_find_ext_cap_by_id(void __iomem *base, int ext_offset, int id)
+
+static inline int xhci_find_next_ext_cap(void __iomem *base, u32 start, int id)
{
u32 val;
- int limit = XHCI_MAX_EXT_CAPS;
-
- while (ext_offset && limit > 0) {
- val = readl(base + ext_offset);
- if (XHCI_EXT_CAPS_ID(val) == id)
- break;
- ext_offset = xhci_find_next_cap_offset(base, ext_offset);
- limit--;
- }
- if (limit > 0)
- return ext_offset;
+ u32 next;
+ u32 offset;
+
+ offset = start;
+ if (!start || start == XHCI_HCC_PARAMS_OFFSET) {
+ val = readl(base + XHCI_HCC_PARAMS_OFFSET);
+ if (val == ~0)
+ return 0;
+ offset = XHCI_HCC_EXT_CAPS(val) << 2;
+ if (!offset)
+ return 0;
+ };
+ do {
+ val = readl(base + offset);
+ if (val == ~0)
+ return 0;
+ if (XHCI_EXT_CAPS_ID(val) == id && offset != start)
+ return offset;
+
+ next = XHCI_EXT_CAPS_NEXT(val);
+ offset += next << 2;
+ } while (next);
+
return 0;
}