Commit 46f48aca authored by Viresh Kumar's avatar Viresh Kumar

OPP: Fix missing debugfs supply directory for OPPs

There is one case where we may end up with no "supply" directory for the
OPPs in debugfs. That happens when the OPP core isn't managing the
regulators for the device and the device's OPP do have microvolt
property. It happens because the opp_table->regulator_count remains set
to 0 and the debugfs routines don't add any supply directory in such a
case.

This commit fixes that by setting opp_table->regulator_count to 1 in
that particular case. But to make everything work nicely and not break
other parts of the core, regulator_count is defined as "int" now instead
of "unsigned int" and it can have different special values now. It is
set to -1 initially to mark it "uninitialized" and later only we set it
to 0 or positive values after checking how many supplies are there.

This also helps in finding the bugs where only few of the OPPs have the
"opp-microvolt" property set and not all.

Fixes: 1fae788e ("PM / OPP: Don't create debugfs "supply-0" directory unnecessarily")
Reported-by: default avatarQuentin Perret <quentin.perret@arm.com>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
parent 90e3577b
...@@ -812,6 +812,9 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) ...@@ -812,6 +812,9 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
mutex_init(&opp_table->lock); mutex_init(&opp_table->lock);
INIT_LIST_HEAD(&opp_table->dev_list); INIT_LIST_HEAD(&opp_table->dev_list);
/* Mark regulator count uninitialized */
opp_table->regulator_count = -1;
opp_dev = _add_opp_dev(dev, opp_table); opp_dev = _add_opp_dev(dev, opp_table);
if (!opp_dev) { if (!opp_dev) {
kfree(opp_table); kfree(opp_table);
...@@ -1028,7 +1031,7 @@ struct dev_pm_opp *_opp_allocate(struct opp_table *table) ...@@ -1028,7 +1031,7 @@ struct dev_pm_opp *_opp_allocate(struct opp_table *table)
int count, supply_size; int count, supply_size;
/* Allocate space for at least one supply */ /* Allocate space for at least one supply */
count = table->regulator_count ? table->regulator_count : 1; count = table->regulator_count > 0 ? table->regulator_count : 1;
supply_size = sizeof(*opp->supplies) * count; supply_size = sizeof(*opp->supplies) * count;
/* allocate new OPP node and supplies structures */ /* allocate new OPP node and supplies structures */
...@@ -1433,7 +1436,7 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, ...@@ -1433,7 +1436,7 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
kfree(opp_table->regulators); kfree(opp_table->regulators);
opp_table->regulators = NULL; opp_table->regulators = NULL;
opp_table->regulator_count = 0; opp_table->regulator_count = -1;
err: err:
dev_pm_opp_put_opp_table(opp_table); dev_pm_opp_put_opp_table(opp_table);
...@@ -1462,7 +1465,7 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table) ...@@ -1462,7 +1465,7 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table)
kfree(opp_table->regulators); kfree(opp_table->regulators);
opp_table->regulators = NULL; opp_table->regulators = NULL;
opp_table->regulator_count = 0; opp_table->regulator_count = -1;
put_opp_table: put_opp_table:
dev_pm_opp_put_opp_table(opp_table); dev_pm_opp_put_opp_table(opp_table);
...@@ -1615,6 +1618,9 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt) ...@@ -1615,6 +1618,9 @@ int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
if (!opp_table) if (!opp_table)
return -ENOMEM; return -ENOMEM;
/* Fix regulator count for dynamic OPPs */
opp_table->regulator_count = 1;
ret = _opp_add_v1(opp_table, dev, freq, u_volt, true); ret = _opp_add_v1(opp_table, dev, freq, u_volt, true);
if (ret) if (ret)
dev_pm_opp_put_opp_table(opp_table); dev_pm_opp_put_opp_table(opp_table);
......
...@@ -150,12 +150,10 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, ...@@ -150,12 +150,10 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
struct opp_table *opp_table) struct opp_table *opp_table)
{ {
u32 *microvolt, *microamp = NULL; u32 *microvolt, *microamp = NULL;
int supplies, vcount, icount, ret, i, j; int supplies = opp_table->regulator_count, vcount, icount, ret, i, j;
struct property *prop = NULL; struct property *prop = NULL;
char name[NAME_MAX]; char name[NAME_MAX];
supplies = opp_table->regulator_count ? opp_table->regulator_count : 1;
/* Search for "opp-microvolt-<name>" */ /* Search for "opp-microvolt-<name>" */
if (opp_table->prop_name) { if (opp_table->prop_name) {
snprintf(name, sizeof(name), "opp-microvolt-%s", snprintf(name, sizeof(name), "opp-microvolt-%s",
...@@ -170,7 +168,13 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, ...@@ -170,7 +168,13 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
/* Missing property isn't a problem, but an invalid entry is */ /* Missing property isn't a problem, but an invalid entry is */
if (!prop) { if (!prop) {
if (!opp_table->regulator_count) if (unlikely(supplies == -1)) {
/* Initialize regulator_count */
opp_table->regulator_count = 0;
return 0;
}
if (!supplies)
return 0; return 0;
dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n", dev_err(dev, "%s: opp-microvolt missing although OPP managing regulators\n",
...@@ -179,6 +183,14 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev, ...@@ -179,6 +183,14 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
} }
} }
if (unlikely(supplies == -1)) {
/* Initialize regulator_count */
supplies = opp_table->regulator_count = 1;
} else if (unlikely(!supplies)) {
dev_err(dev, "%s: opp-microvolt wasn't expected\n", __func__);
return -EINVAL;
}
vcount = of_property_count_u32_elems(opp->np, name); vcount = of_property_count_u32_elems(opp->np, name);
if (vcount < 0) { if (vcount < 0) {
dev_err(dev, "%s: Invalid %s property (%d)\n", dev_err(dev, "%s: Invalid %s property (%d)\n",
......
...@@ -138,7 +138,9 @@ enum opp_table_access { ...@@ -138,7 +138,9 @@ enum opp_table_access {
* @prop_name: A name to postfix to many DT properties, while parsing them. * @prop_name: A name to postfix to many DT properties, while parsing them.
* @clk: Device's clock handle * @clk: Device's clock handle
* @regulators: Supply regulators * @regulators: Supply regulators
* @regulator_count: Number of power supply regulators * @regulator_count: Number of power supply regulators. Its value can be -1
* (uninitialized), 0 (no opp-microvolt property) or > 0 (has opp-microvolt
* property).
* @genpd_performance_state: Device's power domain support performance state. * @genpd_performance_state: Device's power domain support performance state.
* @set_opp: Platform specific set_opp callback * @set_opp: Platform specific set_opp callback
* @set_opp_data: Data to be passed to set_opp callback * @set_opp_data: Data to be passed to set_opp callback
...@@ -176,7 +178,7 @@ struct opp_table { ...@@ -176,7 +178,7 @@ struct opp_table {
const char *prop_name; const char *prop_name;
struct clk *clk; struct clk *clk;
struct regulator **regulators; struct regulator **regulators;
unsigned int regulator_count; int regulator_count;
bool genpd_performance_state; bool genpd_performance_state;
int (*set_opp)(struct dev_pm_set_opp_data *data); int (*set_opp)(struct dev_pm_set_opp_data *data);
......
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