[U-Boot] [PATCH 1/2] Powerpc/i2c: Use the same initialize codes

From: Jerry Huang Chang-Ming.Huang@freescale.com
Make the I2C2 and I2C1 use the same initialize codes.
Signed-off-by: Jerry Huang Chang-Ming.Huang@freescale.com --- drivers/i2c/fsl_i2c.c | 47 +++++++++++++++++++++++++---------------------- 1 files changed, 25 insertions(+), 22 deletions(-)
diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c index cb13dee..258be0a 100644 --- a/drivers/i2c/fsl_i2c.c +++ b/drivers/i2c/fsl_i2c.c @@ -214,11 +214,20 @@ static unsigned int set_i2c_bus_speed(const struct fsl_i2c *dev, return speed; }
+unsigned int get_i2c_clock(int bus) +{ + if (bus) + return gd->i2c2_clk; /* I2C2 clock */ + else + return gd->i2c1_clk; /* I2C1 clock */ +} + void i2c_init(int speed, int slaveadd) { struct fsl_i2c *dev; unsigned int temp; + int bus_num, i;
#ifdef CONFIG_SYS_I2C_INIT_BOARD /* Call board specific i2c bus reset routine before accessing the @@ -227,29 +236,23 @@ i2c_init(int speed, int slaveadd) */ i2c_init_board(); #endif - dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C_OFFSET); - - writeb(0, &dev->cr); /* stop I2C controller */ - udelay(5); /* let it shutdown in peace */ - temp = set_i2c_bus_speed(dev, gd->i2c1_clk, speed); - if (gd->flags & GD_FLG_RELOC) - i2c_bus_speed[0] = temp; - writeb(slaveadd << 1, &dev->adr); /* write slave address */ - writeb(0x0, &dev->sr); /* clear status register */ - writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */ - -#ifdef CONFIG_SYS_I2C2_OFFSET - dev = (struct fsl_i2c *) (CONFIG_SYS_IMMR + CONFIG_SYS_I2C2_OFFSET); - - writeb(0, &dev->cr); /* stop I2C controller */ - udelay(5); /* let it shutdown in peace */ - temp = set_i2c_bus_speed(dev, gd->i2c2_clk, speed); - if (gd->flags & GD_FLG_RELOC) - i2c_bus_speed[1] = temp; - writeb(slaveadd << 1, &dev->adr); /* write slave address */ - writeb(0x0, &dev->sr); /* clear status register */ - writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */ +#ifdef CONFIG_SYS_I2C2_OFFSET + bus_num = 2; +#else + bus_num = 1; #endif + for (i = 0; i < bus_num; i++) { + dev = i2c_dev[i]; + + writeb(0, &dev->cr); /* stop I2C controller */ + udelay(5); /* let it shutdown in peace */ + temp = set_i2c_bus_speed(dev, get_i2c_clock(i), speed); + if (gd->flags & GD_FLG_RELOC) + i2c_bus_speed[i] = temp; + writeb(slaveadd << 1, &dev->adr);/* write slave address */ + writeb(0x0, &dev->sr); /* clear status register */ + writeb(I2C_CR_MEN, &dev->cr); /* start I2C controller */ + }
#ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT /* Call board specific i2c bus reset routine AFTER the bus has been

From: Jerry Huang Chang-Ming.Huang@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@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) { + 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); + } }
#ifdef CONFIG_SYS_I2C_BOARD_LATE_INIT

Hello Chang-Ming,
Chang-Ming.Huang@freescale.com wrote:
From: Jerry Huang Chang-Ming.Huang@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@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 */
Checkpatch doesn't warn, but wrong comment style here, please change.
[...]
bye, Heiko

From: Chang-Ming.Huang@freescale.com
From: Jerry Huang Chang-Ming.Huang@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@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); } }

Thanks and Best Regards Jerry Huang
-----Original Message----- From: Joakim Tjernlund [mailto:joakim.tjernlund@transmode.se] Sent: Thursday, October 27, 2011 3:26 PM To: Huang Changming-R66093 Cc: u-boot@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@freescale.com
From: Jerry Huang Chang-Ming.Huang@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@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

