Commit 74e1fbb1 authored by Joerg Roedel's avatar Joerg Roedel Committed by Rob Herring

of: Introduce struct of_phandle_iterator

This struct carrys all necessary information to iterate over
a list of phandles and extract the arguments. Add an
init-function for the iterator and make use of it in
__of_parse_phandle_with_args().
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
Signed-off-by: default avatarRob Herring <robh@kernel.org>
parent 34b82026
...@@ -1440,35 +1440,56 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args) ...@@ -1440,35 +1440,56 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
printk("\n"); printk("\n");
} }
int of_phandle_iterator_init(struct of_phandle_iterator *it,
const struct device_node *np,
const char *list_name,
const char *cells_name,
int cell_count)
{
const __be32 *list;
int size;
memset(it, 0, sizeof(*it));
list = of_get_property(np, list_name, &size);
if (!list)
return -ENOENT;
it->cells_name = cells_name;
it->cell_count = cell_count;
it->parent = np;
it->list_end = list + size / sizeof(*list);
it->phandle_end = list;
it->cur = list;
return 0;
}
static int __of_parse_phandle_with_args(const struct device_node *np, static int __of_parse_phandle_with_args(const struct device_node *np,
const char *list_name, const char *list_name,
const char *cells_name, const char *cells_name,
int cell_count, int index, int cell_count, int index,
struct of_phandle_args *out_args) struct of_phandle_args *out_args)
{ {
const __be32 *list, *list_end; struct of_phandle_iterator it;
int rc = 0, size, cur_index = 0; int rc, cur_index = 0;
uint32_t count = 0;
struct device_node *node = NULL;
phandle phandle;
/* Retrieve the phandle list property */ rc = of_phandle_iterator_init(&it, np, list_name,
list = of_get_property(np, list_name, &size); cells_name, cell_count);
if (!list) if (rc)
return -ENOENT; return rc;
list_end = list + size / sizeof(*list);
/* Loop over the phandles until all the requested entry is found */ /* Loop over the phandles until all the requested entry is found */
while (list < list_end) { while (it.cur < it.list_end) {
rc = -EINVAL; rc = -EINVAL;
count = 0; it.cur_count = 0;
/* /*
* If phandle is 0, then it is an empty entry with no * If phandle is 0, then it is an empty entry with no
* arguments. Skip forward to the next entry. * arguments. Skip forward to the next entry.
*/ */
phandle = be32_to_cpup(list++); it.phandle = be32_to_cpup(it.cur++);
if (phandle) { if (it.phandle) {
/* /*
* Find the provider node and parse the #*-cells * Find the provider node and parse the #*-cells
* property to determine the argument length. * property to determine the argument length.
...@@ -1478,34 +1499,34 @@ static int __of_parse_phandle_with_args(const struct device_node *np, ...@@ -1478,34 +1499,34 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
* except when we're going to return the found node * except when we're going to return the found node
* below. * below.
*/ */
if (cells_name || cur_index == index) { if (it.cells_name || cur_index == index) {
node = of_find_node_by_phandle(phandle); it.node = of_find_node_by_phandle(it.phandle);
if (!node) { if (!it.node) {
pr_err("%s: could not find phandle\n", pr_err("%s: could not find phandle\n",
np->full_name); it.parent->full_name);
goto err; goto err;
} }
} }
if (cells_name) { if (it.cells_name) {
if (of_property_read_u32(node, cells_name, if (of_property_read_u32(it.node, it.cells_name,
&count)) { &it.cur_count)) {
pr_err("%s: could not get %s for %s\n", pr_err("%s: could not get %s for %s\n",
np->full_name, cells_name, it.parent->full_name, it.cells_name,
node->full_name); it.node->full_name);
goto err; goto err;
} }
} else { } else {
count = cell_count; it.cur_count = it.cell_count;
} }
/* /*
* Make sure that the arguments actually fit in the * Make sure that the arguments actually fit in the
* remaining property data length * remaining property data length
*/ */
if (list + count > list_end) { if (it.cur + it.cur_count > it.list_end) {
pr_err("%s: arguments longer than property\n", pr_err("%s: arguments longer than property\n",
np->full_name); it.parent->full_name);
goto err; goto err;
} }
} }
...@@ -1518,28 +1539,28 @@ static int __of_parse_phandle_with_args(const struct device_node *np, ...@@ -1518,28 +1539,28 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
*/ */
rc = -ENOENT; rc = -ENOENT;
if (cur_index == index) { if (cur_index == index) {
if (!phandle) if (!it.phandle)
goto err; goto err;
if (out_args) { if (out_args) {
int i; int i;
if (WARN_ON(count > MAX_PHANDLE_ARGS)) if (WARN_ON(it.cur_count > MAX_PHANDLE_ARGS))
count = MAX_PHANDLE_ARGS; it.cur_count = MAX_PHANDLE_ARGS;
out_args->np = node; out_args->np = it.node;
out_args->args_count = count; out_args->args_count = it.cur_count;
for (i = 0; i < count; i++) for (i = 0; i < it.cur_count; i++)
out_args->args[i] = be32_to_cpup(list++); out_args->args[i] = be32_to_cpup(it.cur++);
} else { } else {
of_node_put(node); of_node_put(it.node);
} }
/* Found it! return success */ /* Found it! return success */
return 0; return 0;
} }
of_node_put(node); of_node_put(it.node);
node = NULL; it.node = NULL;
list += count; it.cur += it.cur_count;
cur_index++; cur_index++;
} }
...@@ -1551,8 +1572,8 @@ static int __of_parse_phandle_with_args(const struct device_node *np, ...@@ -1551,8 +1572,8 @@ static int __of_parse_phandle_with_args(const struct device_node *np,
*/ */
rc = index < 0 ? cur_index : -ENOENT; rc = index < 0 ? cur_index : -ENOENT;
err: err:
if (node) if (it.node)
of_node_put(node); of_node_put(it.node);
return rc; return rc;
} }
......
...@@ -75,6 +75,23 @@ struct of_phandle_args { ...@@ -75,6 +75,23 @@ struct of_phandle_args {
uint32_t args[MAX_PHANDLE_ARGS]; uint32_t args[MAX_PHANDLE_ARGS];
}; };
struct of_phandle_iterator {
/* Common iterator information */
const char *cells_name;
int cell_count;
const struct device_node *parent;
/* List size information */
const __be32 *list_end;
const __be32 *phandle_end;
/* Current position state */
const __be32 *cur;
uint32_t cur_count;
phandle phandle;
struct device_node *node;
};
struct of_reconfig_data { struct of_reconfig_data {
struct device_node *dn; struct device_node *dn;
struct property *prop; struct property *prop;
...@@ -334,6 +351,13 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np, ...@@ -334,6 +351,13 @@ extern int of_parse_phandle_with_fixed_args(const struct device_node *np,
extern int of_count_phandle_with_args(const struct device_node *np, extern int of_count_phandle_with_args(const struct device_node *np,
const char *list_name, const char *cells_name); const char *list_name, const char *cells_name);
/* phandle iterator functions */
extern int of_phandle_iterator_init(struct of_phandle_iterator *it,
const struct device_node *np,
const char *list_name,
const char *cells_name,
int cell_count);
extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)); extern void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align));
extern int of_alias_get_id(struct device_node *np, const char *stem); extern int of_alias_get_id(struct device_node *np, const char *stem);
extern int of_alias_get_highest_id(const char *stem); extern int of_alias_get_highest_id(const char *stem);
...@@ -608,6 +632,15 @@ static inline int of_count_phandle_with_args(struct device_node *np, ...@@ -608,6 +632,15 @@ static inline int of_count_phandle_with_args(struct device_node *np,
return -ENOSYS; return -ENOSYS;
} }
static inline int of_phandle_iterator_init(struct of_phandle_iterator *it,
const struct device_node *np,
const char *list_name,
const char *cells_name,
int cell_count)
{
return -ENOSYS;
}
static inline int of_alias_get_id(struct device_node *np, const char *stem) static inline int of_alias_get_id(struct device_node *np, const char *stem)
{ {
return -ENOSYS; return -ENOSYS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment