[PATCH v3 1/2] i2c: qcom-geni: add OPP table support

Manikanta Mylavarapu posted 2 patches 3 weeks, 2 days ago
[PATCH v3 1/2] i2c: qcom-geni: add OPP table support
Posted by Manikanta Mylavarapu 3 weeks, 2 days ago
Add support for reading and configuring the OPP table in the GENI I2C
driver. This enables setting the frequency based on device tree data,
removing dependency on bootloader configuration.

Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
---
v3: Fix the format-specifier to correctly display the clock rate and change
   '&pdev->dev' to 'dev' as per suggestions from Andi Shyti.
 
drivers/i2c/busses/i2c-qcom-geni.c | 27 ++++++++++++++++++++++++---
 1 file changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index ff2289b52c84..380581a3699c 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -13,6 +13,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/pm_opp.h>
 #include <linux/pm_runtime.h>
 #include <linux/soc/qcom/geni-se.h>
 #include <linux/spinlock.h>
@@ -779,11 +780,13 @@ static int setup_gpi_dma(struct geni_i2c_dev *gi2c)
 
 static int geni_i2c_probe(struct platform_device *pdev)
 {
-	struct geni_i2c_dev *gi2c;
+	const struct geni_i2c_desc *desc = NULL;
 	u32 proto, tx_depth, fifo_disable;
-	int ret;
 	struct device *dev = &pdev->dev;
-	const struct geni_i2c_desc *desc = NULL;
+	unsigned long freq = ULONG_MAX;
+	struct geni_i2c_dev *gi2c;
+	struct dev_pm_opp *opp;
+	int ret;
 
 	gi2c = devm_kzalloc(dev, sizeof(*gi2c), GFP_KERNEL);
 	if (!gi2c)
@@ -814,6 +817,24 @@ static int geni_i2c_probe(struct platform_device *pdev)
 		gi2c->clk_freq_out = I2C_MAX_STANDARD_MODE_FREQ;
 	}
 
+	ret = devm_pm_opp_set_clkname(dev, "se");
+	if (ret)
+		return ret;
+
+	/* OPP table is optional */
+	ret = devm_pm_opp_of_add_table(dev);
+	if (!ret) {
+		opp = dev_pm_opp_find_freq_floor(dev, &freq);
+		if (IS_ERR(opp))
+			return dev_err_probe(dev, PTR_ERR(opp), "failed to find the frequency\n");
+		dev_pm_opp_put(opp);
+		ret = dev_pm_opp_set_rate(dev, freq);
+		if (ret)
+			return dev_err_probe(dev, ret, "failed to set the rate=%lu\n", freq);
+	} else if (ret && ret != -ENODEV) {
+		return dev_err_probe(dev, ret, "invalid OPP table in device tree\n");
+	}
+
 	if (has_acpi_companion(dev))
 		ACPI_COMPANION_SET(&gi2c->adap.dev, ACPI_COMPANION(dev));
 
-- 
2.34.1