FDTs use phandles as a way to have pointers to nodes in the tree. For
example, nodes may have an "interrupt-parent" property that contains a
phandle that points to the node that defines the interrupt controller
for the interrupts of the device that corresponds to the node. This
phandle is a simple 32-bit integer. The interrupt controller node
will have a "phandle" (or "linux,phandle") property with that same
32-bit integer.
The diff provides both a fdt-style and on OF-style interface. These
interfaces will be used in the armv7 port to do the necessary phandle
lookups.
ok?
Index: dev/ofw/fdt.c
===================================================================
RCS file: /cvs/src/sys/dev/ofw/fdt.c,v
retrieving revision 1.16
diff -u -p -r1.16 fdt.c
--- dev/ofw/fdt.c 8 Jul 2016 18:20:48 -0000 1.16
+++ dev/ofw/fdt.c 8 Jul 2016 19:49:37 -0000
@@ -35,6 +35,7 @@ void *skip_node_name(u_int32_t *);
void *skip_node(void *);
void *skip_nops(u_int32_t *);
void *fdt_parent_node_recurse(void *, void *);
+void *fdt_find_phandle_recurse(void *, uint32_t);
int fdt_node_property_int(void *, char *, int *);
int fdt_node_property_ints(void *, char *, int *, int);
int fdt_translate_memory_address(void *, struct fdt_memory *);
@@ -443,6 +444,34 @@ fdt_parent_node(void *node)
return fdt_parent_node_recurse(pnode, node);
}
+void *
+fdt_find_phandle_recurse(void *node, uint32_t phandle)
+{
+ void *child;
+ char *data;
+ void *tmp;
+ int len;
+
+ len = fdt_node_property(node, "phandle", &data);
+ if (len < 0)
+ len = fdt_node_property(node, "linux,phandle", &data);
+
+ if (len == sizeof(uint32_t) && bemtoh32(data) == phandle)
+ return node;
+
+ for (child = fdt_child_node(node); child; child = fdt_next_node(child))
+ if ((tmp = fdt_find_phandle_recurse(child, phandle)))
+ return tmp;
+
+ return NULL;
+}
+
+void *
+fdt_find_phandle(uint32_t phandle)
+{
+ return fdt_find_phandle_recurse(fdt_next_node(0), phandle);
+}
+
/*
* Translate memory address depending on parent's range.
*
@@ -748,6 +777,15 @@ OF_getnodebyname(int handle, const char
node = fdt_next_node(node);
}
+ return node ? ((char *)node - (char *)tree.header) : 0;
+}
+
+int
+OF_getnodebyphandle(uint32_t phandle)
+{
+ void *node;
+
+ node = fdt_find_phandle(phandle);
return node ? ((char *)node - (char *)tree.header) : 0;
}
Index: dev/ofw/fdt.h
===================================================================
RCS file: /cvs/src/sys/dev/ofw/fdt.h,v
retrieving revision 1.3
diff -u -p -r1.3 fdt.h
--- dev/ofw/fdt.h 8 Jun 2016 15:27:05 -0000 1.3
+++ dev/ofw/fdt.h 8 Jul 2016 19:49:37 -0000
@@ -60,6 +60,7 @@ char *fdt_node_name(void *);
void *fdt_find_node(char *);
int fdt_node_property(void *, char *, char **);
void *fdt_parent_node(void *);
+void *fdt_find_phandle(uint32_t);
int fdt_get_memory_address(void *, int, struct fdt_memory *);
int fdt_is_compatible(void *, const char *);
#ifdef DEBUG
Index: dev/ofw/openfirm.h
===================================================================
RCS file: /cvs/src/sys/dev/ofw/openfirm.h,v
retrieving revision 1.12
diff -u -p -r1.12 openfirm.h
--- dev/ofw/openfirm.h 12 Jun 2016 12:55:42 -0000 1.12
+++ dev/ofw/openfirm.h 8 Jul 2016 19:49:37 -0000
@@ -71,6 +71,7 @@ int OF_interpret(char *cmd, int nreturns
void (*OF_set_callback(void (*newfunc)(void *))) ();
#endif
int OF_getnodebyname(int, const char *);
+int OF_getnodebyphandle(uint32_t);
/*
* Some generic routines for OpenFirmware handling.