diff options
-rw-r--r-- | chip/stm32/spi_master.c | 23 | ||||
-rw-r--r-- | include/spi.h | 10 |
2 files changed, 27 insertions, 6 deletions
diff --git a/chip/stm32/spi_master.c b/chip/stm32/spi_master.c index c18191920a..647dcd9e7a 100644 --- a/chip/stm32/spi_master.c +++ b/chip/stm32/spi_master.c @@ -212,13 +212,20 @@ int spi_transaction_async(const struct spi_device_t *spi_device, { int rv = EC_SUCCESS; int port = spi_device->port; + int full_readback = 0; stm32_spi_regs_t *spi = SPI_REGS[port]; char *buf; - rv = shared_mem_acquire(MAX(txlen, rxlen), &buf); - if (rv != EC_SUCCESS) - return rv; + if (rxlen == SPI_READBACK_ALL) { + buf = rxdata; + rxlen = txlen; + full_readback = 1; + } else { + rv = shared_mem_acquire(MAX(txlen, rxlen), &buf); + if (rv != EC_SUCCESS) + return rv; + } /* Drive SS low */ gpio_set_level(spi_device->gpio_cs, 0); @@ -235,14 +242,15 @@ int spi_transaction_async(const struct spi_device_t *spi_device, if (rv != EC_SUCCESS) goto err_free; - if (rxlen) { + if (!full_readback && rxlen) { rv = spi_dma_start(port, buf, rxdata, rxlen); if (rv != EC_SUCCESS) goto err_free; } err_free: - shared_mem_release(buf); + if (!full_readback) + shared_mem_release(buf); return rv; } @@ -256,6 +264,11 @@ int spi_transaction_flush(const struct spi_device_t *spi_device) return rv; } +int spi_transaction_wait(const struct spi_device_t *spi_device) +{ + return spi_dma_wait(spi_device->port); +} + int spi_transaction(const struct spi_device_t *spi_device, const uint8_t *txdata, int txlen, uint8_t *rxdata, int rxlen) diff --git a/include/spi.h b/include/spi.h index 8fd7b2e311..49bddd3cc3 100644 --- a/include/spi.h +++ b/include/spi.h @@ -64,17 +64,22 @@ extern const unsigned int spi_devices_used; */ int spi_enable(int port, int enable); +#define SPI_READBACK_ALL (-1) + /* Issue a SPI transaction. Assumes SPI port has already been enabled. * * Transmits <txlen> bytes from <txdata>, throwing away the corresponding * received data, then transmits <rxlen> dummy bytes, saving the received data * in <rxdata>. + * If SPI_READBACK_ALL is set in <rxlen>, the received data during transmission + * is recorded in rxdata buffer and it assumes that the real <rxlen> is equal + * to <txlen>. * * @param spi_device the SPI device to use * @param txdata buffer to transmit * @param txlen number of bytes in txdata. * @param rxdata receive buffer. - * @param rxlen number of bytes in rxdata. + * @param rxlen number of bytes in rxdata or SPI_READBACK_ALL. */ int spi_transaction(const struct spi_device_t *spi_device, const uint8_t *txdata, int txlen, @@ -91,6 +96,9 @@ int spi_transaction_async(const struct spi_device_t *spi_device, /* Wait for async response received */ int spi_transaction_flush(const struct spi_device_t *spi_device); +/* Wait for async response received but do not de-assert chip select */ +int spi_transaction_wait(const struct spi_device_t *spi_device); + #ifdef CONFIG_SPI /** * Called when the NSS level changes, signalling the start or end of a SPI |