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