[i2c] I2C on AT91RM9200 receives extra byte

Mike Wolfram wolfram at microdatec.de
Thu Sep 7 14:40:30 CEST 2006


On Thursday 07 September 2006 13:16, Andrew Victor wrote:
> > When I reviewed this driver back in July, I remember asking Andrew to
> > check that the logic around the STOP condition matched the flowchart in
> > the data- sheet.  AFAICT, it didn't; in his latest revision it did. 
> > Looking again at the datasheet this morning, it actually says *nothing*
> > about when to read RHR.
> >
> > So Mike: it wouldn't surprise me if such a change were necessary.  But
> > just to be sure... please point out which of Andrew's revisions you've
> > started with (a link is fine) and also send a patch with your change.
> >
> > Andrew: do you have an update for this driver?  Any other comments?
>
> Since Mike mentions the 2.6.18-rc4 patches I guess he's referring to my
> latest AT91 patch:
>    http://maxim.org.za/AT91RM9200/2.6/
>
> That includes the updated I2C driver that *should* match the flowcharts
> in the datasheet.  Since I actually have a working I2C interface on my
> board, the change hasn't actually been tested though.

Hi,

yes, I took that patch. I also read the flowchart in the latest datasheet when 
I read about the changes in the driver.

It seems to me that if the byte is first read from RHR and then STOP is 
written, that another byte sampling is already in progress and won't be 
stopped when writing the STOP to the CR. So if reading RHR again in the next 
transfer the extra byte from the previous received message becomes the first 
of the next.

In my setup I found this when I was trying to get the RTC8564 driver running. 
In 2.6.17 it worked fine but the rtc module refused to load in 2.6.18. There 
is a validation check when loading the module to check if all registers are 
in range. The first register was ok, but every other got a FF. Changing the 
xfer_read in i2c-at91.c to the version below solved the problem.

Currently I have no time to prepare a patch but this is my currently working 
version. There is one ugly thing left that we now write the STOP twice, once 
before reading last byte and once after in the calling function.

static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
{
	/* Send Start */
	at91_twi_write(AT91_TWI_CR, AT91_TWI_START);

	/* Read data */
	while (length--) {
	    if (!length)
	        at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP);
		if (!at91_poll_status(AT91_TWI_RXRDY)) {
			dev_dbg(&adap->dev, "RXRDY timeout\n");
			return -ETIMEDOUT;
		}
		*buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff);
		dev_dbg(&adap->dev, "read %02X\n", *(buf - 1));
	}

	return 0;
}

--
Mike Wolfram
-- 
MicroDatec GmbH
Zeulenrodaer Str. 17, 99091 Erfurt, Germany
fon +49-361-77821-0, fax +49-361-77821-30
mobile +49-179-4902190



More information about the i2c mailing list