Skip to content

Commit

Permalink
arm: prototype of more MI intr_establish
Browse files Browse the repository at this point in the history
Before this diff we had the issue that we
 * needed to somehow get the irq nr from the DT node
 * needed to call establish on the correct interrupt controller

This diff intends to solve theses issues. The idea is that you
only need to call an "MI" interrupt establish function and it
takes care of letting the correct interrupt controller now what
interrupt to establish.

This is implemented by adding a hook, so that interrupt controller
can register them as interrupt controllers. When the device driver
calls establish using the DT node, the code will look up the device's
interrupt controller and look for that one in the list.

Once found, it will call the IC's establish function and pass the
device node further down. The IC code will take care to properly
read and interpret the interrupt information and actually establish
the interrupt.
  • Loading branch information
bluerise committed Feb 13, 2015
1 parent 94f90a0 commit 8f94a39
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 9 deletions.
6 changes: 2 additions & 4 deletions sys/arch/arm/cortex/agtimer.c
Expand Up @@ -225,7 +225,6 @@ agtimer_attach(struct device *parent, struct device *self, void *args)
struct agtimer_softc *sc = (struct agtimer_softc *)self;
struct cortex_attach_args *ia = args;
bus_space_handle_t ioh, pioh;
uint32_t ints[3*4];
void *node = ia->ca_node;

sc->sc_iot = ia->ca_iot;
Expand Down Expand Up @@ -268,11 +267,10 @@ agtimer_attach(struct device *parent, struct device *self, void *args)

/* establish interrupts */
/* TODO: Add interrupt FDT API. */
if (node && fdt_node_property_ints(node, "interrupts",
ints, 3*4) == 3*4) {
if (node) {
/* Setup secure, non-secure and virtual timer IRQs. */
for (int i = 0; i < 4; i++) {
ampintc_intr_establish(ints[1 + 3 * i] + 16, IPL_CLOCK,
arm_intr_establish_fdt_idx(node, i, IPL_CLOCK,
agtimer_intr, NULL, "tick");
}
} else {
Expand Down
33 changes: 33 additions & 0 deletions sys/arch/arm/cortex/ampintc.c
Expand Up @@ -144,6 +144,7 @@ struct ampintc_softc {
bus_space_tag_t sc_iot;
bus_space_handle_t sc_d_ioh, sc_p_ioh;
struct evcount sc_spur;
int sc_ncells;
};
struct ampintc_softc *ampintc;

Expand All @@ -159,6 +160,8 @@ void *ampintc_intr_establish(int, int, int (*)(void *), void *,
char *);
void *ampintc_intr_establish_ext(int, int, int (*)(void *), void *,
char *);
void *ampintc_intr_establish_fdt_idx(void *, int, int,
int (*)(void *), void *, char *);
void ampintc_intr_disestablish(void *);
void ampintc_irq_handler(void *);
const char *ampintc_intr_string(void *);
Expand Down Expand Up @@ -246,6 +249,11 @@ ampintc_attach(struct device *parent, struct device *self, void *args)
icp = mem.addr;
icpsize = mem.size;
}

if (fdt_node_property_int(node, "#interrupt-cells",
&sc->sc_ncells) != 1)
panic("%s: no #interrupt-cells property",
sc->sc_dev.dv_xname);
}

if (bus_space_map(iot, icp, icpsize, 0, &p_ioh))
Expand Down Expand Up @@ -302,6 +310,8 @@ ampintc_attach(struct device *parent, struct device *self, void *args)
ampintc_setipl, ampintc_intr_establish_ext,
ampintc_intr_disestablish, ampintc_intr_string, ampintc_irq_handler);

arm_set_intr_handler_fdt(node, ampintc_intr_establish_fdt_idx);

/* enable interrupts */
bus_space_write_4(iot, d_ioh, ICD_DCR, 3);
bus_space_write_4(iot, p_ioh, ICPICR, 1);
Expand Down Expand Up @@ -549,6 +559,29 @@ ampintc_intr_establish_ext(int irqno, int level, int (*func)(void *),
return ampintc_intr_establish(irqno+32, level, func, arg, name);
}

void *
ampintc_intr_establish_fdt_idx(void *node, int idx, int level,
int (*func)(void *), void *arg, char *name)
{
struct ampintc_softc *sc = ampintc;
int nints = sc->sc_ncells * (idx + 1);
int ints[nints];
int irq;

if (fdt_node_property_ints(node, "interrupts", ints, nints) != nints)
panic("%s: no interrupts property", sc->sc_dev.dv_xname);

irq = ints[idx * 3 + 1];
if (ints[idx * 3] == 0)
irq += 32;
else if (ints[idx * 3] == 1)
irq += 16;
else
panic("%s: bogus interrupt type", sc->sc_dev.dv_xname);

return ampintc_intr_establish(irq, level, func, arg, name);
}

void *
ampintc_intr_establish(int irqno, int level, int (*func)(void *),
void *arg, char *name)
Expand Down
57 changes: 57 additions & 0 deletions sys/arch/armv7/armv7/intr.c
Expand Up @@ -19,10 +19,12 @@
#include <sys/systm.h>
#include <sys/param.h>
#include <sys/timetc.h>
#include <sys/malloc.h>

