18f446e6fSRajendra Nayak /* 28f446e6fSRajendra Nayak * OF helpers for regulator framework 38f446e6fSRajendra Nayak * 48f446e6fSRajendra Nayak * Copyright (C) 2011 Texas Instruments, Inc. 58f446e6fSRajendra Nayak * Rajendra Nayak <rnayak@ti.com> 68f446e6fSRajendra Nayak * 78f446e6fSRajendra Nayak * This program is free software; you can redistribute it and/or modify 88f446e6fSRajendra Nayak * it under the terms of the GNU General Public License as published by 98f446e6fSRajendra Nayak * the Free Software Foundation; either version 2 of the License, or 108f446e6fSRajendra Nayak * (at your option) any later version. 118f446e6fSRajendra Nayak */ 128f446e6fSRajendra Nayak 13e69af5e9SAxel Lin #include <linux/module.h> 148f446e6fSRajendra Nayak #include <linux/slab.h> 158f446e6fSRajendra Nayak #include <linux/of.h> 168f446e6fSRajendra Nayak #include <linux/regulator/machine.h> 17a0c7b164SMark Brown #include <linux/regulator/driver.h> 181c8fa58fSThierry Reding #include <linux/regulator/of_regulator.h> 198f446e6fSRajendra Nayak 20a0c7b164SMark Brown #include "internal.h" 21a0c7b164SMark Brown 22f32fa89cSKrzysztof Kozlowski static const char *const regulator_states[PM_SUSPEND_MAX + 1] = { 2340e20d68SChanwoo Choi [PM_SUSPEND_MEM] = "regulator-state-mem", 2440e20d68SChanwoo Choi [PM_SUSPEND_MAX] = "regulator-state-disk", 2540e20d68SChanwoo Choi }; 2640e20d68SChanwoo Choi 278f446e6fSRajendra Nayak static void of_get_regulation_constraints(struct device_node *np, 285e5e3a42SJavier Martinez Canillas struct regulator_init_data **init_data, 295e5e3a42SJavier Martinez Canillas const struct regulator_desc *desc) 308f446e6fSRajendra Nayak { 318f446e6fSRajendra Nayak struct regulation_constraints *constraints = &(*init_data)->constraints; 3240e20d68SChanwoo Choi struct regulator_state *suspend_state; 3340e20d68SChanwoo Choi struct device_node *suspend_np; 3440e20d68SChanwoo Choi int ret, i; 3500c877c6SLaxman Dewangan u32 pval; 368f446e6fSRajendra Nayak 378f446e6fSRajendra Nayak constraints->name = of_get_property(np, "regulator-name", NULL); 388f446e6fSRajendra Nayak 39a34785f1SLaxman Dewangan if (!of_property_read_u32(np, "regulator-min-microvolt", &pval)) 40a34785f1SLaxman Dewangan constraints->min_uV = pval; 41a34785f1SLaxman Dewangan 42a34785f1SLaxman Dewangan if (!of_property_read_u32(np, "regulator-max-microvolt", &pval)) 43a34785f1SLaxman Dewangan constraints->max_uV = pval; 448f446e6fSRajendra Nayak 458f446e6fSRajendra Nayak /* Voltage change possible? */ 4645fa2038SMark Brown if (constraints->min_uV != constraints->max_uV) 478f446e6fSRajendra Nayak constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; 4845fa2038SMark Brown 4945fa2038SMark Brown /* Do we have a voltage range, if so try to apply it? */ 5045fa2038SMark Brown if (constraints->min_uV && constraints->max_uV) 51ab62aa93SMark Brown constraints->apply_uV = true; 528f446e6fSRajendra Nayak 531e050eabSSergei Shtylyov if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval)) 541e050eabSSergei Shtylyov constraints->uV_offset = pval; 551e050eabSSergei Shtylyov if (!of_property_read_u32(np, "regulator-min-microamp", &pval)) 561e050eabSSergei Shtylyov constraints->min_uA = pval; 571e050eabSSergei Shtylyov if (!of_property_read_u32(np, "regulator-max-microamp", &pval)) 581e050eabSSergei Shtylyov constraints->max_uA = pval; 598f446e6fSRajendra Nayak 6036e4f839SStephen Boyd if (!of_property_read_u32(np, "regulator-input-current-limit-microamp", 6136e4f839SStephen Boyd &pval)) 6236e4f839SStephen Boyd constraints->ilim_uA = pval; 6336e4f839SStephen Boyd 648f446e6fSRajendra Nayak /* Current change possible? */ 658f446e6fSRajendra Nayak if (constraints->min_uA != constraints->max_uA) 668f446e6fSRajendra Nayak constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; 678f446e6fSRajendra Nayak 681e050eabSSergei Shtylyov constraints->boot_on = of_property_read_bool(np, "regulator-boot-on"); 691e050eabSSergei Shtylyov constraints->always_on = of_property_read_bool(np, "regulator-always-on"); 701e050eabSSergei Shtylyov if (!constraints->always_on) /* status change should be possible. */ 718f446e6fSRajendra Nayak constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; 726f0b2c69SYadwinder Singh Brar 7323c779b9SStephen Boyd constraints->pull_down = of_property_read_bool(np, "regulator-pull-down"); 7423c779b9SStephen Boyd 7593134c7bSKishon Vijay Abraham I if (of_property_read_bool(np, "regulator-allow-bypass")) 7693134c7bSKishon Vijay Abraham I constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; 7793134c7bSKishon Vijay Abraham I 78b263d203SBjorn Andersson if (of_property_read_bool(np, "regulator-allow-set-load")) 79b263d203SBjorn Andersson constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS; 80b263d203SBjorn Andersson 811e050eabSSergei Shtylyov ret = of_property_read_u32(np, "regulator-ramp-delay", &pval); 821e050eabSSergei Shtylyov if (!ret) { 831e050eabSSergei Shtylyov if (pval) 841e050eabSSergei Shtylyov constraints->ramp_delay = pval; 851653ccf4SYadwinder Singh Brar else 861653ccf4SYadwinder Singh Brar constraints->ramp_disable = true; 871653ccf4SYadwinder Singh Brar } 8800c877c6SLaxman Dewangan 89d6c1dc3fSLaxman Dewangan ret = of_property_read_u32(np, "regulator-settling-time-us", &pval); 90d6c1dc3fSLaxman Dewangan if (!ret) 91d6c1dc3fSLaxman Dewangan constraints->settling_time = pval; 92d6c1dc3fSLaxman Dewangan 933ffad468SMatthias Kaehlcke ret = of_property_read_u32(np, "regulator-settling-time-up-us", &pval); 943ffad468SMatthias Kaehlcke if (!ret) 953ffad468SMatthias Kaehlcke constraints->settling_time_up = pval; 963ffad468SMatthias Kaehlcke if (constraints->settling_time_up && constraints->settling_time) { 973ffad468SMatthias Kaehlcke pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n", 983ffad468SMatthias Kaehlcke np->name); 993ffad468SMatthias Kaehlcke constraints->settling_time_up = 0; 1003ffad468SMatthias Kaehlcke } 1013ffad468SMatthias Kaehlcke 1023ffad468SMatthias Kaehlcke ret = of_property_read_u32(np, "regulator-settling-time-down-us", 1033ffad468SMatthias Kaehlcke &pval); 1043ffad468SMatthias Kaehlcke if (!ret) 1053ffad468SMatthias Kaehlcke constraints->settling_time_down = pval; 1063ffad468SMatthias Kaehlcke if (constraints->settling_time_down && constraints->settling_time) { 1073ffad468SMatthias Kaehlcke pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n", 1083ffad468SMatthias Kaehlcke np->name); 1093ffad468SMatthias Kaehlcke constraints->settling_time_down = 0; 1103ffad468SMatthias Kaehlcke } 1113ffad468SMatthias Kaehlcke 11200c877c6SLaxman Dewangan ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval); 11300c877c6SLaxman Dewangan if (!ret) 11400c877c6SLaxman Dewangan constraints->enable_time = pval; 11540e20d68SChanwoo Choi 11657f66b78SStephen Boyd constraints->soft_start = of_property_read_bool(np, 11757f66b78SStephen Boyd "regulator-soft-start"); 118670666b9SLaxman Dewangan ret = of_property_read_u32(np, "regulator-active-discharge", &pval); 119670666b9SLaxman Dewangan if (!ret) { 120670666b9SLaxman Dewangan constraints->active_discharge = 121670666b9SLaxman Dewangan (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE : 122670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_DISABLE; 123670666b9SLaxman Dewangan } 12457f66b78SStephen Boyd 1255e5e3a42SJavier Martinez Canillas if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) { 1265e5e3a42SJavier Martinez Canillas if (desc && desc->of_map_mode) { 1275e5e3a42SJavier Martinez Canillas ret = desc->of_map_mode(pval); 1285e5e3a42SJavier Martinez Canillas if (ret == -EINVAL) 1295e5e3a42SJavier Martinez Canillas pr_err("%s: invalid mode %u\n", np->name, pval); 1305e5e3a42SJavier Martinez Canillas else 1315e5e3a42SJavier Martinez Canillas constraints->initial_mode = ret; 1325e5e3a42SJavier Martinez Canillas } else { 1335e5e3a42SJavier Martinez Canillas pr_warn("%s: mapping for mode %d not defined\n", 1345e5e3a42SJavier Martinez Canillas np->name, pval); 1355e5e3a42SJavier Martinez Canillas } 1365e5e3a42SJavier Martinez Canillas } 1375e5e3a42SJavier Martinez Canillas 13822a10bcaSStephen Boyd if (!of_property_read_u32(np, "regulator-system-load", &pval)) 13922a10bcaSStephen Boyd constraints->system_load = pval; 14022a10bcaSStephen Boyd 1413a003baeSStephen Boyd constraints->over_current_protection = of_property_read_bool(np, 1423a003baeSStephen Boyd "regulator-over-current-protection"); 1433a003baeSStephen Boyd 14440e20d68SChanwoo Choi for (i = 0; i < ARRAY_SIZE(regulator_states); i++) { 14540e20d68SChanwoo Choi switch (i) { 14640e20d68SChanwoo Choi case PM_SUSPEND_MEM: 14740e20d68SChanwoo Choi suspend_state = &constraints->state_mem; 14840e20d68SChanwoo Choi break; 14940e20d68SChanwoo Choi case PM_SUSPEND_MAX: 15040e20d68SChanwoo Choi suspend_state = &constraints->state_disk; 15140e20d68SChanwoo Choi break; 15240e20d68SChanwoo Choi case PM_SUSPEND_ON: 15340e20d68SChanwoo Choi case PM_SUSPEND_FREEZE: 15440e20d68SChanwoo Choi case PM_SUSPEND_STANDBY: 15540e20d68SChanwoo Choi default: 15640e20d68SChanwoo Choi continue; 1577cf225b9SKrzysztof Kozlowski } 15840e20d68SChanwoo Choi 15940e20d68SChanwoo Choi suspend_np = of_get_child_by_name(np, regulator_states[i]); 16040e20d68SChanwoo Choi if (!suspend_np || !suspend_state) 16140e20d68SChanwoo Choi continue; 16240e20d68SChanwoo Choi 1635e5e3a42SJavier Martinez Canillas if (!of_property_read_u32(suspend_np, "regulator-mode", 1645e5e3a42SJavier Martinez Canillas &pval)) { 1655e5e3a42SJavier Martinez Canillas if (desc && desc->of_map_mode) { 1665e5e3a42SJavier Martinez Canillas ret = desc->of_map_mode(pval); 1675e5e3a42SJavier Martinez Canillas if (ret == -EINVAL) 1685e5e3a42SJavier Martinez Canillas pr_err("%s: invalid mode %u\n", 1695e5e3a42SJavier Martinez Canillas np->name, pval); 1705e5e3a42SJavier Martinez Canillas else 1715e5e3a42SJavier Martinez Canillas suspend_state->mode = ret; 1725e5e3a42SJavier Martinez Canillas } else { 1735e5e3a42SJavier Martinez Canillas pr_warn("%s: mapping for mode %d not defined\n", 1745e5e3a42SJavier Martinez Canillas np->name, pval); 1755e5e3a42SJavier Martinez Canillas } 1765e5e3a42SJavier Martinez Canillas } 1775e5e3a42SJavier Martinez Canillas 17840e20d68SChanwoo Choi if (of_property_read_bool(suspend_np, 17940e20d68SChanwoo Choi "regulator-on-in-suspend")) 18040e20d68SChanwoo Choi suspend_state->enabled = true; 18140e20d68SChanwoo Choi else if (of_property_read_bool(suspend_np, 18240e20d68SChanwoo Choi "regulator-off-in-suspend")) 18340e20d68SChanwoo Choi suspend_state->disabled = true; 18440e20d68SChanwoo Choi 1858cbcaea8SDoug Anderson if (!of_property_read_u32(suspend_np, 1868cbcaea8SDoug Anderson "regulator-suspend-microvolt", &pval)) 1878cbcaea8SDoug Anderson suspend_state->uV = pval; 1888cbcaea8SDoug Anderson 189a0f78bc8SKeerthy if (i == PM_SUSPEND_MEM) 190a0f78bc8SKeerthy constraints->initial_state = PM_SUSPEND_MEM; 191a0f78bc8SKeerthy 1924eafec83SJavier Martinez Canillas of_node_put(suspend_np); 19340e20d68SChanwoo Choi suspend_state = NULL; 19440e20d68SChanwoo Choi suspend_np = NULL; 19540e20d68SChanwoo Choi } 1968f446e6fSRajendra Nayak } 1978f446e6fSRajendra Nayak 1988f446e6fSRajendra Nayak /** 1998f446e6fSRajendra Nayak * of_get_regulator_init_data - extract regulator_init_data structure info 2008f446e6fSRajendra Nayak * @dev: device requesting for regulator_init_data 201072e78b1SJavier Martinez Canillas * @node: regulator device node 202072e78b1SJavier Martinez Canillas * @desc: regulator description 2038f446e6fSRajendra Nayak * 2048f446e6fSRajendra Nayak * Populates regulator_init_data structure by extracting data from device 2058f446e6fSRajendra Nayak * tree node, returns a pointer to the populated struture or NULL if memory 2068f446e6fSRajendra Nayak * alloc fails. 2078f446e6fSRajendra Nayak */ 208d9a861ccSShawn Guo struct regulator_init_data *of_get_regulator_init_data(struct device *dev, 209072e78b1SJavier Martinez Canillas struct device_node *node, 210072e78b1SJavier Martinez Canillas const struct regulator_desc *desc) 2118f446e6fSRajendra Nayak { 2128f446e6fSRajendra Nayak struct regulator_init_data *init_data; 2138f446e6fSRajendra Nayak 214d9a861ccSShawn Guo if (!node) 2158f446e6fSRajendra Nayak return NULL; 2168f446e6fSRajendra Nayak 2178f446e6fSRajendra Nayak init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); 2188f446e6fSRajendra Nayak if (!init_data) 2198f446e6fSRajendra Nayak return NULL; /* Out of memory? */ 2208f446e6fSRajendra Nayak 2215e5e3a42SJavier Martinez Canillas of_get_regulation_constraints(node, &init_data, desc); 2228f446e6fSRajendra Nayak return init_data; 2238f446e6fSRajendra Nayak } 224e69af5e9SAxel Lin EXPORT_SYMBOL_GPL(of_get_regulator_init_data); 2251c8fa58fSThierry Reding 22613b3fde8SCharles Keepax struct devm_of_regulator_matches { 22713b3fde8SCharles Keepax struct of_regulator_match *matches; 22813b3fde8SCharles Keepax unsigned int num_matches; 22913b3fde8SCharles Keepax }; 23013b3fde8SCharles Keepax 23113b3fde8SCharles Keepax static void devm_of_regulator_put_matches(struct device *dev, void *res) 23213b3fde8SCharles Keepax { 23313b3fde8SCharles Keepax struct devm_of_regulator_matches *devm_matches = res; 23413b3fde8SCharles Keepax int i; 23513b3fde8SCharles Keepax 23613b3fde8SCharles Keepax for (i = 0; i < devm_matches->num_matches; i++) 23713b3fde8SCharles Keepax of_node_put(devm_matches->matches[i].of_node); 23813b3fde8SCharles Keepax } 23913b3fde8SCharles Keepax 2401c8fa58fSThierry Reding /** 24113511defSStephen Warren * of_regulator_match - extract multiple regulator init data from device tree. 2421c8fa58fSThierry Reding * @dev: device requesting the data 2431c8fa58fSThierry Reding * @node: parent device node of the regulators 2441c8fa58fSThierry Reding * @matches: match table for the regulators 2451c8fa58fSThierry Reding * @num_matches: number of entries in match table 2461c8fa58fSThierry Reding * 24713511defSStephen Warren * This function uses a match table specified by the regulator driver to 24813511defSStephen Warren * parse regulator init data from the device tree. @node is expected to 24913511defSStephen Warren * contain a set of child nodes, each providing the init data for one 25013511defSStephen Warren * regulator. The data parsed from a child node will be matched to a regulator 25113511defSStephen Warren * based on either the deprecated property regulator-compatible if present, 25213511defSStephen Warren * or otherwise the child node's name. Note that the match table is modified 253bd0dda74SCharles Keepax * in place and an additional of_node reference is taken for each matched 254bd0dda74SCharles Keepax * regulator. 2551c8fa58fSThierry Reding * 2561c8fa58fSThierry Reding * Returns the number of matches found or a negative error code on failure. 2571c8fa58fSThierry Reding */ 2581c8fa58fSThierry Reding int of_regulator_match(struct device *dev, struct device_node *node, 2591c8fa58fSThierry Reding struct of_regulator_match *matches, 2601c8fa58fSThierry Reding unsigned int num_matches) 2611c8fa58fSThierry Reding { 2621c8fa58fSThierry Reding unsigned int count = 0; 2631c8fa58fSThierry Reding unsigned int i; 26413511defSStephen Warren const char *name; 2655260cd2bSLaxman Dewangan struct device_node *child; 26613b3fde8SCharles Keepax struct devm_of_regulator_matches *devm_matches; 2671c8fa58fSThierry Reding 2681c8fa58fSThierry Reding if (!dev || !node) 2691c8fa58fSThierry Reding return -EINVAL; 2701c8fa58fSThierry Reding 27113b3fde8SCharles Keepax devm_matches = devres_alloc(devm_of_regulator_put_matches, 27213b3fde8SCharles Keepax sizeof(struct devm_of_regulator_matches), 27313b3fde8SCharles Keepax GFP_KERNEL); 27413b3fde8SCharles Keepax if (!devm_matches) 27513b3fde8SCharles Keepax return -ENOMEM; 27613b3fde8SCharles Keepax 27713b3fde8SCharles Keepax devm_matches->matches = matches; 27813b3fde8SCharles Keepax devm_matches->num_matches = num_matches; 27913b3fde8SCharles Keepax 28013b3fde8SCharles Keepax devres_add(dev, devm_matches); 28113b3fde8SCharles Keepax 282a2f95c36SStephen Warren for (i = 0; i < num_matches; i++) { 283a2f95c36SStephen Warren struct of_regulator_match *match = &matches[i]; 284a2f95c36SStephen Warren match->init_data = NULL; 285a2f95c36SStephen Warren match->of_node = NULL; 286a2f95c36SStephen Warren } 287a2f95c36SStephen Warren 2885260cd2bSLaxman Dewangan for_each_child_of_node(node, child) { 28913511defSStephen Warren name = of_get_property(child, 2905260cd2bSLaxman Dewangan "regulator-compatible", NULL); 29113511defSStephen Warren if (!name) 29213511defSStephen Warren name = child->name; 2931c8fa58fSThierry Reding for (i = 0; i < num_matches; i++) { 2941c8fa58fSThierry Reding struct of_regulator_match *match = &matches[i]; 2955260cd2bSLaxman Dewangan if (match->of_node) 2961c8fa58fSThierry Reding continue; 2971c8fa58fSThierry Reding 29813511defSStephen Warren if (strcmp(match->name, name)) 2995260cd2bSLaxman Dewangan continue; 3005260cd2bSLaxman Dewangan 3015260cd2bSLaxman Dewangan match->init_data = 30275d6b2faSJavier Martinez Canillas of_get_regulator_init_data(dev, child, 30375d6b2faSJavier Martinez Canillas match->desc); 3041c8fa58fSThierry Reding if (!match->init_data) { 3055260cd2bSLaxman Dewangan dev_err(dev, 3065260cd2bSLaxman Dewangan "failed to parse DT for regulator %s\n", 3071c8fa58fSThierry Reding child->name); 3081c8fa58fSThierry Reding return -EINVAL; 3091c8fa58fSThierry Reding } 310bd0dda74SCharles Keepax match->of_node = of_node_get(child); 3111c8fa58fSThierry Reding count++; 3125260cd2bSLaxman Dewangan break; 3135260cd2bSLaxman Dewangan } 3141c8fa58fSThierry Reding } 3151c8fa58fSThierry Reding 3161c8fa58fSThierry Reding return count; 3171c8fa58fSThierry Reding } 3181c8fa58fSThierry Reding EXPORT_SYMBOL_GPL(of_regulator_match); 319a0c7b164SMark Brown 320a0c7b164SMark Brown struct regulator_init_data *regulator_of_get_init_data(struct device *dev, 321a0c7b164SMark Brown const struct regulator_desc *desc, 322bfa21a0dSKrzysztof Kozlowski struct regulator_config *config, 323a0c7b164SMark Brown struct device_node **node) 324a0c7b164SMark Brown { 325a0c7b164SMark Brown struct device_node *search, *child; 326a0c7b164SMark Brown struct regulator_init_data *init_data = NULL; 327a0c7b164SMark Brown const char *name; 328a0c7b164SMark Brown 329a0c7b164SMark Brown if (!dev->of_node || !desc->of_match) 330a0c7b164SMark Brown return NULL; 331a0c7b164SMark Brown 332a0c7b164SMark Brown if (desc->regulators_node) 333a0c7b164SMark Brown search = of_get_child_by_name(dev->of_node, 334a0c7b164SMark Brown desc->regulators_node); 335a0c7b164SMark Brown else 336a0c7b164SMark Brown search = dev->of_node; 337a0c7b164SMark Brown 338a0c7b164SMark Brown if (!search) { 3397de79a1dSMark Brown dev_dbg(dev, "Failed to find regulator container node '%s'\n", 3407de79a1dSMark Brown desc->regulators_node); 341a0c7b164SMark Brown return NULL; 342a0c7b164SMark Brown } 343a0c7b164SMark Brown 344130daa3fSStephen Boyd for_each_available_child_of_node(search, child) { 345a0c7b164SMark Brown name = of_get_property(child, "regulator-compatible", NULL); 346a0c7b164SMark Brown if (!name) 347a0c7b164SMark Brown name = child->name; 348a0c7b164SMark Brown 349a0c7b164SMark Brown if (strcmp(desc->of_match, name)) 350a0c7b164SMark Brown continue; 351a0c7b164SMark Brown 352072e78b1SJavier Martinez Canillas init_data = of_get_regulator_init_data(dev, child, desc); 353a0c7b164SMark Brown if (!init_data) { 354a0c7b164SMark Brown dev_err(dev, 355a0c7b164SMark Brown "failed to parse DT for regulator %s\n", 356a0c7b164SMark Brown child->name); 357a0c7b164SMark Brown break; 358a0c7b164SMark Brown } 359a0c7b164SMark Brown 360bfa21a0dSKrzysztof Kozlowski if (desc->of_parse_cb) { 361bfa21a0dSKrzysztof Kozlowski if (desc->of_parse_cb(child, desc, config)) { 362bfa21a0dSKrzysztof Kozlowski dev_err(dev, 363bfa21a0dSKrzysztof Kozlowski "driver callback failed to parse DT for regulator %s\n", 364bfa21a0dSKrzysztof Kozlowski child->name); 365bfa21a0dSKrzysztof Kozlowski init_data = NULL; 366bfa21a0dSKrzysztof Kozlowski break; 367bfa21a0dSKrzysztof Kozlowski } 368bfa21a0dSKrzysztof Kozlowski } 369bfa21a0dSKrzysztof Kozlowski 370a0c7b164SMark Brown of_node_get(child); 371a0c7b164SMark Brown *node = child; 372a0c7b164SMark Brown break; 373a0c7b164SMark Brown } 374a0c7b164SMark Brown 375a0c7b164SMark Brown of_node_put(search); 376a0c7b164SMark Brown 377a0c7b164SMark Brown return init_data; 378a0c7b164SMark Brown } 379