svn commit: r271914 - in projects/arm_intrng/sys/arm: arm include
Jakub Wojciech Klama
jceel at FreeBSD.org
Sun Sep 21 00:20:42 UTC 2014
Author: jceel
Date: Sun Sep 21 00:20:41 2014
New Revision: 271914
URL: http://svnweb.freebsd.org/changeset/base/271914
Log:
Add method for binding interrupt to CPU in PIC interface (currently unused)
and mechanism for unified caching and translating FDT cells describing
interrupt to actual IRQ number through PIC kobj interface.
Modified:
projects/arm_intrng/sys/arm/arm/intrng.c
projects/arm_intrng/sys/arm/arm/nexus.c
projects/arm_intrng/sys/arm/arm/pic_if.m
projects/arm_intrng/sys/arm/include/intr.h
Modified: projects/arm_intrng/sys/arm/arm/intrng.c
==============================================================================
--- projects/arm_intrng/sys/arm/arm/intrng.c Sun Sep 21 00:05:44 2014 (r271913)
+++ projects/arm_intrng/sys/arm/arm/intrng.c Sun Sep 21 00:20:41 2014 (r271914)
@@ -36,6 +36,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/kernel.h>
#include <sys/syslog.h>
#include <sys/malloc.h>
#include <sys/proc.h>
@@ -47,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/smp.h>
+#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
@@ -58,6 +60,7 @@ __FBSDID("$FreeBSD$");
#define IRQ_VECTOR_IDX(_irq) ((_irq) & 0xff)
#define IRQ_GEN(_pic, _irq) (((_pic) << 8) | ((_irq) & 0xff))
+//#define DEBUG
#ifdef DEBUG
#define debugf(fmt, args...) do { printf("%s(): ", __func__); \
printf(fmt,##args); } while (0)
@@ -70,6 +73,8 @@ typedef void (*mask_fn)(void *);
struct arm_intr_controller {
device_t ic_dev;
phandle_t ic_node;
+ int ic_maxintrs;
+ struct arm_intr_handler *ic_intrs;
};
struct arm_intr_handler {
@@ -77,6 +82,10 @@ struct arm_intr_handler {
const char * ih_ipi_name;
int ih_intrcnt_idx;
int ih_irq;
+ pcell_t ih_cells[8];
+ int ih_ncells;
+ enum intr_trigger ih_trig;
+ enum intr_polarity ih_pol;
struct intr_event * ih_event;
struct arm_intr_controller *ih_pic;
};
@@ -85,13 +94,15 @@ static void arm_mask_irq(void *);
static void arm_unmask_irq(void *);
static void arm_eoi(void *);
-static struct arm_intr_handler arm_intrs[NIRQ];
static struct arm_intr_controller arm_pics[NPIC];
static struct arm_intr_controller *arm_ipi_pic;
static int intrcnt_index = 0;
static int last_printed = 0;
+MALLOC_DECLARE(M_INTRNG);
+MALLOC_DEFINE(M_INTRNG, "intrng", "ARM interrupt handling");
+
/* Data for statistics reporting. */
u_long intrcnt[NIRQ];
char intrnames[NIRQ * INTRNAME_LEN];
@@ -109,6 +120,7 @@ arm_intrnames_init(void)
void
arm_dispatch_irq(device_t dev, struct trapframe *tf, int irq)
{
+ struct arm_intr_controller *ic;
struct arm_intr_handler *ih = NULL;
int i;
@@ -122,11 +134,13 @@ arm_dispatch_irq(device_t dev, struct tr
if (tf == NULL)
tf = PCPU_GET(curthread)->td_intr_frame;
- for (i = 0; arm_intrs[i].ih_dev != NULL; i++) {
- if (arm_intrs[i].ih_pic->ic_dev == dev &&
- arm_intrs[i].ih_irq == irq) {
- ih = &arm_intrs[i];
- break;
+ for (ic = &arm_pics[0]; ic->ic_dev != NULL; ic++) {
+ if (ic->ic_dev == dev) {
+ for (i = 0; i < ic->ic_maxintrs; i++) {
+ ih = &ic->ic_intrs[i];
+ if (irq == ih->ih_irq)
+ break;
+ }
}
}
@@ -147,38 +161,64 @@ arm_dispatch_irq(device_t dev, struct tr
}
static struct arm_intr_handler *
-arm_lookup_intr_handler(device_t pic, int irq)
+arm_lookup_intr_handler(device_t pic, int idx)
{
- int i;
+ struct arm_intr_controller *ic;
- for (i = 0; i < NIRQ; i++) {
- if (arm_intrs[i].ih_pic != NULL &&
- arm_intrs[i].ih_pic->ic_dev == pic &&
- arm_intrs[i].ih_irq == irq)
- return (&arm_intrs[i]);
-
- if (arm_intrs[i].ih_dev == NULL)
- return (&arm_intrs[i]);
+ for (ic = &arm_pics[0]; ic->ic_dev != NULL; ic++) {
+ if (ic->ic_dev != NULL && ic->ic_dev == pic)
+ return (&ic->ic_intrs[idx]);
}
- return NULL;
+ return (NULL);
}
+
int
-arm_fdt_map_irq(phandle_t ic, int irq)
+arm_fdt_map_irq(phandle_t ic, pcell_t *cells, int ncells)
{
- int i;
+ struct arm_intr_controller *pic;
+ struct arm_intr_handler *ih;
+ int i, j;
ic = OF_xref_phandle(ic);
- debugf("ic %08x irq %d\n", ic, irq);
-
- if (ic == CORE_PIC_NODE)
- return (IRQ_GEN(CORE_PIC_IDX, irq));
+ debugf("ic %08x cells <%*D>\n", ic, ncells * sizeof(pcell_t),
+ (char *)cells, ",");
for (i = 0; arm_pics[i].ic_node != 0; i++) {
- if (arm_pics[i].ic_node == ic)
- return (IRQ_GEN(i, irq));
+ pic = &arm_pics[i];
+ if (pic->ic_node == ic) {
+ for (j = 0; j < pic->ic_maxintrs; j++) {
+ ih = &pic->ic_intrs[j];
+
+ /* Compare pcell contents */
+ if (!memcmp(cells, ih->ih_cells, ncells))
+ return (IRQ_GEN(i, j));
+ }
+
+ /* Not found - new entry required */
+ pic->ic_maxintrs++;
+ pic->ic_intrs = realloc(pic->ic_intrs,
+ pic->ic_maxintrs * sizeof(struct arm_intr_handler),
+ M_INTRNG, M_WAITOK | M_ZERO);
+
+ ih = &pic->ic_intrs[pic->ic_maxintrs - 1];
+ ih->ih_pic = pic;
+ ih->ih_ncells = ncells;
+ memcpy(ih->ih_cells, cells, ncells);
+
+ if (pic->ic_dev != NULL) {
+ /* Map IRQ number */
+ PIC_TRANSLATE(pic->ic_dev, cells, &ih->ih_irq,
+ &ih->ih_trig, &ih->ih_pol);
+
+ debugf(pic->ic_dev, "translated to irq %d\n",
+ ih->ih_irq);
+ }
+
+ return (IRQ_GEN(i, pic->ic_maxintrs - 1));
+ };
}
/*
@@ -186,32 +226,53 @@ arm_fdt_map_irq(phandle_t ic, int irq)
* we map a stub for it. 'i' is pointing to free
* first slot in arm_pics table.
*/
- arm_pics[i].ic_node = ic;
- return (IRQ_GEN(i, irq));
+ debugf("allocating new ic at index %d\n", i);
+
+ pic = &arm_pics[i];
+ pic->ic_node = ic;
+ pic->ic_maxintrs = 1;
+ pic->ic_intrs = malloc(sizeof(struct arm_intr_handler), M_INTRNG,
+ M_WAITOK | M_ZERO);
+
+ ih = &pic->ic_intrs[0];
+ ih->ih_pic = pic;
+ ih->ih_ncells = ncells;
+ memcpy(ih->ih_cells, cells, ncells);
+
+ return (IRQ_GEN(i, 0));
}
const char *
arm_describe_irq(int irq)
{
struct arm_intr_controller *pic;
+ struct arm_intr_handler *ih;
static char buffer[INTRNAME_LEN];
static char name[INTRNAME_LEN];
pic = &arm_pics[IRQ_PIC_IDX(irq)];
+ if (pic == NULL)
+ return ("<unknown ic>");
+
+ if (IRQ_VECTOR_IDX(irq) > pic->ic_maxintrs)
+ return ("<unknown irq>");
+
+ ih = &pic->ic_intrs[IRQ_VECTOR_IDX(irq)];
+
if (pic->ic_dev == NULL) {
/*
- * Interrupt controller not attached yet, so we'll use it's
- * FDT "name" property instead
+ * Interrupt controller not attached yet. We don't know the
+ * IC device name nor interrupt number. All we can do is to
+ * use FDT 'name' property.
*/
- OF_getprop(pic->ic_node, "name", name, sizeof(name));
- snprintf(buffer, sizeof(buffer), "%s.%d", name,
- IRQ_VECTOR_IDX(irq));
+ OF_getprop(ih->ih_pic->ic_node, "name", name, sizeof(name));
+ snprintf(buffer, sizeof(buffer), "%s.?", name);
return (buffer);
}
snprintf(buffer, sizeof(buffer), "%s.%d",
- device_get_nameunit(pic->ic_dev), IRQ_VECTOR_IDX(irq));
+ device_get_nameunit(ih->ih_pic->ic_dev), ih->ih_irq);
return (buffer);
}
@@ -220,6 +281,7 @@ void
arm_register_pic(device_t dev, int flags)
{
struct arm_intr_controller *ic = NULL;
+ struct arm_intr_handler *ih;
phandle_t node;
int i;
@@ -247,15 +309,28 @@ arm_register_pic(device_t dev, int flags
ic->ic_dev = dev;
ic->ic_node = node;
- debugf("device %s node %08x slot %d\n", device_get_nameunit(dev), ic->ic_node, i);
+ debugf("device %s node %08x slot %d\n", device_get_nameunit(dev),
+ ic->ic_node, i);
if (flags & PIC_FEATURE_IPI) {
if (arm_ipi_pic != NULL)
- panic("there's already registered interrupt controller for serving IPIs");
+ panic("there's already registered interrupt "
+ "controller for serving IPIs");
arm_ipi_pic = ic;
}
+ /* Resolve IRQ numbers for interrupt handlers added earlier */
+ for (i = 0; i < ic->ic_maxintrs; i++) {
+ ih = &ic->ic_intrs[i];
+
+ /* Map IRQ number */
+ PIC_TRANSLATE(ic->ic_dev, ih->ih_cells, &ih->ih_irq,
+ &ih->ih_trig, &ih->ih_pol);
+
+ debugf(ic->ic_dev, "translated to irq %d\n", ih->ih_irq);
+ }
+
device_printf(dev, "registered as interrupt controller\n");
}
@@ -290,14 +365,14 @@ arm_setup_irqhandler(device_t dev, drive
if (ih->ih_event == NULL) {
error = intr_event_create(&ih->ih_event, (void *)ih, 0, irq,
(mask_fn)arm_mask_irq, (mask_fn)arm_unmask_irq,
- arm_eoi, NULL, "intr%d:", irq);
+ arm_eoi, NULL, "intr%d.%d:", IRQ_PIC_IDX(irq),
+ IRQ_VECTOR_IDX(irq));
if (error)
return;
ih->ih_dev = dev;
ih->ih_ipi_name = ipi ? name : NULL;
- ih->ih_irq = IRQ_VECTOR_IDX(irq);
ih->ih_pic = pic;
arm_unmask_irq(ih);
Modified: projects/arm_intrng/sys/arm/arm/nexus.c
==============================================================================
--- projects/arm_intrng/sys/arm/arm/nexus.c Sun Sep 21 00:05:44 2014 (r271913)
+++ projects/arm_intrng/sys/arm/arm/nexus.c Sun Sep 21 00:20:41 2014 (r271914)
@@ -426,30 +426,8 @@ static int
nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells,
pcell_t *intr)
{
- fdt_pic_decode_t intr_decode;
- phandle_t intr_offset;
- int i, rv, interrupt, trig, pol;
- intr_offset = OF_xref_phandle(iparent);
-
- for (i = 0; i < icells; i++)
- intr[i] = cpu_to_fdt32(intr[i]);
-
- for (i = 0; fdt_pic_table[i] != NULL; i++) {
- intr_decode = fdt_pic_table[i];
- rv = intr_decode(intr_offset, intr, &interrupt, &trig, &pol);
-
- if (rv == 0) {
- /* This was recognized as our PIC and decoded. */
- interrupt = FDT_MAP_IRQ(iparent, interrupt);
- return (interrupt);
- }
- }
-
- /* Not in table, so guess */
- interrupt = FDT_MAP_IRQ(iparent, fdt32_to_cpu(intr[0]));
-
- return (interrupt);
+ return (arm_fdt_map_irq(iparent, intr, icells));
}
#endif
Modified: projects/arm_intrng/sys/arm/arm/pic_if.m
==============================================================================
--- projects/arm_intrng/sys/arm/arm/pic_if.m Sun Sep 21 00:05:44 2014 (r271913)
+++ projects/arm_intrng/sys/arm/arm/pic_if.m Sun Sep 21 00:20:41 2014 (r271914)
@@ -28,10 +28,25 @@
#include <sys/bus.h>
#include <sys/cpuset.h>
+#include <dev/ofw/openfirm.h>
INTERFACE pic;
CODE {
+ static int null_pic_translate(device_t dev, pcell_t *cells, int *irq,
+ enum intr_trigger *trig, enum intr_polarity *pol)
+ {
+ *irq = cells[0];
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ return (0);
+ }
+
+ static void null_pic_bind(device_t dev, int irq, cpuset_t cpumask)
+ {
+ return;
+ }
+
static void null_pic_ipi_send(device_t dev, cpuset_t cpus, int ipi)
{
return;
@@ -60,6 +75,20 @@ METHOD int config {
enum intr_polarity pol;
};
+METHOD int translate {
+ device_t dev;
+ pcell_t *cells;
+ int *irq;
+ enum intr_trigger *trig;
+ enum intr_polarity *pol;
+} DEFAULT null_pic_translate;
+
+METHOD void bind {
+ device_t dev;
+ int irq;
+ cpuset_t cpumask;
+} DEFAULT null_pic_bind;
+
METHOD void eoi {
device_t dev;
int irq;
Modified: projects/arm_intrng/sys/arm/include/intr.h
==============================================================================
--- projects/arm_intrng/sys/arm/include/intr.h Sun Sep 21 00:05:44 2014 (r271913)
+++ projects/arm_intrng/sys/arm/include/intr.h Sun Sep 21 00:20:41 2014 (r271914)
@@ -57,7 +57,7 @@
/* Interrupt controller features used in arm_register_pic(): */
#define PIC_FEATURE_IPI 0x1
-int arm_fdt_map_irq(phandle_t ic, int irq);
+int arm_fdt_map_irq(phandle_t ic, pcell_t *cells, int ncells);
void arm_register_pic(device_t dev, int features);
void arm_unregister_pic(device_t dev);
void arm_dispatch_irq(device_t dev, struct trapframe *tf, int irq);
@@ -113,13 +113,12 @@ extern void (*arm_post_filter)(void *);
extern int (*arm_config_irq)(int irq, enum intr_trigger trig,
enum intr_polarity pol);
-void arm_irq_memory_barrier(uintptr_t);
-
void gic_init_secondary(void);
#endif /* !ARM_INTRNG */
const char *arm_describe_irq(int irq);
void arm_intrnames_init(void);
+void arm_irq_memory_barrier(uintptr_t);
#endif /* _MACHINE_INTR_H */
More information about the svn-src-projects
mailing list