regulator: Extend of_get_regulator_init_data to support non-DT consumers

Extend the of_get_regulator_init_data function so that it can
parse an additional property from regulator device tree nodes
which is needed to support non-device tree consumers.

The new property is named qcom,consumer-supplies.  Its value
is a list of strings of the form:

qcom,consumer-supplies = "supply_name1", "device_name1",
                         "supply_name2", "device_name2", ...

Change-Id: Ia689d04e6de568e6889b807eed15df3116de01d2
Signed-off-by: David Collins <collinsd@codeaurora.org>
This commit is contained in:
David Collins
2012-05-01 15:43:13 -07:00
committed by Stephen Boyd
parent 3cecc29edd
commit ff04efbf35
2 changed files with 79 additions and 0 deletions

View File

@@ -10,6 +10,11 @@ Optional properties:
- regulator-always-on: boolean, regulator should never be disabled
- regulator-boot-on: bootloader/firmware enabled regulator
- <name>-supply: phandle to the parent supply/regulator node
- qcom,consumer-supplies: flattened list of supply and dev_name pairs
This property is used to support regulator consumers that have no device
tree node. An empty string, "", can be used to specify a null device
name. A null device name is used to allow calls such as:
regulator_get(NULL, "pll_vdd").
Example:
@@ -18,6 +23,7 @@ Example:
regulator-max-microvolt = <2500000>;
regulator-always-on;
vin-supply = <&vin>;
qcom,consumer-supplies = "pll_vdd", "", "lcd_vcc", "foo.1";
};
Regulator Consumers:

View File

@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/string.h>
#include <linux/regulator/machine.h>
static void of_get_regulation_constraints(struct device_node *np,
@@ -61,6 +62,71 @@ static void of_get_regulation_constraints(struct device_node *np,
constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
}
static const char *consumer_supply_prop_name = "qcom,consumer-supplies";
#define MAX_DEV_NAME_LEN 256
/*
* Fill in regulator init_data based on qcom legacy requirements.
*/
static int of_get_qcom_regulator_init_data(struct device *dev,
struct regulator_init_data **init_data)
{
struct device_node *node = dev->of_node;
struct regulator_consumer_supply *consumer_supplies;
int i, rc, num_consumer_supplies, array_len;
array_len = of_property_count_strings(node, consumer_supply_prop_name);
if (array_len > 0) {
/* Array length must be divisible by 2. */
if (array_len & 1) {
dev_err(dev, "error: %s device node property value "
"contains an odd number of elements: %d\n",
consumer_supply_prop_name, array_len);
return -EINVAL;
}
num_consumer_supplies = array_len / 2;
consumer_supplies = devm_kzalloc(dev,
sizeof(struct regulator_consumer_supply)
* num_consumer_supplies, GFP_KERNEL);
if (consumer_supplies == NULL) {
dev_err(dev, "devm_kzalloc failed\n");
return -ENOMEM;
}
for (i = 0; i < num_consumer_supplies; i++) {
rc = of_property_read_string_index(node,
consumer_supply_prop_name, i * 2,
&consumer_supplies[i].supply);
if (rc) {
dev_err(dev, "of_property_read_string_index "
"failed, rc=%d\n", rc);
devm_kfree(dev, consumer_supplies);
return rc;
}
rc = of_property_read_string_index(node,
consumer_supply_prop_name, (i * 2) + 1,
&consumer_supplies[i].dev_name);
if (rc) {
dev_err(dev, "of_property_read_string_index "
"failed, rc=%d\n", rc);
devm_kfree(dev, consumer_supplies);
return rc;
}
/* Treat dev_name = "" as a wildcard. */
if (strnlen(consumer_supplies[i].dev_name,
MAX_DEV_NAME_LEN) == 0)
consumer_supplies[i].dev_name = NULL;
}
(*init_data)->consumer_supplies = consumer_supplies;
(*init_data)->num_consumer_supplies = num_consumer_supplies;
}
return 0;
}
/**
* of_get_regulator_init_data - extract regulator_init_data structure info
* @dev: device requesting for regulator_init_data
@@ -73,6 +139,7 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
struct device_node *node)
{
struct regulator_init_data *init_data;
int rc;
if (!node)
return NULL;
@@ -82,6 +149,12 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
return NULL; /* Out of memory? */
of_get_regulation_constraints(node, &init_data);
rc = of_get_qcom_regulator_init_data(dev, &init_data);
if (rc) {
devm_kfree(dev, init_data);
return NULL;
}
return init_data;
}
EXPORT_SYMBOL_GPL(of_get_regulator_init_data);