From f2dac8034e28bc0d21da2fb33c8a3c266f4d03fd Mon Sep 17 00:00:00 2001 From: tao89959 <1036524114@qq.com> Date: Tue, 27 Jan 2026 10:25:08 +0800 Subject: [PATCH] loongson: i2c: support multi bus clock generate mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changelog: 支持多种总线时钟生成模式 Signed-off-by: maoxiaochuan --- drivers/i2c/busses/i2c-ls2x.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-ls2x.c b/drivers/i2c/busses/i2c-ls2x.c index 94ed16677..47faffdc8 100644 --- a/drivers/i2c/busses/i2c-ls2x.c +++ b/drivers/i2c/busses/i2c-ls2x.c @@ -64,7 +64,12 @@ /* The default bus frequency, which is an empirical value */ #define LS2X_I2C_FREQ_STD (33 * HZ_PER_KHZ) +#define I2C_BUS_FREQ_DIV_MODE_D4 (0) +#define I2C_BUS_FREQ_DIV_MODE_D5 (1) +#define I2C_BUS_FREQ_DIV_MODE_INVAILD (I2C_BUS_FREQ_DIV_MODE_D5 + 1) + struct ls2x_i2c_priv { + u8 i2c_bus_freq_div_mode; struct i2c_adapter adapter; void __iomem *base; struct i2c_timings i2c_t; @@ -110,7 +115,11 @@ static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv) * otherwise the high bits will be truncated. * So set the I2C frequency with a sequential writeb() instead of writew(). */ - val = priv->clock_frequency / (5 * t->bus_freq_hz) - 1; + if (priv->i2c_bus_freq_div_mode == I2C_BUS_FREQ_DIV_MODE_D4) + val = priv->clock_frequency / (4 * t->bus_freq_hz) - 1; + else if ((priv->i2c_bus_freq_div_mode == I2C_BUS_FREQ_DIV_MODE_D5)) + val = priv->clock_frequency / (5 * t->bus_freq_hz) - 1; + writeb(FIELD_GET(GENMASK(7, 0), val), priv->base + I2C_LS2X_PRER_LO); writeb(FIELD_GET(GENMASK(15, 8), val), priv->base + I2C_LS2X_PRER_HI); } @@ -331,6 +340,24 @@ static void bus_frequency_get(struct platform_device *pdev, struct device *dev, priv->bus_frequency = 100000; // default 100KHz } +static void bus_frequency_div_mode_get(struct platform_device *pdev, struct device *dev, struct ls2x_i2c_priv *priv) +{ + u32 mode; + + priv->i2c_bus_freq_div_mode = 255; + + if (!(device_property_read_u32(dev, "bus_div_mode", &mode))) + priv->i2c_bus_freq_div_mode = mode; + else + priv->i2c_bus_freq_div_mode = I2C_BUS_FREQ_DIV_MODE_D5; + + if (mode >= I2C_BUS_FREQ_DIV_MODE_INVAILD) + priv->i2c_bus_freq_div_mode = I2C_BUS_FREQ_DIV_MODE_D4; + + if (priv->i2c_bus_freq_div_mode == 255) + priv->i2c_bus_freq_div_mode = I2C_BUS_FREQ_DIV_MODE_D4; +} + static int ls2x_i2c_probe(struct platform_device *pdev) { int ret, irq; @@ -355,6 +382,8 @@ static int ls2x_i2c_probe(struct platform_device *pdev) dev_info(dev, "i2c dev input clock is %lld Hz\n", priv->clock_frequency); bus_frequency_get(pdev, dev, priv); dev_info(dev, "i2c dev bus clock is %d Hz\n", priv->bus_frequency); + bus_frequency_div_mode_get(pdev, dev, priv); + dev_info(dev, "i2c dev bus clock generate mode is %d\n", priv->i2c_bus_freq_div_mode); /* Add the i2c adapter */ adap = &priv->adapter;