summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/amd/common/block/include/amdblocks/spi.h5
-rw-r--r--src/soc/amd/common/block/lpc/spi_dma.c12
-rw-r--r--src/soc/amd/common/block/spi/fch_spi_ctrl.c8
-rw-r--r--src/soc/amd/common/block/spi/fch_spi_util.c3
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)