diff mbox series

[PATCHv2,2/2] i2c: stm32f7: do not set the STOP condition on error

Message ID 20220815145211.31342-2-jorge@foundries.io
State Superseded
Delegated to: Patrice Chotard
Headers show
Series [PATCHv2,1/2] i2c: stm32f7: fix clearing the control register | expand

Commit Message

Jorge Ramirez-Ortiz, Foundries Aug. 15, 2022, 2:52 p.m. UTC
Sending the stop condition without waiting for transfer complete
has been found to lock the bus (BUSY) when NACKF is raised.

Tested accessing the NXP SE05X I2C device.
https://www.nxp.com/docs/en/application-note/AN12399.pdf

Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io>
Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@foundries.io>
---
 drivers/i2c/stm32f7_i2c.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

Patrice CHOTARD Aug. 25, 2022, 8:52 a.m. UTC | #1
+Alain

Alain, can you have a look a this patch and give your feedback on it.

On my side i tested it on stm32mp157c-ev1 and stm32mp157c-dk2, i didn't see any regression
but i prefer to get expert feedback ;-)

Thanks
Patrice

On 8/15/22 16:52, Jorge Ramirez-Ortiz wrote:
> Sending the stop condition without waiting for transfer complete
> has been found to lock the bus (BUSY) when NACKF is raised.
> 
> Tested accessing the NXP SE05X I2C device.
> https://www.nxp.com/docs/en/application-note/AN12399.pdf
> 
> Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io>
> Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@foundries.io>
> ---
>  drivers/i2c/stm32f7_i2c.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
> index 3a727e68ac..14827e5cec 100644
> --- a/drivers/i2c/stm32f7_i2c.c
> +++ b/drivers/i2c/stm32f7_i2c.c
> @@ -485,9 +485,11 @@ static int stm32_i2c_message_xfer(struct stm32_i2c_priv *i2c_priv,
>  		}
>  	}
>  
> -	/* End of transfer, send stop condition */
> -	mask = STM32_I2C_CR2_STOP;
> -	setbits_le32(&regs->cr2, mask);
> +	if (!ret) {
> +		/* End of transfer, send stop condition */
> +		mask = STM32_I2C_CR2_STOP;
> +		setbits_le32(&regs->cr2, mask);
> +	}
>  
>  	return stm32_i2c_check_end_of_message(i2c_priv);
>  }
Patrice CHOTARD Aug. 25, 2022, 1:36 p.m. UTC | #2
+Alain (with the correct email address ;-))

Alain, can you have a look a this patch and give your feedback on it.

On my side i tested it on stm32mp157c-ev1 and stm32mp157c-dk2, i didn't see any regression
but i prefer to get expert feedback 

Thanks
Patrice

On 8/15/22 16:52, Jorge Ramirez-Ortiz wrote:
> Sending the stop condition without waiting for transfer complete
> has been found to lock the bus (BUSY) when NACKF is raised.
> 
> Tested accessing the NXP SE05X I2C device.
> https://www.nxp.com/docs/en/application-note/AN12399.pdf
> 
> Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io>
> Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@foundries.io>
> ---
>  drivers/i2c/stm32f7_i2c.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
> index 3a727e68ac..14827e5cec 100644
> --- a/drivers/i2c/stm32f7_i2c.c
> +++ b/drivers/i2c/stm32f7_i2c.c
> @@ -485,9 +485,11 @@ static int stm32_i2c_message_xfer(struct stm32_i2c_priv *i2c_priv,
>  		}
>  	}
>  
> -	/* End of transfer, send stop condition */
> -	mask = STM32_I2C_CR2_STOP;
> -	setbits_le32(&regs->cr2, mask);
> +	if (!ret) {
> +		/* End of transfer, send stop condition */
> +		mask = STM32_I2C_CR2_STOP;
> +		setbits_le32(&regs->cr2, mask);
> +	}
>  
>  	return stm32_i2c_check_end_of_message(i2c_priv);
>  }
Alain Volmat Sept. 7, 2022, 9:20 a.m. UTC | #3
Hi,

I confirm that a fix is necessary regarding this setting of the stop
condition.  As a matter of fact, the controller is already sending
the stop condition in case of NACK so there is no need to send the
stop condition.
However, this fix is not enough since the nack could be detected
few lines above 

	if (status & (STM32_I2C_ISR_NACKF | STM32_I2C_ISR_ERRORS))
		break;

and in this case the current check would not catch it.

I propose to set the STOP condition upon handling of the transfer
complete.

I've put this fix within a small 3 patches series that I'm going to
send, could you check it to confirm this fixes the issue ?

Regards,
Alain

