Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 254db9b5 authored by Domen Puncer's avatar Domen Puncer Committed by Jean Delvare
Browse files

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 boards by Matthias Fechner and me.

Signed-off-by: default avatarDomen Puncer <domen.puncer@telargo.com>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 1b144df1
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -74,6 +74,25 @@ static irqreturn_t mpc_i2c_isr(int irq, void *dev_id)
	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 *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,9 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
		}
		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();