summaryrefslogtreecommitdiffstats
path: root/drivers/opp/of.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2017-04-26 10:45:46 +0530
committerViresh Kumar <viresh.kumar@linaro.org>2018-05-09 10:15:18 +0530
commitfa9b274f8aeffb97787b055b8cfbf9062e158551 (patch)
tree83f39df6994b292ef978ee6d514648d934f93aca /drivers/opp/of.c
parenta1e8c13600bfd96c51580732ccf31f69bc6de4d1 (diff)
downloadlinux-stable-fa9b274f8aeffb97787b055b8cfbf9062e158551.tar.gz
linux-stable-fa9b274f8aeffb97787b055b8cfbf9062e158551.tar.bz2
linux-stable-fa9b274f8aeffb97787b055b8cfbf9062e158551.zip
PM / OPP: Implement dev_pm_opp_of_add_table_indexed()
The "operating-points-v2" property can contain a list of phandles now, specifically for the power domain providers that provide multiple domains. Add support to parse that. Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/opp/of.c')
-rw-r--r--drivers/opp/of.c50
1 files changed, 41 insertions, 9 deletions
diff --git a/drivers/opp/of.c b/drivers/opp/of.c
index c5c5afcaa2e3..cba669cd00c5 100644
--- a/drivers/opp/of.c
+++ b/drivers/opp/of.c
@@ -250,20 +250,17 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_remove_table);
/* Returns opp descriptor node for a device node, caller must
* do of_node_put() */
-static struct device_node *_opp_of_get_opp_desc_node(struct device_node *np)
+static struct device_node *_opp_of_get_opp_desc_node(struct device_node *np,
+ int index)
{
- /*
- * There should be only ONE phandle present in "operating-points-v2"
- * property.
- */
-
- return of_parse_phandle(np, "operating-points-v2", 0);
+ /* "operating-points-v2" can be an array for power domain providers */
+ return of_parse_phandle(np, "operating-points-v2", index);
}
/* Returns opp descriptor node for a device, caller must do of_node_put() */
struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev)
{
- return _opp_of_get_opp_desc_node(dev->of_node);
+ return _opp_of_get_opp_desc_node(dev->of_node, 0);
}
EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_opp_desc_node);
@@ -517,6 +514,41 @@ int dev_pm_opp_of_add_table(struct device *dev)
}
EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table);
+/**
+ * dev_pm_opp_of_add_table_indexed() - Initialize indexed opp table from device tree
+ * @dev: device pointer used to lookup OPP table.
+ * @index: Index number.
+ *
+ * Register the initial OPP table with the OPP library for given device only
+ * using the "operating-points-v2" property.
+ *
+ * Return:
+ * 0 On success OR
+ * Duplicate OPPs (both freq and volt are same) and opp->available
+ * -EEXIST Freq are same and volt are different OR
+ * Duplicate OPPs (both freq and volt are same) and !opp->available
+ * -ENOMEM Memory allocation failure
+ * -ENODEV when 'operating-points' property is not found or is invalid data
+ * in device node.
+ * -ENODATA when empty 'operating-points' property is found
+ * -EINVAL when invalid entries are found in opp-v2 table
+ */
+int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
+{
+ struct device_node *opp_np;
+ int ret;
+
+ opp_np = _opp_of_get_opp_desc_node(dev->of_node, index);
+ if (!opp_np)
+ return -ENODEV;
+
+ ret = _of_add_opp_table_v2(dev, opp_np);
+ of_node_put(opp_np);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_add_table_indexed);
+
/* CPU device specific helpers */
/**
@@ -621,7 +653,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev,
}
/* Get OPP descriptor node */
- tmp_np = _opp_of_get_opp_desc_node(cpu_np);
+ tmp_np = _opp_of_get_opp_desc_node(cpu_np, 0);
of_node_put(cpu_np);
if (!tmp_np) {
pr_err("%pOF: Couldn't find opp node\n", cpu_np);