All of lore.kernel.org
 help / color / mirror / Atom feed
From: Aurelien Jarno <aurelien@aurel32.net>
To: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Cc: Andi Shyti <andi.shyti@kernel.org>, Yixun Lan <dlan@gentoo.org>,
	Alex Elder <elder@riscstar.com>,
	Troy Mitchell <troymitchell988@gmail.com>,
	linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-riscv@lists.infradead.org, spacemit@lists.linux.dev
Subject: Re: [PATCH 5/6] i2c: spacemit: ensure SDA is released after bus reset
Date: Mon, 22 Sep 2025 22:56:10 +0200	[thread overview]
Message-ID: <aNG36jhaWN-mtgMm@aurel32.net> (raw)
In-Reply-To: <20250827-k1-i2c-atomic-v1-5-e59bea02d680@linux.spacemit.com>

On 2025-08-27 15:39, Troy Mitchell wrote:
> After performing a conditional bus reset, the controller must ensure
> that the SDA line is actually released.
> 
> Previously, the reset routine only performed a single check,
> which could leave the bus in a locked state in some situations.
> 
> This patch introduces a loop that toggles the reset cycle and issues
> a reset request up to SPACEMIT_BUS_RESET_CLK_CNT_MAX times, checking
> SDA after each attempt. If SDA is released before the maximum count,
> the function returns early. Otherwise, a warning is emitted.
> 
> This change improves bus recovery reliability.
> 
> Fixes: 5ea558473fa31 ("i2c: spacemit: add support for SpacemiT K1 SoC")
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  drivers/i2c/busses/i2c-k1.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/i2c/busses/i2c-k1.c b/drivers/i2c/busses/i2c-k1.c
> index 4d78ee7b6929ee43771e500d4f85d9e55e68b221..d2c0d20d19ba73baa8b2e9a6acb02b2cc3b7243f 100644
> --- a/drivers/i2c/busses/i2c-k1.c
> +++ b/drivers/i2c/busses/i2c-k1.c
> @@ -3,6 +3,7 @@
>   * Copyright (C) 2024-2025 Troy Mitchell <troymitchell988@gmail.com>
>   */
>  
> +#include <linux/bitfield.h>
>   #include <linux/clk.h>
>   #include <linux/i2c.h>
>   #include <linux/iopoll.h>
> @@ -26,7 +27,8 @@
>  #define SPACEMIT_CR_MODE_FAST    BIT(8)		/* bus mode (master operation) */
>  /* Bit 9 is reserved */
>  #define SPACEMIT_CR_UR           BIT(10)	/* unit reset */
> -/* Bits 11-12 are reserved */
> +#define SPACEMIT_CR_RSTREQ	 BIT(11)	/* i2c bus reset request */
> +/* Bit 12 is reserved */
>  #define SPACEMIT_CR_SCLE         BIT(13)	/* master clock enable */
>  #define SPACEMIT_CR_IUE          BIT(14)	/* unit enable */
>  /* Bits 15-17 are reserved */
> @@ -78,6 +80,7 @@
>  					SPACEMIT_SR_ALD)
>  
>  #define SPACEMIT_RCR_SDA_GLITCH_NOFIX		BIT(7)		/* bypass the SDA glitch fix */
> +#define SPACEMIT_RCR_FIELD_RST_CYC		GENMASK(3, 0)	/* bypass the SDA glitch fix */

The comment here seems wrong, datasheet says "The cycles of SCL during 
bus reset."

>  /* SPACEMIT_IBMR register fields */
>  #define SPACEMIT_BMR_SDA         BIT(0)		/* SDA line level */
> @@ -91,6 +94,8 @@
>  
>  #define SPACEMIT_SR_ERR	(SPACEMIT_SR_BED | SPACEMIT_SR_RXOV | SPACEMIT_SR_ALD)
>  
> +#define SPACEMIT_BUS_RESET_CLK_CNT_MAX		9
> +
>  enum spacemit_i2c_state {
>  	SPACEMIT_STATE_IDLE,
>  	SPACEMIT_STATE_START,
> @@ -163,6 +168,7 @@ static int spacemit_i2c_handle_err(struct spacemit_i2c_dev *i2c)
>  static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c)
>  {
>  	u32 status;
> +	u8 clk_cnt;
>  
>  	/* if bus is locked, reset unit. 0: locked */
>  	status = readl(i2c->base + SPACEMIT_IBMR);
> @@ -172,6 +178,21 @@ static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c)
>  	spacemit_i2c_reset(i2c);
>  	usleep_range(10, 20);
>  
> +	for (clk_cnt = 0; clk_cnt < SPACEMIT_BUS_RESET_CLK_CNT_MAX; clk_cnt++) {
> +		status = readl(i2c->base + SPACEMIT_IBMR);
> +		if (status & SPACEMIT_BMR_SDA)
> +			break;

What about just adding the return here instead of checking clk_cnt 
below?

> +
> +		/* There's nothing left to save here, we are about to exit */
> +		writel(FIELD_PREP(SPACEMIT_RCR_FIELD_RST_CYC, 1),
> +		       i2c->base + SPACEMIT_IRCR);
> +		writel(SPACEMIT_CR_RSTREQ, i2c->base + SPACEMIT_ICR);
> +		usleep_range(20, 30);
> +	}
> +
> +	if (clk_cnt < SPACEMIT_BUS_RESET_CLK_CNT_MAX)
> +		return;
> +
>  	/* check sda again here */
>  	status = readl(i2c->base + SPACEMIT_IBMR);
>  	if (!(status & SPACEMIT_BMR_SDA))

