diff options
Diffstat (limited to 'drivers/regulator/of_regulator.c')
-rw-r--r-- | drivers/regulator/of_regulator.c | 63 |
1 files changed, 43 insertions, 20 deletions
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 0ead1164e4d6..397918ebba55 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -21,7 +21,8 @@ static const char *const regulator_states[PM_SUSPEND_MAX + 1] = { [PM_SUSPEND_MAX] = "regulator-state-disk", }; -static void of_get_regulation_constraints(struct device_node *np, +static int of_get_regulation_constraints(struct device *dev, + struct device_node *np, struct regulator_init_data **init_data, const struct regulator_desc *desc) { @@ -30,8 +31,13 @@ static void of_get_regulation_constraints(struct device_node *np, struct device_node *suspend_np; unsigned int mode; int ret, i, len; + int n_phandles; u32 pval; + n_phandles = of_count_phandle_with_args(np, "regulator-coupled-with", + NULL); + n_phandles = max(n_phandles, 0); + constraints->name = of_get_property(np, "regulator-name", NULL); if (!of_property_read_u32(np, "regulator-min-microvolt", &pval)) @@ -163,9 +169,17 @@ static void of_get_regulation_constraints(struct device_node *np, if (!of_property_read_u32(np, "regulator-system-load", &pval)) constraints->system_load = pval; - if (!of_property_read_u32(np, "regulator-coupled-max-spread", - &pval)) - constraints->max_spread = pval; + if (n_phandles) { + constraints->max_spread = devm_kzalloc(dev, + sizeof(*constraints->max_spread) * n_phandles, + GFP_KERNEL); + + if (!constraints->max_spread) + return -ENOMEM; + + of_property_read_u32_array(np, "regulator-coupled-max-spread", + constraints->max_spread, n_phandles); + } if (!of_property_read_u32(np, "regulator-max-step-microvolt", &pval)) @@ -242,6 +256,8 @@ static void of_get_regulation_constraints(struct device_node *np, suspend_state = NULL; suspend_np = NULL; } + + return 0; } /** @@ -267,7 +283,9 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, if (!init_data) return NULL; /* Out of memory? */ - of_get_regulation_constraints(node, &init_data, desc); + if (of_get_regulation_constraints(dev, node, &init_data, desc)) + return NULL; + return init_data; } EXPORT_SYMBOL_GPL(of_get_regulator_init_data); @@ -473,7 +491,8 @@ int of_get_n_coupled(struct regulator_dev *rdev) /* Looks for "to_find" device_node in src's "regulator-coupled-with" property */ static bool of_coupling_find_node(struct device_node *src, - struct device_node *to_find) + struct device_node *to_find, + int *index) { int n_phandles, i; bool found = false; @@ -495,8 +514,10 @@ static bool of_coupling_find_node(struct device_node *src, of_node_put(tmp); - if (found) + if (found) { + *index = i; break; + } } return found; @@ -517,22 +538,23 @@ static bool of_coupling_find_node(struct device_node *src, */ bool of_check_coupling_data(struct regulator_dev *rdev) { - int max_spread = rdev->constraints->max_spread; struct device_node *node = rdev->dev.of_node; int n_phandles = of_get_n_coupled(rdev); struct device_node *c_node; + int index; int i; bool ret = true; - if (max_spread <= 0) { - dev_err(&rdev->dev, "max_spread value invalid\n"); - return false; - } - /* iterate over rdev's phandles */ for (i = 0; i < n_phandles; i++) { + int max_spread = rdev->constraints->max_spread[i]; int c_max_spread, c_n_phandles; + if (max_spread <= 0) { + dev_err(&rdev->dev, "max_spread value invalid\n"); + return false; + } + c_node = of_parse_phandle(node, "regulator-coupled-with", i); @@ -549,22 +571,23 @@ bool of_check_coupling_data(struct regulator_dev *rdev) goto clean; } - if (of_property_read_u32(c_node, "regulator-coupled-max-spread", - &c_max_spread)) { + if (!of_coupling_find_node(c_node, node, &index)) { + dev_err(&rdev->dev, "missing 2-way linking for coupled regulators\n"); ret = false; goto clean; } - if (c_max_spread != max_spread) { - dev_err(&rdev->dev, - "coupled regulators max_spread mismatch\n"); + if (of_property_read_u32_index(c_node, "regulator-coupled-max-spread", + index, &c_max_spread)) { ret = false; goto clean; } - if (!of_coupling_find_node(c_node, node)) { - dev_err(&rdev->dev, "missing 2-way linking for coupled regulators\n"); + if (c_max_spread != max_spread) { + dev_err(&rdev->dev, + "coupled regulators max_spread mismatch\n"); ret = false; + goto clean; } clean: |