Raul Rangel has uploaded this change for review.

View Change

soc/amd/common/blocks/xhci: Add an AMD block to generate xHCI ACPI nodes

We can use xhci_for_each_ext_cap to inspect the xHC so we generate the
correct number of device nodes.

BUG=b:154756391
TEST=Boot trembyle and look at ACPI table. See all xHCI nodes.

Signed-off-by: Raul E Rangel <rrangel@chromium.org>
Change-Id: I44ebaef342e45923bc181ceebef882358d33f0d1
---
A src/soc/amd/common/block/xhci/Kconfig
A src/soc/amd/common/block/xhci/Makefile.inc
A src/soc/amd/common/block/xhci/xhci.c
3 files changed, 128 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/00/41900/1
diff --git a/src/soc/amd/common/block/xhci/Kconfig b/src/soc/amd/common/block/xhci/Kconfig
new file mode 100644
index 0000000..5751907
--- /dev/null
+++ b/src/soc/amd/common/block/xhci/Kconfig
@@ -0,0 +1,5 @@
+config SOC_AMD_COMMON_BLOCK_XHCI
+ bool
+ default n
+ help
+ Select this option to use AMD common xhci driver support.
diff --git a/src/soc/amd/common/block/xhci/Makefile.inc b/src/soc/amd/common/block/xhci/Makefile.inc
new file mode 100644
index 0000000..2387450
--- /dev/null
+++ b/src/soc/amd/common/block/xhci/Makefile.inc
@@ -0,0 +1 @@
+ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_XHCI) += xhci.c
diff --git a/src/soc/amd/common/block/xhci/xhci.c b/src/soc/amd/common/block/xhci/xhci.c
new file mode 100644
index 0000000..72bb9bb
--- /dev/null
+++ b/src/soc/amd/common/block/xhci/xhci.c
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpigen.h>
+#include <amdblocks/gpio_banks.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <device/pci_ehci.h>
+#include <soc/acpi.h>
+#include <soc/pci_devs.h>
+#include <soc/smi.h>
+#include <soc/southbridge.h>
+#include <amdblocks/acpimmio.h>
+#include <device/xhci.h>
+
+#define XHCI_GEVENT GEVENT_31
+
+struct port_counts {
+ unsigned int high_speed;
+ unsigned int super_speed;
+};
+
+static void handle_xhci_ext_cap(void *context, const struct xhci_ext_cap *cap)
+{
+ const struct xhci_supported_protocol *data;
+ const char *format;
+ char buf[16];
+ struct port_counts *counts = context;
+ unsigned int *dev_num;
+
+ if (cap->cap_id != XHCI_ECP_CAP_ID_SUPP)
+ return;
+
+ data = &cap->supported_protocol;
+
+ if (memcmp(data->name, "USB ", 4)) {
+ printk(BIOS_INFO, "%s: Unknown Protocol: %.*s\n", __func__,
+ (int)sizeof(data->name), data->name);
+ return;
+ }
+
+ if (data->major_rev == 3) {
+ format = "SS%02d";
+ dev_num = &counts->super_speed;
+ } else if (data->major_rev == 2) {
+ format = "HS%02d";
+ dev_num = &counts->high_speed;
+ } else {
+ printk(BIOS_INFO, "%s: Unknown USB Version: %#x\n", __func__, data->major_rev);
+ return;
+ }
+
+ for (unsigned int i = 0; i < data->port_count; ++i) {
+ snprintf(buf, sizeof(buf), format, ++(*dev_num));
+ acpigen_write_device(buf);
+ acpigen_write_name_byte("_ADR", data->port_offset + i);
+ acpigen_pop_len();
+ }
+}
+
+static void xhci_add_devices(const struct device *device)
+{
+ struct port_counts counts = {0, 0};
+
+ acpigen_write_device("RHUB");
+ acpigen_write_name_integer("_ADR", 0x00000000);
+
+ xhci_for_each_ext_cap(device, &counts, handle_xhci_ext_cap);
+
+ /* Exit RHUB device */
+ acpigen_pop_len();
+}
+
+static void xhci_fill_ssdt_generator(const struct device *device)
+{
+ printk(BIOS_INFO, "xHCI SSDT generation\n");
+
+ /* Write SSDT entry for xHCI controller */
+ acpigen_write_scope(acpi_device_scope(device));
+ acpigen_write_device(acpi_device_name(device));
+ acpigen_write_ADR_pci_device(device);
+ acpigen_write_STA(acpi_device_status(device));
+ acpigen_write_PRW(XHCI_GEVENT, 3);
+
+ xhci_add_devices(device);
+
+ acpigen_write_name_integer("_S0W", 0);
+ acpigen_write_name_integer("_S3W", 4);
+ acpigen_write_name_integer("_S4W", 4);
+
+ acpigen_pop_len(); // xHCI device
+
+ acpigen_pop_len(); // Bridge scope
+}
+
+static struct pci_operations lops_pci = {
+ .set_subsystem = pci_dev_set_subsystem,
+};
+
+static struct device_operations usb_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .scan_bus = scan_static_bus,
+ .ops_pci = &lops_pci,
+ .acpi_fill_ssdt = xhci_fill_ssdt_generator,
+};
+
+static const unsigned short pci_device_ids[] = {
+ PCI_DEVICE_ID_AMD_FAM17H_MODEL18H_XHCI0,
+ PCI_DEVICE_ID_AMD_FAM17H_MODEL18H_XHCI1,
+ PCI_DEVICE_ID_AMD_FAM17H_MODEL20H_XHCI0,
+ 0
+};
+
+static const struct pci_driver usb_0_driver __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_AMD,
+ .devices = pci_device_ids,
+};

To view, visit change 41900. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I44ebaef342e45923bc181ceebef882358d33f0d1
Gerrit-Change-Number: 41900
Gerrit-PatchSet: 1
Gerrit-Owner: Raul Rangel <rrangel@chromium.org>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange