summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-01-10 14:11:57 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-01-23 14:55:02 +0100
commitcfc149bff3044b5029c2b574d5d3de05b979bf62 (patch)
tree39d74ceb94897ff5d8ebbecf9222ac7ac9e125d9
parente4923c85c950f499259dd0efb0fe8b63ca1164b0 (diff)
linux/of_irq.h: Generalize of_irq_to_resource()
Determine interrupt cells via device tree. Update #3277.
-rw-r--r--rtemsbsd/sys/powerpc/compat.c61
1 files 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;