[PATCH 10/20] linux/of_irq.h: Generalize of_irq_to_resource()

Sebastian Huber sebastian.huber at embedded-brains.de
Fri Jan 19 13:54:00 UTC 2018


Determine interrupt cells via device tree.
---
 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 45f06e5d1..01502e8b0 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;
-- 
2.12.3




More information about the devel mailing list