I've come across an interesting problem when trying to hook up the ETRAX 100LX to a peripheral via I2C.
I am writing a driver for the device, and was intending to use the functions in i2c.c and i2c.h in the /arch/cris/drivers directory. I thnk that the peripheral doesn't meet the I2C spec properly, as the peripheral does not correctly respond to i2c_readreg(). I hooked up a scope to the data pins, and following is what occurs. Our device has a 7 bit address of 0x21 (i.e. byte = 0x42 for write, 0x43 for read). START and STOP are the I2C start and stop conditions, NACK/ACK is the device response and I am trying to read register 0x1C
Data line -> START 0x42 ACK 0x1C ACK START 0x43 NACK 0xFF NACK
peripheral doesn't see this peripheral tries to ACK here
The peripheral tries to send an ACK when the I2C bus sends the last bit (R/W) of the device address for the second time. I am fairly sure this is because it sees the second START as a data bit instead. Therefore it thinks that the value of the device address should be written to 0x1C, instead of reading from it.
To check this I made the following change to i2c_readreg(), I placed a STOP condition before the second START. (removed comments for brevity)
i2c_outbyte((theSlave & 0xfe));
error = 1;
error = 1;
/* CHANGE MADE HERE */
i2c_outbyte(theSlave | 0x01);
/* etc */
The peripheral now works correctly, i.e. it returns data in the last byte, and all ACKs etc are performed correctly.
The question I have is will making this change break other I2C devices? If it does, then I will have to write a seperate I2C device driver for this peripheral. From my understanding of I2C, a repeated start condition, for example how i2c_readreg() originally works is supposed to be supported by devices. This doesn't seem the case for the peripheral I'm using.