MPC85xx i2c interface bug
Dan Wilson
dwilson at dslextreme.com
Wed Nov 30 18:18:16 EST 2005
On 11/30/2005 at 12:14 AM Kumar Gala wrote:
> Dan,
>
> Did you see an issue this change fixed? If so can you provide more
> details. Also, can you provide your diff as a unified diff (diff -u) so
> its easier to see where the changes where.
>
> I'm trying to figure out if the same issue exists in the 2.6 driver (and
> if so, why we havent seen it)
>
> thanks
>
> - kumar
>
Yes, there was an issue that this change fixed. Our I2C bus has a number of devices on it. The first device is at address 0x2c, and is an Analog Device AD5173BRM50 software programmable 50K ohm resistor. We connected a logic analyzer to the device and watched the bus activity as linux booted and the i2c bus scan took place. During this scan, the 8541 attempts to address each device and then read a byte from the device. With the original code, the 8541 would reply to the byte read by sending a zero as the TXACK bit, which instructed the 5173 to send an additional byte, but the 8541 didn't attempt to retrieve that byte, since it was already moving on, trying to stop the bus and go on to the next device. The 5173 appeared to not be able to see the stop command since it had received a command to transmit the next byte. The bus didn't seem to ever recover from this: if we allowed linux to complete it's boot and then told it to reboot, the u-boot code was no longer able to identify and configure the SDRAM, since it is also connected to the now non-functional I2C. With the new code, linux correctly identifies all of the devices on the I2C, boots quickly and cleanly, and after a reboot the u-boot code has no problem coming up again.
Here is the diff -u that you requested:
@@ -299,11 +299,11 @@
if(pm->flags & I2C_M_RD) {
/* Change to read mode */
- priv->write(®s->i2ccr, 0, MPC_I2CCR_MTX);
+ priv->write(®s->i2ccr, 0, MPC_I2CCR_MTX | MPC_I2CCR_TXAK);
/* If there is only one byte, we need to TXAK now */
if(len == 1)
- priv->write(®s->i2ccr, 0, MPC_I2CCR_TXAK);
+ priv->write(®s->i2ccr, MPC_I2CCR_TXAK, MPC_I2CCR_TXAK);
/* Do a dummy read, to initiate the first read */
priv->read(®s->i2cdr);
@@ -321,7 +321,7 @@
/* If this is the 2nd to last byte, send
* the TXAK signal */
if(i == len - 2) {
- priv->write(®s->i2ccr, 0, MPC_I2CCR_TXAK);
+ priv->write(®s->i2ccr, MPC_I2CCR_TXAK, MPC_I2CCR_TXAK);
}
/* If this is the last byte, send STOP */
@@ -383,7 +383,6 @@
priv->write(®s->i2csr, 0, MPC_I2CSR_MIF);
mpc_i2c_start(priv);
-
/* Send each message, chaining them together with repeat STARTs */
for(i = 0; i < num && !err; ++i) {
err = mpc_doAddress(priv, &msgs[i]);
Hope this helps,
Dan.
More information about the Linuxppc-embedded
mailing list