From owner-p4-projects@FreeBSD.ORG Sat Oct 7 05:08:19 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 9E64816A40F; Sat, 7 Oct 2006 05:08:19 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 79CC116A407 for ; Sat, 7 Oct 2006 05:08:19 +0000 (UTC) (envelope-from imp@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3B62E43D49 for ; Sat, 7 Oct 2006 05:08:19 +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 k9758J3w023411 for ; Sat, 7 Oct 2006 05:08:19 GMT (envelope-from imp@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k9758IJ9023408 for perforce@freebsd.org; Sat, 7 Oct 2006 05:08:18 GMT (envelope-from imp@freebsd.org) Date: Sat, 7 Oct 2006 05:08:18 GMT Message-Id: <200610070508.k9758IJ9023408@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 107395 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: Sat, 07 Oct 2006 05:08:19 -0000 http://perforce.freebsd.org/chv.cgi?CH=107395 Change 107395 by imp@imp_lighthouse on 2006/10/07 05:07:56 Make this interrupt driven... Also, make it non-locking, since no locks are needed (I don't think) Affected files ... .. //depot/projects/arm/src/sys/arm/at91/at91_spi.c#8 edit Differences ... ==== //depot/projects/arm/src/sys/arm/at91/at91_spi.c#8 (text+ko) ==== @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -50,9 +49,9 @@ void *intrhand; /* Interrupt handle */ struct resource *irq_res; /* IRQ resource */ struct resource *mem_res; /* Memory resource */ - struct mtx sc_mtx; /* basically a perimeter lock */ bus_dma_tag_t dmatag; /* bus dma tag for mbufs */ bus_dmamap_t map[4]; /* Maps for the transaction */ + volatile int rxdone; }; static inline uint32_t @@ -67,19 +66,7 @@ bus_write_4(sc->mem_res, off, val); } -#define AT91_SPI_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) -#define AT91_SPI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define AT91_SPI_LOCK_INIT(_sc) \ - mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \ - "spi", MTX_DEF) -#define AT91_SPI_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); -#define AT91_SPI_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); -#define AT91_SPI_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); - -static devclass_t at91_spi_devclass; - /* bus entry points */ - static int at91_spi_probe(device_t dev); static int at91_spi_attach(device_t dev); static int at91_spi_detach(device_t dev); @@ -87,6 +74,7 @@ /* helper routines */ static int at91_spi_activate(device_t dev); static void at91_spi_deactivate(device_t dev); +static void at91_spi_intr(void *arg); static int at91_spi_probe(device_t dev) @@ -106,8 +94,6 @@ if (err) goto out; - AT91_SPI_LOCK_INIT(sc); - /* * Allocate DMA tags and maps */ @@ -124,6 +110,7 @@ // reset the SPI WR4(sc, SPI_CR, SPI_CR_SWRST); + WR4(sc, SPI_IDR, 0xffffffff); WR4(sc, SPI_MR, (0xf << 24) | SPI_MR_MSTR | SPI_MR_MODFDIS | (0xE << 16)); @@ -164,7 +151,7 @@ at91_spi_activate(device_t dev) { struct at91_spi_softc *sc; - int rid; + int rid, err = ENOMEM; sc = device_get_softc(dev); rid = 0; @@ -175,12 +162,16 @@ rid = 0; sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); - if (sc->mem_res == NULL) + if (sc->irq_res == NULL) + goto errout; + err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE, + at91_spi_intr, sc, &sc->intrhand); + if (err != 0) goto errout; return (0); errout: at91_spi_deactivate(dev); - return (ENOMEM); + return (err); } static void @@ -216,7 +207,7 @@ at91_spi_transfer(device_t dev, device_t child, struct spi_command *cmd) { struct at91_spi_softc *sc; - int i; + int i, rxdone, err; bus_addr_t addr; sc = device_get_softc(dev); @@ -250,27 +241,50 @@ WR4(sc, PDC_RNCR, cmd->tx_data_sz); bus_dmamap_sync(sc->dmatag, sc->map[i], BUS_DMASYNC_PREREAD); + WR4(sc, SPI_IER, SPI_SR_ENDRX); WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN | PDC_PTCR_RXTEN); - // wait for completion - // XXX should be done as an ISR of some sort. - while (RD4(sc, SPI_SR) & SPI_SR_ENDRX) - DELAY(700); - - // Sync the buffers after the DMA is done, and unload them. - bus_dmamap_sync(sc->dmatag, sc->map[0], BUS_DMASYNC_POSTWRITE); - bus_dmamap_sync(sc->dmatag, sc->map[1], BUS_DMASYNC_POSTWRITE); - bus_dmamap_sync(sc->dmatag, sc->map[2], BUS_DMASYNC_POSTREAD); - bus_dmamap_sync(sc->dmatag, sc->map[3], BUS_DMASYNC_POSTREAD); + rxdone = sc->rxdone; + do { + err = msleep(sc, NULL, PCATCH | PZERO, "spi", hz); + } while (rxdone == sc->rxdone && err != EINTR); + WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); + if (err == 0) { + // Sync the buffers after the DMA is done, and unload them. + bus_dmamap_sync(sc->dmatag, sc->map[0], BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(sc->dmatag, sc->map[1], BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(sc->dmatag, sc->map[2], BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(sc->dmatag, sc->map[3], BUS_DMASYNC_POSTREAD); + } for (i = 0; i < 4; i++) bus_dmamap_unload(sc->dmatag, sc->map[i]); - return (0); + return (err); out:; while (i-- > 0) bus_dmamap_unload(sc->dmatag, sc->map[i]); return (EIO); } +static void +at91_spi_intr(void *arg) +{ + struct at91_spi_softc *sc = (struct at91_spi_softc*)arg; + uint32_t sr; + + sr = RD4(sc, SPI_SR) & RD4(sc, SPI_IMR); + if (sr & SPI_SR_ENDRX) { + sc->rxdone++; + WR4(sc, SPI_IDR, SPI_SR_ENDRX); + wakeup(sc); + } + if (sr & ~SPI_SR_ENDRX) { + device_printf(sc->dev, "Unexpected ISR %#x\n", sr); + WR4(sc, SPI_IDR, sr & ~SPI_SR_ENDRX); + } +} + +static devclass_t at91_spi_devclass; + static device_method_t at91_spi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, at91_spi_probe),