mirror of
https://gitee.com/open-loongarch/linux-6.12.git
synced 2026-10-26 04:57:12 +08:00
loongson: i2c: support multi bus clock generate mode
Changelog: 支持多种总线时钟生成模式 Signed-off-by: maoxiaochuan <maoxiaochuan@loongson.cn>
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user