diff mbox series

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

Message ID 20250909054811.3991901-2-quic_mmanikan@quicinc.com
State New
Delegated to: Andi Shyti
Headers show
Series Add I2C support for IPQ5424 | expand

Commit Message

Manikanta Mylavarapu Sept. 9, 2025, 5:48 a.m. UTC
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 mbox series

Patch

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));