diff options
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/spi.h | 5 | ||||
-rw-r--r-- | src/soc/amd/common/block/lpc/spi_dma.c | 12 | ||||
-rw-r--r-- | src/soc/amd/common/block/spi/fch_spi_ctrl.c | 8 | ||||
-rw-r--r-- | src/soc/amd/common/block/spi/fch_spi_util.c | 3 |
4 files changed, 27 insertions, 1 deletions
diff --git a/src/soc/amd/common/block/include/amdblocks/spi.h b/src/soc/amd/common/block/include/amdblocks/spi.h index 35a3782f7a..81da5dd53f 100644 --- a/src/soc/amd/common/block/include/amdblocks/spi.h +++ b/src/soc/amd/common/block/include/amdblocks/spi.h @@ -3,6 +3,7 @@ #ifndef AMD_BLOCK_SPI_H #define AMD_BLOCK_SPI_H +#include <thread.h> #include <types.h> #define SPI_CNTRL0 0x00 @@ -118,4 +119,8 @@ void spi_write32(uint8_t reg, uint32_t val); void fch_spi_config_modes(void); void mainboard_spi_fast_speed_override(uint8_t *fast_speed); + +/* Ensure you hold the mutex when performing SPI transactions */ +extern struct thread_mutex spi_hw_mutex; + #endif /* AMD_BLOCK_SPI_H */ diff --git a/src/soc/amd/common/block/lpc/spi_dma.c b/src/soc/amd/common/block/lpc/spi_dma.c index 5c697790c8..baf1eb8036 100644 --- a/src/soc/amd/common/block/lpc/spi_dma.c +++ b/src/soc/amd/common/block/lpc/spi_dma.c @@ -122,6 +122,12 @@ static void start_spi_dma_transaction(struct spi_dma_transaction *transaction) ctrl |= LPC_ROM_DMA_CTRL_ERROR; /* Clear error */ ctrl |= LPC_ROM_DMA_CTRL_START; + /* + * Ensure we have exclusive access to the SPI controller before starting the LPC SPI DMA + * transaction. + */ + thread_mutex_lock(&spi_hw_mutex); + pci_write_config32(SOC_LPC_DEV, LPC_ROM_DMA_EC_HOST_CONTROL, ctrl); } @@ -135,6 +141,12 @@ static bool continue_spi_dma_transaction(const struct region_device *rd, if (spi_dma_is_busy()) return true; + /* + * Unlock the SPI mutex between DMA transactions to allow other users of the SPI + * controller to interleave their transactions. + */ + thread_mutex_unlock(&spi_hw_mutex); + if (spi_dma_has_error()) { printk(BIOS_ERR, "ERROR: SPI DMA failure: dest: %p, source: %#zx, size: %zu\n", diff --git a/src/soc/amd/common/block/spi/fch_spi_ctrl.c b/src/soc/amd/common/block/spi/fch_spi_ctrl.c index 565fdbe149..d95b64275b 100644 --- a/src/soc/amd/common/block/spi/fch_spi_ctrl.c +++ b/src/soc/amd/common/block/spi/fch_spi_ctrl.c @@ -142,7 +142,13 @@ static int spi_ctrlr_xfer(const struct spi_slave *slave, const void *dout, static int xfer_vectors(const struct spi_slave *slave, struct spi_op vectors[], size_t count) { - return spi_flash_vector_helper(slave, vectors, count, spi_ctrlr_xfer); + int rc; + + thread_mutex_lock(&spi_hw_mutex); + rc = spi_flash_vector_helper(slave, vectors, count, spi_ctrlr_xfer); + thread_mutex_unlock(&spi_hw_mutex); + + return rc; } static int protect_a_range(u32 value) diff --git a/src/soc/amd/common/block/spi/fch_spi_util.c b/src/soc/amd/common/block/spi/fch_spi_util.c index 5cef565baf..862962f0bd 100644 --- a/src/soc/amd/common/block/spi/fch_spi_util.c +++ b/src/soc/amd/common/block/spi/fch_spi_util.c @@ -6,6 +6,9 @@ #include <assert.h> #include <stdint.h> +/* Global SPI controller mutex */ +struct thread_mutex spi_hw_mutex; + static uintptr_t spi_base; void spi_set_base(void *base) |