[PATCH v8 4/5] i2c: davinci: add support for setting bus frequency
From: Marcus Folkesson <marcus.folkesson@gmail.com>
Date: 2026-03-14 09:22:34
Also in:
linux-i2c, lkml
Subsystem:
i2c subsystem, i2c subsystem host drivers, the rest, ti davinci machine support · Maintainers:
Andi Shyti, Linus Torvalds, Bartosz Golaszewski
Populate adapter with clock_hz and .set_clk_freq() to enable support for dynamic bus frequency. Remove bus_freq_hz entirely and only use clock_hz instead. Acked-by: Bartosz Golaszewski <redacted> Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com> --- drivers/i2c/busses/i2c-davinci.c | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-)
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index 549fb22cdf4f..72bc3b286d20 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c@@ -132,8 +132,6 @@ struct davinci_i2c_dev { #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; #endif - /* standard bus frequency */ - unsigned int bus_freq_hz; /* Chip has a ICPFUNC register */ bool has_pfunc; };
@@ -171,6 +169,8 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) u32 clkh; u32 clkl; u32 input_clock = clk_get_rate(dev->clk); + u32 bus_freq_hz = dev->adapter.clock_hz; + /* NOTE: I2C Clock divider programming info * As per I2C specs the following formulas provide prescaler
@@ -207,9 +207,9 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) if (device_is_compatible(dev->dev, "ti,keystone-i2c")) d = 6; - clk = (input_clock / (psc + 1)) / (dev->bus_freq_hz); + clk = (input_clock / (psc + 1)) / (bus_freq_hz); /* Avoid driving the bus too fast because of rounding errors above */ - if (input_clock / (psc + 1) / clk > dev->bus_freq_hz) + if (input_clock / (psc + 1) / clk > bus_freq_hz) clk++; /* * According to I2C-BUS Spec 2.1, in FAST-MODE LOW period should be at
@@ -267,7 +267,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG)); dev_dbg(dev->dev, "CLKH = %d\n", davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG)); - dev_dbg(dev->dev, "bus_freq_hz = %dHz\n", dev->bus_freq_hz); + dev_dbg(dev->dev, "bus_freq_hz = %dHz\n", dev->adapter.clock_hz); /* Take the I2C module out of reset: */
@@ -279,6 +279,27 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev) return 0; } +static int davinci_i2c_set_clk(struct i2c_adapter *adap, u32 clock_hz) +{ + struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); + + if (adap->clock_hz == clock_hz) + return 0; + + adap->clock_hz = clock_hz; + + /* put I2C into reset */ + davinci_i2c_reset_ctrl(dev, 0); + + /* compute clock dividers */ + i2c_davinci_calc_clk_dividers(dev); + + /* Take the I2C module out of reset: */ + davinci_i2c_reset_ctrl(dev, 1); + + return 0; +} + /* * This routine does i2c bus recovery by using i2c_generic_scl_recovery * which is provided by I2C Bus recovery infrastructure.
@@ -755,12 +776,13 @@ static int davinci_i2c_probe(struct platform_device *pdev) dev->dev = &pdev->dev; dev->irq = irq; platform_set_drvdata(pdev, dev); + adap = &dev->adapter; r = device_property_read_u32(&pdev->dev, "clock-frequency", &prop); if (r) prop = I2C_MAX_STANDARD_MODE_FREQ; - dev->bus_freq_hz = prop; + adap->clock_hz = prop; dev->has_pfunc = device_property_present(&pdev->dev, "ti,has-pfunc");
@@ -800,7 +822,6 @@ static int davinci_i2c_probe(struct platform_device *pdev) goto err_unuse_clocks; } - adap = &dev->adapter; i2c_set_adapdata(adap, dev); adap->owner = THIS_MODULE; adap->class = I2C_CLASS_DEPRECATED;
@@ -809,6 +830,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) adap->dev.parent = &pdev->dev; adap->timeout = DAVINCI_I2C_TIMEOUT; adap->dev.of_node = dev_of_node(&pdev->dev); + adap->set_clk_freq = davinci_i2c_set_clk; if (dev->has_pfunc) adap->bus_recovery_info = &davinci_i2c_scl_recovery_info;
--
2.53.0