[U-Boot] [PATCH 2/2] Powerpc/i2c: Force i2c to become bus master out of reset
Huang Changming-R66093
r66093 at freescale.com
Thu Oct 27 09:40:23 CEST 2011
Thanks and Best Regards
Jerry Huang
> -----Original Message-----
> From: Joakim Tjernlund [mailto:joakim.tjernlund at transmode.se]
> Sent: Thursday, October 27, 2011 3:26 PM
> To: Huang Changming-R66093
> Cc: u-boot at lists.denx.de
> Subject: Re: [U-Boot] [PATCH 2/2] Powerpc/i2c: Force i2c to become bus
> master out of reset
>
> > From: <Chang-Ming.Huang at freescale.com>
> >
> > From: Jerry Huang <Chang-Ming.Huang at 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.Huang at 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?
I don't know the kernel version, but I write the u-boot code according to the Reference Manual of PowerPC, e.g p1022:
11.5.6 Generation of SCL When SDA Low
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:
1. Disable the I2C module and set the master bit by setting I2CCR to 0x20
2. Enable the I2C module by setting I2CCR to 0xA0
3. Read the I2CDR
4. Return the I2C module to slave mode by setting I2CCR to 0x80
More information about the U-Boot
mailing list