summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2024-08-06 09:07:16 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2024-08-06 09:07:16 +0000
commit4624597489af78bd36efae3607c0a5eda546d10d (patch)
tree5299958109b4e379d73cbf6920ebba99de13055b
parentb0be597016d19c50ca454147735a79cd2fed10ff (diff)
The devicetree spec says in section 2.4:
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. similar diff as committed for arm64 a couple of days ago ok jca@
-rw-r--r--sys/arch/riscv64/riscv64/intr.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/sys/arch/riscv64/riscv64/intr.c b/sys/arch/riscv64/riscv64/intr.c
index b7cb8c5eb2f..a6cd054305e 100644
--- a/sys/arch/riscv64/riscv64/intr.c
+++ b/sys/arch/riscv64/riscv64/intr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.c,v 1.11 2024/06/26 01:40:49 jsg Exp $ */
+/* $OpenBSD: intr.c,v 1.12 2024/08/06 09:07:15 kettenis Exp $ */
/*
* Copyright (c) 2011 Dale Rahn <drahn@openbsd.org>
@@ -27,7 +27,7 @@
#include <dev/ofw/openfirm.h>
-uint32_t riscv_intr_get_parent(int);
+int riscv_intr_get_parent(int);
uint32_t riscv_intr_map_msi(int, uint64_t *);
void *riscv_intr_prereg_establish_fdt(void *, int *, int, struct cpu_info *,
@@ -74,17 +74,21 @@ riscv_cpu_intr(void *frame)
/*
* Find the interrupt parent by walking up the tree.
*/
-uint32_t
+int
riscv_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
@@ -271,8 +275,6 @@ riscv_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);
@@ -323,7 +325,8 @@ riscv_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 machine_intr_handle *ih;
void *val = NULL;
@@ -338,9 +341,9 @@ riscv_intr_establish_fdt_idx_cpu(int node, int idx, int level,
/* Old style. */
if (!extended) {
- phandle = riscv_intr_get_parent(node);
+ parent = riscv_intr_get_parent(node);
LIST_FOREACH(ic, &interrupt_controllers, ic_list) {
- if (ic->ic_phandle == phandle)
+ if (ic->ic_node == parent)
break;
}