git: 9f24c7d54222 - main - dev: acpica: Add PCI device methods for aarch64

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Thu, 17 Sep 2026 09:56:04 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=9f24c7d5422285d2a89c50253c54aa1502f26dd7

commit 9f24c7d5422285d2a89c50253c54aa1502f26dd7
Author:     Sarah Walker <sarah.walker2@arm.com>
AuthorDate: 2026-08-04 12:35:08 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-09-17 09:20:22 +0000

    dev: acpica: Add PCI device methods for aarch64
    
    Add pci_get_id() and pci_alloc_msi() device methods for aarch64 platforms.
    
    Reviewed by:    markj (earlier version), andrew
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D59169
---
 sys/arm64/acpica/acpi_iort.c | 60 ++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/acpica/acpi.c        | 39 ++++++++++++++++++++++++++++
 sys/dev/acpica/acpivar.h     |  2 ++
 3 files changed, 101 insertions(+)

diff --git a/sys/arm64/acpica/acpi_iort.c b/sys/arm64/acpica/acpi_iort.c
index eef2575fe432..3ca1ff0e32df 100644
--- a/sys/arm64/acpica/acpi_iort.c
+++ b/sys/arm64/acpica/acpi_iort.c
@@ -763,6 +763,19 @@ acpi_iort_lookup_iwb_node(device_t bus, device_t child)
 	return (NULL);
 }
 
+int
+acpi_iort_lookup_pci_id(device_t bus, device_t child, uintptr_t *devid)
+{
+	struct iort_node *node;
+
+	node = acpi_iort_lookup_iwb_node(bus, child);
+	if (!node)
+		return (ENODEV);
+
+	*devid = node->entries.mappings[0].outbase;
+	return (0);
+}
+
 int
 acpi_iort_lookup_its_from_iwb(device_t dev, int *its_id)
 {
@@ -786,6 +799,53 @@ acpi_iort_lookup_its_from_iwb(device_t dev, int *its_id)
 	return (ENODEV);
 }
 
+int
+acpi_iort_alloc_msi(device_t bus, device_t dev, int *count)
+{
+        int *irqs;
+        int irq_count;
+        int error;
+        int i;
+        int its_id;
+        u_int xref;
+        int pxm;
+
+        irq_count = *count;
+        irqs = mallocarray(irq_count, sizeof(int), M_DEVBUF, M_WAITOK | M_ZERO);
+
+        error = acpi_iort_lookup_its_from_iwb(dev, &its_id);
+        if (error)
+                return (error);
+
+        error = acpi_iort_its_lookup(its_id, &xref, &pxm);
+        if (error)
+                return (error);
+
+        error = intr_alloc_msi(bus, dev, xref, irq_count, irq_count, irqs);
+        if (error)
+                return (error);
+
+        for (i = 0; i < irq_count; i++) {
+                error = bus_generic_rl_set_resource(bus, dev, SYS_RES_IRQ,
+                    i + 1, irqs[i], 1);
+                if (error != 0)
+                        break;
+        }
+
+        *count = irq_count;
+
+        /* Clean up resources if something failed */
+        if (error != 0) {
+                for (int j = 0; j < i; j++) {
+                        bus_generic_rl_delete_resource(bus, dev, SYS_RES_IRQ,
+                            j + 1);
+                }
+        }
+
+        free(irqs, M_DEVBUF);
+        return (error);
+}
+
 device_t
 acpi_iort_get_iwb_dev(int iwb_id)
 {
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 351969058d72..5b4a5024b891 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -158,6 +158,9 @@ static acpi_scan_children_t	acpi_device_scan_children;
 
 static isa_pnp_probe_t		acpi_isa_pnp_probe;
 
+static pci_get_id_t		acpi_pci_get_id;
+static pci_alloc_msi_t		acpi_pci_alloc_msi;
+
 static void	acpi_reserve_resources(device_t dev);
 static int	acpi_sysres_alloc(device_t dev);
 static uint32_t	acpi_isa_get_logicalid(device_t dev);
@@ -251,6 +254,10 @@ static device_method_t acpi_methods[] = {
     /* ISA emulation */
     DEVMETHOD(isa_pnp_probe,		acpi_isa_pnp_probe),
 
+    /* PCI emulation */
+    DEVMETHOD(pci_get_id,		acpi_pci_get_id),
+    DEVMETHOD(pci_alloc_msi,		acpi_pci_alloc_msi),
+
     DEVMETHOD_END
 };
 
@@ -2364,6 +2371,38 @@ acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids)
     return_VALUE (result);
 }
 
+static int
+acpi_pci_get_id(device_t dev, device_t child, enum pci_id_type type,
+    uintptr_t *id)
+{
+	if (dev != device_get_parent(child))
+		return (EINVAL);
+
+        if (type != PCI_ID_MSI)
+                return (EINVAL);
+
+#ifdef __aarch64__
+	if (acpi_iort_lookup_pci_id(dev, child, id) == 0)
+		return (0);
+#endif
+
+	return (ENXIO);
+}
+
+static int
+acpi_pci_alloc_msi(device_t bus, device_t child, int *count)
+{
+	if (bus != device_get_parent(child))
+		return (EINVAL);
+
+#ifdef __aarch64__
+	if (acpi_iort_alloc_msi(bus, child, count) == 0)
+		return (0);
+#endif
+
+	return (ENXIO);
+}
+
 /*
  * Look for a MCFG table.  If it is present, use the settings for
  * domain (segment) 0 to setup PCI config space access via the memory
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index 05d581b77fb9..550c6ceb9c97 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -642,6 +642,8 @@ int	acpi_iort_map_named_smmuv3(const char *devname, u_int rid,
 	    uint64_t *xref, u_int *devid);
 int	acpi_iort_lookup_its_from_iwb(device_t dev, int *its_id);
 device_t	acpi_iort_get_iwb_dev(int iwb_id);
+int	acpi_iort_lookup_pci_id(device_t bus, device_t child, uintptr_t *devid);
+int	acpi_iort_alloc_msi(device_t bus, device_t child, int *count);
 #endif
 #endif /* _KERNEL */
 #endif /* !_ACPIVAR_H_ */