Thanks and Best Regards Jerry Huang
-----Original Message----- From: u-boot-bounces@lists.denx.de [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Huang Changming-R66093 Sent: Thursday, October 27, 2011 3:40 PM To: Joakim Tjernlund Cc: u-boot@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@transmode.se] Sent: Thursday, October 27, 2011 3:26 PM To: Huang Changming-R66093 Cc: u-boot@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@freescale.com
From: Jerry Huang Chang-Ming.Huang@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@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:
- 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.

Huang Changming-R66093 r66093@freescale.com wrote on 2011/10/27 09:51:49:
Thanks and Best Regards Jerry Huang
-----Original Message----- From: u-boot-bounces@lists.denx.de [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Huang Changming-R66093 Sent: Thursday, October 27, 2011 3:40 PM To: Joakim Tjernlund Cc: u-boot@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@transmode.se] Sent: Thursday, October 27, 2011 3:26 PM To: Huang Changming-R66093 Cc: u-boot@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@freescale.com
From: Jerry Huang Chang-Ming.Huang@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@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:
- 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

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:
- 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:
- 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.
These tow part codes are doing the different thing due to the different reason: 1. Kernel's code: because Sometimes 9th clock pulse isn't generated, that code is to generate the 9th clock pulse. It happens in the DATA transfer stage. 2. My code: because the system reset does not cause all I2C devices to be reset, the code force the i2c to become the master and drive the SCL. It happens in the i2c controller initialize stage So, I think these code is reasonable.
BTW: My codes has been verified on Emerson's board.

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:
- 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:
- 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.
These tow part codes are doing the different thing due to the different reason: 1. Kernel's code: because Sometimes 9th clock pulse isn't generated, that code is to generate the 9th clock pulse. It happens in the DATA transfer stage. 2. My code: because the system reset does not cause all I2C devices to be reset, the code force the i2c to become the master and drive the SCL. It happens in the i2c controller initialize stage So, I think these code is reasonable.
BTW: My codes has been verified on Emerson's board.

Huang Changming-R66093 r66093@freescale.com wrote on 2011/10/27 11:26:04:
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:
- 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:
- 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.
These tow part codes are doing the different thing due to the different reason:
- Kernel's code:
because Sometimes 9th clock pulse isn't generated, that code is to generate the 9th clock pulse.
What code are you looking at? Are you just reading the comment? Look at http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commit;h=0c2... to get a clue.
Your code isn't complete, you cannot trust the manual to be the whole truth.
Jocke

These tow part codes are doing the different thing due to the
different reason:
- Kernel's code:
because Sometimes 9th clock pulse isn't generated, that code is to
generate the 9th clock pulse.
What code are you looking at? Are you just reading the comment? Look at http://git.kernel.org/?p=linux/kernel/git/next/linux- next.git;a=commit;h=0c2daaafcdec726e89cbccca61d576de8429c537 to get a clue.
Your code isn't complete, you cannot trust the manual to be the whole truth.
I am very confused, why do you always say my code isn't complete? I have described I want to do detailed in comment. "when a system reset does not cause all I2C devices to be reset", My codes will force the I2c module to become bus master and drive SCL, which force this i2c module to generate SCL so that the device driving SDA can finish its transaction. These codes have been used on Emerson's P1022 board and resolved his issue (board will hang when u-boot booting, with my codes, this issue is resolved and board can boot well) This is one feature of FSL I2C almost cover all 85xx platform, and the code according to the RM has been verified, don't you think the manual can be trust?
Below is the description from your link: This patch improves the recovery of the MPC's I2C bus from errors like bus hangs resulting in timeouts: 1. make the bus timeout configurable, as it depends on the bus clock and the attached slave chip(s); default is still 1 second; 2. detect any of the cases indicated by the CF, BB and RXAK MSR flags if a timeout occurs, and add a missing (required) MAL reset; 3. use a more reliable method to fixup the bus if a hang has been detected. The sequence is sent 9 times which seems to be necessary if a slave "misses" more than one clock cycle. For 400 kHz bus speed, the fixup is also ~70us (81us vs. 150us) faster.
This patch is created because a slave miss more than one clock cycle and can resolve this issue.
So, the kernel's patch and my patch is to resolve the different issue.

Hello Huang Changming-R66093,
Huang Changming-R66093 wrote:
These tow part codes are doing the different thing due to the
different reason:
- Kernel's code:
because Sometimes 9th clock pulse isn't generated, that code is to
generate the 9th clock pulse.
What code are you looking at? Are you just reading the comment? Look at http://git.kernel.org/?p=linux/kernel/git/next/linux- next.git;a=commit;h=0c2daaafcdec726e89cbccca61d576de8429c537 to get a clue.
Your code isn't complete, you cannot trust the manual to be the whole truth.
I am very confused, why do you always say my code isn't complete?
Because it is not complete?
I have described I want to do detailed in comment. "when a system reset does not cause all I2C devices to be reset",
You wrote: "So, the kernel's patch and my patch is to resolve the different issue."
Yes! There are more "problems" on i2c bus, as also Joakim described! And if we try to fix them in the common driver (as you did), we should fix all known problems -> so your patch is incomplete.
My codes will force the I2c module to become bus master and drive SCL, which force this i2c module to generate SCL so that the device driving SDA can finish its transaction. These codes have been used on Emerson's P1022 board and resolved his issue (board will hang when u-boot booting, with my codes, this issue is resolved and board can boot well)
Then you maybe define CONFIG_SYS_I2C_BOARD_LATE_INIT for this board and do this in board code.
This is one feature of FSL I2C almost cover all 85xx platform, and the code according to the RM has been verified, don't you think the manual can be trust?
See (for example on a mpc83xx based board) board/keymile/common/common.c functions i2c_write_start_seq() and i2c_make_abort() which solve also a deblocked i2c bus ... and they started with the procedure noted in the RM, but this didn't solved all issues for them.
Below is the description from your link: This patch improves the recovery of the MPC's I2C bus from errors like bus hangs resulting in timeouts:
- make the bus timeout configurable, as it depends on the bus clock and the attached slave chip(s); default is still 1 second;
- detect any of the cases indicated by the CF, BB and RXAK MSR flags if a timeout occurs, and add a missing (required) MAL reset;
- use a more reliable method to fixup the bus if a hang has been detected. The sequence is sent 9 times which seems to be necessary if a slave "misses" more than one clock cycle. For 400 kHz bus speed, the fixup is also ~70us (81us vs. 150us) faster.
This patch is created because a slave miss more than one clock cycle and can resolve this issue.
So, the kernel's patch and my patch is to resolve the different issue.
Yes, and if editing a common driver, we should find a solution which fit for all ... did you tried the linux driver code for your board? Maybe it solves your problem too? So we can adapt it to u-boot code?
bye, Heiko

