MPC85xx i2c interface bug
Kumar Gala
galak at kernel.crashing.org
Wed Dec 7 04:24:35 EST 2005
Dan,
I'm in agreement with your change for the 2.4 kernel. It looks like
the 2.6 kernel driver is handing TXAK correctly. The following is a
snippet from the 2.6 driver:
if (length) {
if (length == 1)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
| CCR_TXAK);
else
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
/* Dummy read */
readb(i2c->base + MPC_I2C_DR);
}
for (i = 0; i < length; i++) {
if (i2c_wait(i2c, timeout, 0) < 0)
return -1;
/* Generate txack on next to last byte */
if (i == length - 2)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
| CCR_TXAK);
/* Generate stop on last byte */
if (i == length - 1)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
data[i] = readb(i2c->base + MPC_I2C_DR);
}
If I'm reading it correctly it matches your changes. If you dont
mind looking at this and verifying that you agree that we are setting
TXAK as expected.
- kumar
On Nov 30, 2005, at 1:18 AM, Dan Wilson wrote:
> 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.
>
>
> _______________________________________________
> Linuxppc-embedded mailing list
> Linuxppc-embedded at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-embedded
More information about the Linuxppc-embedded
mailing list