Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/fdt Add GICv2m support



details:   https://anonhg.NetBSD.org/src/rev/6c0b37d7f498
branches:  trunk
changeset: 445753:6c0b37d7f498
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Nov 11 21:24:28 2018 +0000

description:
Add GICv2m support

diffstat:

 sys/arch/arm/fdt/gic_fdt.c |  80 ++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 70 insertions(+), 10 deletions(-)

diffs (155 lines):

diff -r a72ca79213e6 -r 6c0b37d7f498 sys/arch/arm/fdt/gic_fdt.c
--- a/sys/arch/arm/fdt/gic_fdt.c        Sun Nov 11 20:59:07 2018 +0000
+++ b/sys/arch/arm/fdt/gic_fdt.c        Sun Nov 11 21:24:28 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: gic_fdt.c,v 1.13 2018/09/03 16:29:23 riastradh Exp $ */
+/* $NetBSD: gic_fdt.c,v 1.14 2018/11/11 21:24:28 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2015-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gic_fdt.c,v 1.13 2018/09/03 16:29:23 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gic_fdt.c,v 1.14 2018/11/11 21:24:28 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -39,15 +39,25 @@
 #include <sys/kmem.h>
 #include <sys/queue.h>
 
+#include <dev/pci/pcivar.h>
+
 #include <arm/cortex/gic_intr.h>
+#include <arm/cortex/gic_reg.h>
+#include <arm/cortex/gic_v2m.h>
 #include <arm/cortex/mpcore_var.h>
 
 #include <dev/fdt/fdtvar.h>
 
 #define        GIC_MAXIRQ      1020
 
+extern struct pic_softc *pic_list[];
+
+struct gic_fdt_softc;
+struct gic_fdt_irq;
+
 static int     gic_fdt_match(device_t, cfdata_t, void *);
 static void    gic_fdt_attach(device_t, device_t, void *);
+static void    gic_fdt_attach_v2m(struct gic_fdt_softc *, bus_space_tag_t, int);
 
 static int     gic_fdt_intr(void *);
 
@@ -62,9 +72,6 @@
        .intrstr = gic_fdt_intrstr
 };
 
-struct gic_fdt_softc;
-struct gic_fdt_irq;
-
 struct gic_fdt_irqhandler {
        struct gic_fdt_irq      *ih_irq;
        int                     (*ih_fn)(void *);
@@ -87,8 +94,11 @@
 
 struct gic_fdt_softc {
        device_t                sc_dev;
+       device_t                sc_gicdev;
        int                     sc_phandle;
 
+       int                     sc_v2m_count;
+
        struct gic_fdt_irq      *sc_irq[GIC_MAXIRQ];
 };
 
@@ -107,7 +117,7 @@
        };
        struct fdt_attach_args * const faa = aux;
 
-       return of_compatible(faa->faa_phandle, compatible) >= 0;
+       return of_match_compatible(faa->faa_phandle, compatible);
 }
 
 static void
@@ -115,15 +125,16 @@
 {
        struct gic_fdt_softc * const sc = device_private(self);
        struct fdt_attach_args * const faa = aux;
+       const int phandle = faa->faa_phandle;
        bus_addr_t addr_d, addr_c;
        bus_size_t size_d, size_c;
        bus_space_handle_t bsh;
-       int error;
+       int error, child;
 
        sc->sc_dev = self;
-       sc->sc_phandle = faa->faa_phandle;
+       sc->sc_phandle = phandle;
 
-       error = fdtbus_register_interrupt_controller(self, faa->faa_phandle,
+       error = fdtbus_register_interrupt_controller(self, phandle,
            &gic_fdt_funcs);
        if (error) {
                aprint_error(": couldn't register with fdtbus: %d\n", error);
@@ -160,9 +171,58 @@
                .mpcaa_off2 = addr_c - addr,
        };
 
-       config_found(self, &mpcaa, NULL);
+       sc->sc_gicdev = config_found(self, &mpcaa, NULL);
 
        arm_fdt_irq_set_handler(armgic_irq_handler);
+
+       for (child = OF_child(phandle); child; child = OF_peer(child)) {
+               if (!fdtbus_status_okay(child))
+                       continue;
+               const char * const v2m_compat[] = { "arm,gic-v2m-frame", NULL };
+               if (of_match_compatible(child, v2m_compat))
+                       gic_fdt_attach_v2m(sc, faa->faa_bst, child);
+       }
+}
+
+static void
+gic_fdt_attach_v2m(struct gic_fdt_softc *sc, bus_space_tag_t bst, int phandle)
+{
+       struct gic_v2m_frame *frame;
+       u_int base_spi, num_spis;
+       bus_space_handle_t bsh;
+       bus_addr_t addr;
+       bus_size_t size;
+
+       if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+               aprint_error_dev(sc->sc_gicdev, "couldn't get V2M address\n");
+               return;
+       }
+
+       if (bus_space_map(bst, addr, size, 0, &bsh) != 0) {
+               aprint_error_dev(sc->sc_gicdev, "couldn't map V2M frame\n");
+               return;
+       }
+       const uint32_t typer = bus_space_read_4(bst, bsh, GIC_MSI_TYPER);
+       bus_space_unmap(bst, bsh, size);
+
+       if (of_getprop_uint32(phandle, "arm,msi-base-spi", &base_spi))
+               base_spi = __SHIFTOUT(typer, GIC_MSI_TYPER_BASE);
+       if (of_getprop_uint32(phandle, "arm,msi-num-spis", &num_spis))
+               num_spis = __SHIFTOUT(typer, GIC_MSI_TYPER_NUMBER);
+
+       frame = kmem_zalloc(sizeof(*frame), KM_SLEEP);
+       frame->frame_reg = addr;
+       frame->frame_pic = pic_list[0];
+       frame->frame_base = base_spi;
+       frame->frame_count = num_spis;
+
+       if (gic_v2m_init(frame, sc->sc_gicdev, sc->sc_v2m_count++) != 0) {
+               aprint_error_dev(sc->sc_gicdev, "failed to initialize GICv2m\n");
+       } else {
+               aprint_normal_dev(sc->sc_gicdev, "GICv2m @ %#" PRIx64 ", SPIs %u-%u\n",
+                   (uint64_t)frame->frame_reg, frame->frame_base,
+                   frame->frame_base + frame->frame_count);
+       }
 }
 
 static void *



Home | Main Index | Thread Index | Old Index