summaryrefslogtreecommitdiffstats
path: root/sys/arm/mv
diff options
context:
space:
mode:
authorLuiz Souza <luiz@netgate.com>2017-10-20 20:30:49 -0200
committerLuiz Souza <luiz@netgate.com>2017-10-20 20:37:20 -0200
commit7eae9364d25765fe7150ddc72ae4302922d8209b (patch)
tree057581f68d599cf7f54c0ad5577f1d69753fbd07 /sys/arm/mv
parentb35450b5df04e9b82eebd8b0275c9f26d3ac47f1 (diff)
downloadFreeBSD-src-7eae9364d25765fe7150ddc72ae4302922d8209b.zip
FreeBSD-src-7eae9364d25765fe7150ddc72ae4302922d8209b.tar.gz
Use the single byte FIFO, the correct implementation of the two bytes FIFO in FreeBSD would require more work (command and data buffers had both to be aligned).
(cherry picked from commit 3dd92b2120658589d5b8c1f38012189e748b1ce9)
Diffstat (limited to 'sys/arm/mv')
-rw-r--r--sys/arm/mv/mv_spi.c101
1 files changed, 32 insertions, 69 deletions
diff --git a/sys/arm/mv/mv_spi.c b/sys/arm/mv/mv_spi.c
index 64d4424..a230a89 100644
--- a/sys/arm/mv/mv_spi.c
+++ b/sys/arm/mv/mv_spi.c
@@ -59,7 +59,6 @@ struct mv_spi_softc {
uint32_t sc_flags;
uint32_t sc_written;
void *sc_intrhand;
- bool sc_bytelen;
};
#define MV_SPI_BUSY 0x1
@@ -108,6 +107,7 @@ mv_spi_attach(device_t dev)
{
struct mv_spi_softc *sc;
int rid;
+ uint32_t reg;
sc = device_get_softc(dev);
sc->sc_dev = dev;
@@ -133,7 +133,12 @@ mv_spi_attach(device_t dev)
}
/* Deactivate the bus - just in case... */
- MV_SPI_WRITE(sc, MV_SPI_CONTROL, 0);
+ reg = MV_SPI_READ(sc, MV_SPI_CONTROL);
+ MV_SPI_WRITE(sc, MV_SPI_CONTROL, reg & ~MV_SPI_CTRL_CS_ACTIVE);
+
+ /* Disable the two bytes FIFO. */
+ reg = MV_SPI_READ(sc, MV_SPI_CONF);
+ MV_SPI_WRITE(sc, MV_SPI_CONF, reg & ~MV_SPI_CONF_BYTELEN);
/* Clear and disable interrupts. */
MV_SPI_WRITE(sc, MV_SPI_INTR_MASK, 0);
@@ -178,60 +183,43 @@ mv_spi_detach(device_t dev)
}
static __inline void
-mv_spi_rx_bytes(struct mv_spi_softc *sc)
+mv_spi_rx_byte(struct mv_spi_softc *sc)
{
struct spi_command *cmd;
- uint32_t data, read;
- uint8_t bytes, *p;
+ uint32_t read;
+ uint8_t *p;
- data = 0;
cmd = sc->sc_cmd;
- bytes = (sc->sc_len >= 2) ? 2 : 1;
- if (sc->sc_read < sc->sc_len)
- data = MV_SPI_READ(sc, MV_SPI_DATAIN);
- while (sc->sc_read < sc->sc_len && bytes > 0) {
- p = (uint8_t *)cmd->rx_cmd;
- read = sc->sc_read++;
- if (read >= cmd->rx_cmd_sz) {
- p = (uint8_t *)cmd->rx_data;
- read -= cmd->rx_cmd_sz;
- }
- p[read] = (data >> ((2 - bytes) * 8)) & 0xff;
- bytes--;
+ p = (uint8_t *)cmd->rx_cmd;
+ read = sc->sc_read++;
+ if (read >= cmd->rx_cmd_sz) {
+ p = (uint8_t *)cmd->rx_data;
+ read -= cmd->rx_cmd_sz;
}
+ p[read] = MV_SPI_READ(sc, MV_SPI_DATAIN) & 0xff;
}
static __inline void
-mv_spi_tx_bytes(struct mv_spi_softc *sc)
+mv_spi_tx_byte(struct mv_spi_softc *sc)
{
struct spi_command *cmd;
- uint32_t data, written;
- uint8_t bytes, count, *p;
+ uint32_t written;
+ uint8_t *p;
- data = 0;
- count = 0;
cmd = sc->sc_cmd;
- bytes = (sc->sc_len >= 2) ? 2 : 1;
- while (sc->sc_written < sc->sc_len && bytes > 0) {
- p = (uint8_t *)cmd->tx_cmd;
- written = sc->sc_written++;
- if (written >= cmd->tx_cmd_sz) {
- p = (uint8_t *)cmd->tx_data;
- written -= cmd->tx_cmd_sz;
- }
- data |= p[written] << ((2 - bytes) * 8);
- bytes--;
- count++;
+ p = (uint8_t *)cmd->tx_cmd;
+ written = sc->sc_written++;
+ if (written >= cmd->tx_cmd_sz) {
+ p = (uint8_t *)cmd->tx_data;
+ written -= cmd->tx_cmd_sz;
}
- if (count > 0)
- MV_SPI_WRITE(sc, MV_SPI_DATAOUT, data);
+ MV_SPI_WRITE(sc, MV_SPI_DATAOUT, p[written]);
}
static void
mv_spi_intr(void *arg)
{
struct mv_spi_softc *sc;
- uint32_t reg;
sc = (struct mv_spi_softc *)arg;
MV_SPI_LOCK(sc);
@@ -243,17 +231,10 @@ mv_spi_intr(void *arg)
}
/* RX */
- mv_spi_rx_bytes(sc);
-
- if (sc->sc_bytelen && (sc->sc_len - sc->sc_written) < 2) {
- reg = MV_SPI_READ(sc, MV_SPI_CONF);
- reg &= ~MV_SPI_CONF_BYTELEN;
- MV_SPI_WRITE(sc, MV_SPI_CONF, reg);
- sc->sc_bytelen = false;
- }
+ mv_spi_rx_byte(sc);
/* TX */
- mv_spi_tx_bytes(sc);
+ mv_spi_tx_byte(sc);
/* Check for end of transfer. */
if (sc->sc_written == sc->sc_len && sc->sc_read == sc->sc_len)
@@ -298,30 +279,15 @@ mv_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
reg = MV_SPI_READ(sc, MV_SPI_CONTROL);
MV_SPI_WRITE(sc, MV_SPI_CONTROL, reg | MV_SPI_CTRL_CS_ACTIVE);
- /* Is the buffer big enough to enable the two byte FIFO ? */
- if (sc->sc_len >= 2)
- sc->sc_bytelen = true;
- reg = MV_SPI_READ(sc, MV_SPI_CONF);
- if (sc->sc_bytelen)
- reg |= MV_SPI_CONF_BYTELEN;
- else
- reg &= ~MV_SPI_CONF_BYTELEN;
- MV_SPI_WRITE(sc, MV_SPI_CONF, reg);
-
while ((resid = sc->sc_len - sc->sc_written) > 0) {
- if (sc->sc_bytelen && resid < 2) {
- reg = MV_SPI_READ(sc, MV_SPI_CONF);
- reg &= ~MV_SPI_CONF_BYTELEN;
- MV_SPI_WRITE(sc, MV_SPI_CONF, reg);
- sc->sc_bytelen = false;
- }
+ MV_SPI_WRITE(sc, MV_SPI_INTR_STAT, 0);
/*
* Write to start the transmission and read the byte
* back when ready.
*/
- mv_spi_tx_bytes(sc);
+ mv_spi_tx_byte(sc);
timeout = 1000;
while (--timeout > 0) {
reg = MV_SPI_READ(sc, MV_SPI_CONTROL);
@@ -331,17 +297,14 @@ mv_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
}
if (timeout == 0)
break;
- mv_spi_rx_bytes(sc);
+ mv_spi_rx_byte(sc);
}
/* Stop the controller. */
- MV_SPI_WRITE(sc, MV_SPI_INTR_MASK, 0);
- MV_SPI_WRITE(sc, MV_SPI_INTR_STAT, 0);
reg = MV_SPI_READ(sc, MV_SPI_CONTROL);
MV_SPI_WRITE(sc, MV_SPI_CONTROL, reg & ~MV_SPI_CTRL_CS_ACTIVE);
- reg = MV_SPI_READ(sc, MV_SPI_CONF);
- MV_SPI_WRITE(sc, MV_SPI_CONF, reg & ~MV_SPI_CONF_BYTELEN);
- sc->sc_bytelen = false;
+ MV_SPI_WRITE(sc, MV_SPI_INTR_MASK, 0);
+ MV_SPI_WRITE(sc, MV_SPI_INTR_STAT, 0);
/* Release the controller and wakeup the next thread waiting for it. */
sc->sc_flags = 0;
OpenPOWER on IntegriCloud