Once we have exited the loop, I am not sure we should check SDA once 
more, maybe just display the error message directly.

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                     http://aurel32.net

WARNING: multiple messages have this Message-ID (diff)
From: Aurelien Jarno <aurelien@aurel32.net>
To: Troy Mitchell <troy.mitchell@linux.spacemit.com>
Cc: Andi Shyti <andi.shyti@kernel.org>, Yixun Lan <dlan@gentoo.org>,
	Alex Elder <elder@riscstar.com>,
	Troy Mitchell <troymitchell988@gmail.com>,
	linux-i2c@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-riscv@lists.infradead.org, spacemit@lists.linux.dev
Subject: Re: [PATCH 5/6] i2c: spacemit: ensure SDA is released after bus reset
Date: Mon, 22 Sep 2025 22:56:10 +0200	[thread overview]
Message-ID: <aNG36jhaWN-mtgMm@aurel32.net> (raw)
In-Reply-To: <20250827-k1-i2c-atomic-v1-5-e59bea02d680@linux.spacemit.com>

On 2025-08-27 15:39, Troy Mitchell wrote:
> After performing a conditional bus reset, the controller must ensure
> that the SDA line is actually released.
> 
> Previously, the reset routine only performed a single check,
> which could leave the bus in a locked state in some situations.
> 
> This patch introduces a loop that toggles the reset cycle and issues
> a reset request up to SPACEMIT_BUS_RESET_CLK_CNT_MAX times, checking
> SDA after each attempt. If SDA is released before the maximum count,
> the function returns early. Otherwise, a warning is emitted.
> 
> This change improves bus recovery reliability.
> 
> Fixes: 5ea558473fa31 ("i2c: spacemit: add support for SpacemiT K1 SoC")
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  drivers/i2c/busses/i2c-k1.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/i2c/busses/i2c-k1.c b/drivers/i2c/busses/i2c-k1.c
> index 4d78ee7b6929ee43771e500d4f85d9e55e68b221..d2c0d20d19ba73baa8b2e9a6acb02b2cc3b7243f 100644
> --- a/drivers/i2c/busses/i2c-k1.c
> +++ b/drivers/i2c/busses/i2c-k1.c
> @@ -3,6 +3,7 @@
>   * Copyright (C) 2024-2025 Troy Mitchell <troymitchell988@gmail.com>
>   */
>  
> +#include <linux/bitfield.h>
>   #include <linux/clk.h>
>   #include <linux/i2c.h>
>   #include <linux/iopoll.h>
> @@ -26,7 +27,8 @@
>  #define SPACEMIT_CR_MODE_FAST    BIT(8)		/* bus mode (master operation) */
>  /* Bit 9 is reserved */
>  #define SPACEMIT_CR_UR           BIT(10)	/* unit reset */
> -/* Bits 11-12 are reserved */
> +#define SPACEMIT_CR_RSTREQ	 BIT(11)	/* i2c bus reset request */
> +/* Bit 12 is reserved */
>  #define SPACEMIT_CR_SCLE         BIT(13)	/* master clock enable */
>  #define SPACEMIT_CR_IUE          BIT(14)	/* unit enable */
>  /* Bits 15-17 are reserved */
> @@ -78,6 +80,7 @@
>  					SPACEMIT_SR_ALD)
>  
>  #define SPACEMIT_RCR_SDA_GLITCH_NOFIX		BIT(7)		/* bypass the SDA glitch fix */
> +#define SPACEMIT_RCR_FIELD_RST_CYC		GENMASK(3, 0)	/* bypass the SDA glitch fix */

The comment here seems wrong, datasheet says "The cycles of SCL during 
bus reset."

