From ddc84e010fc28fa553249395fb77773ff2a4e341 Mon Sep 17 00:00:00 2001 From: tao89959 <1036524114@qq.com> Date: Tue, 27 Jan 2026 10:02:03 +0800 Subject: [PATCH] loongson: i2c: support clock and bus freq from dts or acpi MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changelog: 龙芯i2c驱动支持输入时钟和总线时钟从dts或acpi获取 Signed-off-by: maoxiaochuan --- drivers/i2c/busses/i2c-ls2x.c | 66 +++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-ls2x.c b/drivers/i2c/busses/i2c-ls2x.c index b475dd27b..94ed16677 100644 --- a/drivers/i2c/busses/i2c-ls2x.c +++ b/drivers/i2c/busses/i2c-ls2x.c @@ -25,6 +25,7 @@ #include #include #include +#include /* I2C Registers */ #define I2C_LS2X_PRER_LO 0x0 /* Freq Division Low Byte Register */ @@ -68,6 +69,8 @@ struct ls2x_i2c_priv { void __iomem *base; struct i2c_timings i2c_t; struct completion cmd_complete; + u32 bus_frequency; + u64 clock_frequency; }; /* @@ -98,21 +101,16 @@ static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv) u16 val; struct i2c_timings *t = &priv->i2c_t; struct device *dev = priv->adapter.dev.parent; - u32 acpi_speed = i2c_acpi_find_bus_speed(dev); i2c_parse_fw_timings(dev, t, false); - if (acpi_speed || t->bus_freq_hz) - t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed); - else - t->bus_freq_hz = LS2X_I2C_FREQ_STD; - + t->bus_freq_hz = priv->bus_frequency; /* * According to the chip manual, we can only access the registers as bytes, * otherwise the high bits will be truncated. * So set the I2C frequency with a sequential writeb() instead of writew(). */ - val = LS2X_I2C_PCLK_FREQ / (5 * t->bus_freq_hz) - 1; + 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); } @@ -284,6 +282,55 @@ static const struct i2c_algorithm ls2x_i2c_algo = { .functionality = ls2x_i2c_func, }; +static void clock_frequency_get(struct platform_device *pdev, struct device *dev, struct ls2x_i2c_priv *priv) +{ + int err; + u32 clk; + struct clk *clk_unit; + + if (!(device_property_read_u32(dev, "clock-frequency", &clk))) + priv->clock_frequency = clk; + else { + clk_unit = devm_clk_get(&pdev->dev, "i2c-clk"); + + if(IS_ERR(clk_unit)) + goto err_def; + + err = clk_prepare_enable(clk_unit); + if (err) + goto err_def; + + clk = clk_get_rate(clk_unit); + if (!clk) { + clk_disable_unprepare(clk_unit); + goto err_def; + } + + priv->clock_frequency = clk; + clk_unit = NULL; + return; +err_def: + pr_info("i2c-ls2x %s warning: cant get i2c input clock, default value 125000000", pdev->name); + priv->clock_frequency = 125000000; + clk_unit = NULL; + } +} + +static void bus_frequency_get(struct platform_device *pdev, struct device *dev, struct ls2x_i2c_priv *priv) +{ + u32 bus_freq; + + priv->bus_frequency = 0; + + if (!(device_property_read_u32(dev, "bus_freq", &bus_freq))) + priv->bus_frequency = bus_freq; + else + priv->bus_frequency = i2c_acpi_find_bus_speed(dev); + + if (!(priv->bus_frequency)) + priv->bus_frequency = 100000; // default 100KHz +} + static int ls2x_i2c_probe(struct platform_device *pdev) { int ret, irq; @@ -304,6 +351,11 @@ static int ls2x_i2c_probe(struct platform_device *pdev) if (irq < 0) return irq; + clock_frequency_get(pdev, dev, priv); + 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); + /* Add the i2c adapter */ adap = &priv->adapter; adap->retries = 5;