summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2017-03-10 14:14:34 +0100
committerchrome-bot <chrome-bot@chromium.org>2017-03-13 17:53:58 -0700
commit23ea0c9fa39163d3afb3dc5a96dce2962fb5014c (patch)
treed3fccaaf9d37f7d9996ad8c78d0f07da9dff57dc
parent6d7b4bb3d6c6364da3c16a56572d430f549264fb (diff)
downloadchrome-ec-23ea0c9fa39163d3afb3dc5a96dce2962fb5014c.tar.gz
spi: extend spi master API on STM32
Extend the SPI master API to be able to do fancier transactions: - allow to read the incoming bits while transmitting. If SPI_READBACK_ALL is set in 'rxlen' when calling spi_transaction(), then the received data during transmission is recorded in rxdata buffer and the function assumes that the real 'rxlen' is equal to 'txlen'. - add spi_transaction_wait() which is similar to spi_transaction_flush() but without de-asserting the chip select, so we can chain several transfers in a single transaction. Implement them for STM32. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=none BUG=b:35648259 TEST=on Eve, use the FP sensor with the passthru. Change-Id: Iebff617acd3230277d36a4f565766b7748721a1d Reviewed-on: https://chromium-review.googlesource.com/452898 Commit-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Todd Broch <tbroch@chromium.org>
-rw-r--r--chip/stm32/spi_master.c23
-rw-r--r--include/spi.h10
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