> From: <chang-ming.hu...@freescale.com> > > From: Jerry Huang <chang-ming.hu...@freescale.com> > > It is sometimes necessary to force the I2C module to become the I2C bus master > out of reset and drive SCL(even though SDA may already be driven, > which indicates that the bus is busy). This can occur when a system reset > does not cause all I2C devices to be reset. Thus, SDA can be driven low > by another I2C device while this I2C module is coming out of reset > and stays low indefinitely. The following procedure can be used to > force this I2C module to generate SCL so that the device driving SDA > can finish its transaction. > > Signed-off-by: Jerry Huang <chang-ming.hu...@freescale.com> > --- > drivers/i2c/fsl_i2c.c | 18 ++++++++++++++++++ > 1 files changed, 18 insertions(+), 0 deletions(-) > > diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c > index 258be0a..007db70 100644 > --- a/drivers/i2c/fsl_i2c.c > +++ b/drivers/i2c/fsl_i2c.c > @@ -252,6 +252,24 @@ i2c_init(int speed, int slaveadd) > writeb(slaveadd << 1, &dev->adr);/* write slave address */ > writeb(0x0, &dev->sr); /* clear status register */ > writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */ > + > + /* Force I2C module to become bus master which can occure when > + * a system reset does not cause all I2C devices to be reset */ > + udelay(5); > + if (readb(&dev->sr) & I2C_SR_MBB) {
You need to the sequence unconditionally, the slave can be stuck without driving SCL. > + writeb(I2C_CR_MSTA, &dev->cr); > + udelay(5); > + writeb(I2C_CR_MEN | I2C_CR_MSTA, &dev->cr); > + udelay(5); > + readb(&dev->dr); > + udelay(5); > + writeb(I2C_CR_MEN, &dev->cr); > + udelay(5); > + if (readb(&dev->sr) & I2C_SR_MBB) > + debug("I2C%d: Drive SCL failed\n", i + 1); > + else > + debug("I2C%d: Drive SCL succeed\n", i + 1); > + } The above sequence is different than the kernel version, why? Kernel version below: static void mpc_i2c_fixup(struct mpc_i2c *i2c) { int k; u32 delay_val = 1000000 / i2c->real_clk + 1; if (delay_val < 2) delay_val = 2; for (k = 9; k; k--) { writeccr(i2c, 0); writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); udelay(delay_val); writeccr(i2c, CCR_MEN); udelay(delay_val << 1); } } _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot