From: Clifford Wolf <[email protected]>

Retry on arbitration lost until xfer is successful, a non-arbitration-lost
error is triggered or the 1s timeout is hit.

Tested with a freescale MPC8349E host cpu.

Signed-off-by: Clifford Wolf <[email protected]>
Cc: Jean Delvare <[email protected]>
Cc: Ben Dooks <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
---

 drivers/i2c/busses/i2c-mpc.c |   17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff -puN 
drivers/i2c/busses/i2c-mpc.c~i2c-incremental-i2c-mpc-driver-fix-for-multi-master-i2c-busses
 drivers/i2c/busses/i2c-mpc.c
--- 
a/drivers/i2c/busses/i2c-mpc.c~i2c-incremental-i2c-mpc-driver-fix-for-multi-master-i2c-busses
+++ a/drivers/i2c/busses/i2c-mpc.c
@@ -106,7 +106,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);
+                               writeccr(i2c, CCR_MEN);
                                result = -EIO;
                                break;
                        }
@@ -120,10 +120,10 @@ static int i2c_wait(struct mpc_i2c *i2c,
 
                if (unlikely(result < 0)) {
                        pr_debug("I2C: wait interrupted\n");
-                       writeccr(i2c, 0);
+                       writeccr(i2c, CCR_MEN);
                } else if (unlikely(!(i2c->interrupt & CSR_MIF))) {
                        pr_debug("I2C: wait timeout\n");
-                       writeccr(i2c, 0);
+                       writeccr(i2c, CCR_MEN);
                        result = -ETIMEDOUT;
                }
 
@@ -268,7 +268,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);
+                       writeccr(i2c, CCR_MEN);
                        return -EINTR;
                }
                if (time_after(jiffies, orig_jiffies + HZ)) {
@@ -364,6 +364,15 @@ static int __devinit fsl_i2c_probe(struc
        }
        of_register_i2c_devices(&i2c->adap, op->node);
 
+       /* Make sure the adapter is already in master mode some time before
+        * the first xfer to make sure arbitration control had enough time
+        * to monitor the bus. The CCR_MEN flag should never be cleared without
+        * makeing sure there is some delay between setting it again and
+        * starting the first transfer..
+        */
+       writeccr(i2c, CCR_MEN);
+       udelay(100);
+
        return result;
 
  fail_add:
_
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to