Thanks and Best Regards Jerry Huang
-----Original Message----- From: Heiko Schocher [mailto:hs@denx.de] Sent: Friday, October 28, 2011 2:34 PM To: Huang Changming-R66093 Cc: Joakim Tjernlund; u-boot@lists.denx.de Subject: Re: [U-Boot] [PATCH 2/2] Powerpc/i2c: Force i2c to become bus master out of reset
Hello Huang Changming-R66093,
Huang Changming-R66093 wrote:
These tow part codes are doing the different thing due to the
different reason:
- Kernel's code:
because Sometimes 9th clock pulse isn't generated, that code is to
generate the 9th clock pulse.
What code are you looking at? Are you just reading the comment? Look at http://git.kernel.org/?p=linux/kernel/git/next/linux- next.git;a=commit;h=0c2daaafcdec726e89cbccca61d576de8429c537 to get a clue.
Your code isn't complete, you cannot trust the manual to be the
whole
truth.
I am very confused, why do you always say my code isn't complete?
Because it is not complete?
I don't think it is not complete, because this patch resolves my issue.
I have described I want to do detailed in comment. "when a system reset does not cause all I2C devices to be reset",
You wrote: "So, the kernel's patch and my patch is to resolve the different issue."
Yes! There are more "problems" on i2c bus, as also Joakim described! And if we try to fix them in the common driver (as you did), we should fix all known problems -> so your patch is incomplete.
Yes, we should fix all known problems, but we should not hope one patch includes everything. it make sense for one patch to resolve one thing, instead of all.
My codes will force the I2c module to become bus master and drive SCL, which force this i2c module to generate SCL so that the device
driving SDA can finish its transaction.
These codes have been used on Emerson's P1022 board and resolved his issue (board will hang when u-boot booting, with my codes, this issue is resolved and board can boot well)
Then you maybe define CONFIG_SYS_I2C_BOARD_LATE_INIT for this board and do this in board code.
I have pointed out, this is one feature of FSL I2C module and almost cover all 85xx platform, we provides one solution to resolve the i2c bus "reset" issue. So I think it is not necessary to define one macro for one special board.
This is one feature of FSL I2C almost cover all 85xx platform, and
the code according to the RM has been verified, don't you think the manual can be trust?
See (for example on a mpc83xx based board) board/keymile/common/common.c functions i2c_write_start_seq() and i2c_make_abort() which solve also a deblocked i2c bus ... and they started with the procedure noted in the RM, but this didn't solved all issues for them.
Below is the description from your link: This patch improves the recovery of the MPC's I2C bus from errors
like
bus hangs resulting in timeouts:
- make the bus timeout configurable, as it depends on the bus clock
and
the attached slave chip(s); default is still 1 second; 2. detect
any of the cases indicated by the CF, BB and RXAK MSR flags if a timeout occurs, and add a missing (required) MAL reset; 3. use a more reliable method to fixup the bus if a hang has been detected. The sequence is sent 9 times which seems to be necessary if a
slave
"misses" more than one clock cycle. For 400 kHz bus speed, the
fixup is
also ~70us (81us vs. 150us) faster.
This patch is created because a slave miss more than one clock cycle
and can resolve this issue.
So, the kernel's patch and my patch is to resolve the different issue.
Yes, and if editing a common driver, we should find a solution which fit for all ... did you tried the linux driver code for your board? Maybe it solves your problem too? So we can adapt it to u-boot code?
I can't try the Linux driver on my boards, because all boards on my hand has not these two i2c issue. These codes is generated according to FSL Reference Manual, if you check the RM of FSL, you will find out all 85xx chips(now I know) support this feature. And these code can be work on Emerson's p1022 board, if the code according to the RM can work, I don't think I have any reason to ask customer to use the other codes. And the solution RM provide can resolve the issue, why don't we trust the RM?

Huang Changming-R66093 r66093@freescale.com wrote on 2011/10/27 09:40:23:
Thanks and Best Regards Jerry Huang
-----Original Message----- From: Joakim Tjernlund [mailto:joakim.tjernlund@transmode.se] Sent: Thursday, October 27, 2011 3:26 PM To: Huang Changming-R66093 Cc: u-boot@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@freescale.com
From: Jerry Huang Chang-Ming.Huang@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@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:
- Disable the I2C module and set the master bit by setting I2CCR to 0x20
- Enable the I2C module by setting I2CCR to 0xA0
- Read the I2CDR
- Return the I2C module to slave mode by setting I2CCR to 0x80
I think this is incomplete. Basically you need to generate 9 SCL pulses with a start condition in each, then end with a stop to cover all cases.
Jocke

Hello Chang-Ming,
Chang-Ming.Huang@freescale.com wrote:
From: Jerry Huang Chang-Ming.Huang@freescale.com
Make the I2C2 and I2C1 use the same initialize codes.
Signed-off-by: Jerry Huang Chang-Ming.Huang@freescale.com
drivers/i2c/fsl_i2c.c | 47 +++++++++++++++++++++++++---------------------- 1 files changed, 25 insertions(+), 22 deletions(-)
Applied to u-boot-i2c, thanks
bye, Heiko
participants (4)
-
Chang-Ming.Huang@freescale.com
-
Heiko Schocher
-
Huang Changming-R66093
-
Joakim Tjernlund