summaryrefslogtreecommitdiffstats
path: root/sys/arm/mv
diff options
context:
space:
mode:
authorskra <skra@FreeBSD.org>2016-04-04 09:15:25 +0000
committerskra <skra@FreeBSD.org>2016-04-04 09:15:25 +0000
commit11cdd44a031a4decfec0214bfa4990d4afab64c6 (patch)
treef884312693aa8e3bfe57c9d06b22bc2bd6db88d2 /sys/arm/mv
parent153a55cf7ff4f26dd754308d5dade9cbfb85ba63 (diff)
downloadFreeBSD-src-11cdd44a031a4decfec0214bfa4990d4afab64c6.zip
FreeBSD-src-11cdd44a031a4decfec0214bfa4990d4afab64c6.tar.gz
Remove FDT specific parts from INTRNG. Change its interface to make it
universal. (1) New struct intr_map_data is defined as a container for arbitrary description of an interrupt used by a device. Typically, an interrupt number and configuration relevant to an interrupt controller is encoded in such description. However, any additional information may be encoded too like a set of cpus on which an interrupt should be enabled or vendor specific data needed for setup of an interrupt in controller. The struct intr_map_data itself is meant to be opaque for INTRNG. (2) An intr_map_irq() function is created which takes an interrupt controller identification and struct intr_map_data as arguments and returns global interrupt number which identifies an interrupt. (3) A set of functions to be used by bus drivers is created as well as a corresponding set of methods for interrupt controller drivers. These sets take both struct resource and struct intr_map_data as one of the arguments. There is a goal to keep struct intr_map_data in struct resource, however, this way a final solution is not limited to that. (4) Other small changes are done to reflect new situation. This is only first step aiming to create stable interface for interrupt controller drivers. Thus, some temporary solution is taken. Interrupt descriptions for devices are stored in INTRNG and two specific mapping function are created to be temporary used by bus drivers. That's why the struct intr_map_data is not opaque for INTRNG now. This temporary solution will be replaced by final one in next step. Differential Revision: https://reviews.freebsd.org/D5730
Diffstat (limited to 'sys/arm/mv')
-rw-r--r--sys/arm/mv/mpic.c160
1 files changed, 74 insertions, 86 deletions
diff --git a/sys/arm/mv/mpic.c b/sys/arm/mv/mpic.c
index 7d53afe..4f246a4 100644
--- a/sys/arm/mv/mpic.c
+++ b/sys/arm/mv/mpic.c
@@ -98,6 +98,13 @@ __FBSDID("$FreeBSD$");
#define MPIC_PPI 32
+#ifdef ARM_INTRNG
+struct mv_mpic_irqsrc {
+ struct intr_irqsrc mmi_isrc;
+ u_int mmi_irq;
+};
+#endif
+
struct mv_mpic_softc {
device_t sc_dev;
struct resource * mpic_res[4];
@@ -108,8 +115,9 @@ struct mv_mpic_softc {
bus_space_tag_t drbl_bst;
bus_space_handle_t drbl_bsh;
struct mtx mtx;
-
- struct intr_irqsrc ** mpic_isrcs;
+#ifdef ARM_INTRNG
+ struct mv_mpic_irqsrc * mpic_isrcs;
+#endif
int nirqs;
void * intr_hand;
};
@@ -177,6 +185,40 @@ mv_mpic_probe(device_t dev)
return (0);
}
+#ifdef ARM_INTRNG
+static int
+mv_mpic_register_isrcs(struct mv_mpic_softc *sc)
+{
+ int error;
+ uint32_t irq;
+ struct intr_irqsrc *isrc;
+ const char *name;
+
+ sc->mpic_isrcs = malloc(sc->nirqs * sizeof (*sc->mpic_isrcs), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+
+ name = device_get_nameunit(sc->sc_dev);
+ for (irq = 0; irq < sc->nirqs; irq++) {
+ sc->mpic_isrcs[irq].mmi_irq = irq;
+
+ isrc = &sc->mpic_isrcs[irq].mmi_isrc;
+ if (irq < MPIC_PPI) {
+ error = intr_isrc_register(isrc, sc->sc_dev,
+ INTR_ISRCF_PPI, "%s", name);
+ } else {
+ error = intr_isrc_register(isrc, sc->sc_dev, 0, "%s",
+ name);
+ }
+ if (error != 0) {
+ /* XXX call intr_isrc_deregister() */
+ device_printf(sc->sc_dev, "%s failed", __func__);
+ return (error);
+ }
+ }
+ return (0);
+}
+#endif
+
static int
mv_mpic_attach(device_t dev)
{
@@ -227,9 +269,11 @@ mv_mpic_attach(device_t dev)
sc->nirqs = MPIC_CTRL_NIRQS(val);
#ifdef ARM_INTRNG
- sc->mpic_isrcs = malloc(sc->nirqs * sizeof (*sc->mpic_isrcs), M_DEVBUF,
- M_WAITOK | M_ZERO);
-
+ if (mv_mpic_register_isrcs(sc) != 0) {
+ device_printf(dev, "could not register PIC ISRCs\n");
+ bus_release_resources(dev, mv_mpic_spec, sc->mpic_res);
+ return (ENXIO);
+ }
if (intr_pic_register(dev, OF_xref_from_device(dev)) != 0) {
device_printf(dev, "could not register PIC\n");
bus_release_resources(dev, mv_mpic_spec, sc->mpic_res);
@@ -247,14 +291,11 @@ static int
mpic_intr(void *arg)
{
struct mv_mpic_softc *sc;
- struct trapframe *tf;
- struct intr_irqsrc *isrc;
uint32_t cause, irqsrc;
unsigned int irq;
u_int cpuid;
sc = arg;
- tf = curthread->td_intr_frame;
cpuid = PCPU_GET(cpuid);
irq = 0;
@@ -264,117 +305,64 @@ mpic_intr(void *arg)
irqsrc = MPIC_READ(sc, MPIC_INT_CTL(irq));
if ((irqsrc & MPIC_INT_IRQ_FIQ_MASK(cpuid)) == 0)
continue;
- isrc = sc->mpic_isrcs[irq];
- if (isrc == NULL) {
- device_printf(sc->sc_dev, "Stray interrupt %u detected\n", irq);
+ if (intr_isrc_dispatch(&sc->mpic_isrcs[irq].mmi_isrc,
+ curthread->td_intr_frame) != 0) {
mpic_mask_irq(irq);
- continue;
+ device_printf(sc->sc_dev, "Stray irq %u "
+ "disabled\n", irq);
}
- intr_irq_dispatch(isrc, tf);
}
}
return (FILTER_HANDLED);
}
-static int
-mpic_attach_isrc(struct mv_mpic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
+static void
+mpic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
{
- const char *name;
-
- mtx_lock_spin(&sc->mtx);
- if (sc->mpic_isrcs[irq] != NULL) {
- mtx_unlock_spin(&sc->mtx);
- return (sc->mpic_isrcs[irq] == isrc ? 0 : EEXIST);
- }
- sc->mpic_isrcs[irq] = isrc;
- isrc->isrc_data = irq;
- mtx_unlock_spin(&sc->mtx);
-
- name = device_get_nameunit(sc->sc_dev);
- intr_irq_set_name(isrc, "%s", name);
+ u_int irq;
- return (0);
+ irq = ((struct mv_mpic_irqsrc *)isrc)->mmi_irq;
+ mpic_mask_irq(irq);
}
-#ifdef FDT
-static int
-mpic_map_fdt(struct mv_mpic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
+static void
+mpic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
u_int irq;
- int error;
-
- if (isrc->isrc_ncells != 1)
- return (EINVAL);
- irq = isrc->isrc_cells[0];
-
- error = mpic_attach_isrc(sc, isrc, irq);
- if (error != 0)
- return (error);
-
- isrc->isrc_nspc_num = irq;
- isrc->isrc_trig = INTR_TRIGGER_CONFORM;
- isrc->isrc_pol = INTR_POLARITY_CONFORM;
- isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
-
- *irqp = irq;
-
- return (0);
+ irq = ((struct mv_mpic_irqsrc *)isrc)->mmi_irq;
+ mpic_unmask_irq(irq);
}
-#endif
static int
-mpic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
+mpic_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
{
struct mv_mpic_softc *sc;
- int error;
- u_int irq = 0;
sc = device_get_softc(dev);
-#ifdef FDT
- if (isrc->isrc_type == INTR_ISRCT_FDT)
- error = mpic_map_fdt(sc, isrc, &irq);
- else
-#endif
- error = EINVAL;
-
- if (error == 0)
- *is_percpu = irq < MPIC_PPI;
-
- return (error);
-}
-
-static void
-mpic_disable_source(device_t dev, struct intr_irqsrc *isrc)
-{
- u_int irq;
+ if (data->type != INTR_MAP_DATA_FDT || data->fdt.ncells !=1 ||
+ data->fdt.cells[0] >= sc->nirqs)
+ return (EINVAL);
- irq = isrc->isrc_data;
- mpic_mask_irq(irq);
+ *isrcp = &sc->mpic_isrcs[data->fdt.cells[0]].mmi_isrc;
+ return (0);
}
static void
-mpic_enable_source(device_t dev, struct intr_irqsrc *isrc)
-{
- u_int irq;
-
- irq = isrc->isrc_data;
- mpic_unmask_irq(irq);
-}
-static void
mpic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
{
- mpic_disable_source(dev, isrc);
+ mpic_disable_intr(dev, isrc);
}
static void
mpic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
{
- mpic_enable_source(dev, isrc);
+ mpic_enable_intr(dev, isrc);
}
#endif
@@ -383,9 +371,9 @@ static device_method_t mv_mpic_methods[] = {
DEVMETHOD(device_attach, mv_mpic_attach),
#ifdef ARM_INTRNG
- DEVMETHOD(pic_register, mpic_register),
- DEVMETHOD(pic_disable_source, mpic_disable_source),
- DEVMETHOD(pic_enable_source, mpic_enable_source),
+ DEVMETHOD(pic_disable_intr, mpic_disable_intr),
+ DEVMETHOD(pic_enable_intr, mpic_enable_intr),
+ DEVMETHOD(pic_map_intr, mpic_map_intr),
DEVMETHOD(pic_post_ithread, mpic_post_ithread),
DEVMETHOD(pic_pre_ithread, mpic_pre_ithread),
#endif
OpenPOWER on IntegriCloud