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