summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-05-14 18:54:34 +0000
committerian <ian@FreeBSD.org>2014-05-14 18:54:34 +0000
commit21fbbde45943109155a62d78963119afc7f3f290 (patch)
treedeee42515173cf5d1de657da766da3d27cce6bb8
parent9e6ff9cd8c9d75c84e35d396dd9595b3ec4b947f (diff)
downloadFreeBSD-src-21fbbde45943109155a62d78963119afc7f3f290.zip
FreeBSD-src-21fbbde45943109155a62d78963119afc7f3f290.tar.gz
MFC r260281, r260282, r260283, r260285
Implement OFW_BUS_MAP_INTR() in terms of the FDT PIC table Reimplement fdt_intr_to_rl() in terms of OFW_BUS_MAP_INTR() and OFW_BUS_CONFIG_INTR(). Use bus_space_map() rather than pmap_mapdev() in nexus_activate_resource(), when running on FDT systems. Unmap memory in nexus_deactivate_resource(). Remove fdt_pic_table code from MIPS, PowerPC, and x86, as it is no longer used by anything.
-rw-r--r--sys/arm/arm/nexus.c95
-rw-r--r--sys/dev/fdt/fdt_common.c114
-rw-r--r--sys/dev/fdt/fdt_common.h3
-rw-r--r--sys/dev/fdt/fdt_mips.c42
-rw-r--r--sys/dev/fdt/fdt_powerpc.c86
-rw-r--r--sys/dev/fdt/fdt_x86.c3
-rw-r--r--sys/dev/fdt/simplebus.c2
7 files changed, 104 insertions, 241 deletions
diff --git a/sys/arm/arm/nexus.c b/sys/arm/arm/nexus.c
index 94f3c37..5200303 100644
--- a/sys/arm/arm/nexus.c
+++ b/sys/arm/arm/nexus.c
@@ -64,7 +64,9 @@ __FBSDID("$FreeBSD$");
#ifdef FDT
#include <dev/ofw/ofw_nexus.h>
+#include <dev/fdt/fdt_common.h>
#include <machine/fdt.h>
+#include "ofw_bus_if.h"
#else
static MALLOC_DEFINE(M_NEXUSDEV, "nexusdev", "Nexus device");
@@ -94,6 +96,11 @@ static int nexus_setup_intr(device_t dev, device_t child, struct resource *res,
int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep);
static int nexus_teardown_intr(device_t, device_t, struct resource *, void *);
+#ifdef FDT
+static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent,
+ int irq);
+#endif
+
static device_method_t nexus_methods[] = {
#ifndef FDT
/* Device interface */
@@ -109,6 +116,9 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
+#ifdef FDT
+ DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr),
+#endif
{ 0, 0 }
};
@@ -268,35 +278,92 @@ static int
nexus_activate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r)
{
+ int err;
+ bus_addr_t paddr;
+ bus_size_t psize;
+ bus_space_handle_t vaddr;
+
+ if ((err = rman_activate_resource(r)) != 0)
+ return (err);
+
/*
* If this is a memory resource, map it into the kernel.
*/
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
- caddr_t vaddr = 0;
- u_int32_t paddr;
- u_int32_t psize;
- u_int32_t poffs;
-
- paddr = rman_get_start(r);
- psize = rman_get_size(r);
- poffs = paddr - trunc_page(paddr);
- vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs;
- rman_set_virtual(r, vaddr);
+ paddr = (bus_addr_t)rman_get_start(r);
+ psize = (bus_size_t)rman_get_size(r);
#ifdef FDT
+ err = bus_space_map(fdtbus_bs_tag, paddr, psize, 0, &vaddr);
+ if (err != 0) {
+ rman_deactivate_resource(r);
+ return (err);
+ }
rman_set_bustag(r, fdtbus_bs_tag);
#else
+ vaddr = (bus_space_handle_t)pmap_mapdev((vm_offset_t)paddr,
+ (vm_size_t)psize);
+ if (vaddr == 0) {
+ rman_deactivate_resource(r);
+ return (ENOMEM);
+ }
rman_set_bustag(r, (void *)1);
#endif
- rman_set_bushandle(r, (bus_space_handle_t) vaddr);
+ rman_set_virtual(r, (void *)vaddr);
+ rman_set_bushandle(r, vaddr);
}
- return (rman_activate_resource(r));
+ return (0);
}
static int
nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *res)
+ struct resource *r)
{
+ bus_size_t psize;
+ bus_space_handle_t vaddr;
+
+ psize = (bus_size_t)rman_get_size(r);
+ vaddr = rman_get_bushandle(r);
+
+ if (vaddr != 0) {
+#ifdef FDT
+ bus_space_unmap(fdtbus_bs_tag, vaddr, psize);
+#else
+ pmap_unmapdev((vm_offset_t)vaddr, (vm_size_t)psize);
+#endif
+ rman_set_virtual(r, NULL);
+ rman_set_bushandle(r, 0);
+ }
- return (rman_deactivate_resource(res));
+ return (rman_deactivate_resource(r));
}
+#ifdef FDT
+static int
+nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq)
+{
+ pcell_t intr[2];
+ fdt_pic_decode_t intr_decode;
+ phandle_t intr_offset;
+ int i, rv, interrupt, trig, pol;
+
+ intr_offset = OF_xref_phandle(iparent);
+ intr[0] = cpu_to_fdt32(irq);
+
+ 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(intr_parent, interrupt);
+ return (interrupt);
+ }
+ }
+
+ /* Not in table, so guess */
+ interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(*intr));
+
+ return (interrupt);
+}
+#endif
+
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index 15bf964..6233094 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -474,104 +474,32 @@ out:
}
int
-fdt_intr_decode(phandle_t intr_parent, pcell_t *intr, int *interrupt,
- int *trig, int *pol)
-{
- fdt_pic_decode_t intr_decode;
- phandle_t intr_offset;
- int i, rv;
-
- intr_offset = OF_xref_phandle(intr_parent);
-
- for (i = 0; fdt_pic_table[i] != NULL; i++) {
-
- /* XXX check if pic_handle has interrupt-controller prop? */
-
- 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(intr_parent, *interrupt);
- return (0);
- }
- }
-
- /* Not in table, so guess */
- *interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(*intr));
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
-
- return (0);
-}
-
-int
-fdt_intr_to_rl(phandle_t node, struct resource_list *rl,
+fdt_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl,
struct fdt_sense_level *intr_sl)
{
- phandle_t intr_par;
- phandle_t iph;
- pcell_t *intr;
- pcell_t intr_cells;
- int interrupt, trig, pol;
- int i, intr_num, rv;
-
- if (OF_getproplen(node, "interrupts") <= 0)
- /* Node does not have 'interrupts' property. */
- return (0);
-
- /*
- * Find #interrupt-cells of the interrupt domain.
- */
- if (OF_getencprop(node, "interrupt-parent", &iph, sizeof(iph)) <= 0) {
- debugf("no intr-parent phandle\n");
- intr_par = OF_parent(node);
- } else {
- intr_par = OF_xref_phandle(iph);
- }
-
- if (OF_getprop(intr_par, "#interrupt-cells", &intr_cells,
- sizeof(intr_cells)) <= 0) {
- debugf("no intr-cells defined, defaulting to 1\n");
- intr_cells = 1;
- }
- else
- intr_cells = fdt32_to_cpu(intr_cells);
-
- intr_num = OF_getprop_alloc(node, "interrupts",
- intr_cells * sizeof(pcell_t), (void **)&intr);
- if (intr_num <= 0 || intr_num > DI_MAX_INTR_NUM)
- return (ERANGE);
-
- rv = 0;
- for (i = 0; i < intr_num; i++) {
-
- interrupt = -1;
- trig = pol = 0;
-
- if (fdt_intr_decode(iph, &intr[i * intr_cells],
- &interrupt, &trig, &pol) != 0) {
- rv = ENXIO;
- goto out;
+ phandle_t iparent;
+ uint32_t *intr, icells;
+ int nintr, i, k;
+
+ nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr),
+ (void **)&intr);
+ if (nintr > 0) {
+ iparent = 0;
+ OF_searchencprop(node, "interrupt-parent", &iparent,
+ sizeof(iparent));
+ OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells",
+ &icells, sizeof(icells));
+ for (i = 0, k = 0; i < nintr; i += icells, k++) {
+ intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]);
+ resource_list_add(rl, SYS_RES_IRQ, k, intr[i], intr[i],
+ 1);
+ if (icells > 1)
+ ofw_bus_config_intr(dev, intr[i], intr[i+1]);
}
-
- if (interrupt < 0) {
- rv = ERANGE;
- goto out;
- }
-
- debugf("decoded intr = %d, trig = %d, pol = %d\n", interrupt,
- trig, pol);
-
- intr_sl[i].trig = trig;
- intr_sl[i].pol = pol;
-
- resource_list_add(rl, SYS_RES_IRQ, i, interrupt, interrupt, 1);
+ free(intr, M_OFWPROP);
}
-out:
- free(intr, M_OFWPROP);
- return (rv);
+ return (0);
}
int
diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h
index 499d1f8..f3f9b07 100644
--- a/sys/dev/fdt/fdt_common.h
+++ b/sys/dev/fdt/fdt_common.h
@@ -94,8 +94,7 @@ int fdt_get_phyaddr(phandle_t, device_t, int *, void **);
int fdt_get_range(phandle_t, int, u_long *, u_long *);
int fdt_immr_addr(vm_offset_t);
int fdt_regsize(phandle_t, u_long *, u_long *);
-int fdt_intr_decode(phandle_t, pcell_t *, int *, int *, int *);
-int fdt_intr_to_rl(phandle_t, struct resource_list *, struct fdt_sense_level *);
+int fdt_intr_to_rl(device_t, phandle_t, struct resource_list *, struct fdt_sense_level *);
int fdt_is_compatible(phandle_t, const char *);
int fdt_is_compatible_strict(phandle_t, const char *);
int fdt_is_enabled(phandle_t);
diff --git a/sys/dev/fdt/fdt_mips.c b/sys/dev/fdt/fdt_mips.c
index 1904574..4e04602 100644
--- a/sys/dev/fdt/fdt_mips.c
+++ b/sys/dev/fdt/fdt_mips.c
@@ -49,45 +49,3 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
-/*
- * For PIC-free boards, provide a PIC decoder to be used with mips4k CP0
- * interrupt control directly.
- */
-static int
-fdt_pic_decode_mips4k_cp0(phandle_t node, pcell_t *intr, int *interrupt,
- int *trig, int *pol)
-{
-
- if (!fdt_is_compatible(node, "mips,mips4k"))
- return (ENXIO);
-
- *interrupt = fdt32_to_cpu(intr[0]);
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
-
- return (0);
-}
-
-/*
- * CHERI PIC decoder.
- */
-static int
-fdt_pic_decode_beri(phandle_t node, pcell_t *intr, int *interrupt,
- int *trig, int *pol)
-{
-
- if (!fdt_is_compatible(node, "sri-cambridge,beri-pic"))
- return (ENXIO);
-
- *interrupt = fdt32_to_cpu(intr[0]);
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
-
- return (0);
-}
-
-fdt_pic_decode_t fdt_pic_table[] = {
- &fdt_pic_decode_mips4k_cp0,
- &fdt_pic_decode_beri,
- NULL
-};
diff --git a/sys/dev/fdt/fdt_powerpc.c b/sys/dev/fdt/fdt_powerpc.c
index d3e9d4e..f408d0a 100644
--- a/sys/dev/fdt/fdt_powerpc.c
+++ b/sys/dev/fdt/fdt_powerpc.c
@@ -81,89 +81,3 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
-static int
-fdt_pic_decode_iic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
- int *pol)
-{
- if (!fdt_is_compatible(node, "chrp,iic"))
- return (ENXIO);
-
- *interrupt = intr[0];
-
- switch (intr[1]) {
- case 0:
- /* Active L level */
- *trig = INTR_TRIGGER_LEVEL;
- *pol = INTR_POLARITY_LOW;
- break;
- case 1:
- /* Active H level */
- *trig = INTR_TRIGGER_LEVEL;
- *pol = INTR_POLARITY_HIGH;
- break;
- case 2:
- /* H to L edge */
- *trig = INTR_TRIGGER_EDGE;
- *pol = INTR_POLARITY_LOW;
- break;
- case 3:
- /* L to H edge */
- *trig = INTR_TRIGGER_EDGE;
- *pol = INTR_POLARITY_HIGH;
- break;
- default:
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
- }
- return (0);
-}
-
-static int
-fdt_pic_decode_openpic(phandle_t node, pcell_t *intr, int *interrupt,
- int *trig, int *pol)
-{
-
- if (!fdt_is_compatible(node, "chrp,open-pic") &&
- !fdt_is_type(node, "open-pic"))
- return (ENXIO);
-
- /*
- * XXX The interrupt number read out from the MPC85XX device tree is
- * already offset by 16 to reflect the 'internal' IRQ range shift on
- * the OpenPIC.
- */
- *interrupt = intr[0];
-
- switch (intr[1]) {
- case 0:
- /* L to H edge */
- *trig = INTR_TRIGGER_EDGE;
- *pol = INTR_POLARITY_HIGH;
- break;
- case 1:
- /* Active L level */
- *trig = INTR_TRIGGER_LEVEL;
- *pol = INTR_POLARITY_LOW;
- break;
- case 2:
- /* Active H level */
- *trig = INTR_TRIGGER_LEVEL;
- *pol = INTR_POLARITY_HIGH;
- break;
- case 3:
- /* H to L edge */
- *trig = INTR_TRIGGER_EDGE;
- *pol = INTR_POLARITY_LOW;
- break;
- default:
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
- }
- return (0);
-}
-
-fdt_pic_decode_t fdt_pic_table[] = {
- &fdt_pic_decode_iic,
- &fdt_pic_decode_openpic,
- NULL
-};
diff --git a/sys/dev/fdt/fdt_x86.c b/sys/dev/fdt/fdt_x86.c
index 3085f3b..d4d9fc8 100644
--- a/sys/dev/fdt/fdt_x86.c
+++ b/sys/dev/fdt/fdt_x86.c
@@ -46,6 +46,3 @@ struct fdt_fixup_entry fdt_fixup_table[] = {
{ NULL, NULL }
};
-fdt_pic_decode_t fdt_pic_table[] = {
- NULL
-};
diff --git a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c
index 92439cd..5ed145f 100644
--- a/sys/dev/fdt/simplebus.c
+++ b/sys/dev/fdt/simplebus.c
@@ -196,7 +196,7 @@ simplebus_attach(device_t dev)
continue;
}
- if (fdt_intr_to_rl(dt_child, &di->di_res, di->di_intr_sl)) {
+ if (fdt_intr_to_rl(dev, dt_child, &di->di_res, di->di_intr_sl)) {
device_printf(dev, "%s: could not process "
"'interrupts' property\n", di->di_ofw.obd_name);
resource_list_free(&di->di_res);
OpenPOWER on IntegriCloud