summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorcognet <cognet@FreeBSD.org>2005-06-09 12:26:20 +0000
committercognet <cognet@FreeBSD.org>2005-06-09 12:26:20 +0000
commitcbb8d627a3fbeb8a57e0e6a4548e4b4c2e0f23d5 (patch)
treebbf540ccfed9fe660603798a3164154ccbd14bf0 /sys/arm
parent97eb32fd8d89cafdbf76f349f5d634af803dbc6a (diff)
downloadFreeBSD-src-cbb8d627a3fbeb8a57e0e6a4548e4b4c2e0f23d5.zip
FreeBSD-src-cbb8d627a3fbeb8a57e0e6a4548e4b4c2e0f23d5.tar.gz
- MFp4: modify slightly the arm intr API, there's arm CPUs with more than 32
interrupts. - Implement teardown methods where appropriate.
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/arm/intr.c53
-rw-r--r--sys/arm/arm/nexus.c13
-rw-r--r--sys/arm/include/intr.h8
-rw-r--r--sys/arm/sa11x0/sa11x0_irqhandler.c30
-rw-r--r--sys/arm/xscale/i80321/i80321.c9
-rw-r--r--sys/arm/xscale/i80321/i80321_pci.c10
-rw-r--r--sys/arm/xscale/i80321/iq80321.c18
7 files changed, 73 insertions, 68 deletions
diff --git a/sys/arm/arm/intr.c b/sys/arm/arm/intr.c
index 75ed893..cb941f7 100644
--- a/sys/arm/arm/intr.c
+++ b/sys/arm/arm/intr.c
@@ -54,21 +54,6 @@ static struct ithd *ithreads[NIRQ];
static int intrcnt_tab[NIRQ];
static int intrcnt_index = 0;
static int last_printed = 0;
-struct arm_intr {
- driver_intr_t *handler;
- void *arg;
- void *cookiep;
- int irq;
-};
-
-static void
-arm_intr_handler(void *arg)
-{
- struct arm_intr *intr = (struct arm_intr *)arg;
-
- intr->handler(intr->arg);
- arm_unmask_irqs(1 << intr->irq);
-}
void arm_handler_execute(void *, int);
@@ -77,17 +62,14 @@ arm_setup_irqhandler(const char *name, void (*hand)(void*), void *arg,
int irq, int flags, void **cookiep)
{
struct ithd *cur_ith;
- struct arm_intr *intr = NULL;
int error;
if (irq < 0 || irq >= NIRQ)
return;
- if (!(flags & INTR_FAST))
- intr = malloc(sizeof(*intr), M_DEVBUF, M_WAITOK);
cur_ith = ithreads[irq];
if (cur_ith == NULL) {
- error = ithread_create(&cur_ith, irq, 0, NULL, NULL, "intr%d:",
- irq);
+ error = ithread_create(&cur_ith, irq, 0, arm_mask_irq,
+ arm_unmask_irq, "intr%d:", irq);
if (error)
return;
ithreads[irq] = cur_ith;
@@ -100,16 +82,14 @@ arm_setup_irqhandler(const char *name, void (*hand)(void*), void *arg,
intrcnt_index++;
}
- if (!(flags & INTR_FAST)) {
- intr->handler = hand;
- intr->arg = arg;
- intr->irq = irq;
- intr->cookiep = *cookiep;
- ithread_add_handler(cur_ith, name, arm_intr_handler, intr,
- ithread_priority(flags), flags, cookiep);
- } else
- ithread_add_handler(cur_ith, name, hand, arg,
- ithread_priority(flags), flags, cookiep);
+ ithread_add_handler(cur_ith, name, hand, arg,
+ ithread_priority(flags), flags, cookiep);
+}
+
+int
+arm_remove_irqhandler(void *cookie)
+{
+ return (ithread_remove_handler(cookie));
}
void dosoftints(void);
@@ -127,13 +107,8 @@ arm_handler_execute(void *frame, int irqnb)
struct thread *td = curthread;
td->td_intr_nesting_level++;
- if (irqnb == 0)
- irqnb = arm_get_irqnb(frame);
- while (irqnb != 0) {
- arm_mask_irqs(irqnb);
- i = ffs(irqnb) - 1;
+ while ((i = arm_get_next_irq()) != -1) {
intrcnt[intrcnt_tab[i]]++;
- irqnb &= ~(1U << i);
ithd = ithreads[i];
if (!ithd)
continue;
@@ -144,10 +119,10 @@ arm_handler_execute(void *frame, int irqnb)
ih->ih_handler(ih->ih_argument ?
ih->ih_argument : frame);
}
- arm_unmask_irqs(1 << i);
- } else if (ih)
+ } else if (ih) {
+ arm_mask_irq(i);
ithread_schedule(ithd);
- irqnb |= arm_get_irqnb(frame);
+ }
}
td->td_intr_nesting_level--;
}
diff --git a/sys/arm/arm/nexus.c b/sys/arm/arm/nexus.c
index dd47101..131bbc6 100644
--- a/sys/arm/arm/nexus.c
+++ b/sys/arm/arm/nexus.c
@@ -83,6 +83,9 @@ static int nexus_activate_resource(device_t, device_t, int, int,
static int
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
driver_intr_t *intr, void *arg, void **cookiep);
+static int
+nexus_teardown_intr(device_t, device_t, struct resource *, void *);
+
static device_method_t nexus_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, nexus_probe),
@@ -93,6 +96,7 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
DEVMETHOD(bus_activate_resource, nexus_activate_resource),
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
+ DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
{ 0, 0 }
};
@@ -129,6 +133,15 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
return (0);
}
+static int
+nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
+{
+ int error;
+
+ arm_mask_irq(r->r_start);
+ error = arm_remove_irqhandler(ih);
+ return (error);
+}
static int
nexus_attach(device_t dev)
diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h
index cd31eae..dc08c7f 100644
--- a/sys/arm/include/intr.h
+++ b/sys/arm/include/intr.h
@@ -47,10 +47,10 @@
#include <machine/psl.h>
-int arm_get_irqnb(void *);
-void arm_mask_irqs(int);
-void arm_unmask_irqs(int);
-void set_splmasks(void);
+int arm_get_next_irq(void);
+void arm_mask_irq(uintptr_t);
+void arm_unmask_irq(uintptr_t);
void arm_setup_irqhandler(const char *, void (*)(void*), void *, int, int,
void **);
+int arm_remove_irqhandler(void *);
#endif /* _MACHINE_INTR_H */
diff --git a/sys/arm/sa11x0/sa11x0_irqhandler.c b/sys/arm/sa11x0/sa11x0_irqhandler.c
index a3f7db4..5cda4c6 100644
--- a/sys/arm/sa11x0/sa11x0_irqhandler.c
+++ b/sys/arm/sa11x0/sa11x0_irqhandler.c
@@ -102,37 +102,35 @@ int current_intr_depth;
extern struct sa11x0_softc *sa11x0_softc;
-/* Recalculate the interrupt masks from scratch.
- * We could code special registry and deregistry versions of this function that
- * would be faster, but the code would be nastier, and we don't expect this to
- * happen very much anyway.
- */
+static uint32_t sa11x0_irq_mask = 0xfffffff;
+
+extern vm_offset_t saipic_base;
+
int
-arm_get_irqnb(void *frame)
+arm_get_next_irq()
{
- struct sa11x0_softc *sc = sa11x0_softc;
+ int irq;
- return(bus_space_read_4(sc->sc_iot, sc->sc_ioh, SAIPIC_IP));
+ if ((irq = (bus_space_read_4(sc->sc_iot, sc->sc_ioh, SAIPIC_IP) &
+ sa11x0_irq_mask)) != 0)
+ return (ffs(irq) - 1);
+ return (-1);
}
-static uint32_t sa11x0_irq_mask = 0xfffffff;
-
-extern vm_offset_t saipic_base;
-
void
-arm_mask_irqs(int irq)
+arm_mask_irq(uintptr_t irq)
{
- sa11x0_irq_mask &= ~irq;
+ sa11x0_irq_mask &= ~(1 << irq);
__asm __volatile("str %0, [%1, #0x04]" /* SAIPIC_MR */
: : "r" (sa11x0_irq_mask), "r" (saipic_base));
}
void
-arm_unmask_irqs(int irq)
+arm_unmask_irq(uintptr_t irq)
{
- sa11x0_irq_mask |= irq;
+ sa11x0_irq_mask |= (1 << irq);
__asm __volatile("str %0, [%1, #0x04]" /* SAIPIC_MR */
: : "r" (sa11x0_irq_mask), "r" (saipic_base));
}
diff --git a/sys/arm/xscale/i80321/i80321.c b/sys/arm/xscale/i80321/i80321.c
index 23d25a1..dfd03a1 100644
--- a/sys/arm/xscale/i80321/i80321.c
+++ b/sys/arm/xscale/i80321/i80321.c
@@ -259,10 +259,11 @@ i80321_iintsrc_read(void)
}
int
-arm_get_irqnb(void *clockframe)
+arm_get_next_irq()
{
+ int irq;
- return (i80321_iintsrc_read());
+ if ((irq = i80321_iintsrc_read()))
+ return (ffs(irq) - 1);
+ return (-1);
}
-
-
diff --git a/sys/arm/xscale/i80321/i80321_pci.c b/sys/arm/xscale/i80321/i80321_pci.c
index 0bb7810..50ebe49 100644
--- a/sys/arm/xscale/i80321/i80321_pci.c
+++ b/sys/arm/xscale/i80321/i80321_pci.c
@@ -426,6 +426,14 @@ i80321_pci_setup_intr(device_t dev, device_t child,
return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
intr, arg, cookiep));
}
+
+static int
+i80321_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
static device_method_t i80321_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, i80321_pci_probe),
@@ -443,7 +451,7 @@ static device_method_t i80321_pci_methods[] = {
DEVMETHOD(bus_activate_resource, i80321_pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, i80321_pci_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_teardown_intr, i80321_pci_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, i80321_pci_maxslots),
diff --git a/sys/arm/xscale/i80321/iq80321.c b/sys/arm/xscale/i80321/iq80321.c
index 20a11c7..3292406 100644
--- a/sys/arm/xscale/i80321/iq80321.c
+++ b/sys/arm/xscale/i80321/iq80321.c
@@ -263,19 +263,20 @@ iq80321_attach(device_t dev)
}
void
-arm_mask_irqs(int nb)
+arm_mask_irq(uintptr_t nb)
{
- intr_enabled &= ~nb;
+ intr_enabled &= ~(1 << nb);
i80321_set_intrmask();
}
void
-arm_unmask_irqs(int nb)
+arm_unmask_irq(uintptr_t nb)
{
- intr_enabled |= nb;
+ intr_enabled |= (1 << nb);
i80321_set_intrmask();
}
+
void
cpu_reset()
{
@@ -311,12 +312,21 @@ iq80321_setup_intr(device_t dev, device_t child,
return (0);
}
+
+static int
+iq80321_teardown_intr(device_t dev, device_t child, struct resource *res,
+ void *cookie)
+{
+ return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
+}
+
static device_method_t iq80321_methods[] = {
DEVMETHOD(device_probe, iq80321_probe),
DEVMETHOD(device_attach, iq80321_attach),
DEVMETHOD(device_identify, iq80321_identify),
DEVMETHOD(bus_alloc_resource, iq80321_alloc_resource),
DEVMETHOD(bus_setup_intr, iq80321_setup_intr),
+ DEVMETHOD(bus_teardown_intr, iq80321_teardown_intr),
{0, 0},
};
OpenPOWER on IntegriCloud