diff options
author | ian <ian@FreeBSD.org> | 2014-05-14 18:54:34 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2014-05-14 18:54:34 +0000 |
commit | 21fbbde45943109155a62d78963119afc7f3f290 (patch) | |
tree | deee42515173cf5d1de657da766da3d27cce6bb8 | |
parent | 9e6ff9cd8c9d75c84e35d396dd9595b3ec4b947f (diff) | |
download | FreeBSD-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.c | 95 | ||||
-rw-r--r-- | sys/dev/fdt/fdt_common.c | 114 | ||||
-rw-r--r-- | sys/dev/fdt/fdt_common.h | 3 | ||||
-rw-r--r-- | sys/dev/fdt/fdt_mips.c | 42 | ||||
-rw-r--r-- | sys/dev/fdt/fdt_powerpc.c | 86 | ||||
-rw-r--r-- | sys/dev/fdt/fdt_x86.c | 3 | ||||
-rw-r--r-- | sys/dev/fdt/simplebus.c | 2 |
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); |