svn commit: r309622 - in head/sys: arm/arm arm64/arm64

Andrew Turner andrew at FreeBSD.org
Tue Dec 6 15:12:17 UTC 2016


Author: andrew
Date: Tue Dec  6 15:12:14 2016
New Revision: 309622
URL: https://svnweb.freebsd.org/changeset/base/309622

Log:
  Create two GIC ivars to find the bus type and GIC hardware version. These
  will be used by the gicv2m and ITS ACPI drivers to only attach to the
  correct parent.
  
  Obtained from:	ABT Systems Ltd
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/sys/arm/arm/gic.c
  head/sys/arm/arm/gic.h
  head/sys/arm/arm/gic_common.h
  head/sys/arm/arm/gic_fdt.c
  head/sys/arm64/arm64/gic_v3.c
  head/sys/arm64/arm64/gic_v3_fdt.c
  head/sys/arm64/arm64/gic_v3_reg.h
  head/sys/arm64/arm64/gic_v3_var.h

Modified: head/sys/arm/arm/gic.c
==============================================================================
--- head/sys/arm/arm/gic.c	Tue Dec  6 14:31:47 2016	(r309621)
+++ head/sys/arm/arm/gic.c	Tue Dec  6 15:12:14 2016	(r309622)
@@ -467,6 +467,9 @@ arm_gic_attach(device_t dev)
 	    "pn 0x%x, arch 0x%x, rev 0x%x, implementer 0x%x irqs %u\n",
 	    GICD_IIDR_PROD(icciidr), GICD_IIDR_VAR(icciidr),
 	    GICD_IIDR_REV(icciidr), GICD_IIDR_IMPL(icciidr), sc->nirqs);
+#ifdef INTRNG
+	sc->gic_iidr = icciidr;
+#endif
 
 	/* Set all global interrupts to be level triggered, active low. */
 	for (i = 32; i < sc->nirqs; i += 16) {
@@ -611,6 +614,33 @@ arm_gic_alloc_resource(device_t bus, dev
 	    count, flags));
 }
 
