From owner-p4-projects@FreeBSD.ORG Tue Nov 28 21:45:46 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 0948216A40F; Tue, 28 Nov 2006 21:45:46 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id BCAE316A403 for ; Tue, 28 Nov 2006 21:45:45 +0000 (UTC) (envelope-from imp@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.FreeBSD.org (Postfix) with ESMTP id A4E0443CC6 for ; Tue, 28 Nov 2006 21:45:40 +0000 (GMT) (envelope-from imp@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id kASLjjaV096331 for ; Tue, 28 Nov 2006 21:45:45 GMT (envelope-from imp@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id kASLjjWa096328 for perforce@freebsd.org; Tue, 28 Nov 2006 21:45:45 GMT (envelope-from imp@freebsd.org) Date: Tue, 28 Nov 2006 21:45:45 GMT Message-Id: <200611282145.kASLjjWa096328@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to imp@freebsd.org using -f From: Warner Losh To: Perforce Change Reviews Cc: Subject: PERFORCE change 110635 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Nov 2006 21:45:46 -0000 http://perforce.freebsd.org/chv.cgi?CH=110635 Change 110635 by imp@imp_lighthouse on 2006/11/28 21:44:53 Go to an interrupt driven model. This saves 4.00 out of 4.00 system time seconds in reading a 2k part. The final speed is unaffected. Allow zero length read/write transactions. They aren't allowed in linux, but are useful for (a) probing (b) waiting for the device to become active during a long running operation like writing to eeprom. Affected files ... .. //depot/projects/arm/src/sys/arm/at91/at91_twi.c#29 edit Differences ... ==== //depot/projects/arm/src/sys/arm/at91/at91_twi.c#29 (text+ko) ==== @@ -52,9 +52,7 @@ struct resource *irq_res; /* IRQ resource */ struct resource *mem_res; /* Memory resource */ struct mtx sc_mtx; /* basically a perimeter lock */ - volatile int flags; -#define RXRDY 4 -#define TXRDY 0x10 + volatile uint32_t flags; uint32_t cwgr; int sc_started; int twi_addr; @@ -131,8 +129,6 @@ WR4(sc, TWI_CR, TWI_CR_SWRST); WR4(sc, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS); WR4(sc, TWI_CWGR, sc->cwgr); -// WR4(sc, TWI_IER, TWI_SR_RXRDY | TWI_SR_OVRE | TWI_SR_UNRE | -// TWI_SR_NACK); if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) device_printf(dev, "could not allocate iicbus instance\n"); @@ -210,15 +206,15 @@ /* Reading the status also clears the interrupt */ status = RD4(sc, TWI_SR); - printf("status %x\n", status); if (status == 0) return; - AT91_TWI_LOCK(sc); if (status & TWI_SR_RXRDY) - sc->flags |= RXRDY; + sc->flags |= TWI_SR_RXRDY; if (status & TWI_SR_TXRDY) - sc->flags |= TXRDY; - AT91_TWI_UNLOCK(sc); + sc->flags |= TWI_SR_TXRDY; + if (status & TWI_SR_TXCOMP) + sc->flags |= TWI_SR_TXCOMP; + WR4(sc, TWI_IDR, status); wakeup(sc); return; } @@ -226,13 +222,15 @@ static int at91_twi_wait(struct at91_twi_softc *sc, uint32_t bit) { - int err = 0; - int counter = 100000; + int err; - while (!(RD4(sc, TWI_SR) & bit) && counter-- >= 0) - continue; - if (counter <= 0) - err = EIO; + sc->flags = 0; + WR4(sc, TWI_IER, bit); + err = msleep(sc, &sc->sc_mtx, PZERO | PCATCH, "iic", MAX(1,hz/10)); + if (sc->flags & bit) + err = 0; + else if (err == 0) + err = EBUSY; return (err); } @@ -303,11 +301,13 @@ at91_twi_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) { struct at91_twi_softc *sc; - int i, len; + int i, len, err; uint32_t rdwr; uint8_t *buf; sc = device_get_softc(dev); + err = 0; + AT91_TWI_LOCK(sc); for (i = 0; i < nmsgs; i++) { /* * The linux atmel driver doesn't use the internal device @@ -320,15 +320,15 @@ WR4(sc, TWI_MMR, TWI_MMR_DADR(msgs[i].slave) | rdwr); len = msgs[i].len; buf = msgs[i].buf; - if (len == 0 || buf == NULL) + if (len != 0 && buf == NULL) return (EINVAL); 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 (at91_twi_wait(sc, TWI_SR_RXRDY)) - return (EIO); + if ((err = at91_twi_wait(sc, TWI_SR_RXRDY))) + goto out; *buf++ = RD4(sc, TWI_RHR) & 0xff; } } else { @@ -336,14 +336,16 @@ WR4(sc, TWI_THR, *buf++); if (len == 0) WR4(sc, TWI_CR, TWI_CR_STOP); - if (at91_twi_wait(sc, TWI_SR_TXRDY)) - return (EIO); + if ((err = at91_twi_wait(sc, TWI_SR_TXRDY))) + goto out; } } - if (at91_twi_wait(sc, TWI_SR_TXCOMP)) - return (EIO); + if ((err = at91_twi_wait(sc, TWI_SR_TXCOMP))) + break; } - return (0); +out:; + AT91_TWI_UNLOCK(sc); + return (err); } static device_method_t at91_twi_methods[] = {