[U-Boot] [PATCH 2/2] Powerpc/i2c: Force i2c to become bus master out of reset

Joakim Tjernlund joakim.tjernlund at transmode.se
Thu Oct 27 10:10:00 CEST 2011


Huang Changming-R66093 <r66093 at freescale.com> wrote on 2011/10/27 09:51:49:
>
>
>
> 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.

Not so, there is more than that if you look closer. The description in the kernel
is a bit misleading(or so I think). I prefer the kernel version for 2 reasons:
1) It has been there for quite some time so if there were something wrong with,
   it should have been noticed by now.
2) I have a vauge memory of checking it again the mpc8321 manual and I was happy
   with it.

 Jocke



More information about the U-Boot mailing list