device/xhci: Add xHCI utility to enumerate capabilities

This will allow enumerating an xHCI controller to allow dynamically
generating the ACPI device nodes.

BUG=b:154756391
TEST=Boot trembyle and see capabilities printed on console
xHCI Supported Protocol:
  Major: 0x2, Minor: 0x0, Protocol: 'USB '
  Port Offset: 1, Port Count: 2
xHCI Supported Protocol:
  Major: 0x3, Minor: 0x10, Protocol: 'USB '
  Port Offset: 3, Port Count: 1

Signed-off-by: Raul E Rangel <rrangel@chromium.org>
Change-Id: I3065c3fffad01b5378a55cfe904f971079b13d0f
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41899
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
Raul E Rangel 2020-05-29 17:16:20 -06:00 committed by Patrick Georgi
parent 26a0c66c13
commit a5b7ddf940
4 changed files with 150 additions and 0 deletions

View file

@ -811,4 +811,9 @@ config RESOURCE_ALLOCATOR_V4
ranges for allocating resources. This allows allocation of resources ranges for allocating resources. This allows allocation of resources
above 4G boundary as well. above 4G boundary as well.
config XHCI_UTILS
def_bool n
help
Provides xHCI utility functions.
endmenu endmenu

View file

@ -62,3 +62,5 @@ ramstage-y += mmio.c
ramstage-y += resource_allocator_common.c ramstage-y += resource_allocator_common.c
ramstage-$(CONFIG_RESOURCE_ALLOCATOR_V3) += resource_allocator_v3.c ramstage-$(CONFIG_RESOURCE_ALLOCATOR_V3) += resource_allocator_v3.c
ramstage-$(CONFIG_RESOURCE_ALLOCATOR_V4) += resource_allocator_v4.c ramstage-$(CONFIG_RESOURCE_ALLOCATOR_V4) += resource_allocator_v4.c
ramstage-$(CONFIG_XHCI_UTILS) += xhci.c

86
src/device/xhci.c Normal file
View file

@ -0,0 +1,86 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <device/xhci.h>
#include <console/console.h>
#include <device/pci_def.h>
#include <arch/mmio.h>
union xhci_ext_caps_header {
uint32_t val;
struct {
uint32_t cap_id : 8;
uint32_t next_ptr : 8;
uint32_t reserved : 16;
};
};
enum cb_err xhci_for_each_ext_cap(const struct device *device, void *context,
void (*callback)(void *context,
const struct xhci_ext_cap *cap))
{
struct resource *res;
uint32_t *ext_cap_ptr;
uint32_t ext_caps_word_offset;
union xhci_ext_caps_header header;
struct xhci_ext_cap cap;
if (!device || !callback)
return CB_ERR_ARG;
res = probe_resource(device, PCI_BASE_ADDRESS_0);
if (!res) {
printk(BIOS_ERR, "%s: Unable to find BAR resource for %s\n", __func__,
dev_path(device));
return CB_ERR;
}
if (!(res->flags & IORESOURCE_ASSIGNED)) {
printk(BIOS_ERR, "%s: BAR is is not assigned\n", __func__);
return CB_ERR;
}
if (res->limit > 0xFFFFFFFF) {
printk(BIOS_ERR, "%s: 64-bit BAR is not supported\n", __func__);
return CB_ERR;
}
ext_caps_word_offset = read16(res2mmio(res, XHCI_HCCPARAMS1_XECP, 0));
if (!ext_caps_word_offset) {
printk(BIOS_ERR, "%s: No extended capabilities defined\n", __func__);
return CB_ERR;
}
ext_cap_ptr = res2mmio(res, ext_caps_word_offset << 2, 0);
while ((uintptr_t)ext_cap_ptr < (uintptr_t)res->limit) {
header.val = read32(ext_cap_ptr);
cap.cap_id = header.cap_id;
if (header.cap_id == XHCI_ECP_CAP_ID_SUPP) {
cap.supported_protocol.reg0 = header.val;
cap.supported_protocol.reg1 = read32(ext_cap_ptr + 1);
cap.supported_protocol.reg2 = read32(ext_cap_ptr + 2);
}
callback(context, &cap);
if (!header.next_ptr)
break;
ext_cap_ptr += header.next_ptr;
}
return CB_SUCCESS;
}
void xhci_print_supported_protocol(const struct xhci_supported_protocol *supported_protocol)
{
printk(BIOS_DEBUG, "xHCI Supported Protocol:\n");
printk(BIOS_DEBUG, " Major: %#x, Minor: %#x, Protocol: '%.*s'\n",
supported_protocol->major_rev, supported_protocol->minor_rev,
(int)sizeof(supported_protocol->name), supported_protocol->name);
printk(BIOS_DEBUG, " Port Offset: %d, Port Count: %d\n",
supported_protocol->port_offset, supported_protocol->port_count);
}

57
src/include/device/xhci.h Normal file
View file

@ -0,0 +1,57 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef __DEVICE_XHCI_H__
#define __DEVICE_XHCI_H__
#include <stdint.h>
#include <device/device.h>
#include <commonlib/bsd/cb_err.h>
#define XHCI_HCCPARAMS1_XECP 0x12
#define XHCI_ECP_CAP_ID_LEGACY 1
#define XHCI_ECP_CAP_ID_SUPP 2
struct xhci_supported_protocol {
union {
uint32_t reg0;
struct {
uint32_t cap_id : 8;
uint32_t next_ptr : 8;
uint32_t minor_rev : 8;
uint32_t major_rev : 8;
};
};
union {
uint32_t reg1;
char name[4];
};
union {
uint32_t reg2;
struct {
uint32_t port_offset : 8;
uint32_t port_count : 8;
uint32_t reserved : 12;
uint32_t protocol_speed_id_count : 4;
};
};
};
struct xhci_ext_cap {
uint32_t cap_id;
/* cap_id is used to select the correct struct in the union. */
union {
struct xhci_supported_protocol supported_protocol;
};
};
/**
* Iterates over the xHCI Extended Capabilities List.
*/
enum cb_err xhci_for_each_ext_cap(const struct device *device, void *context,
void (*callback)(void *context,
const struct xhci_ext_cap *cap));
void xhci_print_supported_protocol(const struct xhci_supported_protocol *supported_protocol);
#endif /* __DEVICE_XHCI_H__ */