#include <dev/clock_subr.h>
#include <arm/cpufunc.h>
#include <machine/cpu.h>
#include <machine/fdt.h>
#include <machine/intr.h>

int arm_dflt_splraise(int);
Expand Down Expand Up @@ -65,16 +67,51 @@ arm_dflt_intr(void *frame)
panic("arm_dflt_intr() called");
}

SLIST_HEAD(, ic_entry) ic_list = SLIST_HEAD_INITIALIZER(ic_list);
struct ic_entry {
SLIST_ENTRY(ic_entry) ie_list;
void *ie_node;
struct device *ie_dev;
void *(*ie_intr_establish)(void *node, int idx, int level,
int (*func)(void *), void *cookie, char *name);
};

void *arm_intr_establish_fdt(void *node, int level, int (*func)(void *),
void *cookie, char *name)
{
return arm_intr_establish_fdt_idx(node, 0, level, func, cookie, name);
}

void *arm_intr_establish_fdt_idx(void *node, int idx, int level,
int (*func)(void *), void *cookie, char *name)
{
struct ic_entry *ie, *ip;

ip = fdt_get_interrupt_controller(node);
if (ip == NULL)
return NULL;

SLIST_FOREACH(ie, &ic_list, ie_list) {
if (ie->ie_node != ip)
continue;
return ie->ie_intr_establish(node, idx, level, func, cookie,
name);
}

return NULL;
}

void *arm_intr_establish(int irqno, int level, int (*func)(void *),
void *cookie, char *name)
{
return arm_intr_func.intr_establish(irqno, level, func, cookie, name);
}

void arm_intr_disestablish(void *cookie)
{
arm_intr_func.intr_disestablish(cookie);
}

const char *arm_intr_string(void *cookie)
{
return arm_intr_func.intr_string(cookie);
Expand Down Expand Up @@ -200,6 +237,26 @@ arm_do_pending_intr(int pcpl)
intr_restore(oldirqstate);
}

void
arm_set_intr_handler_fdt(void *node,
void *(*intr_establish)(void *node, int idx, int level,
int (*func)(void *), void *cookie, char *name))
{
struct ic_entry *ie;

if (node == NULL)
return;

ie = malloc(sizeof(*ie), M_DEVBUF, M_NOWAIT|M_ZERO);
if (ie == NULL)
panic("%s: cannot allocate ic entry", __func__);

ie->ie_node = node;
ie->ie_intr_establish = intr_establish;

SLIST_INSERT_HEAD(&ic_list, ie, ie_list);
}

void arm_set_intr_handler(int (*raise)(int), int (*lower)(int),
void (*x)(int), void (*setipl)(int),
void *(*intr_establish)(int irqno, int level, int (*func)(void *),
Expand Down
7 changes: 7 additions & 0 deletions sys/arch/armv7/include/intr.h
Expand Up @@ -84,6 +84,9 @@ int spllower(int);
void splx(int);

void arm_do_pending_intr(int);
void arm_set_intr_handler_fdt(void *node,
void *(*intr_establish)(void *node, int idx, int level,
int (*func)(void *), void *cookie, char *name));
void arm_set_intr_handler(int (*raise)(int), int (*lower)(int),
void (*x)(int), void (*setipl)(int),
void *(*intr_establish)(int irqno, int level, int (*func)(void *),
Expand Down Expand Up @@ -163,6 +166,10 @@ void arm_setsoftintr(int si);

void *arm_intr_establish(int irqno, int level, int (*func)(void *),
void *cookie, char *name);
void *arm_intr_establish_fdt(void *node, int level, int (*func)(void *),
void *cookie, char *name);
void *arm_intr_establish_fdt_idx(void *node, int idx, int level,
int (*func)(void *), void *cookie, char *name);
void arm_intr_disestablish(void *cookie);
const char *arm_intr_string(void *cookie);

Expand Down
6 changes: 1 addition & 5 deletions sys/arch/armv7/virt/virtio_mmio.c
Expand Up @@ -104,7 +104,6 @@ struct virtio_mmio_softc {
bus_size_t sc_iosize;
bus_dma_tag_t sc_dmat;

int sc_irqno;
void *sc_ih;

int sc_config_offset;
Expand Down Expand Up @@ -195,9 +194,6 @@ virtio_mmio_attach(struct device *parent, struct device *self, void *aux)
if (fdt_get_memory_address(aa->aa_node, 0, &mem))
panic("%s: could not extract memory data from FDT", __func__);

if (fdt_get_interrupt(aa->aa_node, &sc->sc_irqno))
panic("%s: could not extract interrupt data from FDT", __func__);

sc->sc_iosize = mem.size;
sc->sc_iot = aa->aa_iot;
sc->sc_dmat = aa->aa_dmat;
Expand Down Expand Up @@ -252,7 +248,7 @@ virtio_mmio_attach(struct device *parent, struct device *self, void *aux)
goto fail_1;
}

sc->sc_ih = arm_intr_establish(sc->sc_irqno, vsc->sc_ipl,
sc->sc_ih = arm_intr_establish_fdt(aa->aa_node, vsc->sc_ipl,
virtio_mmio_intr, sc, vsc->sc_dev.dv_xname);
if (sc->sc_ih == NULL) {
printf("%s: couldn't establish interrupt\n",
Expand Down

0 comments on commit 8f94a39

Please sign in to comment.