Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/arm/samsung XU4 interrupt combiner



details:   https://anonhg.NetBSD.org/src/rev/56fd43f5e8fe
branches:  trunk
changeset: 812636:56fd43f5e8fe
user:      marty <marty%NetBSD.org@localhost>
date:      Thu Dec 24 21:20:17 2015 +0000

description:
XU4 interrupt combiner

Written but untested.  I'm still confused about how to handle two things:

1) at interrupt disestablishment, where do I get an interrupt number so
   that I can disable the interrupt on the combiner?

2) How is interrupt multiplexing handled?  I don't seem to have any sort of
   interrupt dispatch routine that takes the 1 interrupt that reaches the
   gic and turn it into one of eight combined interrupts to call the
   established interrupt for the original uncombined interrupt source.

diffstat:

 sys/arch/arm/samsung/exynos_combiner.c |  75 ++++++++++++++-------------------
 1 files changed, 31 insertions(+), 44 deletions(-)

diffs (124 lines):

diff -r f6442e15da6e -r 56fd43f5e8fe sys/arch/arm/samsung/exynos_combiner.c
--- a/sys/arch/arm/samsung/exynos_combiner.c    Thu Dec 24 17:35:57 2015 +0000
+++ b/sys/arch/arm/samsung/exynos_combiner.c    Thu Dec 24 21:20:17 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: exynos_combiner.c,v 1.2 2015/12/21 04:58:50 marty Exp $ */
+/*     $NetBSD: exynos_combiner.c,v 1.3 2015/12/24 21:20:17 marty Exp $ */
 
 /*-
 * Copyright (c) 2015 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
 #include "gpio.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: exynos_combiner.c,v 1.2 2015/12/21 04:58:50 marty Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exynos_combiner.c,v 1.3 2015/12/24 21:20:17 marty Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -50,8 +50,16 @@
 
 #include <dev/fdt/fdtvar.h>
 
+#define COMBINER_IESR_OFFSET  0x00
+#define COMBINER_IECR_OFFSET  0x04
+#define COMBINER_ISTR_OFFSET  0x08
+#define COMBINER_IMSR_OFFSET  0x0C
+#define COMBINER_BLOCK_SIZE   0x10
+
 struct exynos_combiner_softc {
        device_t                sc_dev;
+       bus_space_tag_t         sc_bst;
+       bus_space_handle_t      sc_bsh;
        int                     sc_phandle;
 
 };
@@ -99,6 +107,15 @@
 
        sc->sc_dev = self;
        sc->sc_phandle = faa->faa_phandle;
+       sc->sc_bst = faa->faa_bst;
+
+       error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh);
+       if (error) {
+               aprint_error(": couldn't map %#llx: %d",
+                            (uint64_t)addr, error);
+               return;
+       }
+
        error = fdtbus_register_interrupt_controller(self, faa->faa_phandle,
            &exynos_combiner_funcs);
        if (error) {
@@ -106,15 +123,12 @@
                return;
        }
 
-
-       aprint_normal(" @ 0x%08x: interrupt combiner,  NOT IMPLEMENTED",
-                     (uint)addr);
+       aprint_normal(" @ 0x%08x: interrupt combiner", (uint)addr);
        aprint_naive("\n");
        aprint_normal("\n");
 
 }
 
-
 static void *
 exynos_combiner_establish(device_t dev, int phandle, u_int index, int ipl,
                          int flags,
@@ -122,44 +136,17 @@
 {
        struct exynos_combiner_softc * const sc = device_private(dev);
        int iflags = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0;
-       u_int *interrupts;
-       int interrupt_cells, len;
-
-       if (of_getprop_uint32(sc->sc_phandle, "#interrupt-cells",
-           &interrupt_cells)) {
-               return NULL;
-       }
-
-       len = OF_getproplen(phandle, "interrupts");
-       if (len <= 0)
-               return NULL;
-
-       const u_int clen = interrupt_cells * 4;
-       const u_int nintr = len / interrupt_cells;
-
-       if (index >= nintr)
-               return NULL;
-
-       interrupts = kmem_alloc(len, KM_SLEEP);
-
-       if (OF_getprop(phandle, "interrupts", interrupts, len) != len) {
-               kmem_free(interrupts, len);
-               return NULL;
-       }
-
-       /* 1st cell is the interrupt type; */
-       /* 2nd cell is the interrupt number */
-       /* 3rd cell is flags */
-
-       const u_int type = be32toh(interrupts[index * clen + 0]);
-       const u_int intr = be32toh(interrupts[index * clen + 1]);
-       const u_int irq = type == 0 ? IRQ_SPI(intr) : IRQ_PPI(intr);
-       const u_int trig = be32toh(interrupts[index * clen + 2]) & 0xf;
-       const u_int level = (trig & 0x3) ? IST_EDGE : IST_LEVEL;
-
-       kmem_free(interrupts, len);
-
-       return intr_establish(irq, ipl, level | iflags, func, arg);
+       int iblock = index >> 3;
+       int ioffset = index & 0x07;
+       int block_offset =
+               iblock * COMBINER_BLOCK_SIZE + COMBINER_IESR_OFFSET;
+       int istatus =
+               bus_space_read_4(sc->sc_bst, sc->sc_bsh, block_offset);
+       printf("Establishing irq %d (0x%x) @ iblock = %d, ioffset = %d\n",
+              index, index, iblock, ioffset);
+       istatus |= 1 << ioffset;
+       bus_space_write_4(sc->sc_bst, sc->sc_bsh, block_offset, istatus);
+       return intr_establish(index, ipl, iflags, func, arg);
 }
 
 static void



Home | Main Index | Thread Index | Old Index