|
@@ -23,6 +23,24 @@
|
|
|
|
|
|
#include "opp.h"
|
|
|
|
|
|
+/*
|
|
|
+ * 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,
|
|
|
+ int index)
|
|
|
+{
|
|
|
+ /* "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, 0);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_opp_desc_node);
|
|
|
+
|
|
|
static struct opp_table *_managed_opp(const struct device_node *np)
|
|
|
{
|
|
|
struct opp_table *opp_table, *managed_table = NULL;
|
|
@@ -55,22 +73,37 @@ static struct opp_table *_managed_opp(const struct device_node *np)
|
|
|
void _of_init_opp_table(struct opp_table *opp_table, struct device *dev,
|
|
|
int index)
|
|
|
{
|
|
|
- struct device_node *np;
|
|
|
+ struct device_node *np, *opp_np;
|
|
|
+ u32 val;
|
|
|
|
|
|
/*
|
|
|
* Only required for backward compatibility with v1 bindings, but isn't
|
|
|
* harmful for other cases. And so we do it unconditionally.
|
|
|
*/
|
|
|
np = of_node_get(dev->of_node);
|
|
|
- if (np) {
|
|
|
- u32 val;
|
|
|
-
|
|
|
- if (!of_property_read_u32(np, "clock-latency", &val))
|
|
|
- opp_table->clock_latency_ns_max = val;
|
|
|
- of_property_read_u32(np, "voltage-tolerance",
|
|
|
- &opp_table->voltage_tolerance_v1);
|
|
|
- of_node_put(np);
|
|
|
- }
|
|
|
+ if (!np)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (!of_property_read_u32(np, "clock-latency", &val))
|
|
|
+ opp_table->clock_latency_ns_max = val;
|
|
|
+ of_property_read_u32(np, "voltage-tolerance",
|
|
|
+ &opp_table->voltage_tolerance_v1);
|
|
|
+
|
|
|
+ /* Get OPP table node */
|
|
|
+ opp_np = _opp_of_get_opp_desc_node(np, index);
|
|
|
+ of_node_put(np);
|
|
|
+
|
|
|
+ if (!opp_np)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (of_property_read_bool(opp_np, "opp-shared"))
|
|
|
+ opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
|
|
|
+ else
|
|
|
+ opp_table->shared_opp = OPP_TABLE_ACCESS_EXCLUSIVE;
|
|
|
+
|
|
|
+ opp_table->np = opp_np;
|
|
|
+
|
|
|
+ of_node_put(opp_np);
|
|
|
}
|
|
|
|
|
|
static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
|
|
@@ -250,22 +283,6 @@ void dev_pm_opp_of_remove_table(struct device *dev)
|
|
|
}
|
|
|
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,
|
|
|
- int index)
|
|
|
-{
|
|
|
- /* "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, 0);
|
|
|
-}
|
|
|
-EXPORT_SYMBOL_GPL(dev_pm_opp_of_get_opp_desc_node);
|
|
|
-
|
|
|
/**
|
|
|
* _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
|
|
|
* @opp_table: OPP table
|
|
@@ -392,6 +409,9 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np,
|
|
|
/* OPPs are already managed */
|
|
|
if (!_add_opp_dev(dev, opp_table))
|
|
|
ret = -ENOMEM;
|
|
|
+ else if (!opp_table->parsed_static_opps)
|
|
|
+ goto initialize_static_opps;
|
|
|
+
|
|
|
goto put_opp_table;
|
|
|
}
|
|
|
|
|
@@ -399,6 +419,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np,
|
|
|
if (!opp_table)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+initialize_static_opps:
|
|
|
/* We have opp-table node now, iterate over it and add OPPs */
|
|
|
for_each_available_child_of_node(opp_np, np) {
|
|
|
count++;
|
|
@@ -434,11 +455,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct device_node *opp_np,
|
|
|
if (pstate_count)
|
|
|
opp_table->genpd_performance_state = true;
|
|
|
|
|
|
- opp_table->np = opp_np;
|
|
|
- if (of_property_read_bool(opp_np, "opp-shared"))
|
|
|
- opp_table->shared_opp = OPP_TABLE_ACCESS_SHARED;
|
|
|
- else
|
|
|
- opp_table->shared_opp = OPP_TABLE_ACCESS_EXCLUSIVE;
|
|
|
+ opp_table->parsed_static_opps = true;
|
|
|
|
|
|
put_opp_table:
|
|
|
dev_pm_opp_put_opp_table(opp_table);
|