public inbox for linux-i2c@vger.kernel.org
 help / color / mirror / Atom feed
From: Adrian Huang <adrianhuang0701@gmail.com>
To: Jarkko Nikula <jarkko.nikula@linux.intel.com>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Mika Westerberg <mika.westerberg@linux.intel.com>,
	Jan Dabros <jsd@semihalf.com>
Cc: Andi Shyti <andi.shyti@kernel.org>,
	linux-i2c@vger.kernel.org, Adrian Huang <ahuang12@lenovo.com>,
	Dong Wang <wangdong28@lenovo.com>
Subject: [PATCH 1/1] i2c: designware: Fix wrong setting for {ss,fs}_{h,l}cnt registers
Date: Wed, 17 Jul 2024 14:59:17 +0800	[thread overview]
Message-ID: <20240717065917.18399-1-ahuang12@lenovo.com> (raw)

From: Adrian Huang <ahuang12@lenovo.com>

When disabling CONFIG_X86_AMD_PLATFORM_DEVICE option, the driver
'drivers/acpi/acpi_apd.c' won't be compiled. This leads to a situation
where BMC (Baseboard Management Controller) cannot retrieve the memory
temperature via the i2c interface after i2c DW driver is loaded. Note
that BMC can retrieve the memory temperature before booting into OS.

[Debugging Detail]
  1. dev->pclk and dev->clk are NULL when calling devm_clk_get_optional()
     in dw_i2c_plat_probe().

  2. The callings of i2c_dw_scl_hcnt() in i2c_dw_set_timings_master()
     return 65528 (-8 in integer format) or 65533 (-3 in integer format).
     The following log shows SS's HCNT/LCNT:

       i2c_designware AMDI0010:01: Standard Mode HCNT:LCNT = 65533:65535

  3. The callings of i2c_dw_scl_lcnt() in i2c_dw_set_timings_master()
     return 65535 (-1 in integer format). The following log shows SS's
     HCNT/LCNT:

       i2c_designware AMDI0010:01: Fast Mode HCNT:LCNT = 65533:65535

  4. i2c_dw_init_master() configures the register IC_SS_SCL_HCNT with
     the value 65533. However, the DW i2c databook mentioned the value
     cannot be higher than 65525. Quote from the DW i2c databook:

       NOTE: This register must not be programmed to a value higher than
             65525, because DW_apb_i2c uses a 16-bit counter to flag an
             I2C bus idle condition when this counter reaches a value of
             IC_SS_SCL_HCNT + 10.

  5. Since ss_hcnt, ss_lcnt, fs_hcnt, and fs_lcnt are the invalid
     values, we should not write the corresponding registers.

Fix the issue by returning 0 if ic_clk is 0 in i2c_dw_scl_{h,l}cnt().
Then, do not write the corresponding registers if those values are 0.

Signed-off-by: Adrian Huang <ahuang12@lenovo.com>
Reported-by: Dong Wang <wangdong28@lenovo.com>
Tested-by: Dong Wang <wangdong28@lenovo.com>
---
 drivers/i2c/busses/i2c-designware-common.c |  6 ++++++
 drivers/i2c/busses/i2c-designware-master.c | 16 ++++++++++------
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index e8a688d04aee..6c7e331c32cb 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -334,6 +334,9 @@ EXPORT_SYMBOL_GPL(i2c_dw_adjust_bus_speed);
 
 u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
 {
+	if (!ic_clk)
+		return 0;
+
 	/*
 	 * DesignWare I2C core doesn't seem to have solid strategy to meet
 	 * the tHD;STA timing spec.  Configuring _HCNT based on tHIGH spec
@@ -374,6 +377,9 @@ u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
 
 u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
 {
+	if (!ic_clk)
+		return 0;
+
 	/*
 	 * Conditional expression:
 	 *
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index c7e56002809a..68c523d9d10b 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -184,13 +184,17 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
 	/* Disable the adapter */
 	__i2c_dw_disable(dev);
 
-	/* Write standard speed timing parameters */
-	regmap_write(dev->map, DW_IC_SS_SCL_HCNT, dev->ss_hcnt);
-	regmap_write(dev->map, DW_IC_SS_SCL_LCNT, dev->ss_lcnt);
+	if (dev->ss_hcnt && dev->ss_lcnt) {
+		/* Write standard speed timing parameters */
+		regmap_write(dev->map, DW_IC_SS_SCL_HCNT, dev->ss_hcnt);
+		regmap_write(dev->map, DW_IC_SS_SCL_LCNT, dev->ss_lcnt);
+	}
 
-	/* Write fast mode/fast mode plus timing parameters */
-	regmap_write(dev->map, DW_IC_FS_SCL_HCNT, dev->fs_hcnt);
-	regmap_write(dev->map, DW_IC_FS_SCL_LCNT, dev->fs_lcnt);
+	if (dev->fs_hcnt && dev->fs_lcnt) {
+		/* Write fast mode/fast mode plus timing parameters */
+		regmap_write(dev->map, DW_IC_FS_SCL_HCNT, dev->fs_hcnt);
+		regmap_write(dev->map, DW_IC_FS_SCL_LCNT, dev->fs_lcnt);
+	}
 
 	/* Write high speed timing parameters if supported */
 	if (dev->hs_hcnt && dev->hs_lcnt) {
-- 
2.34.1


             reply	other threads:[~2024-07-17  6:59 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-17  6:59 Adrian Huang [this message]
2024-08-01 14:10 ` [PATCH 1/1] i2c: designware: Fix wrong setting for {ss,fs}_{h,l}cnt registers Jarkko Nikula
2024-08-02 13:06   ` Huang Adrian

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=20240717065917.18399-1-ahuang12@lenovo.com \
    --to=adrianhuang0701@gmail.com \
    --cc=ahuang12@lenovo.com \
    --cc=andi.shyti@kernel.org \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=jarkko.nikula@linux.intel.com \
    --cc=jsd@semihalf.com \
    --cc=linux-i2c@vger.kernel.org \
    --cc=mika.westerberg@linux.intel.com \
    --cc=wangdong28@lenovo.com \
    /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