Date: Thu, 15 Nov 2018 17:05:03 +0000 (UTC) From: Luiz Otavio O Souza <loos@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r340458 - head/sys/arm/mv Message-ID: <201811151705.wAFH53fH072226@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: loos Date: Thu Nov 15 17:05:02 2018 New Revision: 340458 URL: https://svnweb.freebsd.org/changeset/base/340458 Log: Set the SPI clock speed and polarity on each transfer to catch up with recent changes in spibus and allow the use of different SPI modes on the same bus. Reported by: ian Sponsored by: Rubicon Communications, LLC (Netgate) Modified: head/sys/arm/mv/mv_spi.c Modified: head/sys/arm/mv/mv_spi.c ============================================================================== --- head/sys/arm/mv/mv_spi.c Thu Nov 15 16:42:59 2018 (r340457) +++ head/sys/arm/mv/mv_spi.c Thu Nov 15 17:05:02 2018 (r340458) @@ -44,6 +44,8 @@ __FBSDID("$FreeBSD$"); #include <dev/spibus/spi.h> #include <dev/spibus/spibusvar.h> +#include <arm/mv/mvvar.h> + #include "spibus_if.h" struct mv_spi_softc { @@ -70,11 +72,23 @@ struct mv_spi_softc { #define MV_SPI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) #define MV_SPI_CONTROL 0 +#define MV_SPI_CTRL_CS_MASK 7 #define MV_SPI_CTRL_CS_SHIFT 2 #define MV_SPI_CTRL_SMEMREADY (1 << 1) #define MV_SPI_CTRL_CS_ACTIVE (1 << 0) #define MV_SPI_CONF 0x4 +#define MV_SPI_CONF_MODE_SHIFT 12 +#define MV_SPI_CONF_MODE_MASK (3 << MV_SPI_CONF_MODE_SHIFT) #define MV_SPI_CONF_BYTELEN (1 << 5) +#define MV_SPI_CONF_CLOCK_SPR_MASK 0xf +#define MV_SPI_CONF_CLOCK_SPPR_MASK 1 +#define MV_SPI_CONF_CLOCK_SPPR_SHIFT 4 +#define MV_SPI_CONF_CLOCK_SPPRHI_MASK 3 +#define MV_SPI_CONF_CLOCK_SPPRHI_SHIFT 6 +#define MV_SPI_CONF_CLOCK_MASK \ + ((MV_SPI_CONF_CLOCK_SPPRHI_MASK << MV_SPI_CONF_CLOCK_SPPRHI_SHIFT) | \ + (MV_SPI_CONF_CLOCK_SPPR_MASK << MV_SPI_CONF_CLOCK_SPPR_SHIFT) | \ + MV_SPI_CONF_CLOCK_SPR_MASK) #define MV_SPI_DATAOUT 0x8 #define MV_SPI_DATAIN 0xc #define MV_SPI_INTR_STAT 0x10 @@ -244,10 +258,27 @@ mv_spi_intr(void *arg) } static int +mv_spi_psc_calc(uint32_t clock, uint32_t *spr, uint32_t *sppr) +{ + uint32_t divider, tclk; + + tclk = get_tclk_armada38x(); + for (*spr = 2; *spr <= 15; (*spr)++) { + for (*sppr = 0; *sppr <= 7; (*sppr)++) { + divider = *spr * (1 << *sppr); + if (tclk / divider <= clock) + return (0); + } + } + + return (EINVAL); +} + +static int mv_spi_transfer(device_t dev, device_t child, struct spi_command *cmd) { struct mv_spi_softc *sc; - uint32_t cs, reg; + uint32_t clock, cs, mode, reg, spr, sppr; int resid, timeout; KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, @@ -255,9 +286,23 @@ mv_spi_transfer(device_t dev, device_t child, struct s KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, ("TX/RX data sizes should be equal")); - /* Get the proper chip select for this child. */ + /* Get the proper chip select, mode and clock for this transfer. */ spibus_get_cs(child, &cs); cs &= ~SPIBUS_CS_HIGH; + spibus_get_mode(child, &mode); + if (mode > 3) { + device_printf(dev, + "Invalid mode %u requested by %s\n", mode, + device_get_nameunit(child)); + return (EINVAL); + } + spibus_get_clock(child, &clock); + if (clock == 0 || mv_spi_psc_calc(clock, &spr, &sppr) != 0) { + device_printf(dev, + "Invalid clock %uHz requested by %s\n", clock, + device_get_nameunit(child)); + return (EINVAL); + } sc = device_get_softc(dev); MV_SPI_LOCK(sc); @@ -275,7 +320,20 @@ mv_spi_transfer(device_t dev, device_t child, struct s sc->sc_written = 0; sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz; - MV_SPI_WRITE(sc, MV_SPI_CONTROL, cs << MV_SPI_CTRL_CS_SHIFT); + /* Set SPI Mode and Clock. */ + reg = MV_SPI_READ(sc, MV_SPI_CONF); + reg &= ~(MV_SPI_CONF_MODE_MASK | MV_SPI_CONF_CLOCK_MASK); + reg |= mode << MV_SPI_CONF_MODE_SHIFT; + reg |= spr & MV_SPI_CONF_CLOCK_SPR_MASK; + reg |= (sppr & MV_SPI_CONF_CLOCK_SPPR_MASK) << + MV_SPI_CONF_CLOCK_SPPR_SHIFT; + reg |= (sppr & MV_SPI_CONF_CLOCK_SPPRHI_MASK) << + MV_SPI_CONF_CLOCK_SPPRHI_SHIFT; + MV_SPI_WRITE(sc, MV_SPI_CONTROL, reg); + + /* Set CS number and assert CS. */ + reg = (cs & MV_SPI_CTRL_CS_MASK) << MV_SPI_CTRL_CS_SHIFT; + MV_SPI_WRITE(sc, MV_SPI_CONTROL, reg); reg = MV_SPI_READ(sc, MV_SPI_CONTROL); MV_SPI_WRITE(sc, MV_SPI_CONTROL, reg | MV_SPI_CTRL_CS_ACTIVE);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201811151705.wAFH53fH072226>