From cfc149bff3044b5029c2b574d5d3de05b979bf62 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 10 Jan 2018 14:11:57 +0100 Subject: linux/of_irq.h: Generalize of_irq_to_resource() Determine interrupt cells via device tree. Update #3277. --- rtemsbsd/sys/powerpc/compat.c | 61 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/rtemsbsd/sys/powerpc/compat.c b/rtemsbsd/sys/powerpc/compat.c index 45f06e5d..01502e8b 100644 --- a/rtemsbsd/sys/powerpc/compat.c +++ b/rtemsbsd/sys/powerpc/compat.c @@ -362,32 +362,73 @@ of_address_to_resource(struct device_node *dn, int index, return (0); } +static int +get_interrupt_cells(const void *fdt, int node) +{ + do { + const fdt32_t *p; + int len; + + p = fdt_getprop(fdt, node, "interrupt-parent", &len); + if (p != NULL) { + if (len != sizeof(*p)) + return (-EINVAL); + + node = fdt_node_offset_by_phandle(fdt, + fdt32_to_cpu(*p)); + } else { + node = fdt_parent_offset(fdt, node); + } + + p = fdt_getprop(fdt, node, "#interrupt-cells", &len); + if (p != NULL) { + if (len != sizeof(*p)) + return (-EINVAL); + + return ((int)fdt32_to_cpu(*p)); + } + } while (node >= 0); + + return (-EINVAL); +} + int of_irq_to_resource(struct device_node *dn, int index, struct resource *res) { const void *fdt = bsp_fdt_get(); int len; - const fdt32_t *p; + uint32_t spec_buf[8]; + const fdt32_t *spec; + int node; + int ic; int i; + int j; + int item_len; int irq; if (res != NULL) memset(res, 0, sizeof(*res)); - p = fdt_getprop(fdt, dn->offset, "interrupts", &len); - if (p == NULL) + node = dn->offset; + + spec = fdt_getprop(fdt, node, "interrupts", &len); + if (spec == NULL) return (-EINVAL); - i = index * 16; - if (i + 16 > len) + ic = get_interrupt_cells(fdt, node); + if (ic < 0 || ic >= RTEMS_ARRAY_SIZE(spec_buf)) + return (EINVAL); + + item_len = ic * 4; + i = index * item_len; + if (i + item_len > len) return (-EINVAL); - irq = (int)fdt32_to_cpu(p[i / sizeof(*p)]); -#ifdef __PPC__ - /* FIXME */ - irq -= 16; -#endif + for (j = 0; j < ic; ++j) + spec_buf[j] = fdt32_to_cpu(spec[i / sizeof(*spec)]); + + irq = bsp_fdt_map_intr(spec_buf, (size_t)ic); if (res != NULL) { res->start = irq; -- cgit v1.2.3