#include <dm.h>
#include <fdtdec.h>
#include <fdt_support.h>
+#include <malloc.h>
#include <linux/libfdt.h>
#include <dm/of_access.h>
#include <dm/of_addr.h>
int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
{
+ return ofnode_read_u32_index(node, propname, 0, outp);
+}
+
+u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
+{
+ assert(ofnode_valid(node));
+ ofnode_read_u32_index(node, propname, 0, &def);
+
+ return def;
+}
+
+int ofnode_read_u32_index(ofnode node, const char *propname, int index,
+ u32 *outp)
+{
+ const fdt32_t *cell;
+ int len;
+
assert(ofnode_valid(node));
debug("%s: %s: ", __func__, propname);
- if (ofnode_is_np(node)) {
- return of_read_u32(ofnode_to_np(node), propname, outp);
- } else {
- const fdt32_t *cell;
- int len;
+ if (ofnode_is_np(node))
+ return of_read_u32_index(ofnode_to_np(node), propname, index,
+ outp);
- cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
- propname, &len);
- if (!cell || len < sizeof(int)) {
- debug("(not found)\n");
- return -EINVAL;
- }
- *outp = fdt32_to_cpu(cell[0]);
+ cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
+ &len);
+ if (!cell) {
+ debug("(not found)\n");
+ return -EINVAL;
}
+
+ if (len < (sizeof(int) * (index + 1))) {
+ debug("(not large enough)\n");
+ return -EOVERFLOW;
+ }
+
+ *outp = fdt32_to_cpu(cell[index]);
debug("%#x (%d)\n", *outp, *outp);
return 0;
}
-int ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
+u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
+ u32 def)
{
assert(ofnode_valid(node));
- ofnode_read_u32(node, propname, &def);
+ ofnode_read_u32_index(node, propname, index, &def);
return def;
}
int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
{
- const fdt64_t *cell;
+ const unaligned_fdt64_t *cell;
int len;
assert(ofnode_valid(node));
return 0;
}
-int ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
+u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
{
assert(ofnode_valid(node));
ofnode_read_u64(node, propname, &def);
return prop ? true : false;
}
-const char *ofnode_read_string(ofnode node, const char *propname)
+const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
{
- const char *str = NULL;
- int len = -1;
+ const char *val = NULL;
+ int len;
assert(ofnode_valid(node));
debug("%s: %s: ", __func__, propname);
if (ofnode_is_np(node)) {
struct property *prop = of_find_property(
- ofnode_to_np(node), propname, NULL);
+ ofnode_to_np(node), propname, &len);
if (prop) {
- str = prop->value;
+ val = prop->value;
len = prop->length;
}
} else {
- str = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
+ val = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
propname, &len);
}
- if (!str) {
+ if (!val) {
debug("<not found>\n");
+ if (sizep)
+ *sizep = -FDT_ERR_NOTFOUND;
return NULL;
}
+ if (sizep)
+ *sizep = len;
+
+ return val;
+}
+
+const char *ofnode_read_string(ofnode node, const char *propname)
+{
+ const char *str;
+ int len;
+
+ str = ofnode_read_prop(node, propname, &len);
+ if (!str)
+ return NULL;
+
if (strnlen(str, len) >= len) {
debug("<invalid>\n");
return NULL;
return str;
}
+int ofnode_read_size(ofnode node, const char *propname)
+{
+ int len;
+
+ if (!ofnode_read_prop(node, propname, &len))
+ return -EINVAL;
+
+ return len;
+}
+
ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
{
ofnode subnode;
const char *ofnode_get_name(ofnode node)
{
- assert(ofnode_valid(node));
+ if (!ofnode_valid(node)) {
+ debug("%s node not valid\n", __func__);
+ return NULL;
+ }
+
if (ofnode_is_np(node))
return strrchr(node.np->full_name, '/') + 1;
return node;
}
-int ofnode_read_size(ofnode node, const char *propname)
-{
- int len;
-
- if (ofnode_is_np(node)) {
- struct property *prop = of_find_property(
- ofnode_to_np(node), propname, NULL);
-
- if (prop)
- return prop->length;
- } else {
- if (fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
- &len))
- return len;
- }
-
- return -EINVAL;
-}
-
-fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
+fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
{
int na, ns;
if (ofnode_is_np(node)) {
const __be32 *prop_val;
+ u64 size64;
uint flags;
- prop_val = of_get_address(ofnode_to_np(node), index,
- NULL, &flags);
+ prop_val = of_get_address(ofnode_to_np(node), index, &size64,
+ &flags);
if (!prop_val)
return FDT_ADDR_T_NONE;
+ if (size)
+ *size = size64;
ns = of_n_size_cells(ofnode_to_np(node));
ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
return fdtdec_get_addr_size_fixed(gd->fdt_blob,
ofnode_to_offset(node), "reg",
- index, na, ns, NULL, true);
+ index, na, ns, size, true);
}
return FDT_ADDR_T_NONE;
}
+fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
+{
+ fdt_size_t size;
+
+ return ofnode_get_addr_size_index(node, index, &size);
+}
+
fdt_addr_t ofnode_get_addr(ofnode node)
{
return ofnode_get_addr_index(node, 0);
return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
}
-const char *ofnode_get_chosen_prop(const char *name)
+const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
{
ofnode chosen_node;
chosen_node = ofnode_path("/chosen");
- return ofnode_read_string(chosen_node, name);
+ return ofnode_read_prop(chosen_node, propname, sizep);
+}
+
+const char *ofnode_read_chosen_string(const char *propname)
+{
+ return ofnode_read_chosen_prop(propname, NULL);
}
ofnode ofnode_get_chosen_node(const char *name)
{
const char *prop;
- prop = ofnode_get_chosen_prop(name);
+ prop = ofnode_read_chosen_prop(name, NULL);
if (!prop)
return ofnode_null();
return ofnode_path(prop);
}
+int ofnode_get_child_count(ofnode parent)
+{
+ ofnode child;
+ int num = 0;
+
+ ofnode_for_each_subnode(child, parent)
+ num++;
+
+ return num;
+}
+
static int decode_timing_property(ofnode node, const char *name,
struct timing_entry *result)
{
propname, lenp);
}
+int ofnode_get_first_property(ofnode node, struct ofprop *prop)
+{
+ prop->node = node;
+
+ if (ofnode_is_np(node)) {
+ prop->prop = of_get_first_property(ofnode_to_np(prop->node));
+ if (!prop->prop)
+ return -FDT_ERR_NOTFOUND;
+ } else {
+ prop->offset =
+ fdt_first_property_offset(gd->fdt_blob,
+ ofnode_to_offset(prop->node));
+ if (prop->offset < 0)
+ return prop->offset;
+ }
+
+ return 0;
+}
+
+int ofnode_get_next_property(struct ofprop *prop)
+{
+ if (ofnode_is_np(prop->node)) {
+ prop->prop = of_get_next_property(ofnode_to_np(prop->node),
+ prop->prop);
+ if (!prop->prop)
+ return -FDT_ERR_NOTFOUND;
+ } else {
+ prop->offset = fdt_next_property_offset(gd->fdt_blob,
+ prop->offset);
+ if (prop->offset < 0)
+ return prop->offset;
+ }
+
+ return 0;
+}
+
+const void *ofnode_get_property_by_prop(const struct ofprop *prop,
+ const char **propname, int *lenp)
+{
+ if (ofnode_is_np(prop->node))
+ return of_get_property_by_prop(ofnode_to_np(prop->node),
+ prop->prop, propname, lenp);
+ else
+ return fdt_getprop_by_offset(gd->fdt_blob,
+ prop->offset,
+ propname, lenp);
+}
+
bool ofnode_is_available(ofnode node)
{
if (ofnode_is_np(node))
if ((fdt32_to_cpu(*cell) & type) == type) {
addr->phys_hi = fdt32_to_cpu(cell[0]);
addr->phys_mid = fdt32_to_cpu(cell[1]);
- addr->phys_lo = fdt32_to_cpu(cell[1]);
+ addr->phys_lo = fdt32_to_cpu(cell[2]);
break;
}
return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
}
+u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
+{
+ if (ofnode_is_np(node))
+ return of_translate_dma_address(ofnode_to_np(node), in_addr);
+ else
+ return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
+}
+
int ofnode_device_is_compatible(ofnode node, const char *compat)
{
if (ofnode_is_np(node))
if (value)
return ofnode_write_string(node, "status", "okay");
else
- return ofnode_write_string(node, "status", "disable");
+ return ofnode_write_string(node, "status", "disabled");
}