linux-sh.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH/RFC] i2c: rcar: Fix order of restart and clear status
@ 2015-02-15 14:43 Yoshihiro Kaneko
  2015-02-23 13:07 ` Wolfram Sang
  0 siblings, 1 reply; 8+ messages in thread
From: Yoshihiro Kaneko @ 2015-02-15 14:43 UTC (permalink / raw)
  To: linux-i2c; +Cc: Wolfram Sang, Simon Horman, Magnus Damm, linux-sh

From: Ryo Kataoka <ryo.kataoka.wt@renesas.com>

In case of repeated START condition, the restart has to be kicked
before clear status (MSR register). If it is kicked after clear status,
R-Car I2C may transfer data (TXD register) or receive data (RXD register)
instead of transferring slave address (MAR register).

Signed-off-by: Ryo Kataoka <ryo.kataoka.wt@renesas.com>
Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
---

This patch is based on i2c/for-next branch of Wolfram Sang's linux tree.

 drivers/i2c/busses/i2c-rcar.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index 71a6e07..96c349f 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -2,6 +2,7 @@
  * Driver for the Renesas RCar I2C unit
  *
  * Copyright (C) 2014 Wolfram Sang <wsa@sang-engineering.com>
+ * Copyright (C) 2013-2014 Renesas Electronics Corporation
  *
  * Copyright (C) 2012-14 Renesas Solutions Corp.
  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
@@ -99,6 +100,7 @@
 #define ID_DONE		(1 << 2)
 #define ID_ARBLOST	(1 << 3)
 #define ID_NACK		(1 << 4)
+#define ID_FIRST_MSG	(1 << 5)
 
 enum rcar_i2c_type {
 	I2C_RCAR_GEN1,
@@ -125,6 +127,7 @@ struct rcar_i2c_priv {
 #define rcar_i2c_is_recv(p)		((p)->msg->flags & I2C_M_RD)
 
 #define rcar_i2c_flags_set(p, f)	((p)->flags |= (f))
+#define rcar_i2c_flags_clr(p, f)	((p)->flags &= ~(f))
 #define rcar_i2c_flags_has(p, f)	((p)->flags & (f))
 
 #define LOOP_TIMEOUT	1024
@@ -257,8 +260,14 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
 	int read = !!rcar_i2c_is_recv(priv);
 
 	rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
-	rcar_i2c_write(priv, ICMSR, 0);
-	rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+	if (rcar_i2c_flags_has(priv, ID_FIRST_MSG)) {	/* start */
+		rcar_i2c_write(priv, ICMSR, 0);
+		rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+		rcar_i2c_flags_clr(priv, ID_FIRST_MSG);
+	} else {	/* restart */
+		rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
+		rcar_i2c_write(priv, ICMSR, 0);
+	}
 	rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND);
 }
 
@@ -524,6 +533,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 		priv->msg	= &msgs[i];
 		priv->pos	= 0;
 		priv->flags	= 0;
+		if (i = 0)
+			rcar_i2c_flags_set(priv, ID_FIRST_MSG);
 		if (i = num - 1)
 			rcar_i2c_flags_set(priv, ID_LAST_MSG);
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH/RFC] i2c: rcar: Fix order of restart and clear status
  2015-02-15 14:43 [PATCH/RFC] i2c: rcar: Fix order of restart and clear status Yoshihiro Kaneko
@ 2015-02-23 13:07 ` Wolfram Sang
  2015-03-04  4:08   ` Simon Horman
  0 siblings, 1 reply; 8+ messages in thread
From: Wolfram Sang @ 2015-02-23 13:07 UTC (permalink / raw)
  To: Yoshihiro Kaneko; +Cc: linux-i2c, Simon Horman, Magnus Damm, linux-sh

Hi,

On 2015-02-15 15:43, Yoshihiro Kaneko wrote:
> From: Ryo Kataoka <ryo.kataoka.wt@renesas.com>
>
> In case of repeated START condition, the restart has to be kicked
> before clear status (MSR register). If it is kicked after clear 
> status,
> R-Car I2C may transfer data (TXD register) or receive data (RXD 
> register)
> instead of transferring slave address (MAR register).
>
> Signed-off-by: Ryo Kataoka <ryo.kataoka.wt@renesas.com>
> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>

Thanks for the patch!

I wondered if we couldn't always kick the start/restart before clearing 
the status register?
I am not sure if this simulates the flaw accurately, but I inserted a 
udelay(500)
in the original code after clearing the status register. Then, I 
couldn't access
the audio codec on my Lager board anymore. By always first "kicking" 
and then
clearing, access was possible again. But as said, I am not sure if my 
scenario
matches yours. Have you considered to treat start and repeated start 
the same
and always kick the condition before clearing the status?

Kind regards,

    Wolfram

> ---
>
> This patch is based on i2c/for-next branch of Wolfram Sang's linux 
> tree.
>
>  drivers/i2c/busses/i2c-rcar.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i2c/busses/i2c-rcar.c 
> b/drivers/i2c/busses/i2c-rcar.c
> index 71a6e07..96c349f 100644
> --- a/drivers/i2c/busses/i2c-rcar.c
> +++ b/drivers/i2c/busses/i2c-rcar.c
> @@ -2,6 +2,7 @@
>   * Driver for the Renesas RCar I2C unit
>   *
>   * Copyright (C) 2014 Wolfram Sang <wsa@sang-engineering.com>
> + * Copyright (C) 2013-2014 Renesas Electronics Corporation
>   *
>   * Copyright (C) 2012-14 Renesas Solutions Corp.
>   * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> @@ -99,6 +100,7 @@
>  #define ID_DONE		(1 << 2)
>  #define ID_ARBLOST	(1 << 3)
>  #define ID_NACK		(1 << 4)
> +#define ID_FIRST_MSG	(1 << 5)
>
>  enum rcar_i2c_type {
>  	I2C_RCAR_GEN1,
> @@ -125,6 +127,7 @@ struct rcar_i2c_priv {
>  #define rcar_i2c_is_recv(p)		((p)->msg->flags & I2C_M_RD)
>
>  #define rcar_i2c_flags_set(p, f)	((p)->flags |= (f))
> +#define rcar_i2c_flags_clr(p, f)	((p)->flags &= ~(f))
>  #define rcar_i2c_flags_has(p, f)	((p)->flags & (f))
>
>  #define LOOP_TIMEOUT	1024
> @@ -257,8 +260,14 @@ static void rcar_i2c_prepare_msg(struct
> rcar_i2c_priv *priv)
>  	int read = !!rcar_i2c_is_recv(priv);
>
>  	rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
> -	rcar_i2c_write(priv, ICMSR, 0);
> -	rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
> +	if (rcar_i2c_flags_has(priv, ID_FIRST_MSG)) {	/* start */
> +		rcar_i2c_write(priv, ICMSR, 0);
> +		rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
> +		rcar_i2c_flags_clr(priv, ID_FIRST_MSG);
> +	} else {	/* restart */
> +		rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START);
> +		rcar_i2c_write(priv, ICMSR, 0);
> +	}
>  	rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND);
>  }
>
> @@ -524,6 +533,8 @@ static int rcar_i2c_master_xfer(struct 
> i2c_adapter *adap,
>  		priv->msg	= &msgs[i];
>  		priv->pos	= 0;
>  		priv->flags	= 0;
> +		if (i = 0)
> +			rcar_i2c_flags_set(priv, ID_FIRST_MSG);
>  		if (i = num - 1)
>  			rcar_i2c_flags_set(priv, ID_LAST_MSG);


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH/RFC] i2c: rcar: Fix order of restart and clear status
  2015-02-23 13:07 ` Wolfram Sang
@ 2015-03-04  4:08   ` Simon Horman
  2015-03-06 22:05     ` Wolfram Sang
  0 siblings, 1 reply; 8+ messages in thread
From: Simon Horman @ 2015-03-04  4:08 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: Yoshihiro Kaneko, linux-i2c, Magnus Damm, linux-sh

Hi Wolfram,

On Mon, Feb 23, 2015 at 02:07:18PM +0100, Wolfram Sang wrote:
> Hi,
> 
> On 2015-02-15 15:43, Yoshihiro Kaneko wrote:
> >From: Ryo Kataoka <ryo.kataoka.wt@renesas.com>
> >
> >In case of repeated START condition, the restart has to be kicked
> >before clear status (MSR register). If it is kicked after clear status,
> >R-Car I2C may transfer data (TXD register) or receive data (RXD register)
> >instead of transferring slave address (MAR register).
> >
> >Signed-off-by: Ryo Kataoka <ryo.kataoka.wt@renesas.com>
> >Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
> 
> Thanks for the patch!
> 
> I wondered if we couldn't always kick the start/restart before clearing
> the status register?

I asked Kataoka-san about this and his response was as follows:

If system(CPU) is busy, the driver can't clear the status register soon
after kicking start.

If sequence of first start is as follows, there is a problem.
Because H/W starts by 1.
But sequence of re-start is as follows, there is no problem.
Because H/W starts by 2.

  1. Issue START condition by ESG bit of ICMCR register.
                  <--- If there is too much time, H/W finish transmitting
                       and set status in status register.
  2. Clear interrupt status (ICMSR).
  3. Open interrupt mask.
  4. Wait interrupt.
                  <--- If status is cleared, interrupt does not occur.

