Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 7 May 2022 10:20:31 GMT
From:      Ruslan Bukin <br@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: a5ec261a7c57 - main - Add FDT attachment driver for ARM System MMU v3.2 controller.
Message-ID:  <202205071020.247AKV0B064635@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by br:

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

commit a5ec261a7c57758e9b77c1c3af0bdbb5165b3e3c
Author:     Ruslan Bukin <br@FreeBSD.org>
AuthorDate: 2022-05-07 10:13:46 +0000
Commit:     Ruslan Bukin <br@FreeBSD.org>
CommitDate: 2022-05-07 10:18:35 +0000

    Add FDT attachment driver for ARM System MMU v3.2 controller.
    
    Tested on ARM Morello Board.
    
    Sponsored by:   UKRI
---
 sys/arm64/iommu/smmu.c      |  63 ++++++++++++++++----
 sys/arm64/iommu/smmu_acpi.c |   4 +-
 sys/arm64/iommu/smmu_fdt.c  | 138 ++++++++++++++++++++++++++++++++++++++++++++
 sys/arm64/iommu/smmuvar.h   |   2 +-
 sys/conf/files.arm64        |   3 +-
 5 files changed, 195 insertions(+), 15 deletions(-)

diff --git a/sys/arm64/iommu/smmu.c b/sys/arm64/iommu/smmu.c
index 1f2d7283be72..74b68ce1d07a 100644
--- a/sys/arm64/iommu/smmu.c
+++ b/sys/arm64/iommu/smmu.c
@@ -98,13 +98,15 @@ __FBSDID("$FreeBSD$");
 #include <sys/bus.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/mutex.h>
 #include <sys/rman.h>
 #include <sys/lock.h>
+#include <sys/sysctl.h>
 #include <sys/tree.h>
 #include <sys/taskqueue.h>
 #include <vm/vm.h>
 #include <vm/vm_page.h>
-#if DEV_ACPI
+#ifdef DEV_ACPI
 #include <contrib/dev/acpica/include/acpi.h>
 #include <dev/acpica/acpivar.h>
 #endif
@@ -113,6 +115,14 @@ __FBSDID("$FreeBSD$");
 #include <dev/iommu/iommu.h>
 #include <arm64/iommu/iommu_pmap.h>
 
+#include <machine/bus.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
 #include "iommu.h"
 #include "iommu_if.h"
 
@@ -144,6 +154,7 @@ static struct resource_spec smmu_spec[] = {
 	{ SYS_RES_IRQ, 0, RF_ACTIVE },
 	{ SYS_RES_IRQ, 1, RF_ACTIVE },
 	{ SYS_RES_IRQ, 2, RF_ACTIVE },
+	{ SYS_RES_IRQ, 3, RF_ACTIVE },
 	RESOURCE_SPEC_END
 };
 
@@ -1129,7 +1140,7 @@ smmu_enable_interrupts(struct smmu_softc *sc)
 	return (0);
 }
 
-#if DEV_ACPI
+#ifdef DEV_ACPI
 static void
 smmu_configure_intr(struct smmu_softc *sc, struct resource *res)
 {
@@ -1155,14 +1166,15 @@ smmu_setup_interrupts(struct smmu_softc *sc)
 
 	dev = sc->dev;
 
-#if DEV_ACPI
+#ifdef DEV_ACPI
 	/*
 	 * Configure SMMU interrupts as EDGE triggered manually
 	 * as ACPI tables carries no information for that.
 	 */
 	smmu_configure_intr(sc, sc->res[1]);
-	smmu_configure_intr(sc, sc->res[2]);
+	/* PRIQ is not in use. */
 	smmu_configure_intr(sc, sc->res[3]);
+	smmu_configure_intr(sc, sc->res[4]);
 #endif
 
 	error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC,
@@ -1172,7 +1184,7 @@ smmu_setup_interrupts(struct smmu_softc *sc)
 		return (ENXIO);
 	}
 
