Date: Sun, 10 Dec 2006 04:41:36 GMT From: Warner Losh <imp@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 111366 for review Message-ID: <200612100441.kBA4faGE069138@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=111366 Change 111366 by imp@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)))
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200612100441.kBA4faGE069138>