Module Name: src Committed By: jmcneill Date: Mon Dec 9 22:15:34 UTC 2024
Modified Files: src/sys/dev/acpi: xhci_acpi.c Log Message: acpi: xhci: Add support for generic USB role switching device nodes. URS nodes have a child node that contains the interrupt resource for the XHCI. Match the URS nodes and add support for obtaining the interrupt from this child node. To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/sys/dev/acpi/xhci_acpi.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/acpi/xhci_acpi.c diff -u src/sys/dev/acpi/xhci_acpi.c:1.13 src/sys/dev/acpi/xhci_acpi.c:1.14 --- src/sys/dev/acpi/xhci_acpi.c:1.13 Sat Aug 7 16:19:09 2021 +++ src/sys/dev/acpi/xhci_acpi.c Mon Dec 9 22:15:33 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: xhci_acpi.c,v 1.13 2021/08/07 16:19:09 thorpej Exp $ */ +/* $NetBSD: xhci_acpi.c,v 1.14 2024/12/09 22:15:33 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xhci_acpi.c,v 1.13 2021/08/07 16:19:09 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xhci_acpi.c,v 1.14 2024/12/09 22:15:33 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -49,6 +49,8 @@ __KERNEL_RCSID(0, "$NetBSD: xhci_acpi.c, #include <dev/acpi/acpi_intr.h> #include <dev/acpi/acpi_usb.h> +#define XHCI_ACPI_FLAG_URS __BIT(0) + static const struct device_compatible_entry compat_data[] = { /* XHCI-compliant USB controller without standard debug */ { .compat = "PNP0D10" }, @@ -57,7 +59,10 @@ static const struct device_compatible_en { .compat = "PNP0D15" }, /* DesignWare Dual Role SuperSpeed USB controller */ - { .compat = "808622B7", }, + { .compat = "808622B7" }, + + /* XHCI-compliant URS USB controller */ + { .compat = "PNP0CA1", .value = XHCI_ACPI_FLAG_URS }, DEVICE_COMPAT_EOL }; @@ -90,14 +95,18 @@ xhci_acpi_attach(device_t parent, device struct xhci_acpi_softc * const asc = device_private(self); struct xhci_softc * const sc = &asc->sc_xhci; struct acpi_attach_args *aa = aux; - struct acpi_resources res; + struct acpi_resources res, res_urs; struct acpi_mem *mem; struct acpi_irq *irq; uint32_t hccparams; + uintptr_t flags; ACPI_STATUS rv; + bool res_urs_valid = false; int error; void *ih; + flags = acpi_compatible_lookup(aa, compat_data)->value; + asc->sc_handle = aa->aa_node->ad_handle; sc->sc_dev = self; @@ -117,10 +126,38 @@ xhci_acpi_attach(device_t parent, device goto done; } - irq = acpi_res_irq(&res, 0); - if (irq == NULL) { - aprint_error_dev(self, "couldn't find irq resource\n"); - goto done; + if ((flags & XHCI_ACPI_FLAG_URS) == 0) { + irq = acpi_res_irq(&res, 0); + if (irq == NULL) { + aprint_error_dev(self, "couldn't find irq resource\n"); + goto done; + } + } else { + struct acpi_devnode *ad; + + /* For URS nodes, the interrupt resources is on a child with _ADR=0. */ + irq = NULL; + SIMPLEQ_FOREACH(ad, &aa->aa_node->ad_child_head, ad_child_list) { + ACPI_INTEGER adr; + if (acpi_eval_integer(ad->ad_handle, "_ADR", &adr) == AE_OK && + adr == 0) { + rv = acpi_resource_parse(sc->sc_dev, ad->ad_handle, + "_CRS", &res_urs, &acpi_resource_parse_ops_quiet); + if (ACPI_FAILURE(rv)) { + aprint_error_dev(self, + "couldn't parse URS resources: %s\n", + AcpiFormatException(rv)); + goto done; + } + res_urs_valid = true; + irq = acpi_res_irq(&res_urs, 0); + break; + } + } + if (irq == NULL) { + aprint_error_dev(self, "couldn't find irq resource\n"); + goto done; + } } sc->sc_ios = mem->ar_length; @@ -146,8 +183,7 @@ xhci_acpi_attach(device_t parent, device sc->sc_bus.ub_dmatag = aa->aa_dmat; } - ih = acpi_intr_establish(self, - (uint64_t)(uintptr_t)aa->aa_node->ad_handle, + ih = acpi_intr_establish_irq(self, irq, IPL_USB, true, xhci_intr, sc, device_xname(self)); if (ih == NULL) { aprint_error_dev(self, "couldn't establish interrupt\n"); @@ -166,6 +202,9 @@ xhci_acpi_attach(device_t parent, device done: acpi_resource_cleanup(&res); + if (res_urs_valid) { + acpi_resource_cleanup(&res_urs); + } } static void