summaryrefslogtreecommitdiff
path: root/src/soc/amd
diff options
context:
space:
mode:
authorRaul E Rangel <rrangel@chromium.org>2021-11-02 11:51:48 -0600
committerRaul Rangel <rrangel@chromium.org>2021-11-15 16:16:54 +0000
commit964eb67de6375e0eadffe0f329e460f340217daf (patch)
tree2405c350dc79714c479d78bda0da34e18cc42199 /src/soc/amd
parenta3811fe5e74575cc6173f8e2fc153c6f9884f89c (diff)
soc/amd/common/block: Add spi_hw mutex
There are currently two users of the SPI hardware, the LPC SPI DMA controller, and the boot_device_rw device. We need to ensure exclusivity to the SPI hardware otherwise the SPI DMA controller can be interrupted and it will silently skip transferring some blocks. Depending on the SPI speed, this change might add a small delay when clearing the elog since a DMA transaction might be in flight. I'll continue optimizing the boot flow to avoid the delay. BUG=b:179699789 TEST=Hack up the code to interleave SPI transactions and verify this patch fixes the silent data corruption. Signed-off-by: Raul E Rangel <rrangel@chromium.org> Change-Id: I5eee812a6979c8c0fb313dd2fbccc14b73d7d741 Reviewed-on: https://review.coreboot.org/c/coreboot/+/58926 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
Diffstat (limited to 'src/soc/amd')
-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)