+static int
+arm_gic_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+	struct arm_gic_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	switch(which) {
+	case GIC_IVAR_HW_REV:
+		KASSERT(GICD_IIDR_VAR(sc->gic_iidr) < 3 &&
+		    GICD_IIDR_VAR(sc->gic_iidr) != 0,
+		    ("arm_gic_read_ivar: Unknown IIDR revision %u (%.08x)",
+		     GICD_IIDR_VAR(sc->gic_iidr), sc->gic_iidr));
+		*result = GICD_IIDR_VAR(sc->gic_iidr);
+		return (0);
+	case GIC_IVAR_BUS:
+		KASSERT(sc->gic_bus != GIC_BUS_UNKNOWN,
+		    ("arm_gic_read_ivar: Unknown bus type"));
+		KASSERT(sc->gic_bus <= GIC_BUS_MAX,
+		    ("arm_gic_read_ivar: Invalid bus type %u", sc->gic_bus));
+		*result = sc->gic_bus;
+		return (0);
+	}
+
+	return (ENOENT);
+}
+
 int
 arm_gic_intr(void *arg)
 {
@@ -1307,6 +1337,7 @@ static device_method_t arm_gic_methods[]
 	DEVMETHOD(bus_alloc_resource,	arm_gic_alloc_resource),
 	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
 	DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
+	DEVMETHOD(bus_read_ivar,	arm_gic_read_ivar),
 
 	/* Interrupt controller interface */
 	DEVMETHOD(pic_disable_intr,	arm_gic_disable_intr),

Modified: head/sys/arm/arm/gic.h
==============================================================================
--- head/sys/arm/arm/gic.h	Tue Dec  6 14:31:47 2016	(r309621)
+++ head/sys/arm/arm/gic.h	Tue Dec  6 15:12:14 2016	(r309622)
@@ -75,6 +75,9 @@ struct arm_gic_softc {
 #endif
 
 #ifdef INTRNG
+	uint32_t		gic_iidr;
+	u_int			gic_bus;
+
 	int			nranges;
 	struct arm_gic_range *	ranges;
 #endif

Modified: head/sys/arm/arm/gic_common.h
==============================================================================
--- head/sys/arm/arm/gic_common.h	Tue Dec  6 14:31:47 2016	(r309621)
+++ head/sys/arm/arm/gic_common.h	Tue Dec  6 15:12:14 2016	(r309622)
@@ -32,6 +32,18 @@
 #ifndef _GIC_COMMON_H_
 #define _GIC_COMMON_H_
 
+#define	GIC_IVAR_HW_REV		500
+#define	GIC_IVAR_BUS		501
+
+/* GIC_IVAR_BUS values */
+#define	GIC_BUS_UNKNOWN		0
+#define	GIC_BUS_FDT		1
+#define	GIC_BUS_ACPI		2
+#define	GIC_BUS_MAX		2
+
+__BUS_ACCESSOR(gic, hw_rev, GIC, HW_REV, u_int);
+__BUS_ACCESSOR(gic, bus, GIC, BUS, u_int);
+
 /* Common register values */
 #define	GICD_CTLR		0x0000				/* v1 ICDDCR */
 #define	GICD_TYPER		0x0004				/* v1 ICDICTR */

Modified: head/sys/arm/arm/gic_fdt.c
==============================================================================
--- head/sys/arm/arm/gic_fdt.c	Tue Dec  6 14:31:47 2016	(r309621)
+++ head/sys/arm/arm/gic_fdt.c	Tue Dec  6 15:12:14 2016	(r309622)
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus_subr.h>
 
 #include <arm/arm/gic.h>
+#include <arm/arm/gic_common.h>
 
 #ifdef INTRNG
 struct arm_gic_devinfo {
@@ -140,6 +141,10 @@ gic_fdt_attach(device_t dev)
 #endif
 	int err;
 
+#ifdef INTRNG
+	sc->base.gic_bus = GIC_BUS_FDT;
+#endif
+
 	err = arm_gic_attach(dev);
 	if (err != 0)
 		return (err);

Modified: head/sys/arm64/arm64/gic_v3.c
==============================================================================
--- head/sys/arm64/arm64/gic_v3.c	Tue Dec  6 14:31:47 2016	(r309621)
+++ head/sys/arm64/arm64/gic_v3.c	Tue Dec  6 15:12:14 2016	(r309622)
@@ -297,6 +297,13 @@ gic_v3_attach(device_t dev)
 		}
 	}
 
+	/*
+	 * Read the Peripheral ID2 register. This is an implementation
+	 * defined register, but seems to be implemented in all GICv3
+	 * parts and Linux expects it to be there.
+	 */
+	sc->gic_pidr2 = gic_d_read(sc, 4, GICD_PIDR2);
+
 	/* Get the number of supported interrupt identifier bits */
 	sc->gic_idbits = GICD_TYPER_IDBITS(typer);
 
@@ -358,6 +365,21 @@ gic_v3_read_ivar(device_t dev, device_t 
 		*result = (uintptr_t)rman_get_virtual(
 		    sc->gic_redists.pcpu[PCPU_GET(cpuid)]);
 		return (0);
+	case GIC_IVAR_HW_REV:
+		KASSERT(
+		    GICR_PIDR2_ARCH(sc->gic_pidr2) == GICR_PIDR2_ARCH_GICv3 ||
+		    GICR_PIDR2_ARCH(sc->gic_pidr2) == GICR_PIDR2_ARCH_GICv4,
+		    ("gic_v3_read_ivar: Invalid GIC architecture: %d (%.08X)",
+		     GICR_PIDR2_ARCH(sc->gic_pidr2), sc->gic_pidr2));
+		*result = GICR_PIDR2_ARCH(sc->gic_pidr2);
+		return (0);
+	case GIC_IVAR_BUS:
+		KASSERT(sc->gic_bus != GIC_BUS_UNKNOWN,
+		    ("gic_v3_read_ivar: Unknown bus type"));
+		KASSERT(sc->gic_bus <= GIC_BUS_MAX,
+		    ("gic_v3_read_ivar: Invalid bus type %u", sc->gic_bus));
+		*result = sc->gic_bus;
+		return (0);
 	}
 
 	return (ENOENT);
@@ -1101,7 +1123,7 @@ gic_v3_redist_find(struct gic_v3_softc *
 		r_bsh = rman_get_bushandle(&r_res);
 
 		pidr2 = bus_read_4(&r_res, GICR_PIDR2);
-		switch (pidr2 & GICR_PIDR2_ARCH_MASK) {
+		switch (GICR_PIDR2_ARCH(pidr2)) {
 		case GICR_PIDR2_ARCH_GICv3: /* fall through */
 		case GICR_PIDR2_ARCH_GICv4:
 			break;

Modified: head/sys/arm64/arm64/gic_v3_fdt.c
==============================================================================
--- head/sys/arm64/arm64/gic_v3_fdt.c	Tue Dec  6 14:31:47 2016	(r309621)
+++ head/sys/arm64/arm64/gic_v3_fdt.c	Tue Dec  6 15:12:14 2016	(r309622)
@@ -123,6 +123,7 @@ gic_v3_fdt_attach(device_t dev)
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
+	sc->gic_bus = GIC_BUS_FDT;
 
 	/*
 	 * Recover number of the Re-Distributor regions.

Modified: head/sys/arm64/arm64/gic_v3_reg.h
==============================================================================
--- head/sys/arm64/arm64/gic_v3_reg.h	Tue Dec  6 14:31:47 2016	(r309621)
+++ head/sys/arm64/arm64/gic_v3_reg.h	Tue Dec  6 15:12:14 2016	(r309622)
@@ -80,9 +80,12 @@
 #define	GICD_PIDR1		0xFFE4
 #define	GICD_PIDR2		0xFFE8
 
+#define	GICR_PIDR2_ARCH_SHIFT	4
 #define	GICR_PIDR2_ARCH_MASK	0xF0
-#define	GICR_PIDR2_ARCH_GICv3	0x30
-#define	GICR_PIDR2_ARCH_GICv4	0x40
+#define	GICR_PIDR2_ARCH(x)				\
+    (((x) & GICR_PIDR2_ARCH_MASK) >> GICR_PIDR2_ARCH_SHIFT)
+#define	GICR_PIDR2_ARCH_GICv3	0x3
+#define	GICR_PIDR2_ARCH_GICv4	0x4
 
 #define	GICD_PIDR3		0xFFEC
 

Modified: head/sys/arm64/arm64/gic_v3_var.h
==============================================================================
--- head/sys/arm64/arm64/gic_v3_var.h	Tue Dec  6 14:31:47 2016	(r309621)
+++ head/sys/arm64/arm64/gic_v3_var.h	Tue Dec  6 15:12:14 2016	(r309622)
@@ -68,6 +68,9 @@ struct gic_v3_softc {
 	/* Re-Distributors */
 	struct gic_redists	gic_redists;
 
+	uint32_t		gic_pidr2;
+	u_int			gic_bus;
+
 	u_int			gic_nirqs;
 	u_int			gic_idbits;
 


More information about the svn-src-head mailing list