Linux I2C development
 help / color / mirror / Atom feed
From: Hongliang Wang <wanghongliang@loongson.cn>
To: Huacai Chen <chenhuacai@kernel.org>
Cc: Binbin Zhou <zhoubinbin@loongson.cn>,
	Andi Shyti <andi.shyti@kernel.org>, Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzk+dt@kernel.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Wolfram Sang <wsa+renesas@sang-engineering.com>,
	linux-i2c@vger.kernel.org, devicetree@vger.kernel.org,
	loongarch@lists.linux.dev
Subject: Re: [PATCH v2] i2c: ls2x: Add clocks property parsing and adjust bus speed
Date: Sat, 9 May 2026 11:06:22 +0800	[thread overview]
Message-ID: <e1a77c4d-b347-e378-ead8-b641560d8bc7@loongson.cn> (raw)
In-Reply-To: <CAAhV-H46sOPPAoH31DijWYK+v5fEzgq7ZVucCuoyRTwTgUHYxA@mail.gmail.com>

Hi, Huacai,

On 2026/5/8 上午11:06, Huacai Chen wrote:
> Hi, Hongliang,
>
> On Thu, May 7, 2026 at 4:11 PM Hongliang Wang <wanghongliang@loongson.cn> wrote:
>> From: wanghongliang <wanghongliang@loongson.cn>
>>
>> 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 factor by device data.
>> In acpi, by passing clocks property to describe i2c bus reference
>> clock and clock-div property to describe factor.
>> Based on i2c bus reference clock(clock_a), i2c bus speed(clock_s)
>> and factor, calculate the prcescale of i2c divider register.
>> The calculation formula is
>> prcescale = clock_a/(factor*clock_s)-1
>>
>> Signed-off-by: wanghongliang <wanghongliang@loongson.cn>
>> ---
>>   drivers/i2c/busses/i2c-ls2x.c | 42 ++++++++++++++++++++++++++++++++---
>>   1 file changed, 39 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-ls2x.c b/drivers/i2c/busses/i2c-ls2x.c
>> index b475dd27b7af..7db91e7a5d78 100644
>> --- a/drivers/i2c/busses/i2c-ls2x.c
>> +++ b/drivers/i2c/busses/i2c-ls2x.c
>> @@ -13,6 +13,7 @@
>>   #include <linux/bitfield.h>
>>   #include <linux/bits.h>
>>   #include <linux/completion.h>
>> +#include <linux/clk.h>
> This should be before completion.h.
>
OK.
>>   #include <linux/device.h>
>>   #include <linux/iopoll.h>
>>   #include <linux/i2c.h>
>> @@ -63,11 +64,16 @@
>>   /* The default bus frequency, which is an empirical value */
>>   #define LS2X_I2C_FREQ_STD      (33 * HZ_PER_KHZ)
>>
>> +struct ls2x_i2c_chip_data {
>> +       unsigned int    factor;
>> +};
>> +
>>   struct ls2x_i2c_priv {
>>          struct i2c_adapter      adapter;
>>          void __iomem            *base;
>>          struct i2c_timings      i2c_t;
>>          struct completion       cmd_complete;
>> +       const struct ls2x_i2c_chip_data *chip_data;
> Use "unsigned int    factor" directly?
>
OK,  I will adjust it
>>   };
>>
>>   /*
>> @@ -96,6 +102,8 @@ static irqreturn_t ls2x_i2c_isr(int this_irq, void *dev_id)
>>   static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv)
>>   {
>>          u16 val;
>> +       u32 pclk, factor;
> factor or div? If factor is better, then rename clock-div to
> clock-factor; if div is better, then rename factor to div.
div is better,  I will adjust it
>> +       struct clk *clk;
>>          struct i2c_timings *t = &priv->i2c_t;
>>          struct device *dev = priv->adapter.dev.parent;
>>          u32 acpi_speed = i2c_acpi_find_bus_speed(dev);
>> @@ -107,12 +115,30 @@ static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv)
>>          else
>>                  t->bus_freq_hz = LS2X_I2C_FREQ_STD;
>>
>> +       if (dev_of_node(dev)) {
>> +               clk = devm_clk_get_optional_enabled(dev, NULL);
>> +               if (IS_ERR(clk) || !clk)
>> +                       pclk = LS2X_I2C_PCLK_FREQ;
>> +               else
>> +                       pclk = clk_get_rate(clk);
> Reverse the "if & else" so the default case will be the last one, this
> is also the same as the ACPI case below.
OK
> Huacai
>
>> +
>> +               factor = priv->chip_data->factor;
>> +
>> +               val = (pclk * 10) / (factor * t->bus_freq_hz) - 1;
>> +       } else {
>> +               if (!device_property_read_u32(dev, "clocks", &pclk) &&
>> +                   !device_property_read_u32(dev, "clock-div", &factor) &&
>> +                   factor != 0)
>> +                       val = (pclk * 10) / (factor * t->bus_freq_hz) - 1;
>> +               else
>> +                       val = LS2X_I2C_PCLK_FREQ / (5 * 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);
>>   }
>> @@ -295,6 +321,8 @@ static int ls2x_i2c_probe(struct platform_device *pdev)
>>          if (!priv)
>>                  return -ENOMEM;
>>
>> +       priv->chip_data = device_get_match_data(dev);
>> +
>>          /* Map hardware registers */
>>          priv->base = devm_platform_ioremap_resource(pdev, 0);
>>          if (IS_ERR(priv->base))
>> @@ -348,9 +376,17 @@ static int ls2x_i2c_resume(struct device *dev)
>>   static DEFINE_RUNTIME_DEV_PM_OPS(ls2x_i2c_pm_ops,
>>                                   ls2x_i2c_suspend, ls2x_i2c_resume, NULL);
>>
>> +static const struct ls2x_i2c_chip_data ls2x_i2c_2k_data = {
>> +       .factor = 4,
>> +};
>> +
>> +static const struct ls2x_i2c_chip_data ls2x_i2c_7a_data = {
>> +       .factor = 5,
>> +};
>> +
>>   static const struct of_device_id ls2x_i2c_id_table[] = {
>> -       { .compatible = "loongson,ls2k-i2c" },
>> -       { .compatible = "loongson,ls7a-i2c" },
>> +       { .compatible = "loongson,ls2k-i2c", .data = &ls2x_i2c_2k_data, },
>> +       { .compatible = "loongson,ls7a-i2c", .data = &ls2x_i2c_7a_data, },
>>          { /* sentinel */ }
>>   };
>>   MODULE_DEVICE_TABLE(of, ls2x_i2c_id_table);
>> --
>> 2.47.2
>>
>>
Best regards,
Hongliang Wang


  reply	other threads:[~2026-05-09  3:07 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-07  8:10 [PATCH v2] dt-bindings: i2c: ls2x-i2c: Add clocks and clock-frequency properties Hongliang Wang
2026-05-07  8:10 ` [PATCH v2] i2c: ls2x: Add clocks property parsing and adjust bus speed Hongliang Wang
2026-05-08  3:06   ` Huacai Chen
2026-05-09  3:06     ` Hongliang Wang [this message]
2026-05-07 17:29 ` [PATCH v2] dt-bindings: i2c: ls2x-i2c: Add clocks and clock-frequency properties Conor Dooley
2026-05-08  1:29   ` Hongliang Wang
2026-05-08 14:56     ` Conor Dooley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=e1a77c4d-b347-e378-ead8-b641560d8bc7@loongson.cn \
    --to=wanghongliang@loongson.cn \
    --cc=andi.shyti@kernel.org \
    --cc=chenhuacai@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=krzk+dt@kernel.org \
    --cc=linux-i2c@vger.kernel.org \
    --cc=loongarch@lists.linux.dev \
    --cc=robh@kernel.org \
    --cc=wsa+renesas@sang-engineering.com \
    --cc=zhoubinbin@loongson.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox