Skip to contentSkip to conversation

i2c-mpc: work around missing-9th-clock-pulse bug

PATCH Applied Domen Puncer 4 participants 13 messages Jul 9, 2007 – Aug 8, 2007

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 i2c-mpc: work around missing-9th-clock-pulse bug

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 based boards by Matthias and me.

---
 drivers/i2c/busses/i2c-mpc.c |   19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
drivers/i2c/busses/i2c-mpc.c +19 -0
Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================
@@ -74,6 +74,20 @@ static irqreturn_t mpc_i2c_isr(int irq, 
 	return IRQ_HANDLED;
 }
 
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+	writeccr(i2c, 0);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+}
+
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 {
 	unsigned long orig_jiffies = jiffies;
@@ -153,6 +167,9 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
 	writeccr(i2c, CCR_MEN);
+	mb();
+	writeccr(i2c, 0);
+	mb();
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +262,8 @@ static int mpc_xfer(struct i2c_adapter *
 		}
 		if (time_after(jiffies, orig_jiffies + HZ)) {
 			pr_debug("I2C: timeout\n");
+			if (readb(i2c->base + MPC_I2C_SR) == (CSR_MCF | CSR_MBB | CSR_RXAK))
+				mpc_i2c_fixup(i2c);
 			return -EIO;
 		}
 		schedule();
#1 lore raw
Quoted 10 lines · Domen Puncer

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 based boards by Matthias and me.

Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================

drivers/i2c/busses/i2c-mpc.c static void mpc_i2c_start(struct mpc_i2c · line 173

Quoted 7 lines
drivers/i2c/busses/i2c-mpc.c +3 -0
@@ -153,6 +167,9 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
        writeccr(i2c, CCR_MEN);
+       mb();
+       writeccr(i2c, 0);
+       mb();
 }

Are the mb() calls necessary? The writeccr path includes eieio; is that not sufficient?

Cheers,
g.

Signature · 4 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
[email protected]
(403) 399-0195
#2 lore raw
Quoted 6 lines · Grant Likely
Quoted 5 lines · Domen Puncer

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 based boards by Matthias and me.

Quoted 15 lines

drivers/i2c/busses/i2c-mpc.c static void mpc_i2c_start(struct mpc_i2c · line 173

Quoted 12 lines

Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================

drivers/i2c/busses/i2c-mpc.c +3 -0
@@ -153,6 +167,9 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
       writeccr(i2c, CCR_MEN);
+       mb();
+       writeccr(i2c, 0);
+       mb();
 }

Are the mb() calls necessary? The writeccr path includes eieio; is that not sufficient?

Right, v2:

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 boards by Matthias and me.

---
 drivers/i2c/busses/i2c-mpc.c |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)
drivers/i2c/busses/i2c-mpc.c +17 -0
Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================
@@ -74,6 +74,20 @@ static irqreturn_t mpc_i2c_isr(int irq, 
 	return IRQ_HANDLED;
 }
 
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+	writeccr(i2c, 0);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+}
+
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 {
 	unsigned long orig_jiffies = jiffies;
@@ -153,6 +167,7 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
 	writeccr(i2c, CCR_MEN);
+	writeccr(i2c, 0);
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +260,8 @@ static int mpc_xfer(struct i2c_adapter *
 		}
 		if (time_after(jiffies, orig_jiffies + HZ)) {
 			pr_debug("I2C: timeout\n");
+			if (readb(i2c->base + MPC_I2C_SR) == (CSR_MCF | CSR_MBB | CSR_RXAK))
+				mpc_i2c_fixup(i2c);
 			return -EIO;
 		}
 		schedule();
Acked-by
#3 lore raw
Quoted 26 lines · Domen Puncer
Quoted 6 lines · Grant Likely
Quoted 5 lines · Domen Puncer

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 based boards by Matthias and me.

Quoted 15 lines

drivers/i2c/busses/i2c-mpc.c static void mpc_i2c_start(struct mpc_i2c · line 173

Quoted 12 lines

Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================

drivers/i2c/busses/i2c-mpc.c +3 -0
@@ -153,6 +167,9 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
       writeccr(i2c, CCR_MEN);
+       mb();
+       writeccr(i2c, 0);
+       mb();
 }

Are the mb() calls necessary? The writeccr path includes eieio; is that not sufficient?

Right, v2:

Quoted 7 lines

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 boards by Matthias and me.

Looks good to me,

Quoted 48 lines
---
 drivers/i2c/busses/i2c-mpc.c |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)

Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================

drivers/i2c/busses/i2c-mpc.c +17 -0
@@ -74,6 +74,20 @@ static irqreturn_t mpc_i2c_isr(int irq,
        return IRQ_HANDLED;
 }
 
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+       writeccr(i2c, 0);
+       udelay(30);
+       writeccr(i2c, CCR_MEN);
+       udelay(30);
+       writeccr(i2c, CCR_MSTA | CCR_MTX);
+       udelay(30);
+       writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+       udelay(30);
+       writeccr(i2c, CCR_MEN);
+       udelay(30);
+}
+
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 {
        unsigned long orig_jiffies = jiffies;
@@ -153,6 +167,7 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
        writeccr(i2c, CCR_MEN);
+       writeccr(i2c, 0);
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +260,8 @@ static int mpc_xfer(struct i2c_adapter *
                }
                if (time_after(jiffies, orig_jiffies + HZ)) {
                        pr_debug("I2C: timeout\n");
+                       if (readb(i2c->base + MPC_I2C_SR) == (CSR_MCF | CSR_MBB | CSR_RXAK))
+                               mpc_i2c_fixup(i2c);
                        return -EIO;
                }
                schedule();
Signature · 4 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
[email protected]
(403) 399-0195
#4 lore raw

Hi Grant, hi Domen,

Quoted 7 lines · Grant Likely
Quoted 6 lines · Domen Puncer

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 boards by Matthias and me.

Quoted 5 lines
Quoted 1 line

Looks good to me,

OK, I will take this patch, but I'd like you to add a comment before mpc_i2c_fixup() explaining what exactly the problem is and how it is worked around. Otherwise it's a bit obscure what is going on.

I guess you want this patch in 2.6.23-rc1?

Quoted 47 lines
Quoted 47 lines
---
 drivers/i2c/busses/i2c-mpc.c |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)

Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================

