PERFORCE change 111366 for review
Warner Losh
imp at FreeBSD.org
Sat Dec 9 20:41:37 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=111366
Change 111366 by imp at imp_lighthouse on 2006/12/10 04:41:02
Fixes for writing a single byte to IIC as well as robust detection
of NACK bit in SR indicating no ACK from the transfer. This
is useful when probing the bus.
Many of these changes were from tisco based on his experience with
the Atmel sample code and the AT91SAM7 processors he's used in
the past. These tweaks are somewhat underdocumented in the AT91RM9200
processor manual, but also appear to be hinted at in the errata.
As far as I can tell, nothing breaks when we do this, but I've only
tested on my KB9202 board.
Submitted by: tisco
Affected files ...
.. //depot/projects/arm/src/sys/arm/at91/at91_twi.c#38 edit
Differences ...
==== //depot/projects/arm/src/sys/arm/at91/at91_twi.c#38 (text+ko) ====
@@ -226,7 +226,8 @@
int counter = 100000;
uint32_t sr;
- while (!((sr = RD4(sc, TWI_SR)) & bit) && counter-- > 0)
+ while (!((sr = RD4(sc, TWI_SR)) & bit) && counter-- > 0 &&
+ !(sr & TWI_SR_NACK))
continue;
if (counter <= 0)
err = EBUSY;
@@ -300,6 +301,7 @@
int i, len, err;
uint32_t rdwr;
uint8_t *buf;
+ uint32_t sr;
sc = device_get_softc(dev);
err = 0;
@@ -318,24 +320,35 @@
WR4(sc, TWI_MMR, TWI_MMR_DADR(msgs[i].slave) | rdwr);
len = msgs[i].len;
buf = msgs[i].buf;
- if (len != 0 && buf == NULL)
+ /* zero byte transfers aren't allowed */
+ if (len == 0 || buf == NULL)
return (EINVAL);
- WR4(sc, TWI_CR, TWI_CR_START);
+ if (len == 1)
+ WR4(sc, TWI_CR, TWI_CR_START | TWI_CR_STOP);
+ else
+ WR4(sc, TWI_CR, TWI_CR_START);
if (msgs[i].flags & IIC_M_RD) {
- while (len--) {
- if (len == 0)
- WR4(sc, TWI_CR, TWI_CR_STOP);
- if ((err = at91_twi_wait(sc, TWI_SR_RXRDY)))
- goto out;
- *buf++ = RD4(sc, TWI_RHR) & 0xff;
+ sr = RD4(sc, TWI_SR);
+ while (!(sr & TWI_SR_TXCOMP)) {
+ sr = RD4(sc, TWI_SR);
+ if ((sr = RD4(sc, TWI_SR)) & TWI_SR_RXRDY) {
+ len--;
+ *buf++ = RD4(sc, TWI_RHR) & 0xff;
+ if (len == 0 && msgs[i].len != 1)
+ WR4(sc, TWI_CR, TWI_CR_STOP);
+ }
+ }
+ if (sr & TWI_SR_NACK) {
+ err = EADDRNOTAVAIL;
+ goto out;
}
} else {
while (len--) {
- WR4(sc, TWI_THR, *buf++);
- if (len == 0)
+ if (len == 0 && msgs[i].len != 1)
WR4(sc, TWI_CR, TWI_CR_STOP);
if ((err = at91_twi_wait(sc, TWI_SR_TXRDY)))
goto out;
+ WR4(sc, TWI_THR, *buf++);
}
}
if ((err = at91_twi_wait(sc, TWI_SR_TXCOMP)))
More information about the p4-projects
mailing list