Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/intel/spi.c
Show First 20 Lines • Show All 298 Lines • ▼ Show 20 Lines | intelspi_set_cs(struct intelspi_softc *sc, int level) | ||||
INTELSPI_WRITE(sc, SPI_CS_CTRL(sc), reg); | INTELSPI_WRITE(sc, SPI_CS_CTRL(sc), reg); | ||||
} | } | ||||
int | int | ||||
intelspi_transfer(device_t dev, device_t child, struct spi_command *cmd) | intelspi_transfer(device_t dev, device_t child, struct spi_command *cmd) | ||||
{ | { | ||||
struct intelspi_softc *sc; | struct intelspi_softc *sc; | ||||
int err; | int err, poll_limit; | ||||
uint32_t sscr0, sscr1, mode, clock; | uint32_t sscr0, sscr1, mode, clock, cs_delay; | ||||
bool restart = false; | bool restart = false; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
err = 0; | err = 0; | ||||
KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, | KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, | ||||
("TX/RX command sizes should be equal")); | ("TX/RX command sizes should be equal")); | ||||
KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, | KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, | ||||
("TX/RX data sizes should be equal")); | ("TX/RX data sizes should be equal")); | ||||
INTELSPI_LOCK(sc); | INTELSPI_LOCK(sc); | ||||
/* If the controller is in use wait until it is available. */ | /* If the controller is in use wait until it is available. */ | ||||
while (sc->sc_flags & INTELSPI_BUSY) { | while (sc->sc_flags & INTELSPI_BUSY) { | ||||
if ((cmd->flags & SPI_FLAG_NO_SLEEP) == SPI_FLAG_NO_SLEEP) | |||||
return (EBUSY); | |||||
err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", 0); | err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", 0); | ||||
if (err == EINTR) { | if (err == EINTR) { | ||||
INTELSPI_UNLOCK(sc); | INTELSPI_UNLOCK(sc); | ||||
return (err); | return (err); | ||||
} | } | ||||
} | } | ||||
/* Now we have control over SPI controller. */ | /* Now we have control over SPI controller. */ | ||||
▲ Show 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | intelspi_transfer(device_t dev, device_t child, struct spi_command *cmd) | ||||
/* Save a pointer to the SPI command. */ | /* Save a pointer to the SPI command. */ | ||||
sc->sc_cmd = cmd; | sc->sc_cmd = cmd; | ||||
sc->sc_read = 0; | sc->sc_read = 0; | ||||
sc->sc_written = 0; | sc->sc_written = 0; | ||||
sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz; | sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz; | ||||
/* Enable CS */ | /* Enable CS */ | ||||
intelspi_set_cs(sc, CS_LOW); | intelspi_set_cs(sc, CS_LOW); | ||||
/* Wait the CS delay */ | |||||
spibus_get_cs_delay(child, &cs_delay); | |||||
DELAY(cs_delay); | |||||
/* Transfer as much as possible to FIFOs */ | /* Transfer as much as possible to FIFOs */ | ||||
if ((cmd->flags & SPI_FLAG_NO_SLEEP) == SPI_FLAG_NO_SLEEP) { | |||||
/* We cannot wait with mtx_sleep if we're called from e.g. an ithread */ | |||||
poll_limit = 100; | |||||
while (!intelspi_transact(sc) && poll_limit-- > 0) | |||||
DELAY(1000); | |||||
if (poll_limit == 0) | |||||
device_printf(dev, "polling was stuck, transaction not finished\n"); | |||||
} else { | |||||
if (!intelspi_transact(sc)) { | if (!intelspi_transact(sc)) { | ||||
/* If FIFO is not large enough - enable interrupts */ | /* If FIFO is not large enough - enable interrupts */ | ||||
sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1); | sscr1 = INTELSPI_READ(sc, INTELSPI_SSPREG_SSCR1); | ||||
sscr1 |= (SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE); | sscr1 |= (SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE); | ||||
INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1); | INTELSPI_WRITE(sc, INTELSPI_SSPREG_SSCR1, sscr1); | ||||
/* and wait for transaction to complete */ | /* and wait for transaction to complete */ | ||||
err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", hz * 2); | err = mtx_sleep(dev, &sc->sc_mtx, 0, "intelspi", hz * 2); | ||||
} | } | ||||
} | |||||
/* de-asser CS */ | /* De-assert CS */ | ||||
if ((cmd->flags & SPI_FLAG_KEEP_CS) == 0) | |||||
intelspi_set_cs(sc, CS_HIGH); | intelspi_set_cs(sc, CS_HIGH); | ||||
/* Clear transaction details */ | /* Clear transaction details */ | ||||
sc->sc_cmd = NULL; | sc->sc_cmd = NULL; | ||||
sc->sc_read = 0; | sc->sc_read = 0; | ||||
sc->sc_written = 0; | sc->sc_written = 0; | ||||
sc->sc_len = 0; | sc->sc_len = 0; | ||||
/* Make sure the SPI engine and interrupts are disabled. */ | /* Make sure the SPI engine and interrupts are disabled. */ | ||||
▲ Show 20 Lines • Show All 141 Lines • Show Last 20 Lines |