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

Reply via email to