-	error = bus_setup_intr(dev, sc->res[3], INTR_TYPE_MISC,
+	error = bus_setup_intr(dev, sc->res[4], INTR_TYPE_MISC,
 	    smmu_gerr_intr, NULL, sc, &sc->intr_cookie[2]);
 	if (error) {
 		device_printf(dev, "Couldn't setup Gerr interrupt handler\n");
@@ -1761,18 +1773,28 @@ smmu_ctx_alloc(device_t dev, struct iommu_domain *iodom, device_t child,
 	struct smmu_domain *domain;
 	struct smmu_softc *sc;
 	struct smmu_ctx *ctx;
+#ifdef DEV_ACPI
 	uint16_t rid;
-	u_int xref, sid;
+	u_int xref;
 	int seg;
+#else
+	struct pci_id_ofw_iommu pi;
+#endif
+	u_int sid;
 	int err;
 
 	sc = device_get_softc(dev);
 	domain = (struct smmu_domain *)iodom;
 
+#ifdef DEV_ACPI
 	seg = pci_get_domain(child);
 	rid = pci_get_rid(child);
 	err = acpi_iort_map_pci_smmuv3(seg, rid, &xref, &sid);
-	if (err)
+#else
+	err = pci_get_id(child, PCI_ID_OFW_IOMMU, (uintptr_t *)&pi);
+	sid = pi.id;
+#endif
+	if (err != 0)
 		return (NULL);
 
 	if (sc->features & SMMU_FEATURE_2_LVL_STREAM_TABLE) {
@@ -1852,7 +1874,7 @@ smmu_ctx_lookup_by_sid(device_t dev, u_int sid)
 static struct iommu_ctx *
 smmu_ctx_lookup(device_t dev, device_t child)
 {
-	struct iommu_unit *iommu;
+	struct iommu_unit *iommu __unused;
 	struct smmu_softc *sc;
 	struct smmu_domain *domain;
 	struct smmu_unit *unit;
@@ -1883,15 +1905,24 @@ static int
 smmu_find(device_t dev, device_t child)
 {
 	struct smmu_softc *sc;
-	u_int xref, sid;
-	uint16_t rid;
+	u_int xref;
 	int error;
+#ifdef DEV_ACPI
+	uint16_t rid;
 	int seg;
+	u_int sid;
+#else
+	phandle_t node;
+	uint64_t base, size;
+	struct pci_id_ofw_iommu pi;
+#endif
 
 	sc = device_get_softc(dev);
 
+#ifdef DEV_ACPI
 	rid = pci_get_rid(child);
 	seg = pci_get_domain(child);
+#endif
 
 	/*
 	 * Find an xref of an IOMMU controller that serves traffic for dev.
@@ -1903,8 +1934,16 @@ smmu_find(device_t dev, device_t child)
 		return (ENOENT);
 	}
 #else
-	/* TODO: add FDT support. */
-	return (ENXIO);
+	error = pci_get_id(child, PCI_ID_OFW_IOMMU, (uintptr_t *)&pi);
+	if (error) {
+		/* Could not find reference to an SMMU device. */
+		return (ENOENT);
+	}
+
+	/* Our xref is memory base address. */
+	node = OF_node_from_xref(pi.xref);
+	fdt_regsize(node, &base, &size);
+	xref = base;
 #endif
 
 	/* Check if xref is ours. */
diff --git a/sys/arm64/iommu/smmu_acpi.c b/sys/arm64/iommu/smmu_acpi.c
index d7a2c0444fdf..6ddbb0138c87 100644
--- a/sys/arm64/iommu/smmu_acpi.c
+++ b/sys/arm64/iommu/smmu_acpi.c
@@ -146,8 +146,10 @@ smmu_acpi_identify(driver_t *driver, device_t parent)
 		BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 0,
 		    iort_data.smmu[i]->EventGsiv, 1);
 		BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 1,
-		    iort_data.smmu[i]->SyncGsiv, 1);
+		    iort_data.smmu[i]->PriGsiv, 1);
 		BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 2,
+		    iort_data.smmu[i]->SyncGsiv, 1);
+		BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 3,
 		    iort_data.smmu[i]->GerrGsiv, 1);
 		BUS_SET_RESOURCE(parent, dev, SYS_RES_MEMORY, 0,
 		    iort_data.smmu[i]->BaseAddress, MEMORY_RESOURCE_SIZE);
diff --git a/sys/arm64/iommu/smmu_fdt.c b/sys/arm64/iommu/smmu_fdt.c
new file mode 100644
index 000000000000..86cf0f9fd0cf
--- /dev/null
+++ b/sys/arm64/iommu/smmu_fdt.c
@@ -0,0 +1,138 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2022 Ruslan Bukin <br@bsdpad.com>
+ *
+ * This work was supported by Innovate UK project 105694, "Digital Security
+ * by Design (DSbD) Technology Platform Prototype".
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/bitstring.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/tree.h>
+#include <sys/taskqueue.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/iommu/iommu.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/iommu/iommu.h>
+
+#include <arm64/iommu/iommu.h>
+
+#include "smmuvar.h"
+
+static struct ofw_compat_data compat_data[] = {
+	{ "arm,smmu-v3",			1 },
+	{ NULL,					0 }
+};
+
+static int
+smmu_fdt_probe(device_t dev)
+{
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+		return (ENXIO);
+
+	device_set_desc(dev, "ARM System MMU (SMMU) v3");
+
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+smmu_fdt_attach(device_t dev)
+{
+	struct smmu_softc *sc;
+	struct smmu_unit *unit;
+	struct iommu_unit *iommu;
+	int err;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+
+	err = smmu_attach(dev);
+	if (err != 0)
+		goto error;
+
+	unit = &sc->unit;
+	unit->dev = dev;
+
+	iommu = &unit->iommu;
+	iommu->dev = dev;
+
+	LIST_INIT(&unit->domain_list);
+
+	/* Use memory start address as an xref. */
+	sc->xref = bus_get_resource_start(dev, SYS_RES_MEMORY, 0);
+
+	err = iommu_register(iommu);
+	if (err) {
+		device_printf(dev, "Failed to register SMMU.\n");
+		return (ENXIO);
+	}
+
+	return (0);
+
+error:
+	if (bootverbose) {
+		device_printf(dev,
+		    "Failed to attach. Error %d\n", err);
+	}
+
+	/* Failure so free resources. */
+	smmu_detach(dev);
+
+	return (err);
+}
+
+static device_method_t smmu_fdt_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		smmu_fdt_probe),
+	DEVMETHOD(device_attach,	smmu_fdt_attach),
+	DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(smmu, smmu_fdt_driver, smmu_fdt_methods,
+    sizeof(struct smmu_softc), smmu_driver);
+
+static devclass_t smmu_fdt_devclass;
+
+EARLY_DRIVER_MODULE(smmu, simplebus, smmu_fdt_driver, smmu_fdt_devclass,
+    0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
diff --git a/sys/arm64/iommu/smmuvar.h b/sys/arm64/iommu/smmuvar.h
index 3a1e5a269c01..76d4f238002d 100644
--- a/sys/arm64/iommu/smmuvar.h
+++ b/sys/arm64/iommu/smmuvar.h
@@ -136,7 +136,7 @@ struct smmu_strtab {
 
 struct smmu_softc {
 	device_t		dev;
-	struct resource		*res[4];
+	struct resource		*res[5];
 	void			*intr_cookie[3];
 	uint32_t		ias; /* Intermediate Physical Address */
 	uint32_t		oas; /* Physical Address */
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 5ee973a7b514..30358a5d67d1 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -106,7 +106,8 @@ arm64/iommu/iommu.c				optional iommu
 arm64/iommu/iommu_if.m				optional iommu
 arm64/iommu/iommu_pmap.c			optional iommu
 arm64/iommu/smmu.c				optional iommu
-arm64/iommu/smmu_acpi.c				optional acpi iommu
+arm64/iommu/smmu_acpi.c				optional iommu acpi
+arm64/iommu/smmu_fdt.c				optional iommu fdt
 arm64/iommu/smmu_quirks.c			optional iommu
 dev/iommu/busdma_iommu.c			optional iommu
 dev/iommu/iommu_gas.c				optional iommu



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202205071020.247AKV0B064635>