diff options
Diffstat (limited to 'chip/g/spi_controller.c')
-rw-r--r-- | chip/g/spi_controller.c | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/chip/g/spi_controller.c b/chip/g/spi_controller.c index 912520e52f..4f7a5ee512 100644 --- a/chip/g/spi_controller.c +++ b/chip/g/spi_controller.c @@ -33,10 +33,12 @@ static enum spi_clock_mode clock_mode[SPI_NUM_PORTS]; * The Cr50 SPI controller is not DMA auto-fill/drain capable, so async and * flush are not defined on purpose. */ -int spi_transaction(const struct spi_device_t *spi_device, - const uint8_t *txdata, int txlen, - uint8_t *rxdata, int rxlen) +int spi_sub_transaction(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen, bool deassert_cs) { + static bool cs_asserted; + int port = spi_device->port; int rv = EC_SUCCESS; timestamp_t timeout; @@ -74,8 +76,9 @@ int spi_transaction(const struct spi_device_t *spi_device, rxoffset = txlen; } - /* Grab the port's mutex. */ - mutex_lock(&spi_mutex[port]); + if (!cs_asserted) + /* Grab the port's mutex. */ + mutex_lock(&spi_mutex[port]); #ifdef CONFIG_STREAM_SIGNATURE /* @@ -88,10 +91,13 @@ int spi_transaction(const struct spi_device_t *spi_device, /* Copy the txdata into the 128B Transmit Buffer. */ memmove((uint8_t *)GREG32_ADDR_I(SPI, port, TX_DATA), txdata, txlen); + if (!cs_asserted) { #ifndef CONFIG_SPI_CONTROLLER_NO_CS_GPIOS - /* Drive chip select low. */ - gpio_set_level(spi_device->gpio_cs, 0); -#endif /* CONFIG_SPI_CONTROLLER_NO_CS_GPIOS */ + /* Drive chip select low. */ + gpio_set_level(spi_device->gpio_cs, 0); +#endif + cs_asserted = true; + } /* Initiate the transaction. */ GWRITE_FIELD_I(SPI, port, ISTATE_CLR, TXDONE, 1); @@ -120,16 +126,26 @@ int spi_transaction(const struct spi_device_t *spi_device, rxlen); err_cs_high: + if ((rv != EC_SUCCESS) || deassert_cs) { #ifndef CONFIG_SPI_CONTROLLER_NO_CS_GPIOS - /* Drive chip select high. */ - gpio_set_level(spi_device->gpio_cs, 1); + /* Drive chip select high. */ + gpio_set_level(spi_device->gpio_cs, 1); #endif /* CONFIG_SPI_CONTROLLER_NO_CS_GPIOS */ - - /* Release the port's mutex. */ - mutex_unlock(&spi_mutex[port]); + cs_asserted = false; + /* Release the port's mutex. */ + mutex_unlock(&spi_mutex[port]); + } return rv; } +int spi_transaction(const struct spi_device_t *spi_device, + const uint8_t *txdata, int txlen, uint8_t *rxdata, + int rxlen) +{ + return spi_sub_transaction(spi_device, txdata, txlen, rxdata, rxlen, + true); +} + /* * Configure the SPI port's clock mode. The SPI port must be re-enabled after * changing the clocking mode. |