loongson: i2c: support multi bus clock generate mode

Changelog: 支持多种总线时钟生成模式
Signed-off-by: maoxiaochuan <maoxiaochuan@loongson.cn>
This commit is contained in:
tao89959
2026-08-24 14:17:10 +08:00
committed by maoxiaochuan
parent ddc84e010f
commit f2dac8034e
+30 -1
View File
@@ -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;