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;
 
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to