On Thu, Aug 25, 2022 at 03:36:36PM +0200, Patrice CHOTARD wrote:
> +Alain (with the correct email address ;-))
> 
> Alain, can you have a look a this patch and give your feedback on it.
> 
> On my side i tested it on stm32mp157c-ev1 and stm32mp157c-dk2, i didn't see any regression
> but i prefer to get expert feedback 
> 
> Thanks
> Patrice
> 
> On 8/15/22 16:52, Jorge Ramirez-Ortiz wrote:
> > Sending the stop condition without waiting for transfer complete
> > has been found to lock the bus (BUSY) when NACKF is raised.
> > 
> > Tested accessing the NXP SE05X I2C device.
> > https://www.nxp.com/docs/en/application-note/AN12399.pdf
> > 
> > Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io>
> > Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@foundries.io>
> > ---
> >  drivers/i2c/stm32f7_i2c.c | 8 +++++---
> >  1 file changed, 5 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
> > index 3a727e68ac..14827e5cec 100644
> > --- a/drivers/i2c/stm32f7_i2c.c
> > +++ b/drivers/i2c/stm32f7_i2c.c
> > @@ -485,9 +485,11 @@ static int stm32_i2c_message_xfer(struct stm32_i2c_priv *i2c_priv,
> >  		}
> >  	}
> >  
> > -	/* End of transfer, send stop condition */
> > -	mask = STM32_I2C_CR2_STOP;
> > -	setbits_le32(&regs->cr2, mask);
> > +	if (!ret) {
> > +		/* End of transfer, send stop condition */
> > +		mask = STM32_I2C_CR2_STOP;
> > +		setbits_le32(&regs->cr2, mask);
> > +	}
> >  
> >  	return stm32_i2c_check_end_of_message(i2c_priv);
> >  }
Patrick DELAUNAY Sept. 9, 2022, 9:35 a.m. UTC | #4
Hi,

On 9/7/22 11:20, Alain Volmat wrote:
> Hi,
>
> I confirm that a fix is necessary regarding this setting of the stop
> condition.  As a matter of fact, the controller is already sending
> the stop condition in case of NACK so there is no need to send the
> stop condition.
> However, this fix is not enough since the nack could be detected
> few lines above
>
> 	if (status & (STM32_I2C_ISR_NACKF | STM32_I2C_ISR_ERRORS))
> 		break;
>
> and in this case the current check would not catch it.
>
> I propose to set the STOP condition upon handling of the transfer
> complete.
>
> I've put this fix within a small 3 patches series that I'm going to
> send, could you check it to confirm this fixes the issue ?
>
> Regards,
> Alain
>
> On Thu, Aug 25, 2022 at 03:36:36PM +0200, Patrice CHOTARD wrote:
>> +Alain (with the correct email address ;-))
>>
>> Alain, can you have a look a this patch and give your feedback on it.
>>
>> On my side i tested it on stm32mp157c-ev1 and stm32mp157c-dk2, i didn't see any regression
>> but i prefer to get expert feedback
>>
>> Thanks
>> Patrice
>>
>> On 8/15/22 16:52, Jorge Ramirez-Ortiz wrote:
>>> Sending the stop condition without waiting for transfer complete
>>> has been found to lock the bus (BUSY) when NACKF is raised.
>>>
>>> Tested accessing the NXP SE05X I2C device.
>>> https://www.nxp.com/docs/en/application-note/AN12399.pdf
>>>
>>> Signed-off-by: Jorge Ramirez-Ortiz <jorge@foundries.io>
>>> Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@foundries.io>
>>> ---
>>>   drivers/i2c/stm32f7_i2c.c | 8 +++++---
>>>   1 file changed, 5 insertions(+), 3 deletions(-)
>>>

For reference, this patch is superseded by Alain Volmat patch:

[v2,1/3] i2c: stm32: fix comment and remove unused AUTOEND bit

http://patchwork.ozlabs.org/project/uboot/patch/20220908105934.1764482-2-alain.volmat@foss.st.com/

in the serie "i2c: stm32: cleanup & stop handling fix"

http://patchwork.ozlabs.org/project/uboot/list/?series=317443&state=*


Regards


Patrick
diff mbox series

Patch

diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
index 3a727e68ac..14827e5cec 100644
--- a/drivers/i2c/stm32f7_i2c.c
+++ b/drivers/i2c/stm32f7_i2c.c
@@ -485,9 +485,11 @@  static int stm32_i2c_message_xfer(struct stm32_i2c_priv *i2c_priv,
 		}
 	}
 
-	/* End of transfer, send stop condition */
-	mask = STM32_I2C_CR2_STOP;
-	setbits_le32(&regs->cr2, mask);
+	if (!ret) {
+		/* End of transfer, send stop condition */
+		mask = STM32_I2C_CR2_STOP;
+		setbits_le32(&regs->cr2, mask);
+	}
 
 	return stm32_i2c_check_end_of_message(i2c_priv);
 }