Re: [PATCH v8 2/2] i2c: ls2x: Add clocks property parsing and adjust bus speed
Hongliang Wang <[email protected]> Sat, 1 Aug 2026 17:12:29 +0800
| Newsgroups | dev.linux.lists.loongarch,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-i2c,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
Hi Ruoyao, On 2026/7/29 下午4:09, Xi Ruoyao wrote: > On Tue, 2026-07-21 at 20:26 +0800, Hongliang Wang wrote: >> The i2c-ls2x driver supports dts and acpi parameter passing. >> >> In dts, uses clock framework, by parsing clocks property to >> get i2c bus reference clock, and define the div of reference >> clock by device data. >> >> In acpi, by passing clocks property to describe i2c bus reference >> clock and clock-div property to describe the div of reference clock. >> >> Based on i2c bus reference clock(clock_a), i2c bus speed(clock_s) >> and div, calculate the prcescale of i2c divider register. The >> calculation formula is >> >> prcescale = (clock_a*10)/(div*clock_s)-1 >> >> Reviewed-by: Huacai Chen<[email protected]> >> Cc:[email protected] >> Signed-off-by: Hongliang Wang<[email protected]> > This resolves the jittery touchpad input on the EAECIS NL60R laptop. > > Tested-by: Xi Ruoyao<[email protected]> Thank you for testing! >> --- >> drivers/i2c/busses/i2c-ls2x.c | 40 ++++++++++++++++++++++++++++++++--- >> 1 file changed, 37 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/i2c/busses/i2c-ls2x.c b/drivers/i2c/busses/i2c-ls2x.c >> index b475dd27b7af..25f8301ae14f 100644 >> --- a/drivers/i2c/busses/i2c-ls2x.c >> +++ b/drivers/i2c/busses/i2c-ls2x.c >> @@ -12,6 +12,7 @@ >> >> #include <linux/bitfield.h> >> #include <linux/bits.h> >> +#include <linux/clk.h> >> #include <linux/completion.h> >> #include <linux/device.h> >> #include <linux/iopoll.h> >> @@ -63,11 +64,19 @@ >> /* The default bus frequency, which is an empirical value */ >> #define LS2X_I2C_FREQ_STD (33 * HZ_PER_KHZ) >> >> +/* The div of i2c reference clock on LS2K0500/2K1000/2K2000 */ >> +#define LS2X_I2C_2K_CLOCK_DIV 40 >> + >> +/* The div of i2c reference clock on LS7A1000/7A2000 */ >> +#define LS2X_I2C_7A_CLOCK_DIV 50 >> + >> struct ls2x_i2c_priv { >> struct i2c_adapter adapter; >> void __iomem *base; >> struct i2c_timings i2c_t; >> struct completion cmd_complete; >> + unsigned int div; >> + unsigned int pclk; >> }; >> >> /* >> @@ -107,12 +116,13 @@ static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv) >> else >> t->bus_freq_hz = LS2X_I2C_FREQ_STD; >> >> + val = (priv->pclk * 10) / (priv->div * t->bus_freq_hz) - 1; >> + >> /* >> * 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; >> 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); >> } >> @@ -287,6 +297,7 @@ static const struct i2c_algorithm ls2x_i2c_algo = { >> static int ls2x_i2c_probe(struct platform_device *pdev) >> { >> int ret, irq; >> + struct clk *clk; >> struct i2c_adapter *adap; >> struct ls2x_i2c_priv *priv; >> struct device *dev = &pdev->dev; >> @@ -304,6 +315,29 @@ static int ls2x_i2c_probe(struct platform_device *pdev) >> if (irq < 0) >> return irq; >> >> + if (dev_of_node(dev)) { >> + clk = devm_clk_get_optional_enabled(dev, NULL); >> + if (IS_ERR(clk)) >> + return PTR_ERR(clk); >> + if (clk) >> + priv->pclk = clk_get_rate(clk); >> + else >> + priv->pclk = LS2X_I2C_PCLK_FREQ; >> + >> + priv->div = (unsigned long)device_get_match_data(dev); >> + if (!priv->div) >> + priv->div = LS2X_I2C_2K_CLOCK_DIV; >> + } else { >> + /* clocks and clock-div are only ACPI properties. */ >> + ret = device_property_read_u32(dev, "clocks", &priv->pclk); >> + if (ret) >> + priv->pclk = LS2X_I2C_PCLK_FREQ; >> + >> + ret = device_property_read_u32(dev, "clock-div", &priv->div); >> + if (ret || !priv->div) >> + priv->div = LS2X_I2C_7A_CLOCK_DIV; >> + } >> + >> /* Add the i2c adapter */ >> adap = &priv->adapter; >> adap->retries = 5; >> @@ -349,8 +383,8 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ls2x_i2c_pm_ops, >> ls2x_i2c_suspend, ls2x_i2c_resume, NULL); >> >> static const struct of_device_id ls2x_i2c_id_table[] = { >> - { .compatible = "loongson,ls2k-i2c" }, >> - { .compatible = "loongson,ls7a-i2c" }, >> + { .compatible = "loongson,ls2k-i2c", .data = (void *)LS2X_I2C_2K_CLOCK_DIV, }, >> + { .compatible = "loongson,ls7a-i2c", .data = (void *)LS2X_I2C_7A_CLOCK_DIV, }, >> { /* sentinel */ } >> }; >> MODULE_DEVICE_TABLE(of, ls2x_i2c_id_table); Best regards, Hongliang Wang