>  /* SPACEMIT_IBMR register fields */
>  #define SPACEMIT_BMR_SDA         BIT(0)		/* SDA line level */
> @@ -91,6 +94,8 @@
>  
>  #define SPACEMIT_SR_ERR	(SPACEMIT_SR_BED | SPACEMIT_SR_RXOV | SPACEMIT_SR_ALD)
>  
> +#define SPACEMIT_BUS_RESET_CLK_CNT_MAX		9
> +
>  enum spacemit_i2c_state {
>  	SPACEMIT_STATE_IDLE,
>  	SPACEMIT_STATE_START,
> @@ -163,6 +168,7 @@ static int spacemit_i2c_handle_err(struct spacemit_i2c_dev *i2c)
>  static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c)
>  {
>  	u32 status;
> +	u8 clk_cnt;
>  
>  	/* if bus is locked, reset unit. 0: locked */
>  	status = readl(i2c->base + SPACEMIT_IBMR);
> @@ -172,6 +178,21 @@ static void spacemit_i2c_conditionally_reset_bus(struct spacemit_i2c_dev *i2c)
>  	spacemit_i2c_reset(i2c);
>  	usleep_range(10, 20);
>  
> +	for (clk_cnt = 0; clk_cnt < SPACEMIT_BUS_RESET_CLK_CNT_MAX; clk_cnt++) {
> +		status = readl(i2c->base + SPACEMIT_IBMR);
> +		if (status & SPACEMIT_BMR_SDA)
> +			break;

What about just adding the return here instead of checking clk_cnt 
below?

> +
> +		/* There's nothing left to save here, we are about to exit */
> +		writel(FIELD_PREP(SPACEMIT_RCR_FIELD_RST_CYC, 1),
> +		       i2c->base + SPACEMIT_IRCR);
> +		writel(SPACEMIT_CR_RSTREQ, i2c->base + SPACEMIT_ICR);
> +		usleep_range(20, 30);
> +	}
> +
> +	if (clk_cnt < SPACEMIT_BUS_RESET_CLK_CNT_MAX)
> +		return;
> +
>  	/* check sda again here */
>  	status = readl(i2c->base + SPACEMIT_IBMR);
>  	if (!(status & SPACEMIT_BMR_SDA))

Once we have exited the loop, I am not sure we should check SDA once 
more, maybe just display the error message directly.

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                     http://aurel32.net

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

  reply	other threads:[~2025-09-22 20:56 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-27  7:39 [PATCH 0/6] i2c: spacemit: fix and introduce pio Troy Mitchell
2025-08-27  7:39 ` Troy Mitchell
2025-08-27  7:39 ` [PATCH 1/6] i2c: spacemit: ensure bus release check runs when wait_bus_idle() fails Troy Mitchell
2025-08-27  7:39   ` Troy Mitchell
2025-09-22 20:55   ` Aurelien Jarno
2025-09-22 20:55     ` Aurelien Jarno
2025-08-27  7:39 ` [PATCH 2/6] i2c: spacemit: remove stop function to avoid bus error Troy Mitchell
2025-08-27  7:39   ` Troy Mitchell
2025-09-22 20:55   ` Aurelien Jarno
2025-09-22 20:55     ` Aurelien Jarno
2025-09-23  0:44     ` Troy Mitchell
2025-09-23  0:44       ` Troy Mitchell
2025-08-27  7:39 ` [PATCH 3/6] i2c: spacemit: disable SDA glitch fix to avoid restart delay Troy Mitchell
2025-08-27  7:39   ` Troy Mitchell
2025-08-27  9:32   ` Troy Mitchell
2025-08-27  9:32     ` Troy Mitchell
2025-09-22 20:56   ` Aurelien Jarno
2025-09-22 20:56     ` Aurelien Jarno
2025-09-23  0:46     ` Troy Mitchell
2025-09-23  0:46       ` Troy Mitchell
2025-08-27  7:39 ` [PATCH 4/6] i2c: spacemit: check SDA instead of SCL after bus reset Troy Mitchell
2025-08-27  7:39   ` Troy Mitchell
2025-09-22 20:56   ` Aurelien Jarno
2025-09-22 20:56     ` Aurelien Jarno
2025-09-23  0:47     ` Troy Mitchell
2025-09-23  0:47       ` Troy Mitchell
2025-08-27  7:39 ` [PATCH 5/6] i2c: spacemit: ensure SDA is released " Troy Mitchell
2025-08-27  7:39   ` Troy Mitchell
2025-09-22 20:56   ` Aurelien Jarno [this message]
2025-09-22 20:56     ` Aurelien Jarno
2025-09-23  0:49     ` Troy Mitchell
2025-09-23  0:49       ` Troy Mitchell
2025-08-27  7:39 ` [PATCH 6/6] i2c: spacemit: introduce pio for k1 Troy Mitchell
2025-08-27  7:39   ` Troy Mitchell
2025-09-22 20:56   ` Aurelien Jarno
2025-09-22 20:56     ` Aurelien Jarno
2025-09-23  1:14     ` Troy Mitchell
2025-09-23  1:14       ` Troy Mitchell
2025-09-23  1:21       ` Troy Mitchell
2025-09-23  1:21         ` Troy Mitchell
2025-09-22 20:55 ` [PATCH 0/6] i2c: spacemit: fix and introduce pio Aurelien Jarno
2025-09-22 20:55   ` Aurelien Jarno
2025-09-23  1:24   ` Troy Mitchell
2025-09-23  1:24     ` Troy Mitchell

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=aNG36jhaWN-mtgMm@aurel32.net \
    --to=aurelien@aurel32.net \
    --cc=andi.shyti@kernel.org \
    --cc=dlan@gentoo.org \
    --cc=elder@riscstar.com \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=spacemit@lists.linux.dev \
    --cc=troy.mitchell@linux.spacemit.com \
    --cc=troymitchell988@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.