summaryrefslogtreecommitdiffstats
path: root/sys/dev/ofw/ofw_fdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ofw/ofw_fdt.c')
-rw-r--r--sys/dev/ofw/ofw_fdt.c71
1 files changed, 41 insertions, 30 deletions
diff --git a/sys/dev/ofw/ofw_fdt.c b/sys/dev/ofw/ofw_fdt.c
index 68d3149..806f17c 100644
--- a/sys/dev/ofw/ofw_fdt.c
+++ b/sys/dev/ofw/ofw_fdt.c
@@ -109,22 +109,48 @@ ofw_fdt_init(ofw_t ofw, void *data)
}
/*
- * Device tree functions
+ * Device tree functions.
+ *
+ * We use the offset from fdtp to the node as the 'phandle' in OF interface.
+ *
+ * phandle is a u32 value, therefore we cannot use the pointer to node as
+ * phandle in 64 bit. We also do not use the usual fdt offset as phandle,
+ * as it can be 0, and the OF interface has special meaning for phandle 0.
*/
+static phandle_t
+fdt_offset_phandle(int offset)
+{
+ if (offset < 0)
+ return (0);
+ return ((phandle_t)offset + fdt_off_dt_struct(fdtp));
+}
+
static int
fdt_phandle_offset(phandle_t p)
{
- const char *dt_struct;
+ int pint = (int)p;
+ int dtoff = fdt_off_dt_struct(fdtp);
+
+ if (pint < dtoff)
+ return (-1);
+ return (pint - dtoff);
+}
+
+static int
+fdt_pointer_offset(const void *ptr)
+{
+ uintptr_t dt_struct, p;
int offset;
- dt_struct = (const char *)fdtp + fdt_off_dt_struct(fdtp);
+ p = (uintptr_t)ptr;
+ dt_struct = (uintptr_t)fdtp + fdt_off_dt_struct(fdtp);
- if (((const char *)p < dt_struct) ||
- (const char *)p > (dt_struct + fdt_size_dt_struct(fdtp)))
+ if ((p < dt_struct) ||
+ p > (dt_struct + fdt_size_dt_struct(fdtp)))
return (-1);
- offset = (const char *)p - dt_struct;
+ offset = p - dt_struct;
if (offset < 0)
return (-1);
@@ -135,15 +161,13 @@ fdt_phandle_offset(phandle_t p)
static phandle_t
ofw_fdt_peer(ofw_t ofw, phandle_t node)
{
- phandle_t p;
int depth, offset;
if (node == 0) {
/* Find root node */
offset = fdt_path_offset(fdtp, "/");
- p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(p));
- return (p);
+ return (fdt_offset_phandle(offset));
}
offset = fdt_phandle_offset(node);
@@ -155,10 +179,8 @@ ofw_fdt_peer(ofw_t ofw, phandle_t node)
offset = fdt_next_node(fdtp, offset, &depth)) {
if (depth < 0)
return (0);
- if (depth == 1) {
- p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(p));
- return (p);
- }
+ if (depth == 1)
+ return (fdt_offset_phandle(offset));
}
return (0);
@@ -168,7 +190,6 @@ ofw_fdt_peer(ofw_t ofw, phandle_t node)
static phandle_t
ofw_fdt_child(ofw_t ofw, phandle_t node)
{
- phandle_t p;
int depth, offset;
offset = fdt_phandle_offset(node);
@@ -180,10 +201,8 @@ ofw_fdt_child(ofw_t ofw, phandle_t node)
offset = fdt_next_node(fdtp, offset, &depth)) {
if (depth < 0)
return (0);
- if (depth == 1) {
- p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(p));
- return (p);
- }
+ if (depth == 1)
+ return (fdt_offset_phandle(offset));
}
return (0);
@@ -193,7 +212,6 @@ ofw_fdt_child(ofw_t ofw, phandle_t node)
static phandle_t
ofw_fdt_parent(ofw_t ofw, phandle_t node)
{
- phandle_t p;
int offset, paroffset;
offset = fdt_phandle_offset(node);
@@ -201,15 +219,13 @@ ofw_fdt_parent(ofw_t ofw, phandle_t node)
return (0);
paroffset = fdt_parent_offset(fdtp, offset);
- p = (phandle_t)fdt_offset_ptr(fdtp, paroffset, sizeof(phandle_t));
- return (p);
+ return (fdt_offset_phandle(paroffset));
}
/* Return the package handle that corresponds to an instance handle. */
static phandle_t
ofw_fdt_instance_to_package(ofw_t ofw, ihandle_t instance)
{
- phandle_t p;
int offset;
/*
@@ -223,8 +239,7 @@ ofw_fdt_instance_to_package(ofw_t ofw, ihandle_t instance)
if (offset < 0)
return (-1);
- p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(phandle_t));
- return (p);
+ return (fdt_offset_phandle(offset));
}
/* Get the length of a property of a package. */
@@ -343,7 +358,7 @@ ofw_fdt_nextprop(ofw_t ofw, phandle_t package, const char *previous, char *buf,
if (prop == NULL)
return (-1);
- offset = fdt_phandle_offset((phandle_t)prop);
+ offset = fdt_pointer_offset(prop);
rv = fdt_nextprop(offset, buf, size);
return (rv);
}
@@ -374,14 +389,10 @@ ofw_fdt_canon(ofw_t ofw, const char *device, char *buf, size_t len)
static phandle_t
ofw_fdt_finddevice(ofw_t ofw, const char *device)
{
- phandle_t p;
int offset;
offset = fdt_path_offset(fdtp, device);
-
- p = (phandle_t)fdt_offset_ptr(fdtp, offset, sizeof(p));
-
- return (p);
+ return (fdt_offset_phandle(offset));
}
/* Return the fully qualified pathname corresponding to an instance. */
OpenPOWER on IntegriCloud