@@ -1442,6 +1442,96 @@ void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
printk("\n");
}
+
+static int __of_parse_one_phandle_with_args(const __be32 **list,
+ const char *cells_name,
+ int cell_count,
+ struct of_phandle_args **out_args)
+{
+ struct device_node *node;
+ phandle phandle;
+ struct of_phandle_args *args = *out_args;
+ const __be32 *start_list = *list;
+ u32 i, count = 0;
+ int ret;
+
+ /*
+ * If phandle is 0, then it is an empty entry with no
+ * arguments. Skip forward to the next entry.
+ */
+ phandle = be32_to_cpup(*list++);
+ if (phandle) {
+ /*
+ * Find the provider node and parse the #*-cells
+ * property to determine the argument length.
+ *
+ * This is not needed if the cell count is hard-coded
+ * (i.e. cells_name not set, but cell_count is set),
+ * except when we're going to return the found node
+ * below.
+ */
+ node = of_find_node_by_phandle(phandle);
+ if (!node)
+ return -ENOENT;
+
+ if (cells_name) {
+ ret = of_property_read_u32(node, cells_name, &count);
+ if (ret) {
+ pr_err("could not get %s for %s\n",
+ cells_name, node->full_name);
+ return ret;
+ }
+ } else {
+ count = cell_count;
+ }
+ }
+
+ if (args && WARN_ON(count > MAX_PHANDLE_ARGS))
+ count = MAX_PHANDLE_ARGS;
+
+ if (!args) {
+ args = kzalloc(sizeof(*args) + (count * sizeof(uint32_t))), GFP_KERNEL);
+ *out_args = args;
+ }
+ if (!args)
+ return -ENOMEM;
+
+ if (!phandle) {
+ memset(args, 0, sizeof(*args));
+ return -ENOENT;
+ }
+
+ args->np = node;
+ args->val = start_list;
+ args->args_count = count;
+ for (i = 0; i < count; i++)
+ args->args[i] = be32_to_cpup(*list++);
+
+ return 0;
+}
+
+of_phandle_args *of_prop_next_phandle_args(struct property *prop,
+ const char *cells_name,
+ int cell_count,
+ struct of_phandle_args *last)
+{
+ struct of_phandle_args *args = NULL;
+ const __be32 *start_list;
+
+ if (!prop)
+ return NULL;
+
+ if (!last) {
+ start_list = prop->value;
+ } else {
+ start_list = last->val;
+ kfree(last);
+ }
+ __of_parse_one_phandle_with_args(list, cells_name, cell_count, &args);
+ return args;
+}
+EXPORT_SYMBOL_GPL(of_prop_next_phandle_args);
+
static int __of_parse_phandle_with_args(const struct device_node *np,
const char *list_name,
const char *cells_name,
@@ -879,6 +879,13 @@ static inline int of_property_read_s32(const struct device_node *np,
s; \
s = of_prop_next_string(prop, s))
+#define of_property_for_each_phandle_with_args(np, propname, cells_name, cell_count, prop, arg) \
+ for (prop = of_find_property(np, propname, NULL), \
+ arg = of_prop_next_phandle_args(prop, NULL); \
+ arg; \
+ arg = of_prop_next_phandle_args(prop, arg))
+
+
#define for_each_node_by_name(dn, name) \
for (dn = of_find_node_by_name(NULL, name); dn; \
dn = of_find_node_by_name(dn, name))