Commit e5acb199 authored by Viresh Kumar's avatar Viresh Kumar

OPP: Simplify opp_parse_supplies() by restructuring it

opp_parse_supplies() has grown into too big of a routine (~190 lines)
and it is not straight-forward to understand it anymore.

Break it into smaller routines and reduce code redundancy a bit by using
the same code to parse properties.

This shouldn't result in any logical changes.
Tested-by: default avatarJames Calligeros <jcalligeros99@gmail.com>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent 71b09429
...@@ -578,179 +578,126 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table, ...@@ -578,179 +578,126 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
return false; return false;
} }
static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, static u32 *_parse_named_prop(struct dev_pm_opp *opp, struct device *dev,
struct opp_table *opp_table) struct opp_table *opp_table,
const char *prop_type, bool *triplet)
{ {
u32 *microvolt, *microamp = NULL, *microwatt = NULL;
int supplies = opp_table->regulator_count;
int vcount, icount, pcount, ret, i, j;
struct property *prop = NULL; struct property *prop = NULL;
char name[NAME_MAX]; char name[NAME_MAX];
int count, ret;
u32 *out;
/* Search for "opp-microvolt-<name>" */ /* Search for "opp-<prop_type>-<name>" */
if (opp_table->prop_name) { if (opp_table->prop_name) {
snprintf(name, sizeof(name), "opp-microvolt-%s", snprintf(name, sizeof(name), "opp-%s-%s", prop_type,
opp_table->prop_name); opp_table->prop_name);
prop = of_find_property(opp->np, name, NULL); prop = of_find_property(opp->np, name, NULL);
} }
if (!prop) { if (!prop) {
/* Search for "opp-microvolt" */ /* Search for "opp-<prop_type>" */
sprintf(name, "opp-microvolt"); snprintf(name, sizeof(name), "opp-%s", prop_type);
prop = of_find_property(opp->np, name, NULL); prop = of_find_property(opp->np, name, NULL);
if (!prop)
/* Missing property isn't a problem, but an invalid entry is */ return NULL;
if (!prop) {
if (unlikely(supplies == -1)) {
/* Initialize regulator_count */
opp_table->regulator_count = 0;
return 0;
} }
if (!supplies) count = of_property_count_u32_elems(opp->np, name);
return 0; if (count < 0) {
dev_err(dev, "%s: Invalid %s property (%d)\n", __func__, name,
dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n", count);
__func__); return ERR_PTR(count);
return -EINVAL;
}
} }
if (unlikely(supplies == -1)) { /*
/* Initialize regulator_count */ * Initialize regulator_count, if regulator information isn't provided
supplies = opp_table->regulator_count = 1; * by the platform. Now that one of the properties is available, fix the
} else if (unlikely(!supplies)) { * regulator_count to 1.
dev_err(dev, "%s: opp-microvolt wasn't expected\n", __func__); */
return -EINVAL; if (unlikely(opp_table->regulator_count == -1))
} opp_table->regulator_count = 1;
vcount = of_property_count_u32_elems(opp->np, name); if (count != opp_table->regulator_count &&
if (vcount < 0) { (!triplet || count != opp_table->regulator_count * 3)) {
dev_err(dev, "%s: Invalid %s property (%d)\n", dev_err(dev, "%s: Invalid number of elements in %s property (%u) with supplies (%d)\n",
__func__, name, vcount); __func__, prop_type, count, opp_table->regulator_count);
return vcount; return ERR_PTR(-EINVAL);
} }
/* There can be one or three elements per supply */ out = kmalloc_array(count, sizeof(*out), GFP_KERNEL);
if (vcount != supplies && vcount != supplies * 3) { if (!out)
dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n", return ERR_PTR(-EINVAL);
__func__, name, vcount, supplies);
return -EINVAL;
}
microvolt = kmalloc_array(vcount, sizeof(*microvolt), GFP_KERNEL); ret = of_property_read_u32_array(opp->np, name, out, count);
if (!microvolt)
return -ENOMEM;
ret = of_property_read_u32_array(opp->np, name, microvolt, vcount);
if (ret) { if (ret) {
dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret); dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
ret = -EINVAL; kfree(out);
goto free_microvolt; return ERR_PTR(-EINVAL);
} }
/* Search for "opp-microamp-<name>" */ if (triplet)
prop = NULL; *triplet = count != opp_table->regulator_count;
if (opp_table->prop_name) {
snprintf(name, sizeof(name), "opp-microamp-%s",
opp_table->prop_name);
prop = of_find_property(opp->np, name, NULL);
}
if (!prop) { return out;
/* Search for "opp-microamp" */ }
sprintf(name, "opp-microamp");
prop = of_find_property(opp->np, name, NULL);
}
if (prop) { static u32 *opp_parse_microvolt(struct dev_pm_opp *opp, struct device *dev,
icount = of_property_count_u32_elems(opp->np, name); struct opp_table *opp_table, bool *triplet)
if (icount < 0) { {
dev_err(dev, "%s: Invalid %s property (%d)\n", __func__, u32 *microvolt;
name, icount);
ret = icount;
goto free_microvolt;
}
if (icount != supplies) { microvolt = _parse_named_prop(opp, dev, opp_table, "microvolt", triplet);
dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n", if (IS_ERR(microvolt))
__func__, name, icount, supplies); return microvolt;
ret = -EINVAL;
goto free_microvolt;
}
microamp = kmalloc_array(icount, sizeof(*microamp), GFP_KERNEL); if (!microvolt) {
if (!microamp) { /*
ret = -EINVAL; * Missing property isn't a problem, but an invalid
goto free_microvolt; * entry is. This property isn't optional if regulator
} * information is provided.
*/
ret = of_property_read_u32_array(opp->np, name, microamp, if (opp_table->regulator_count > 0) {
icount); dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n",
if (ret) { __func__);
dev_err(dev, "%s: error parsing %s: %d\n", __func__, return ERR_PTR(-EINVAL);
name, ret);
ret = -EINVAL;
goto free_microamp;
} }
} }
/* Search for "opp-microwatt-<name>" */ return microvolt;
prop = NULL; }
if (opp_table->prop_name) {
snprintf(name, sizeof(name), "opp-microwatt-%s",
opp_table->prop_name);
prop = of_find_property(opp->np, name, NULL);
}
if (!prop) { static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
/* Search for "opp-microwatt" */ struct opp_table *opp_table)
sprintf(name, "opp-microwatt"); {
prop = of_find_property(opp->np, name, NULL); u32 *microvolt, *microamp, *microwatt;
} int ret = 0, i, j;
bool triplet;
if (prop) { microvolt = opp_parse_microvolt(opp, dev, opp_table, &triplet);
pcount = of_property_count_u32_elems(opp->np, name); if (IS_ERR_OR_NULL(microvolt))
if (pcount < 0) { return PTR_ERR(microvolt);
dev_err(dev, "%s: Invalid %s property (%d)\n", __func__,
name, pcount);
ret = pcount;
goto free_microamp;
}
if (pcount != supplies) { microamp = _parse_named_prop(opp, dev, opp_table, "microamp", NULL);
dev_err(dev, "%s: Invalid number of elements in %s property (%d) with supplies (%d)\n", if (IS_ERR(microamp)) {
__func__, name, pcount, supplies); ret = PTR_ERR(microamp);
ret = -EINVAL; goto free_microvolt;
goto free_microamp;
} }
microwatt = kmalloc_array(pcount, sizeof(*microwatt), microwatt = _parse_named_prop(opp, dev, opp_table, "microwatt", NULL);
GFP_KERNEL); if (IS_ERR(microwatt)) {
if (!microwatt) { ret = PTR_ERR(microwatt);
ret = -EINVAL;
goto free_microamp; goto free_microamp;
} }
ret = of_property_read_u32_array(opp->np, name, microwatt, for (i = 0, j = 0; i < opp_table->regulator_count; i++) {
pcount);
if (ret) {
dev_err(dev, "%s: error parsing %s: %d\n", __func__,
name, ret);
ret = -EINVAL;
goto free_microwatt;
}
}
for (i = 0, j = 0; i < supplies; i++) {
opp->supplies[i].u_volt = microvolt[j++]; opp->supplies[i].u_volt = microvolt[j++];
if (vcount == supplies) { if (triplet) {
opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
} else {
opp->supplies[i].u_volt_min = microvolt[j++]; opp->supplies[i].u_volt_min = microvolt[j++];
opp->supplies[i].u_volt_max = microvolt[j++]; opp->supplies[i].u_volt_max = microvolt[j++];
} else {
opp->supplies[i].u_volt_min = opp->supplies[i].u_volt;
opp->supplies[i].u_volt_max = opp->supplies[i].u_volt;
} }
if (microamp) if (microamp)
...@@ -760,7 +707,6 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, ...@@ -760,7 +707,6 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
opp->supplies[i].u_watt = microwatt[i]; opp->supplies[i].u_watt = microwatt[i];
} }
free_microwatt:
kfree(microwatt); kfree(microwatt);
free_microamp: free_microamp:
kfree(microamp); kfree(microamp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment