summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2017-04-08 22:31:34 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2017-04-08 22:31:34 +0000
commitab93abaff23e02ac1b282b6ca4053997ee0df1e6 (patch)
treefe4052e9d6db0d5bd669ce442bb2c603bdc49e09 /sys/arch
parent00574fd94ade93250b8f12795d1d87a36c013433 (diff)
Bring over the changes I made to the armv7 version of this driver such that
interrupts are correctly routed to the boot cpu if that isn't the one connected to CPU interface zero on the interrupt controller. ok patrick@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/arm64/dev/ampintc.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/sys/arch/arm64/dev/ampintc.c b/sys/arch/arm64/dev/ampintc.c
index 11953200981..acca8ac5745 100644
--- a/sys/arch/arm64/dev/ampintc.c
+++ b/sys/arch/arm64/dev/ampintc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ampintc.c,v 1.7 2017/02/25 17:04:19 patrick Exp $ */
+/* $OpenBSD: ampintc.c,v 1.8 2017/04/08 22:31:33 kettenis Exp $ */
/*
* Copyright (c) 2007,2009,2011 Dale Rahn <drahn@openbsd.org>
*
@@ -138,6 +138,7 @@ struct ampintc_softc {
int sc_nintr;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_d_ioh, sc_p_ioh;
+ uint8_t sc_cpu_mask[ICD_ICTR_CPU_M + 1];
struct evcount sc_spur;
struct interrupt_controller sc_ic;
};
@@ -184,7 +185,7 @@ void ampintc_set_priority(int, int);
void ampintc_intr_enable(int);
void ampintc_intr_disable(int);
void ampintc_intr_config(int, int);
-void ampintc_route(int, int , int);
+void ampintc_route(int, int, struct cpu_info *);
struct cfattach ampintc_ca = {
sizeof (struct ampintc_softc), ampintc_match, ampintc_attach
@@ -220,7 +221,8 @@ ampintc_attach(struct device *parent, struct device *self, void *aux)
{
struct ampintc_softc *sc = (struct ampintc_softc *)self;
struct fdt_attach_args *faa = aux;
- int i, nintr;
+ int i, nintr, ncpu;
+ uint32_t ictr;
ampintc = sc;
@@ -240,11 +242,16 @@ ampintc_attach(struct device *parent, struct device *self, void *aux)
evcount_attach(&sc->sc_spur, "irq1023/spur", NULL);
- nintr = 32 * (bus_space_read_4(sc->sc_iot, sc->sc_d_ioh,
- ICD_ICTR) & ICD_ICTR_ITL_M);
+ ictr = bus_space_read_4(sc->sc_iot, sc->sc_d_ioh, ICD_ICTR);
+ nintr = 32 * ((ictr >> ICD_ICTR_ITL_SH) & ICD_ICTR_ITL_M);
nintr += 32; /* ICD_ICTR + 1, irq 0-31 is SGI, 32+ is PPI */
sc->sc_nintr = nintr;
- printf(" nirq %d", nintr);
+ ncpu = ((ictr >> ICD_ICTR_CPU_SH) & ICD_ICTR_CPU_M) + 1;
+ printf(" nirq %d, ncpu %d", nintr, ncpu);
+
+ KASSERT(curcpu()->ci_cpuid <= ICD_ICTR_CPU_M);
+ sc->sc_cpu_mask[curcpu()->ci_cpuid] =
+ bus_space_read_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(0));
/* Disable all interrupts, clear all pending */
for (i = 0; i < nintr/32; i++) {
@@ -403,11 +410,10 @@ ampintc_calc_mask(void)
if (min != IPL_NONE) {
ampintc_set_priority(irq, min);
ampintc_intr_enable(irq);
- ampintc_route(irq, IRQ_ENABLE, 0);
+ ampintc_route(irq, IRQ_ENABLE, ci);
} else {
ampintc_intr_disable(irq);
- ampintc_route(irq, IRQ_DISABLE, 0);
-
+ ampintc_route(irq, IRQ_DISABLE, ci);
}
}
ampintc_setipl(ci->ci_cpl);
@@ -476,16 +482,19 @@ ampintc_eoi(uint32_t eoi)
}
void
-ampintc_route(int irq, int enable, int cpu)
+ampintc_route(int irq, int enable, struct cpu_info *ci)
{
- uint8_t val;
struct ampintc_softc *sc = ampintc;
+ uint8_t mask, val;
+
+ KASSERT(ci->ci_cpuid <= ICD_ICTR_CPU_M);
+ mask = sc->sc_cpu_mask[ci->ci_cpuid];
val = bus_space_read_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(irq));
if (enable == IRQ_ENABLE)
- val |= (1 << cpu);
+ val |= mask;
else
- val &= ~(1 << cpu);
+ val &= ~mask;
bus_space_write_1(sc->sc_iot, sc->sc_d_ioh, ICD_IPTRn(irq), val);
}