The devicetree spec says in section 2.4:
authorkettenis <kettenis@openbsd.org>
Mon, 5 Aug 2024 13:55:34 +0000 (13:55 +0000)
committerkettenis <kettenis@openbsd.org>
Mon, 5 Aug 2024 13:55:34 +0000 (13:55 +0000)
If an interrupt-generating device does not have an interrupt-parent
property, its interrupt parent is assumed to be its devicetree
parent.

Implement this aspect of the spec in the same way as Linux does by not
just looking at the immediate parent but keep on walking up the tree
until we hit a node with an "interrupt-controller" property or a node
that has an "interrupt-parent" property.

same diff as committed for arm64 yesterday
ok patrick@

sys/arch/armv7/armv7/intr.c

index 2251783..2fab0c3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.c,v 1.22 2024/06/26 01:40:49 jsg Exp $ */
+/* $OpenBSD: intr.c,v 1.23 2024/08/05 13:55:34 kettenis Exp $ */
 /*
  * Copyright (c) 2011 Dale Rahn <drahn@openbsd.org>
  *
@@ -25,7 +25,7 @@
 
 #include <dev/ofw/openfirm.h>
 
-uint32_t arm_intr_get_parent(int);
+int arm_intr_get_parent(int);
 uint32_t arm_intr_map_msi(int, uint64_t *);
 
 void *arm_intr_prereg_establish_fdt(void *, int *, int, struct cpu_info *,
@@ -94,17 +94,21 @@ arm_intr_string(void *cookie)
 /*
  * Find the interrupt parent by walking up the tree.
  */
-uint32_t
+int
 arm_intr_get_parent(int node)
 {
-       uint32_t phandle = 0;
+       uint32_t phandle;
 
-       while (node && !phandle) {
+       while (node) {
                phandle = OF_getpropint(node, "interrupt-parent", 0);
+               if (phandle)
+                       return OF_getnodebyphandle(phandle);
                node = OF_parent(node);
+               if (OF_getpropbool(node, "interrupt-controller"))
+                       return node;
        }
 
-       return phandle;
+       return 0;
 }
 
 uint32_t
@@ -280,8 +284,6 @@ arm_intr_register_fdt(struct interrupt_controller *ic)
 
        ic->ic_cells = OF_getpropint(ic->ic_node, "#interrupt-cells", 0);
        ic->ic_phandle = OF_getpropint(ic->ic_node, "phandle", 0);
-       if (ic->ic_phandle == 0)
-               return;
        KASSERT(ic->ic_cells <= MAX_INTERRUPT_CELLS);
 
        LIST_INSERT_HEAD(&interrupt_controllers, ic, ic_list);
@@ -335,7 +337,8 @@ arm_intr_establish_fdt_idx_cpu(int node, int idx, int level, struct cpu_info *ci
     int (*func)(void *), void *cookie, char *name)
 {
        struct interrupt_controller *ic;
-       int i, len, ncells, extended = 1;
+       int i, len, ncells, parent;
+       int extended = 1;
        uint32_t *cell, *cells, phandle;
        struct arm_intr_handle *ih;
        void *val = NULL;
@@ -350,9 +353,9 @@ arm_intr_establish_fdt_idx_cpu(int node, int idx, int level, struct cpu_info *ci
 
        /* Old style. */
        if (!extended) {
-               phandle = arm_intr_get_parent(node);
+               parent = arm_intr_get_parent(node);
                LIST_FOREACH(ic, &interrupt_controllers, ic_list) {
-                       if (ic->ic_phandle == phandle)
+                       if (ic->ic_node == parent)
                                break;
                }
 
@@ -563,12 +566,12 @@ arm_intr_parent_establish_fdt(void *cookie, int *cell, int level,
 {
        struct interrupt_controller *ic = cookie;
        struct arm_intr_handle *ih;
-       uint32_t phandle;
+       int parent;
        void *val;
 
-       phandle = arm_intr_get_parent(ic->ic_node);
+       parent = arm_intr_get_parent(ic->ic_node);
        LIST_FOREACH(ic, &interrupt_controllers, ic_list) {
-               if (ic->ic_phandle == phandle)
+               if (ic->ic_node == parent)
                        break;
        }
        if (ic == NULL)