diff mbox series

[RFC,2/4] opp: Add dev_pm_opp_table_get_device

Message ID 53d047703057fb09a0345b0a13715576d6eea3da.1565089196.git.leonard.crestez@nxp.com (mailing list archive)
State RFC, archived
Headers show
Series opp: Parse required-opp as dev_pm_qos_request | expand

Commit Message

Leonard Crestez Aug. 6, 2019, 11:12 a.m. UTC
This API is the opposite of dev_pm_opp_get_opp_table. OPP tables can be
shared between devices but this ambiguity can be handled by returning an
error if opp table is not exclusive.

This can used for fetching the device pointed to by "required-opps".

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
---
 drivers/opp/core.c     | 30 ++++++++++++++++++++++++++++++
 include/linux/pm_opp.h |  6 ++++++
 2 files changed, 36 insertions(+)
diff mbox series

Patch

diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 77814d3bc4e6..b8bbabbbe44a 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -87,10 +87,40 @@  struct opp_table *_find_opp_table(struct device *dev)
 	mutex_unlock(&opp_table_lock);
 
 	return opp_table;
 }
 
+/**
+ * _find_opp_table() - find device struct using opp_table pointer
+ *
+ * OPP table must be exclusive: not be shared between devices.
+ */
+struct device *dev_pm_opp_table_get_device(struct opp_table *opp_table)
+{
+	struct opp_device *opp_dev;
+	struct device *dev = ERR_PTR(-EINVAL);
+	int opp_dev_cnt = 0;
+
+	mutex_lock(&opp_table->lock);
+
+	/* OPP table must not be shared: only one device */
+	if (opp_table->shared_opp != OPP_TABLE_ACCESS_EXCLUSIVE)
+		goto out;
+	list_for_each_entry(opp_dev, &opp_table->dev_list, node)
+		opp_dev_cnt++;
+	if (opp_dev_cnt != 1)
+		goto out;
+
+	opp_dev = list_first_entry(&opp_table->dev_list, struct opp_device, node);
+	dev = opp_dev->dev;
+
+out:
+	mutex_unlock(&opp_table->lock);
+	return dev;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_table_get_device);
+
 /**
  * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an opp
  * @opp:	opp for which voltage has to be returned for
  *
  * Return: voltage in micro volt corresponding to the opp, else
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
index b8197ab014f2..a4db3f42d787 100644
--- a/include/linux/pm_opp.h
+++ b/include/linux/pm_opp.h
@@ -76,10 +76,11 @@  struct dev_pm_set_opp_data {
 #if defined(CONFIG_PM_OPP)
 
 struct opp_table *dev_pm_opp_get_opp_table(struct device *dev);
 struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *dev, int index);
 void dev_pm_opp_put_opp_table(struct opp_table *opp_table);
+struct device *dev_pm_opp_table_get_device(struct opp_table *opp_table);
 
 unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
 
 unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
 
@@ -149,10 +150,15 @@  static inline struct opp_table *dev_pm_opp_get_opp_table_indexed(struct device *
 	return ERR_PTR(-ENOTSUPP);
 }
 
 static inline void dev_pm_opp_put_opp_table(struct opp_table *opp_table) {}
 
+struct struct device *dev_pm_opp_table_get_device(struct opp_table *opp_table)
+{
+	return ERR_PTR(-ENOTSUPP);
+}
+
 static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
 {
 	return 0;
 }