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;