drivers/i2c/busses/i2c-mpc.c +17 -0
@@ -74,6 +74,20 @@ static irqreturn_t mpc_i2c_isr(int irq,
        return IRQ_HANDLED;
 }
 
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+       writeccr(i2c, 0);
+       udelay(30);
+       writeccr(i2c, CCR_MEN);
+       udelay(30);
+       writeccr(i2c, CCR_MSTA | CCR_MTX);
+       udelay(30);
+       writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+       udelay(30);
+       writeccr(i2c, CCR_MEN);
+       udelay(30);
+}
+
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 {
        unsigned long orig_jiffies = jiffies;
@@ -153,6 +167,7 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
        writeccr(i2c, CCR_MEN);
+       writeccr(i2c, 0);
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +260,8 @@ static int mpc_xfer(struct i2c_adapter *
                }
                if (time_after(jiffies, orig_jiffies + HZ)) {
                        pr_debug("I2C: timeout\n");
+                       if (readb(i2c->base + MPC_I2C_SR) == (CSR_MCF | CSR_MBB | CSR_RXAK))
+                               mpc_i2c_fixup(i2c);
                        return -EIO;
                }
                schedule();
Signature · 1 line
Jean Delvare
#5 lore raw
Quoted 12 lines · Jean Delvare

Hi Grant, hi Domen,

Quoted 9 lines · Grant Likely
Quoted 7 lines · Domen Puncer

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 boards by Matthias and me.

Quoted 7 lines
Quoted 3 lines

Looks good to me,

OK, I will take this patch, but I'd like you to add a comment before mpc_i2c_fixup() explaining what exactly the problem is and how it is worked around. Otherwise it's a bit obscure what is going on.

OK.

Quoted 2 lines

I guess you want this patch in 2.6.23-rc1?

Yes.

So... v3:
<----------- cut ------------->

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 boards by Matthias Fechner and me.

---
 drivers/i2c/busses/i2c-mpc.c |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
drivers/i2c/busses/i2c-mpc.c +21 -0
Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================
@@ -74,6 +74,24 @@ static irqreturn_t mpc_i2c_isr(int irq, 
 	return IRQ_HANDLED;
 }
 
+/* Sometimes 9th clock pulse isn't generated, so slave doesn't release
+ * the bus.  Documented and suggested workaround on
+ * http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
+ */
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+	writeccr(i2c, 0);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+}
+
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 {
 	unsigned long orig_jiffies = jiffies;
@@ -153,6 +171,7 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
 	writeccr(i2c, CCR_MEN);
+	writeccr(i2c, 0);
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +264,8 @@ static int mpc_xfer(struct i2c_adapter *
 		}
 		if (time_after(jiffies, orig_jiffies + HZ)) {
 			pr_debug("I2C: timeout\n");
+			if (readb(i2c->base + MPC_I2C_SR) == (CSR_MCF | CSR_MBB | CSR_RXAK))
+				mpc_i2c_fixup(i2c);
 			return -EIO;
 		}
 		schedule();
#6 lore raw
Quoted 48 lines · Domen Puncer
Quoted 12 lines · Jean Delvare

Hi Grant, hi Domen,

Quoted 9 lines · Grant Likely
Quoted 7 lines · Domen Puncer

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 boards by Matthias and me.

Quoted 7 lines
Quoted 3 lines

Looks good to me,

OK, I will take this patch, but I'd like you to add a comment before mpc_i2c_fixup() explaining what exactly the problem is and how it is worked around. Otherwise it's a bit obscure what is going on.

OK.

Quoted 2 lines

I guess you want this patch in 2.6.23-rc1?

Yes.

So... v3:
<----------- cut ------------->

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 boards by Matthias Fechner and me.

---
 drivers/i2c/busses/i2c-mpc.c |   21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================

drivers/i2c/busses/i2c-mpc.c static irqreturn_t mpc_i2c_isr(int irq, · line 80

Quoted 7 lines
drivers/i2c/busses/i2c-mpc.c +4 -0
@@ -74,6 +74,24 @@ static irqreturn_t mpc_i2c_isr(int irq,
        return IRQ_HANDLED;
 }
 
+/* Sometimes 9th clock pulse isn't generated, so slave doesn't release
+ * the bus.  Documented and suggested workaround on
+ * http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
+ */

I don't think it's a great idea to use a link; You should copy the important parts into the .c file. Archives may not be forever, and links cannot be read when offline. If the text is too long for the middle of the C file; then put the documentation at the top right after the header block.

g.

Signature · 4 lines
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
[email protected]
(403) 399-0195
#7 lore raw
Quoted 2 lines · Grant Likely
Quoted 1 line · Domen Puncer

On 10/07/07 14:40 +0200, Jean Delvare wrote:

...

Quoted 10 lines
Quoted 4 lines

+/* Sometimes 9th clock pulse isn't generated, so slave doesn't release
+ * the bus. Documented and suggested workaround on
+ * http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
+ */

I don't think it's a great idea to use a link; You should copy the important parts into the .c file. Archives may not be forever, and links cannot be read when offline. If the text is too long for the middle of the C file; then put the documentation at the top right after the header block.

And v4:
<----------- cut ------------->

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 boards by Matthias Fechner and me.

---
 drivers/i2c/busses/i2c-mpc.c |   22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
drivers/i2c/busses/i2c-mpc.c +22 -0
Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================
@@ -74,6 +74,25 @@ static irqreturn_t mpc_i2c_isr(int irq, 
 	return IRQ_HANDLED;
 }
 
+/* Sometimes 9th clock pulse isn't generated, and slave doesn't release
+ * the bus, because it wants to send ACK.
+ * Following sequence of enabling/disabling and sending start/stop generates
+ * the pulse, so it's all OK.
+ */
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+	writeccr(i2c, 0);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+}
+
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 {
 	unsigned long orig_jiffies = jiffies;
@@ -153,6 +172,7 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
 	writeccr(i2c, CCR_MEN);
+	writeccr(i2c, 0);
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +265,8 @@ static int mpc_xfer(struct i2c_adapter *
 		}
 		if (time_after(jiffies, orig_jiffies + HZ)) {
 			pr_debug("I2C: timeout\n");
+			if (readb(i2c->base + MPC_I2C_SR) == (CSR_MCF | CSR_MBB | CSR_RXAK))
+				mpc_i2c_fixup(i2c);
 			return -EIO;
 		}
 		schedule();
Applied
#8 lore raw

Hi Domen,

Quoted 10 lines · Domen Puncer
Quoted 5 lines · Grant Likely

I don't think it's a great idea to use a link; You should copy the important parts into the .c file. Archives may not be forever, and links cannot be read when offline. If the text is too long for the middle of the C file; then put the documentation at the top right after the header block.

And v4:
<----------- cut ------------->

Quoted 7 lines

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 boards by Matthias Fechner and me.

Applied, thanks.

Signature · 1 line
Jean Delvare
#9 lore raw
In reply to Domen Puncer
Quoted 4 lines · Domen Puncer

Work around a problem reported on:
http://ozlabs.org/pipermail/linuxppc-embedded/2005-July/019038.html
Without this patch I2C on mpc5200 becomes unusable after a while. Tested on mpc5200 based boards by Matthias and me.

Domen, unfortunately, your suspicion, expressed on IRC, was right. It is this patch that breaks i2c on mpc8241 (linkstation). Reverting it fixes the problem. For reference, here's a rtc-debug log with this patch (linux-2.6 tree of 19.07):

rtc-rs5c372 0-0032: rs5c372_probe
rtc-rs5c372 0-0032: 52 28 21 (04) 19 07 07 (15), 04 00 6a, 08 00 3e; 00 20
rtc-rs5c372 0-0032: 28 21 04 (19) 07 07 15 (04), 00 6a 08, 00 3e 00; 20 52
rtc-rs5c372 0-0032: rs5c372_get_datetime: tm is secs=28, mins=21, hours=4, mday=7, mon=6, year=115, wday=1 rtc-rs5c372 0-0032: rs5c372b found, 24hr, driver version 0.5
rtc-rs5c372: dev (254:0)
rtc-rs5c372 0-0032: rtc core: registered rtc-rs5c372 as rtc0
rtc-rs5c372 0-0032: 21 04 19 (07) 07 15 04 (00), 6a 08 00, 3e 00 20; 52 28
rtc-rs5c372 0-0032: rs5c372_get_datetime: tm is secs=21, mins=4, hours=19, mday=7, mon=14, year=104, wday=7 rtc-rs5c372 0-0032: hctosys: unable to read the hardware clock

Let me know when you'll have any patches to test.

Thanks
Guennadi

Quoted 53 lines
---
 drivers/i2c/busses/i2c-mpc.c |   19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================

drivers/i2c/busses/i2c-mpc.c +19 -0
@@ -74,6 +74,20 @@ static irqreturn_t mpc_i2c_isr(int irq, 
 	return IRQ_HANDLED;
 }
 
+static void mpc_i2c_fixup(struct mpc_i2c *i2c)
+{
+	writeccr(i2c, 0);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX);
+	udelay(30);
+	writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN);
+	udelay(30);
+	writeccr(i2c, CCR_MEN);
+	udelay(30);
+}
+
 static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
 {
 	unsigned long orig_jiffies = jiffies;
@@ -153,6 +167,9 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
 	writeccr(i2c, CCR_MEN);
+	mb();
+	writeccr(i2c, 0);
+	mb();
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -245,6 +262,8 @@ static int mpc_xfer(struct i2c_adapter *
 		}
 		if (time_after(jiffies, orig_jiffies + HZ)) {
 			pr_debug("I2C: timeout\n");
+			if (readb(i2c->base + MPC_I2C_SR) == (CSR_MCF | CSR_MBB | CSR_RXAK))
+				mpc_i2c_fixup(i2c);
 			return -EIO;
 		}
 		schedule();
Quoted 5 lines

_______________________________________________
i2c mailing list
[email protected]
http://lists.lm-sensors.org/mailman/listinfo/i2c

---
Guennadi Liakhovetski

#10 lore raw

PATCH 1/1 i2c-mpc: don't disable I2C module on stop condition.

Disabling module on stop doesn't work on some CPUs (ie. mpc8241, as reported by Guennadi Liakhovetski), so remove that.

Disable I2C module on errors/interrupts to prevent it from locking up on mpc5200b.

---
Hi!

So I fixed i2c on one board, and broke it on another :-( This patch works on both Guennadi's and mine (hey, it might break a third one!).
Jean, can you please push this, if there are no objections and "doesn't work for me" reports.

Domen

 drivers/i2c/busses/i2c-mpc.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/i2c/busses/i2c-mpc.c +6 -3
Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================
@@ -105,6 +105,7 @@ static int i2c_wait(struct mpc_i2c *i2c,
 			schedule();
 			if (time_after(jiffies, orig_jiffies + timeout)) {
 				pr_debug("I2C: timeout\n");
+				writeccr(i2c, 0);
 				result = -EIO;
 				break;
 			}
@@ -116,10 +117,12 @@ static int i2c_wait(struct mpc_i2c *i2c,
 		result = wait_event_interruptible_timeout(i2c->queue,
 			(i2c->interrupt & CSR_MIF), timeout * HZ);
 
-		if (unlikely(result < 0))
+		if (unlikely(result < 0)) {
 			pr_debug("I2C: wait interrupted\n");
-		else if (unlikely(!(i2c->interrupt & CSR_MIF))) {
+			writeccr(i2c, 0);
+		} else if (unlikely(!(i2c->interrupt & CSR_MIF))) {
 			pr_debug("I2C: wait timeout\n");
+			writeccr(i2c, 0);
 			result = -ETIMEDOUT;
 		}
 
@@ -172,7 +175,6 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
 	writeccr(i2c, CCR_MEN);
-	writeccr(i2c, 0);
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -261,6 +263,7 @@ static int mpc_xfer(struct i2c_adapter *
 	while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
 		if (signal_pending(current)) {
 			pr_debug("I2C: Interrupted\n");
+			writeccr(i2c, 0);
 			return -EINTR;
 		}
 		if (time_after(jiffies, orig_jiffies + HZ)) {
Applied
#11 lore raw

Re: [PATCH] i2c-mpc: don't disable I2C module on stop condition.

Hi Domen,

Quoted 8 lines · Domen Puncer

Disabling module on stop doesn't work on some CPUs (ie. mpc8241, as reported by Guennadi Liakhovetski), so remove that.

Disable I2C module on errors/interrupts to prevent it from locking up on mpc5200b.

Quoted 8 lines

---
Hi!

So I fixed i2c on one board, and broke it on another :-( This patch works on both Guennadi's and mine (hey, it might break a third one!).
Jean, can you please push this, if there are no objections and "doesn't work for me" reports.

Queued for 2.6.23-rc3, thanks. Guennadi, can you please confirm that this patch fixes your problem?

Quoted 51 lines

Domen

 drivers/i2c/busses/i2c-mpc.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

Index: work-powerpc.git/drivers/i2c/busses/i2c-mpc.c
===================================================================

drivers/i2c/busses/i2c-mpc.c +6 -3
@@ -105,6 +105,7 @@ static int i2c_wait(struct mpc_i2c *i2c,
 			schedule();
 			if (time_after(jiffies, orig_jiffies + timeout)) {
 				pr_debug("I2C: timeout\n");
+				writeccr(i2c, 0);
 				result = -EIO;
 				break;
 			}
@@ -116,10 +117,12 @@ static int i2c_wait(struct mpc_i2c *i2c,
 		result = wait_event_interruptible_timeout(i2c->queue,
 			(i2c->interrupt & CSR_MIF), timeout * HZ);
 
-		if (unlikely(result < 0))
+		if (unlikely(result < 0)) {
 			pr_debug("I2C: wait interrupted\n");
-		else if (unlikely(!(i2c->interrupt & CSR_MIF))) {
+			writeccr(i2c, 0);
+		} else if (unlikely(!(i2c->interrupt & CSR_MIF))) {
 			pr_debug("I2C: wait timeout\n");
+			writeccr(i2c, 0);
 			result = -ETIMEDOUT;
 		}
 
@@ -172,7 +175,6 @@ static void mpc_i2c_start(struct mpc_i2c
 static void mpc_i2c_stop(struct mpc_i2c *i2c)
 {
 	writeccr(i2c, CCR_MEN);
-	writeccr(i2c, 0);
 }
 
 static int mpc_write(struct mpc_i2c *i2c, int target,
@@ -261,6 +263,7 @@ static int mpc_xfer(struct i2c_adapter *
 	while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) {
 		if (signal_pending(current)) {
 			pr_debug("I2C: Interrupted\n");
+			writeccr(i2c, 0);
 			return -EINTR;
 		}
 		if (time_after(jiffies, orig_jiffies + HZ)) {
Signature · 1 line
Jean Delvare
#12 lore raw

Re: [PATCH] i2c-mpc: don't disable I2C module on stop condition.

Quoted 14 lines · Jean Delvare

Hi Domen,

Quoted 11 lines · Domen Puncer

Disabling module on stop doesn't work on some CPUs (ie. mpc8241, as reported by Guennadi Liakhovetski), so remove that.

Disable I2C module on errors/interrupts to prevent it from locking up on mpc5200b.

---
Hi!

Quoted 8 lines
Quoted 5 lines

So I fixed i2c on one board, and broke it on another :-( This patch works on both Guennadi's and mine (hey, it might break a third one!).
Jean, can you please push this, if there are no objections and "doesn't work for me" reports.

Queued for 2.6.23-rc3, thanks. Guennadi, can you please confirm that this patch fixes your problem?

Yes, it does. Also tested with i2c bus debugging on and with interrupting hwclock, thereby messages

I2C: Interrupted

come, but the controller stays functional. Looks good so far:-)

Thanks
Guennadi
---
Guennadi Liakhovetski