> I am not sure if this simulates the flaw accurately, but I inserted a
> udelay(500) in the original code after clearing the status register.
> Then, I couldn't access the audio codec on my Lager board anymore. By
> always first "kicking" and then clearing, access was possible again. But
> as said, I am not sure if my scenario matches yours. Have you considered
> to treat start and repeated start the same and always kick the condition
> before clearing the status?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH/RFC] i2c: rcar: Fix order of restart and clear status
  2015-03-04  4:08   ` Simon Horman
@ 2015-03-06 22:05     ` Wolfram Sang
  2015-03-07 10:33       ` Wolfram Sang
  0 siblings, 1 reply; 8+ messages in thread
From: Wolfram Sang @ 2015-03-06 22:05 UTC (permalink / raw)
  To: Simon Horman; +Cc: Yoshihiro Kaneko, linux-i2c, Magnus Damm, linux-sh

[-- Attachment #1: Type: text/plain, Size: 823 bytes --]


> I asked Kataoka-san about this and his response was as follows:

Thanks, Simon!

> If system(CPU) is busy, the driver can't clear the status register soon
> after kicking start.
> 
> If sequence of first start is as follows, there is a problem.
> Because H/W starts by 1.
> But sequence of re-start is as follows, there is no problem.
> Because H/W starts by 2.
> 
>   1. Issue START condition by ESG bit of ICMCR register.
>                   <--- If there is too much time, H/W finish transmitting
>                        and set status in status register.
>   2. Clear interrupt status (ICMSR).
>   3. Open interrupt mask.
>   4. Wait interrupt.
>                   <--- If status is cleared, interrupt does not occur.

I understand. I'll add this explanation to the patch and apply it soon.


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH/RFC] i2c: rcar: Fix order of restart and clear status
  2015-03-06 22:05     ` Wolfram Sang
@ 2015-03-07 10:33       ` Wolfram Sang
  2015-03-27 13:10         ` Wolfram Sang
  0 siblings, 1 reply; 8+ messages in thread
From: Wolfram Sang @ 2015-03-07 10:33 UTC (permalink / raw)
  To: Simon Horman; +Cc: Yoshihiro Kaneko, linux-i2c, Magnus Damm, linux-sh

