From owner-svn-src-head@FreeBSD.ORG Wed Oct 16 02:10:35 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id CCA49C6; Wed, 16 Oct 2013 02:10:35 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id B99BA271C; Wed, 16 Oct 2013 02:10:35 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r9G2AZIp075443; Wed, 16 Oct 2013 02:10:35 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r9G2AZTm075441; Wed, 16 Oct 2013 02:10:35 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201310160210.r9G2AZTm075441@svn.freebsd.org> From: Adrian Chadd Date: Wed, 16 Oct 2013 02:10:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r256572 - head/sys/mips/atheros X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Oct 2013 02:10:36 -0000 Author: adrian Date: Wed Oct 16 02:10:35 2013 New Revision: 256572 URL: http://svnweb.freebsd.org/changeset/base/256572 Log: Add bus space barriers to the AR71xx SPI code. This is required for correct, stable operation on the MIPS74k SoCs that are dual-issue, superscalar pipelines. Tested: * AR9344 SoC (MIPS74k) * AR9331 SoC (MIPS24k) Modified: head/sys/mips/atheros/ar71xx_spi.c Modified: head/sys/mips/atheros/ar71xx_spi.c ============================================================================== --- head/sys/mips/atheros/ar71xx_spi.c Wed Oct 16 01:39:26 2013 (r256571) +++ head/sys/mips/atheros/ar71xx_spi.c Wed Oct 16 02:10:35 2013 (r256572) @@ -62,8 +62,16 @@ __FBSDID("$FreeBSD$"); /* * register space access macros */ -#define SPI_WRITE(sc, reg, val) do { \ - bus_write_4(sc->sc_mem_res, (reg), (val)); \ + +#define SPI_BARRIER_WRITE(sc) bus_barrier((sc)->sc_mem_res, 0, 0, \ + BUS_SPACE_BARRIER_WRITE) +#define SPI_BARRIER_READ(sc) bus_barrier((sc)->sc_mem_res, 0, 0, \ + BUS_SPACE_BARRIER_READ) +#define SPI_BARRIER_RW(sc) bus_barrier((sc)->sc_mem_res, 0, 0, \ + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) + +#define SPI_WRITE(sc, reg, val) do { \ + bus_write_4(sc->sc_mem_res, (reg), (val)); \ } while (0) #define SPI_READ(sc, reg) bus_read_4(sc->sc_mem_res, (reg)) @@ -102,12 +110,30 @@ ar71xx_spi_attach(device_t dev) return (ENXIO); } - SPI_WRITE(sc, AR71XX_SPI_FS, 1); + + /* Flush out read before reading the control register */ + SPI_BARRIER_WRITE(sc); + sc->sc_reg_ctrl = SPI_READ(sc, AR71XX_SPI_CTRL); + + /* + * XXX TODO: document what the SPI control register does. + */ SPI_WRITE(sc, AR71XX_SPI_CTRL, 0x43); + + /* + * Ensure the config register write has gone out before configuring + * the chip select mask. + */ + SPI_BARRIER_WRITE(sc); SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, SPI_IO_CTRL_CSMASK); + /* + * .. and ensure the write has gone out before continuing. + */ + SPI_BARRIER_WRITE(sc); + device_add_child(dev, "spibus", -1); return (bus_generic_attach(dev)); } @@ -121,7 +147,15 @@ ar71xx_spi_chip_activate(struct ar71xx_s */ ioctrl &= ~(SPI_IO_CTRL_CS0 << cs); + /* + * Make sure any other writes have gone out to the + * device before changing the chip select line; + * then ensure that it has made it out to the device + * before continuing. + */ + SPI_BARRIER_WRITE(sc); SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, ioctrl); + SPI_BARRIER_WRITE(sc); } static void @@ -150,14 +184,18 @@ ar71xx_spi_txrx(struct ar71xx_spi_softc iod = ioctrl | SPI_IO_CTRL_DO; else iod = ioctrl & ~SPI_IO_CTRL_DO; + SPI_BARRIER_WRITE(sc); SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, iod); + SPI_BARRIER_WRITE(sc); SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, iod | SPI_IO_CTRL_CLK); } /* * Provide falling edge for connected device by clear clock bit. */ + SPI_BARRIER_WRITE(sc); SPI_WRITE(sc, AR71XX_SPI_IO_CTRL, iod); + SPI_BARRIER_WRITE(sc); rds = SPI_READ(sc, AR71XX_SPI_RDS); return (rds & 0xff); @@ -206,8 +244,25 @@ ar71xx_spi_detach(device_t dev) { struct ar71xx_spi_softc *sc = device_get_softc(dev); + /* + * Ensure any other writes to the device are finished + * before we tear down the SPI device. + */ + SPI_BARRIER_WRITE(sc); + + /* + * Restore the control register; ensure it has hit the + * hardware before continuing. + */ SPI_WRITE(sc, AR71XX_SPI_CTRL, sc->sc_reg_ctrl); + SPI_BARRIER_WRITE(sc); + + /* + * And now, put the flash back into mapped IO mode and + * ensure _that_ has completed before we finish up. + */ SPI_WRITE(sc, AR71XX_SPI_FS, 0); + SPI_BARRIER_WRITE(sc); if (sc->sc_mem_res) bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);