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> 171c8fa58fSThierry Reding #include <linux/regulator/of_regulator.h> 188f446e6fSRajendra Nayak 198f446e6fSRajendra Nayak static void of_get_regulation_constraints(struct device_node *np, 208f446e6fSRajendra Nayak struct regulator_init_data **init_data) 218f446e6fSRajendra Nayak { 228f446e6fSRajendra Nayak const __be32 *min_uV, *max_uV, *uV_offset; 236f0b2c69SYadwinder Singh Brar const __be32 *min_uA, *max_uA, *ramp_delay; 248f446e6fSRajendra Nayak struct regulation_constraints *constraints = &(*init_data)->constraints; 258f446e6fSRajendra Nayak 268f446e6fSRajendra Nayak constraints->name = of_get_property(np, "regulator-name", NULL); 278f446e6fSRajendra Nayak 288f446e6fSRajendra Nayak min_uV = of_get_property(np, "regulator-min-microvolt", NULL); 298f446e6fSRajendra Nayak if (min_uV) 308f446e6fSRajendra Nayak constraints->min_uV = be32_to_cpu(*min_uV); 318f446e6fSRajendra Nayak max_uV = of_get_property(np, "regulator-max-microvolt", NULL); 328f446e6fSRajendra Nayak if (max_uV) 338f446e6fSRajendra Nayak constraints->max_uV = be32_to_cpu(*max_uV); 348f446e6fSRajendra Nayak 358f446e6fSRajendra Nayak /* Voltage change possible? */ 368f446e6fSRajendra Nayak if (constraints->min_uV != constraints->max_uV) 378f446e6fSRajendra Nayak constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; 38ab62aa93SMark Brown /* Only one voltage? Then make sure it's set. */ 398a093049SKarol Lewandowski if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) 40ab62aa93SMark Brown constraints->apply_uV = true; 418f446e6fSRajendra Nayak 428f446e6fSRajendra Nayak uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); 438f446e6fSRajendra Nayak if (uV_offset) 448f446e6fSRajendra Nayak constraints->uV_offset = be32_to_cpu(*uV_offset); 458f446e6fSRajendra Nayak min_uA = of_get_property(np, "regulator-min-microamp", NULL); 468f446e6fSRajendra Nayak if (min_uA) 478f446e6fSRajendra Nayak constraints->min_uA = be32_to_cpu(*min_uA); 488f446e6fSRajendra Nayak max_uA = of_get_property(np, "regulator-max-microamp", NULL); 498f446e6fSRajendra Nayak if (max_uA) 508f446e6fSRajendra Nayak constraints->max_uA = be32_to_cpu(*max_uA); 518f446e6fSRajendra Nayak 528f446e6fSRajendra Nayak /* Current change possible? */ 538f446e6fSRajendra Nayak if (constraints->min_uA != constraints->max_uA) 548f446e6fSRajendra Nayak constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; 558f446e6fSRajendra Nayak 568f446e6fSRajendra Nayak if (of_find_property(np, "regulator-boot-on", NULL)) 578f446e6fSRajendra Nayak constraints->boot_on = true; 588f446e6fSRajendra Nayak 598f446e6fSRajendra Nayak if (of_find_property(np, "regulator-always-on", NULL)) 608f446e6fSRajendra Nayak constraints->always_on = true; 618f446e6fSRajendra Nayak else /* status change should be possible if not always on. */ 628f446e6fSRajendra Nayak constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; 636f0b2c69SYadwinder Singh Brar 646f0b2c69SYadwinder Singh Brar ramp_delay = of_get_property(np, "regulator-ramp-delay", NULL); 656f0b2c69SYadwinder Singh Brar if (ramp_delay) 66086ccd43SAxel Lin constraints->ramp_delay = be32_to_cpu(*ramp_delay); 678f446e6fSRajendra Nayak } 688f446e6fSRajendra Nayak 698f446e6fSRajendra Nayak /** 708f446e6fSRajendra Nayak * of_get_regulator_init_data - extract regulator_init_data structure info 718f446e6fSRajendra Nayak * @dev: device requesting for regulator_init_data 728f446e6fSRajendra Nayak * 738f446e6fSRajendra Nayak * Populates regulator_init_data structure by extracting data from device 748f446e6fSRajendra Nayak * tree node, returns a pointer to the populated struture or NULL if memory 758f446e6fSRajendra Nayak * alloc fails. 768f446e6fSRajendra Nayak */ 77d9a861ccSShawn Guo struct regulator_init_data *of_get_regulator_init_data(struct device *dev, 78d9a861ccSShawn Guo struct device_node *node) 798f446e6fSRajendra Nayak { 808f446e6fSRajendra Nayak struct regulator_init_data *init_data; 818f446e6fSRajendra Nayak 82d9a861ccSShawn Guo if (!node) 838f446e6fSRajendra Nayak return NULL; 848f446e6fSRajendra Nayak 858f446e6fSRajendra Nayak init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); 868f446e6fSRajendra Nayak if (!init_data) 878f446e6fSRajendra Nayak return NULL; /* Out of memory? */ 888f446e6fSRajendra Nayak 89d9a861ccSShawn Guo of_get_regulation_constraints(node, &init_data); 908f446e6fSRajendra Nayak return init_data; 918f446e6fSRajendra Nayak } 92e69af5e9SAxel Lin EXPORT_SYMBOL_GPL(of_get_regulator_init_data); 931c8fa58fSThierry Reding 941c8fa58fSThierry Reding /** 955260cd2bSLaxman Dewangan * of_regulator_match - extract regulator init data when node 965260cd2bSLaxman Dewangan * property "regulator-compatible" matches with the regulator name. 971c8fa58fSThierry Reding * @dev: device requesting the data 981c8fa58fSThierry Reding * @node: parent device node of the regulators 991c8fa58fSThierry Reding * @matches: match table for the regulators 1001c8fa58fSThierry Reding * @num_matches: number of entries in match table 1011c8fa58fSThierry Reding * 1021c8fa58fSThierry Reding * This function uses a match table specified by the regulator driver and 1035260cd2bSLaxman Dewangan * looks up the corresponding init data in the device tree if 1045260cd2bSLaxman Dewangan * regulator-compatible matches. Note that the match table is modified 1055260cd2bSLaxman Dewangan * in place. 1061c8fa58fSThierry Reding * 1071c8fa58fSThierry Reding * Returns the number of matches found or a negative error code on failure. 1081c8fa58fSThierry Reding */ 1091c8fa58fSThierry Reding int of_regulator_match(struct device *dev, struct device_node *node, 1101c8fa58fSThierry Reding struct of_regulator_match *matches, 1111c8fa58fSThierry Reding unsigned int num_matches) 1121c8fa58fSThierry Reding { 1131c8fa58fSThierry Reding unsigned int count = 0; 1141c8fa58fSThierry Reding unsigned int i; 1155260cd2bSLaxman Dewangan const char *regulator_comp; 1165260cd2bSLaxman Dewangan struct device_node *child; 1171c8fa58fSThierry Reding 1181c8fa58fSThierry Reding if (!dev || !node) 1191c8fa58fSThierry Reding return -EINVAL; 1201c8fa58fSThierry Reding 1215260cd2bSLaxman Dewangan for_each_child_of_node(node, child) { 1225260cd2bSLaxman Dewangan regulator_comp = of_get_property(child, 1235260cd2bSLaxman Dewangan "regulator-compatible", NULL); 1245260cd2bSLaxman Dewangan if (!regulator_comp) { 1255260cd2bSLaxman Dewangan dev_err(dev, "regulator-compatible is missing for node %s\n", 1265260cd2bSLaxman Dewangan child->name); 1275260cd2bSLaxman Dewangan continue; 1285260cd2bSLaxman Dewangan } 1291c8fa58fSThierry Reding for (i = 0; i < num_matches; i++) { 1301c8fa58fSThierry Reding struct of_regulator_match *match = &matches[i]; 1315260cd2bSLaxman Dewangan if (match->of_node) 1321c8fa58fSThierry Reding continue; 1331c8fa58fSThierry Reding 1345260cd2bSLaxman Dewangan if (strcmp(match->name, regulator_comp)) 1355260cd2bSLaxman Dewangan continue; 1365260cd2bSLaxman Dewangan 1375260cd2bSLaxman Dewangan match->init_data = 1385260cd2bSLaxman Dewangan of_get_regulator_init_data(dev, child); 1391c8fa58fSThierry Reding if (!match->init_data) { 1405260cd2bSLaxman Dewangan dev_err(dev, 1415260cd2bSLaxman Dewangan "failed to parse DT for regulator %s\n", 1421c8fa58fSThierry Reding child->name); 1431c8fa58fSThierry Reding return -EINVAL; 1441c8fa58fSThierry Reding } 1451c8fa58fSThierry Reding match->of_node = child; 1461c8fa58fSThierry Reding count++; 1475260cd2bSLaxman Dewangan break; 1485260cd2bSLaxman Dewangan } 1491c8fa58fSThierry Reding } 1501c8fa58fSThierry Reding 1511c8fa58fSThierry Reding return count; 1521c8fa58fSThierry Reding } 1531c8fa58fSThierry Reding EXPORT_SYMBOL_GPL(of_regulator_match); 154