[-- Attachment #1: Type: text/plain, Size: 1143 bytes --]

On Fri, Mar 06, 2015 at 11:05:31PM +0100, Wolfram Sang wrote:
> 
> > I asked Kataoka-san about this and his response was as follows:
> 
> Thanks, Simon!
> 
> > If system(CPU) is busy, the driver can't clear the status register soon
> > after kicking start.
> > 
> > If sequence of first start is as follows, there is a problem.
> > Because H/W starts by 1.
> > But sequence of re-start is as follows, there is no problem.
> > Because H/W starts by 2.
> > 
> >   1. Issue START condition by ESG bit of ICMCR register.
> >                   <--- If there is too much time, H/W finish transmitting
> >                        and set status in status register.
> >   2. Clear interrupt status (ICMSR).
> >   3. Open interrupt mask.
> >   4. Wait interrupt.
> >                   <--- If status is cleared, interrupt does not occur.
> 
> I understand. I'll add this explanation to the patch and apply it soon.

Sorry, another question came up while applying:

How can this interruption happen? The function is called in a
spin_lock_irqsave protected area. Is this an RT_PREEMPT related issue?
Am I missing something?


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH/RFC] i2c: rcar: Fix order of restart and clear status
  2015-03-07 10:33       ` Wolfram Sang
@ 2015-03-27 13:10         ` Wolfram Sang
  2015-03-30  0:15           ` Simon Horman
  0 siblings, 1 reply; 8+ messages in thread
From: Wolfram Sang @ 2015-03-27 13:10 UTC (permalink / raw)
  To: Simon Horman
  Cc: Yoshihiro Kaneko, linux-i2c-u79uwXL29TY76Z2rM5mHXA, Magnus Damm,
	linux-sh-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 1327 bytes --]

On Sat, Mar 07, 2015 at 11:33:49AM +0100, Wolfram Sang wrote:
> On Fri, Mar 06, 2015 at 11:05:31PM +0100, Wolfram Sang wrote:
> > 
> > > I asked Kataoka-san about this and his response was as follows:
> > 
> > Thanks, Simon!
> > 
> > > If system(CPU) is busy, the driver can't clear the status register soon
> > > after kicking start.
> > > 
> > > If sequence of first start is as follows, there is a problem.
> > > Because H/W starts by 1.
> > > But sequence of re-start is as follows, there is no problem.
> > > Because H/W starts by 2.
> > > 
> > >   1. Issue START condition by ESG bit of ICMCR register.
> > >                   <--- If there is too much time, H/W finish transmitting
> > >                        and set status in status register.
> > >   2. Clear interrupt status (ICMSR).
> > >   3. Open interrupt mask.
> > >   4. Wait interrupt.
> > >                   <--- If status is cleared, interrupt does not occur.
> > 
> > I understand. I'll add this explanation to the patch and apply it soon.
> 
> Sorry, another question came up while applying:
> 
> How can this interruption happen? The function is called in a
> spin_lock_irqsave protected area. Is this an RT_PREEMPT related issue?
> Am I missing something?

Hi,

any news on this one?

Kind regards,

   Wolfram


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH/RFC] i2c: rcar: Fix order of restart and clear status
  2015-03-27 13:10         ` Wolfram Sang
@ 2015-03-30  0:15           ` Simon Horman
  2015-05-18  6:04             ` Simon Horman
  0 siblings, 1 reply; 8+ messages in thread
From: Simon Horman @ 2015-03-30  0:15 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: Yoshihiro Kaneko, linux-i2c-u79uwXL29TY76Z2rM5mHXA, Magnus Damm,
	linux-sh-u79uwXL29TY76Z2rM5mHXA

On Fri, Mar 27, 2015 at 02:10:45PM +0100, Wolfram Sang wrote:
> On Sat, Mar 07, 2015 at 11:33:49AM +0100, Wolfram Sang wrote:
> > On Fri, Mar 06, 2015 at 11:05:31PM +0100, Wolfram Sang wrote:
> > > 
> > > > I asked Kataoka-san about this and his response was as follows:
> > > 
> > > Thanks, Simon!
> > > 
> > > > If system(CPU) is busy, the driver can't clear the status register soon
> > > > after kicking start.
> > > > 
> > > > If sequence of first start is as follows, there is a problem.
> > > > Because H/W starts by 1.
> > > > But sequence of re-start is as follows, there is no problem.
> > > > Because H/W starts by 2.
> > > > 
> > > >   1. Issue START condition by ESG bit of ICMCR register.
> > > >                   <--- If there is too much time, H/W finish transmitting
> > > >                        and set status in status register.
> > > >   2. Clear interrupt status (ICMSR).
> > > >   3. Open interrupt mask.
> > > >   4. Wait interrupt.
> > > >                   <--- If status is cleared, interrupt does not occur.
> > > 
> > > I understand. I'll add this explanation to the patch and apply it soon.
> > 
> > Sorry, another question came up while applying:
> > 
> > How can this interruption happen? The function is called in a
> > spin_lock_irqsave protected area. Is this an RT_PREEMPT related issue?
> > Am I missing something?
> 
> Hi,
> 
> any news on this one?

