1 /* SPDX-License-Identifier: GPL-2.0-or-later */
4 #include <console/console.h>
5 #include <device/pci_def.h>
6 #include <device/xhci.h>
9 union xhci_ext_caps_header
{
13 uint32_t next_ptr
: 8;
14 uint32_t reserved
: 16;
18 enum cb_err
xhci_resource_for_each_ext_cap(const struct resource
*res
, void *context
,
19 void (*callback
)(void *context
,
20 const struct xhci_ext_cap
*cap
))
22 uint32_t *ext_cap_ptr
;
23 uint32_t ext_caps_word_offset
;
24 union xhci_ext_caps_header header
;
25 struct xhci_ext_cap cap
;
27 if (!res
|| !callback
)
30 if (!(res
->flags
& IORESOURCE_ASSIGNED
)) {
31 printk(BIOS_ERR
, "%s: BAR is not assigned\n", __func__
);
35 if (res
->limit
> 0xFFFFFFFF) {
36 printk(BIOS_ERR
, "%s: 64-bit BAR is not supported\n", __func__
);
40 ext_caps_word_offset
= read16(res2mmio(res
, XHCI_HCCPARAMS1_XECP
, 0));
42 if (!ext_caps_word_offset
) {
43 printk(BIOS_ERR
, "%s: No extended capabilities defined\n", __func__
);
47 ext_cap_ptr
= res2mmio(res
, ext_caps_word_offset
<< 2, 0);
49 while ((uintptr_t)ext_cap_ptr
< (uintptr_t)res
->limit
) {
50 header
.val
= read32(ext_cap_ptr
);
52 cap
.cap_id
= header
.cap_id
;
54 if (header
.cap_id
== XHCI_ECP_CAP_ID_SUPP
) {
55 cap
.supported_protocol
.reg0
= header
.val
;
56 cap
.supported_protocol
.reg1
= read32(ext_cap_ptr
+ 1);
57 cap
.supported_protocol
.reg2
= read32(ext_cap_ptr
+ 2);
60 callback(context
, &cap
);
65 ext_cap_ptr
+= header
.next_ptr
;
71 struct supported_usb_cap_context
{
73 void (*callback
)(void *context
, const struct xhci_supported_protocol
*data
);
76 static void xhci_supported_usb_cap_handler(void *context
, const struct xhci_ext_cap
*cap
)
78 const struct xhci_supported_protocol
*data
;
79 struct supported_usb_cap_context
*internal_context
= context
;
81 if (cap
->cap_id
!= XHCI_ECP_CAP_ID_SUPP
)
84 data
= &cap
->supported_protocol
;
86 if (memcmp(data
->name
, "USB ", 4)) {
87 printk(BIOS_DEBUG
, "%s: Unknown Protocol: %.*s\n", __func__
,
88 (int)sizeof(data
->name
), data
->name
);
92 internal_context
->callback(internal_context
->context
, data
);
95 enum cb_err
xhci_resource_for_each_supported_usb_cap(
96 const struct resource
*res
, void *context
,
97 void (*callback
)(void *context
, const struct xhci_supported_protocol
*data
))
99 struct supported_usb_cap_context internal_context
= {
101 .callback
= callback
,
104 return xhci_resource_for_each_ext_cap(res
, &internal_context
,
105 xhci_supported_usb_cap_handler
);
108 void xhci_print_supported_protocol(const struct xhci_supported_protocol
*supported_protocol
)
110 printk(BIOS_DEBUG
, "xHCI Supported Protocol:\n");
111 printk(BIOS_DEBUG
, " Major: %#x, Minor: %#x, Protocol: '%.*s'\n",
112 supported_protocol
->major_rev
, supported_protocol
->minor_rev
,
113 (int)sizeof(supported_protocol
->name
), supported_protocol
->name
);
114 printk(BIOS_DEBUG
, " Port Offset: %d, Port Count: %d\n",
115 supported_protocol
->port_offset
, supported_protocol
->port_count
);