17941b27bSPantelis Antoniou /* 27941b27bSPantelis Antoniou * Functions for dealing with DT resolution 37941b27bSPantelis Antoniou * 47941b27bSPantelis Antoniou * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com> 57941b27bSPantelis Antoniou * Copyright (C) 2012 Texas Instruments Inc. 67941b27bSPantelis Antoniou * 77941b27bSPantelis Antoniou * This program is free software; you can redistribute it and/or 87941b27bSPantelis Antoniou * modify it under the terms of the GNU General Public License 97941b27bSPantelis Antoniou * version 2 as published by the Free Software Foundation. 107941b27bSPantelis Antoniou */ 117941b27bSPantelis Antoniou 12606ad42aSRob Herring #define pr_fmt(fmt) "OF: resolver: " fmt 13606ad42aSRob Herring 147941b27bSPantelis Antoniou #include <linux/kernel.h> 157941b27bSPantelis Antoniou #include <linux/module.h> 167941b27bSPantelis Antoniou #include <linux/of.h> 177941b27bSPantelis Antoniou #include <linux/of_device.h> 187941b27bSPantelis Antoniou #include <linux/string.h> 197941b27bSPantelis Antoniou #include <linux/ctype.h> 207941b27bSPantelis Antoniou #include <linux/errno.h> 217941b27bSPantelis Antoniou #include <linux/string.h> 227941b27bSPantelis Antoniou #include <linux/slab.h> 237941b27bSPantelis Antoniou 247941b27bSPantelis Antoniou /* illegal phandle value (set when unresolved) */ 257941b27bSPantelis Antoniou #define OF_PHANDLE_ILLEGAL 0xdeadbeef 267941b27bSPantelis Antoniou 277941b27bSPantelis Antoniou /** 287941b27bSPantelis Antoniou * Find a node with the give full name by recursively following any of 297941b27bSPantelis Antoniou * the child node links. 307941b27bSPantelis Antoniou */ 317941b27bSPantelis Antoniou static struct device_node *__of_find_node_by_full_name(struct device_node *node, 327941b27bSPantelis Antoniou const char *full_name) 337941b27bSPantelis Antoniou { 347941b27bSPantelis Antoniou struct device_node *child, *found; 357941b27bSPantelis Antoniou 367941b27bSPantelis Antoniou if (node == NULL) 377941b27bSPantelis Antoniou return NULL; 387941b27bSPantelis Antoniou 397941b27bSPantelis Antoniou if (of_node_cmp(node->full_name, full_name) == 0) 4082f68756SAmitoj Kaur Chawla return of_node_get(node); 417941b27bSPantelis Antoniou 427941b27bSPantelis Antoniou for_each_child_of_node(node, child) { 437941b27bSPantelis Antoniou found = __of_find_node_by_full_name(child, full_name); 4482f68756SAmitoj Kaur Chawla if (found != NULL) { 4582f68756SAmitoj Kaur Chawla of_node_put(child); 467941b27bSPantelis Antoniou return found; 477941b27bSPantelis Antoniou } 4882f68756SAmitoj Kaur Chawla } 497941b27bSPantelis Antoniou 507941b27bSPantelis Antoniou return NULL; 517941b27bSPantelis Antoniou } 527941b27bSPantelis Antoniou 537941b27bSPantelis Antoniou /* 547941b27bSPantelis Antoniou * Find live tree's maximum phandle value. 557941b27bSPantelis Antoniou */ 567941b27bSPantelis Antoniou static phandle of_get_tree_max_phandle(void) 577941b27bSPantelis Antoniou { 587941b27bSPantelis Antoniou struct device_node *node; 597941b27bSPantelis Antoniou phandle phandle; 607941b27bSPantelis Antoniou unsigned long flags; 617941b27bSPantelis Antoniou 627941b27bSPantelis Antoniou raw_spin_lock_irqsave(&devtree_lock, flags); 637941b27bSPantelis Antoniou phandle = 0; 647941b27bSPantelis Antoniou for_each_of_allnodes(node) { 657941b27bSPantelis Antoniou if (node->phandle != OF_PHANDLE_ILLEGAL && 667941b27bSPantelis Antoniou node->phandle > phandle) 677941b27bSPantelis Antoniou phandle = node->phandle; 687941b27bSPantelis Antoniou } 697941b27bSPantelis Antoniou raw_spin_unlock_irqrestore(&devtree_lock, flags); 707941b27bSPantelis Antoniou 717941b27bSPantelis Antoniou return phandle; 727941b27bSPantelis Antoniou } 737941b27bSPantelis Antoniou 747941b27bSPantelis Antoniou /* 757941b27bSPantelis Antoniou * Adjust a subtree's phandle values by a given delta. 767941b27bSPantelis Antoniou */ 777941b27bSPantelis Antoniou static void __of_adjust_tree_phandles(struct device_node *node, 787941b27bSPantelis Antoniou int phandle_delta) 797941b27bSPantelis Antoniou { 807941b27bSPantelis Antoniou struct device_node *child; 817941b27bSPantelis Antoniou struct property *prop; 827941b27bSPantelis Antoniou phandle phandle; 837941b27bSPantelis Antoniou 847941b27bSPantelis Antoniou if (node->phandle != 0 && node->phandle != OF_PHANDLE_ILLEGAL) 857941b27bSPantelis Antoniou node->phandle += phandle_delta; 867941b27bSPantelis Antoniou 877941b27bSPantelis Antoniou for_each_property_of_node(node, prop) { 887941b27bSPantelis Antoniou 897941b27bSPantelis Antoniou if (of_prop_cmp(prop->name, "phandle") != 0 && 907941b27bSPantelis Antoniou of_prop_cmp(prop->name, "linux,phandle") != 0) 917941b27bSPantelis Antoniou continue; 927941b27bSPantelis Antoniou 937941b27bSPantelis Antoniou if (prop->length < 4) 947941b27bSPantelis Antoniou continue; 957941b27bSPantelis Antoniou 967941b27bSPantelis Antoniou phandle = be32_to_cpup(prop->value); 97a67976ecSFrank Rowand if (phandle == OF_PHANDLE_ILLEGAL) 987941b27bSPantelis Antoniou continue; 997941b27bSPantelis Antoniou 1007941b27bSPantelis Antoniou *(uint32_t *)prop->value = cpu_to_be32(node->phandle); 1017941b27bSPantelis Antoniou } 1027941b27bSPantelis Antoniou 1037941b27bSPantelis Antoniou for_each_child_of_node(node, child) 1047941b27bSPantelis Antoniou __of_adjust_tree_phandles(child, phandle_delta); 1057941b27bSPantelis Antoniou } 1067941b27bSPantelis Antoniou 107da56d04cSPantelis Antoniou static int __of_adjust_phandle_ref(struct device_node *node, 108da56d04cSPantelis Antoniou struct property *rprop, int value) 1097941b27bSPantelis Antoniou { 1107941b27bSPantelis Antoniou phandle phandle; 1117941b27bSPantelis Antoniou struct device_node *refnode; 1127941b27bSPantelis Antoniou struct property *sprop; 1137941b27bSPantelis Antoniou char *propval, *propcur, *propend, *nodestr, *propstr, *s; 1147941b27bSPantelis Antoniou int offset, propcurlen; 1157941b27bSPantelis Antoniou int err = 0; 1167941b27bSPantelis Antoniou 1177941b27bSPantelis Antoniou propval = kmalloc(rprop->length, GFP_KERNEL); 1187941b27bSPantelis Antoniou if (!propval) { 1197941b27bSPantelis Antoniou pr_err("%s: Could not copy value of '%s'\n", 1207941b27bSPantelis Antoniou __func__, rprop->name); 1217941b27bSPantelis Antoniou return -ENOMEM; 1227941b27bSPantelis Antoniou } 1237941b27bSPantelis Antoniou memcpy(propval, rprop->value, rprop->length); 1247941b27bSPantelis Antoniou 1257941b27bSPantelis Antoniou propend = propval + rprop->length; 1267941b27bSPantelis Antoniou for (propcur = propval; propcur < propend; propcur += propcurlen + 1) { 1277941b27bSPantelis Antoniou propcurlen = strlen(propcur); 1287941b27bSPantelis Antoniou 1297941b27bSPantelis Antoniou nodestr = propcur; 1307941b27bSPantelis Antoniou s = strchr(propcur, ':'); 1317941b27bSPantelis Antoniou if (!s) { 1327941b27bSPantelis Antoniou pr_err("%s: Illegal symbol entry '%s' (1)\n", 1337941b27bSPantelis Antoniou __func__, propcur); 1347941b27bSPantelis Antoniou err = -EINVAL; 1357941b27bSPantelis Antoniou goto err_fail; 1367941b27bSPantelis Antoniou } 1377941b27bSPantelis Antoniou *s++ = '\0'; 1387941b27bSPantelis Antoniou 1397941b27bSPantelis Antoniou propstr = s; 1407941b27bSPantelis Antoniou s = strchr(s, ':'); 1417941b27bSPantelis Antoniou if (!s) { 1427941b27bSPantelis Antoniou pr_err("%s: Illegal symbol entry '%s' (2)\n", 1437941b27bSPantelis Antoniou __func__, (char *)rprop->value); 1447941b27bSPantelis Antoniou err = -EINVAL; 1457941b27bSPantelis Antoniou goto err_fail; 1467941b27bSPantelis Antoniou } 1477941b27bSPantelis Antoniou 1487941b27bSPantelis Antoniou *s++ = '\0'; 1497941b27bSPantelis Antoniou err = kstrtoint(s, 10, &offset); 1507941b27bSPantelis Antoniou if (err != 0) { 1517941b27bSPantelis Antoniou pr_err("%s: Could get offset '%s'\n", 1527941b27bSPantelis Antoniou __func__, (char *)rprop->value); 1537941b27bSPantelis Antoniou goto err_fail; 1547941b27bSPantelis Antoniou } 1557941b27bSPantelis Antoniou 1567941b27bSPantelis Antoniou refnode = __of_find_node_by_full_name(node, nodestr); 1577941b27bSPantelis Antoniou if (!refnode) { 1587941b27bSPantelis Antoniou pr_warn("%s: Could not find refnode '%s'\n", 1597941b27bSPantelis Antoniou __func__, (char *)rprop->value); 1607941b27bSPantelis Antoniou continue; 1617941b27bSPantelis Antoniou } 1627941b27bSPantelis Antoniou 1637941b27bSPantelis Antoniou for_each_property_of_node(refnode, sprop) { 1647941b27bSPantelis Antoniou if (of_prop_cmp(sprop->name, propstr) == 0) 1657941b27bSPantelis Antoniou break; 1667941b27bSPantelis Antoniou } 16782f68756SAmitoj Kaur Chawla of_node_put(refnode); 1687941b27bSPantelis Antoniou 1697941b27bSPantelis Antoniou if (!sprop) { 1707941b27bSPantelis Antoniou pr_err("%s: Could not find property '%s'\n", 1717941b27bSPantelis Antoniou __func__, (char *)rprop->value); 1727941b27bSPantelis Antoniou err = -ENOENT; 1737941b27bSPantelis Antoniou goto err_fail; 1747941b27bSPantelis Antoniou } 1757941b27bSPantelis Antoniou 176da56d04cSPantelis Antoniou phandle = value; 1777941b27bSPantelis Antoniou *(__be32 *)(sprop->value + offset) = cpu_to_be32(phandle); 1787941b27bSPantelis Antoniou } 1797941b27bSPantelis Antoniou 1807941b27bSPantelis Antoniou err_fail: 1817941b27bSPantelis Antoniou kfree(propval); 1827941b27bSPantelis Antoniou return err; 1837941b27bSPantelis Antoniou } 1847941b27bSPantelis Antoniou 185da56d04cSPantelis Antoniou /* compare nodes taking into account that 'name' strips out the @ part */ 186da56d04cSPantelis Antoniou static int __of_node_name_cmp(const struct device_node *dn1, 187da56d04cSPantelis Antoniou const struct device_node *dn2) 188da56d04cSPantelis Antoniou { 189da56d04cSPantelis Antoniou const char *n1 = strrchr(dn1->full_name, '/') ? : "/"; 190da56d04cSPantelis Antoniou const char *n2 = strrchr(dn2->full_name, '/') ? : "/"; 191da56d04cSPantelis Antoniou 192da56d04cSPantelis Antoniou return of_node_cmp(n1, n2); 193da56d04cSPantelis Antoniou } 194da56d04cSPantelis Antoniou 1957941b27bSPantelis Antoniou /* 1967941b27bSPantelis Antoniou * Adjust the local phandle references by the given phandle delta. 197da56d04cSPantelis Antoniou * Assumes the existances of a __local_fixups__ node at the root. 198da56d04cSPantelis Antoniou * Assumes that __of_verify_tree_phandle_references has been called. 199da56d04cSPantelis Antoniou * Does not take any devtree locks so make sure you call this on a tree 200da56d04cSPantelis Antoniou * which is at the detached state. 2017941b27bSPantelis Antoniou */ 2027941b27bSPantelis Antoniou static int __of_adjust_tree_phandle_references(struct device_node *node, 203da56d04cSPantelis Antoniou struct device_node *target, int phandle_delta) 2047941b27bSPantelis Antoniou { 205da56d04cSPantelis Antoniou struct device_node *child, *childtarget; 206da56d04cSPantelis Antoniou struct property *rprop, *sprop; 207da56d04cSPantelis Antoniou int err, i, count; 208da56d04cSPantelis Antoniou unsigned int off; 209da56d04cSPantelis Antoniou phandle phandle; 2107941b27bSPantelis Antoniou 211da56d04cSPantelis Antoniou if (node == NULL) 2127941b27bSPantelis Antoniou return 0; 2137941b27bSPantelis Antoniou 214da56d04cSPantelis Antoniou for_each_property_of_node(node, rprop) { 215da56d04cSPantelis Antoniou 2167941b27bSPantelis Antoniou /* skip properties added automatically */ 217da56d04cSPantelis Antoniou if (of_prop_cmp(rprop->name, "name") == 0 || 218da56d04cSPantelis Antoniou of_prop_cmp(rprop->name, "phandle") == 0 || 219da56d04cSPantelis Antoniou of_prop_cmp(rprop->name, "linux,phandle") == 0) 2207941b27bSPantelis Antoniou continue; 2217941b27bSPantelis Antoniou 222da56d04cSPantelis Antoniou if ((rprop->length % 4) != 0 || rprop->length == 0) { 223da56d04cSPantelis Antoniou pr_err("%s: Illegal property (size) '%s' @%s\n", 224da56d04cSPantelis Antoniou __func__, rprop->name, node->full_name); 225da56d04cSPantelis Antoniou return -EINVAL; 226da56d04cSPantelis Antoniou } 227da56d04cSPantelis Antoniou count = rprop->length / sizeof(__be32); 228da56d04cSPantelis Antoniou 229da56d04cSPantelis Antoniou for_each_property_of_node(target, sprop) { 230da56d04cSPantelis Antoniou if (of_prop_cmp(sprop->name, rprop->name) == 0) 231da56d04cSPantelis Antoniou break; 232da56d04cSPantelis Antoniou } 233da56d04cSPantelis Antoniou 234da56d04cSPantelis Antoniou if (sprop == NULL) { 235da56d04cSPantelis Antoniou pr_err("%s: Could not find target property '%s' @%s\n", 236da56d04cSPantelis Antoniou __func__, rprop->name, node->full_name); 237da56d04cSPantelis Antoniou return -EINVAL; 238da56d04cSPantelis Antoniou } 239da56d04cSPantelis Antoniou 240da56d04cSPantelis Antoniou for (i = 0; i < count; i++) { 241da56d04cSPantelis Antoniou off = be32_to_cpu(((__be32 *)rprop->value)[i]); 242da56d04cSPantelis Antoniou if (off >= sprop->length || 243da56d04cSPantelis Antoniou (off + 4) > sprop->length) { 244da56d04cSPantelis Antoniou pr_err("%s: Illegal property '%s' @%s\n", 245da56d04cSPantelis Antoniou __func__, rprop->name, 246da56d04cSPantelis Antoniou node->full_name); 247da56d04cSPantelis Antoniou return -EINVAL; 248da56d04cSPantelis Antoniou } 249da56d04cSPantelis Antoniou 250da56d04cSPantelis Antoniou if (phandle_delta) { 251da56d04cSPantelis Antoniou phandle = be32_to_cpu(*(__be32 *)(sprop->value + off)); 252da56d04cSPantelis Antoniou phandle += phandle_delta; 253da56d04cSPantelis Antoniou *(__be32 *)(sprop->value + off) = cpu_to_be32(phandle); 254da56d04cSPantelis Antoniou } 255da56d04cSPantelis Antoniou } 256da56d04cSPantelis Antoniou } 257da56d04cSPantelis Antoniou 258da56d04cSPantelis Antoniou for_each_child_of_node(node, child) { 259da56d04cSPantelis Antoniou 260da56d04cSPantelis Antoniou for_each_child_of_node(target, childtarget) 261da56d04cSPantelis Antoniou if (__of_node_name_cmp(child, childtarget) == 0) 262da56d04cSPantelis Antoniou break; 263da56d04cSPantelis Antoniou 264da56d04cSPantelis Antoniou if (!childtarget) { 265da56d04cSPantelis Antoniou pr_err("%s: Could not find target child '%s' @%s\n", 266da56d04cSPantelis Antoniou __func__, child->name, node->full_name); 267da56d04cSPantelis Antoniou return -EINVAL; 268da56d04cSPantelis Antoniou } 269da56d04cSPantelis Antoniou 270da56d04cSPantelis Antoniou err = __of_adjust_tree_phandle_references(child, childtarget, 271da56d04cSPantelis Antoniou phandle_delta); 272da56d04cSPantelis Antoniou if (err != 0) 2737941b27bSPantelis Antoniou return err; 2747941b27bSPantelis Antoniou } 2757941b27bSPantelis Antoniou 2767941b27bSPantelis Antoniou return 0; 2777941b27bSPantelis Antoniou } 2787941b27bSPantelis Antoniou 2797941b27bSPantelis Antoniou /** 2807941b27bSPantelis Antoniou * of_resolve - Resolve the given node against the live tree. 2817941b27bSPantelis Antoniou * 2827941b27bSPantelis Antoniou * @resolve: Node to resolve 2837941b27bSPantelis Antoniou * 2847941b27bSPantelis Antoniou * Perform dynamic Device Tree resolution against the live tree 2857941b27bSPantelis Antoniou * to the given node to resolve. This depends on the live tree 2867941b27bSPantelis Antoniou * having a __symbols__ node, and the resolve node the __fixups__ & 2877941b27bSPantelis Antoniou * __local_fixups__ nodes (if needed). 2887941b27bSPantelis Antoniou * The result of the operation is a resolve node that it's contents 2897941b27bSPantelis Antoniou * are fit to be inserted or operate upon the live tree. 2907941b27bSPantelis Antoniou * Returns 0 on success or a negative error value on error. 2917941b27bSPantelis Antoniou */ 2927941b27bSPantelis Antoniou int of_resolve_phandles(struct device_node *resolve) 2937941b27bSPantelis Antoniou { 294da56d04cSPantelis Antoniou struct device_node *child, *childroot, *refnode; 2957941b27bSPantelis Antoniou struct device_node *root_sym, *resolve_sym, *resolve_fix; 2967941b27bSPantelis Antoniou struct property *rprop; 2977941b27bSPantelis Antoniou const char *refpath; 2987941b27bSPantelis Antoniou phandle phandle, phandle_delta; 2997941b27bSPantelis Antoniou int err; 3007941b27bSPantelis Antoniou 3015de3bbc8SMichal Suchanek if (!resolve) 3025de3bbc8SMichal Suchanek pr_err("%s: null node\n", __func__); 3035de3bbc8SMichal Suchanek if (resolve && !of_node_check_flag(resolve, OF_DETACHED)) 3045de3bbc8SMichal Suchanek pr_err("%s: node %s not detached\n", __func__, 3055de3bbc8SMichal Suchanek resolve->full_name); 3067941b27bSPantelis Antoniou if (!resolve || !of_node_check_flag(resolve, OF_DETACHED)) 3077941b27bSPantelis Antoniou return -EINVAL; 3087941b27bSPantelis Antoniou 3097941b27bSPantelis Antoniou phandle_delta = of_get_tree_max_phandle() + 1; 3107941b27bSPantelis Antoniou __of_adjust_tree_phandles(resolve, phandle_delta); 311da56d04cSPantelis Antoniou 312da56d04cSPantelis Antoniou childroot = NULL; 313da56d04cSPantelis Antoniou for_each_child_of_node(resolve, childroot) 314da56d04cSPantelis Antoniou if (of_node_cmp(childroot->name, "__local_fixups__") == 0) 315da56d04cSPantelis Antoniou break; 316da56d04cSPantelis Antoniou 317da56d04cSPantelis Antoniou if (childroot != NULL) { 318da56d04cSPantelis Antoniou err = __of_adjust_tree_phandle_references(childroot, 319da56d04cSPantelis Antoniou resolve, 0); 3207941b27bSPantelis Antoniou if (err != 0) 3217941b27bSPantelis Antoniou return err; 3227941b27bSPantelis Antoniou 323da56d04cSPantelis Antoniou BUG_ON(__of_adjust_tree_phandle_references(childroot, 324da56d04cSPantelis Antoniou resolve, phandle_delta)); 325da56d04cSPantelis Antoniou } 326da56d04cSPantelis Antoniou 3277941b27bSPantelis Antoniou root_sym = NULL; 3287941b27bSPantelis Antoniou resolve_sym = NULL; 3297941b27bSPantelis Antoniou resolve_fix = NULL; 3307941b27bSPantelis Antoniou 3317941b27bSPantelis Antoniou root_sym = of_find_node_by_path("/__symbols__"); 3327941b27bSPantelis Antoniou 3337941b27bSPantelis Antoniou for_each_child_of_node(resolve, child) { 3347941b27bSPantelis Antoniou 3357941b27bSPantelis Antoniou if (!resolve_sym && 3367941b27bSPantelis Antoniou of_node_cmp(child->name, "__symbols__") == 0) 3377941b27bSPantelis Antoniou resolve_sym = child; 3387941b27bSPantelis Antoniou 3397941b27bSPantelis Antoniou if (!resolve_fix && 3407941b27bSPantelis Antoniou of_node_cmp(child->name, "__fixups__") == 0) 3417941b27bSPantelis Antoniou resolve_fix = child; 3427941b27bSPantelis Antoniou 3437941b27bSPantelis Antoniou if (resolve_sym && resolve_fix) 3447941b27bSPantelis Antoniou break; 3457941b27bSPantelis Antoniou } 3467941b27bSPantelis Antoniou 3477941b27bSPantelis Antoniou if (!resolve_fix) { 348a67976ecSFrank Rowand err = 0; 3497941b27bSPantelis Antoniou goto out; 3507941b27bSPantelis Antoniou } 3517941b27bSPantelis Antoniou 3527941b27bSPantelis Antoniou if (!root_sym) { 3535de3bbc8SMichal Suchanek pr_err("%s: no symbols in root of device tree.\n", __func__); 3547941b27bSPantelis Antoniou err = -EINVAL; 3557941b27bSPantelis Antoniou goto out; 3567941b27bSPantelis Antoniou } 3577941b27bSPantelis Antoniou 3587941b27bSPantelis Antoniou for_each_property_of_node(resolve_fix, rprop) { 3597941b27bSPantelis Antoniou 3607941b27bSPantelis Antoniou /* skip properties added automatically */ 3617941b27bSPantelis Antoniou if (of_prop_cmp(rprop->name, "name") == 0) 3627941b27bSPantelis Antoniou continue; 3637941b27bSPantelis Antoniou 3647941b27bSPantelis Antoniou err = of_property_read_string(root_sym, 3657941b27bSPantelis Antoniou rprop->name, &refpath); 3667941b27bSPantelis Antoniou if (err != 0) { 3677941b27bSPantelis Antoniou pr_err("%s: Could not find symbol '%s'\n", 3687941b27bSPantelis Antoniou __func__, rprop->name); 3697941b27bSPantelis Antoniou goto out; 3707941b27bSPantelis Antoniou } 3717941b27bSPantelis Antoniou 3727941b27bSPantelis Antoniou refnode = of_find_node_by_path(refpath); 3737941b27bSPantelis Antoniou if (!refnode) { 3747941b27bSPantelis Antoniou pr_err("%s: Could not find node by path '%s'\n", 3757941b27bSPantelis Antoniou __func__, refpath); 3767941b27bSPantelis Antoniou err = -ENOENT; 3777941b27bSPantelis Antoniou goto out; 3787941b27bSPantelis Antoniou } 3797941b27bSPantelis Antoniou 3807941b27bSPantelis Antoniou phandle = refnode->phandle; 3817941b27bSPantelis Antoniou of_node_put(refnode); 3827941b27bSPantelis Antoniou 3837941b27bSPantelis Antoniou pr_debug("%s: %s phandle is 0x%08x\n", 3847941b27bSPantelis Antoniou __func__, rprop->name, phandle); 3857941b27bSPantelis Antoniou 386da56d04cSPantelis Antoniou err = __of_adjust_phandle_ref(resolve, rprop, phandle); 3877941b27bSPantelis Antoniou if (err) 3887941b27bSPantelis Antoniou break; 3897941b27bSPantelis Antoniou } 3907941b27bSPantelis Antoniou 3917941b27bSPantelis Antoniou out: 3927941b27bSPantelis Antoniou of_node_put(root_sym); 3937941b27bSPantelis Antoniou 3947941b27bSPantelis Antoniou return err; 3957941b27bSPantelis Antoniou } 3967941b27bSPantelis Antoniou EXPORT_SYMBOL_GPL(of_resolve_phandles); 397