Sorry, I seem to have dropped the ball here. I've (finally) forwarded
your question on to the BSP team.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH/RFC] i2c: rcar: Fix order of restart and clear status
  2015-03-30  0:15           ` Simon Horman
@ 2015-05-18  6:04             ` Simon Horman
  0 siblings, 0 replies; 8+ messages in thread
From: Simon Horman @ 2015-05-18  6:04 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: Yoshihiro Kaneko, linux-i2c, Magnus Damm, linux-sh

Hi Wolfram,

On Mon, Mar 30, 2015 at 09:15:30AM +0900, Simon Horman wrote:
> On Fri, Mar 27, 2015 at 02:10:45PM +0100, Wolfram Sang wrote:
> > On Sat, Mar 07, 2015 at 11:33:49AM +0100, Wolfram Sang wrote:
> > > On Fri, Mar 06, 2015 at 11:05:31PM +0100, Wolfram Sang wrote:
> > > > 
> > > > > I asked Kataoka-san about this and his response was as follows:
> > > > 
> > > > Thanks, Simon!
> > > > 
> > > > > If system(CPU) is busy, the driver can't clear the status register soon
> > > > > after kicking start.
> > > > > 
> > > > > If sequence of first start is as follows, there is a problem.
> > > > > Because H/W starts by 1.
> > > > > But sequence of re-start is as follows, there is no problem.
> > > > > Because H/W starts by 2.
> > > > > 
> > > > >   1. Issue START condition by ESG bit of ICMCR register.
> > > > >                   <--- If there is too much time, H/W finish transmitting
> > > > >                        and set status in status register.
> > > > >   2. Clear interrupt status (ICMSR).
> > > > >   3. Open interrupt mask.
> > > > >   4. Wait interrupt.
> > > > >                   <--- If status is cleared, interrupt does not occur.
> > > > 
> > > > I understand. I'll add this explanation to the patch and apply it soon.
> > > 
> > > Sorry, another question came up while applying:
> > > 
> > > How can this interruption happen? The function is called in a
> > > spin_lock_irqsave protected area. Is this an RT_PREEMPT related issue?
> > > Am I missing something?
> > 
> > Hi,
> > 
> > any news on this one?
> 
> Sorry, I seem to have dropped the ball here. I've (finally) forwarded
> your question on to the BSP team.

Thanks for your patience, I have a response from the BSP team:

rcar_i2c_start(), rcar_i2c_recv() and rcar_i2c_send() are called in a
spin_lock_irqsave protected area. Therefore, interruption and preemption
doesn't happen in these functions.

But I think the driver should work fine even if the CPU is very slow.
If above sequence 1 and 2 are slow, and if H/W is fast, there is a problem.

Since H/W is kicked by sequence 1 then the driver waits the change of status,
sequence 2 should be executed before sequence 1 even if the CPU is fast enough.
I think it is a custom of software.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2015-05-18  6:04 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-15 14:43 [PATCH/RFC] i2c: rcar: Fix order of restart and clear status Yoshihiro Kaneko
2015-02-23 13:07 ` Wolfram Sang
2015-03-04  4:08   ` Simon Horman
2015-03-06 22:05     ` Wolfram Sang
2015-03-07 10:33       ` Wolfram Sang
2015-03-27 13:10         ` Wolfram Sang
2015-03-30  0:15           ` Simon Horman
2015-05-18  6:04             ` Simon Horman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).