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; 241653ccf4SYadwinder Singh Brar struct property *prop; 258f446e6fSRajendra Nayak struct regulation_constraints *constraints = &(*init_data)->constraints; 2600c877c6SLaxman Dewangan int ret; 2700c877c6SLaxman Dewangan u32 pval; 288f446e6fSRajendra Nayak 298f446e6fSRajendra Nayak constraints->name = of_get_property(np, "regulator-name", NULL); 308f446e6fSRajendra Nayak 318f446e6fSRajendra Nayak min_uV = of_get_property(np, "regulator-min-microvolt", NULL); 328f446e6fSRajendra Nayak if (min_uV) 338f446e6fSRajendra Nayak constraints->min_uV = be32_to_cpu(*min_uV); 348f446e6fSRajendra Nayak max_uV = of_get_property(np, "regulator-max-microvolt", NULL); 358f446e6fSRajendra Nayak if (max_uV) 368f446e6fSRajendra Nayak constraints->max_uV = be32_to_cpu(*max_uV); 378f446e6fSRajendra Nayak 388f446e6fSRajendra Nayak /* Voltage change possible? */ 398f446e6fSRajendra Nayak if (constraints->min_uV != constraints->max_uV) 408f446e6fSRajendra Nayak constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; 41ab62aa93SMark Brown /* Only one voltage? Then make sure it's set. */ 428a093049SKarol Lewandowski if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) 43ab62aa93SMark Brown constraints->apply_uV = true; 448f446e6fSRajendra Nayak 458f446e6fSRajendra Nayak uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); 468f446e6fSRajendra Nayak if (uV_offset) 478f446e6fSRajendra Nayak constraints->uV_offset = be32_to_cpu(*uV_offset); 488f446e6fSRajendra Nayak min_uA = of_get_property(np, "regulator-min-microamp", NULL); 498f446e6fSRajendra Nayak if (min_uA) 508f446e6fSRajendra Nayak constraints->min_uA = be32_to_cpu(*min_uA); 518f446e6fSRajendra Nayak max_uA = of_get_property(np, "regulator-max-microamp", NULL); 528f446e6fSRajendra Nayak if (max_uA) 538f446e6fSRajendra Nayak constraints->max_uA = be32_to_cpu(*max_uA); 548f446e6fSRajendra Nayak 558f446e6fSRajendra Nayak /* Current change possible? */ 568f446e6fSRajendra Nayak if (constraints->min_uA != constraints->max_uA) 578f446e6fSRajendra Nayak constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; 588f446e6fSRajendra Nayak 598f446e6fSRajendra Nayak if (of_find_property(np, "regulator-boot-on", NULL)) 608f446e6fSRajendra Nayak constraints->boot_on = true; 618f446e6fSRajendra Nayak 628f446e6fSRajendra Nayak if (of_find_property(np, "regulator-always-on", NULL)) 638f446e6fSRajendra Nayak constraints->always_on = true; 648f446e6fSRajendra Nayak else /* status change should be possible if not always on. */ 658f446e6fSRajendra Nayak constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; 666f0b2c69SYadwinder Singh Brar 6793134c7bSKishon Vijay Abraham I if (of_property_read_bool(np, "regulator-allow-bypass")) 6893134c7bSKishon Vijay Abraham I constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; 6993134c7bSKishon Vijay Abraham I 701653ccf4SYadwinder Singh Brar prop = of_find_property(np, "regulator-ramp-delay", NULL); 711653ccf4SYadwinder Singh Brar if (prop && prop->value) { 721653ccf4SYadwinder Singh Brar ramp_delay = prop->value; 731653ccf4SYadwinder Singh Brar if (*ramp_delay) 74086ccd43SAxel Lin constraints->ramp_delay = be32_to_cpu(*ramp_delay); 751653ccf4SYadwinder Singh Brar else 761653ccf4SYadwinder Singh Brar constraints->ramp_disable = true; 771653ccf4SYadwinder Singh Brar } 7800c877c6SLaxman Dewangan 7900c877c6SLaxman Dewangan ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval); 8000c877c6SLaxman Dewangan if (!ret) 8100c877c6SLaxman Dewangan constraints->enable_time = pval; 828f446e6fSRajendra Nayak } 838f446e6fSRajendra Nayak 848f446e6fSRajendra Nayak /** 858f446e6fSRajendra Nayak * of_get_regulator_init_data - extract regulator_init_data structure info 868f446e6fSRajendra Nayak * @dev: device requesting for regulator_init_data 878f446e6fSRajendra Nayak * 888f446e6fSRajendra Nayak * Populates regulator_init_data structure by extracting data from device 898f446e6fSRajendra Nayak * tree node, returns a pointer to the populated struture or NULL if memory 908f446e6fSRajendra Nayak * alloc fails. 918f446e6fSRajendra Nayak */ 92d9a861ccSShawn Guo struct regulator_init_data *of_get_regulator_init_data(struct device *dev, 93d9a861ccSShawn Guo struct device_node *node) 948f446e6fSRajendra Nayak { 958f446e6fSRajendra Nayak struct regulator_init_data *init_data; 968f446e6fSRajendra Nayak 97d9a861ccSShawn Guo if (!node) 988f446e6fSRajendra Nayak return NULL; 998f446e6fSRajendra Nayak 1008f446e6fSRajendra Nayak init_data = devm_kzalloc(dev, sizeof(*init_data), GFP_KERNEL); 1018f446e6fSRajendra Nayak if (!init_data) 1028f446e6fSRajendra Nayak return NULL; /* Out of memory? */ 1038f446e6fSRajendra Nayak 104d9a861ccSShawn Guo of_get_regulation_constraints(node, &init_data); 1058f446e6fSRajendra Nayak return init_data; 1068f446e6fSRajendra Nayak } 107e69af5e9SAxel Lin EXPORT_SYMBOL_GPL(of_get_regulator_init_data); 1081c8fa58fSThierry Reding 1091c8fa58fSThierry Reding /** 11013511defSStephen Warren * of_regulator_match - extract multiple regulator init data from device tree. 1111c8fa58fSThierry Reding * @dev: device requesting the data 1121c8fa58fSThierry Reding * @node: parent device node of the regulators 1131c8fa58fSThierry Reding * @matches: match table for the regulators 1141c8fa58fSThierry Reding * @num_matches: number of entries in match table 1151c8fa58fSThierry Reding * 11613511defSStephen Warren * This function uses a match table specified by the regulator driver to 11713511defSStephen Warren * parse regulator init data from the device tree. @node is expected to 11813511defSStephen Warren * contain a set of child nodes, each providing the init data for one 11913511defSStephen Warren * regulator. The data parsed from a child node will be matched to a regulator 12013511defSStephen Warren * based on either the deprecated property regulator-compatible if present, 12113511defSStephen Warren * or otherwise the child node's name. Note that the match table is modified 122bd0dda74SCharles Keepax * in place and an additional of_node reference is taken for each matched 123bd0dda74SCharles Keepax * regulator. 1241c8fa58fSThierry Reding * 1251c8fa58fSThierry Reding * Returns the number of matches found or a negative error code on failure. 1261c8fa58fSThierry Reding */ 1271c8fa58fSThierry Reding int of_regulator_match(struct device *dev, struct device_node *node, 1281c8fa58fSThierry Reding struct of_regulator_match *matches, 1291c8fa58fSThierry Reding unsigned int num_matches) 1301c8fa58fSThierry Reding { 1311c8fa58fSThierry Reding unsigned int count = 0; 1321c8fa58fSThierry Reding unsigned int i; 13313511defSStephen Warren const char *name; 1345260cd2bSLaxman Dewangan struct device_node *child; 1351c8fa58fSThierry Reding 1361c8fa58fSThierry Reding if (!dev || !node) 1371c8fa58fSThierry Reding return -EINVAL; 1381c8fa58fSThierry Reding 139a2f95c36SStephen Warren for (i = 0; i < num_matches; i++) { 140a2f95c36SStephen Warren struct of_regulator_match *match = &matches[i]; 141a2f95c36SStephen Warren match->init_data = NULL; 142a2f95c36SStephen Warren match->of_node = NULL; 143a2f95c36SStephen Warren } 144a2f95c36SStephen Warren 1455260cd2bSLaxman Dewangan for_each_child_of_node(node, child) { 14613511defSStephen Warren name = of_get_property(child, 1475260cd2bSLaxman Dewangan "regulator-compatible", NULL); 14813511defSStephen Warren if (!name) 14913511defSStephen Warren name = child->name; 1501c8fa58fSThierry Reding for (i = 0; i < num_matches; i++) { 1511c8fa58fSThierry Reding struct of_regulator_match *match = &matches[i]; 1525260cd2bSLaxman Dewangan if (match->of_node) 1531c8fa58fSThierry Reding continue; 1541c8fa58fSThierry Reding 15513511defSStephen Warren if (strcmp(match->name, name)) 1565260cd2bSLaxman Dewangan continue; 1575260cd2bSLaxman Dewangan 1585260cd2bSLaxman Dewangan match->init_data = 1595260cd2bSLaxman Dewangan of_get_regulator_init_data(dev, child); 1601c8fa58fSThierry Reding if (!match->init_data) { 1615260cd2bSLaxman Dewangan dev_err(dev, 1625260cd2bSLaxman Dewangan "failed to parse DT for regulator %s\n", 1631c8fa58fSThierry Reding child->name); 1641c8fa58fSThierry Reding return -EINVAL; 1651c8fa58fSThierry Reding } 166bd0dda74SCharles Keepax match->of_node = of_node_get(child); 1671c8fa58fSThierry Reding count++; 1685260cd2bSLaxman Dewangan break; 1695260cd2bSLaxman Dewangan } 1701c8fa58fSThierry Reding } 1711c8fa58fSThierry Reding 1721c8fa58fSThierry Reding return count; 1731c8fa58fSThierry Reding } 1741c8fa58fSThierry Reding EXPORT_SYMBOL_GPL(of_regulator_match); 175