[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:51:49 CEST 2011



Thanks and Best Regards
Jerry Huang


> -----Original Message-----
> From: u-boot-bounces at lists.denx.de [mailto:u-boot-bounces at lists.denx.de]
> On Behalf Of Huang Changming-R66093
> Sent: Thursday, October 27, 2011 3:40 PM
> To: Joakim Tjernlund
> 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
> 
> 
> 
> 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
> 
Compare with kernel version, the difference is one line:
Uboot:  readb(&dev->dr);
Kernel has no any operation.
But, I check the comment of kernel, because the 9th clock pulse isn't generated, 
the sequence of function mpc_i2c_fixup is needed to generate 9th clock pulse.



More information about the U-Boot mailing list