summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@chromium.org>2018-10-16 15:55:18 +0800
committerchrome-bot <chrome-bot@chromium.org>2018-10-17 05:55:04 -0700
commit8b7f9fa4e650b7f714b05cb19088824c195742fc (patch)
treef9bfb259729e5b78fb5f449b454e58bac0ac2433
parent9c84d5eb7158c91fe28c62b23e04c84355d5ada7 (diff)
downloadchrome-ec-8b7f9fa4e650b7f714b05cb19088824c195742fc.tar.gz
kukui/emmc: Wait for SPI FIFO to become empty (instead of 200us sleep)
It appears that the SPI FIFO takes about ~160us to become empty (because the eMMC master stops clocking CLK), which is why adding a delay of 200us (instead of 100us) helped get rid of the issue described in: c08473231923 "kukui/emmc: Wait 200us between dma_disable and flush SPI TX FIFO" Instead of a fixed sleep time, just wait for the FIFO to become empty, up to 1 ms (if we have to wait that long, we may hit the bug again, but something else is probably broken). Also, just disable TX DMA in emmc_disable_spi: we can only boot the AP once per EC reboot anyway, so it does not matter if we are able to feed the AP another bootblock. BRANCH=none BUG=b:117253718 TEST=Put kukui in a reboot loop, ~1000 sucessful boots without ever requiring a 4th transfer. Change-Id: I94a4b367264704d141321a54b2f2ec9616429bd9 Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1282525 Reviewed-by: Yilun Lin <yllin@chromium.org>
-rw-r--r--board/kukui/emmc.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/board/kukui/emmc.c b/board/kukui/emmc.c
index af2d4b1701..72b620ee06 100644
--- a/board/kukui/emmc.c
+++ b/board/kukui/emmc.c
@@ -35,6 +35,7 @@
#include "endian.h"
#include "gpio.h"
#include "hooks.h"
+#include "hwtimer.h"
#include "system.h"
#include "task.h"
#include "timer.h"
@@ -103,16 +104,19 @@ static void bootblock_transfer(void)
/* Abort an ongoing transfer. */
static void bootblock_stop(void)
{
+ const uint32_t timeout = 1 * MSEC;
+ uint32_t start;
+
dma_disable(STM32_DMAC_SPI_EMMC_TX);
/*
- * Wait a bit to for DMA to stop writing (we can't really wait for the
- * buffer to get empty, as the bus may not be clocked anymore).
- *
- * TODO(b:117253718): For some reason, a delay >=200us is necessary,
- * else the SPI/DMA skips bytes when the transfer is resumed.
+ * Wait for SPI FIFO to become empty.
+ * We timeout after 1 ms in case the bus is not clocked anymore.
*/
- udelay(200);
+ start = __hw_clock_source_read();
+ while (STM32_SPI_EMMC_REGS->sr & STM32_SPI_SR_FTLVL &&
+ __hw_clock_source_read() - start < timeout)
+ ;
/* Then flush SPI FIFO, and make sure DAT line stays idle (high). */
STM32_SPI_EMMC_REGS->dr = 0xff;
@@ -266,8 +270,8 @@ static void emmc_disable_spi(void)
hook_call_deferred(&emmc_check_status_data, -1);
gpio_disable_interrupt(GPIO_EMMC_CMD);
- /* Disable any pending transfer. */
- bootblock_stop();
+ /* Disable TX DMA. */
+ dma_disable(STM32_DMAC_SPI_EMMC_TX);
/* Disable internal chip select. */
STM32_SPI_EMMC_REGS->cr1 |= STM32_SPI_CR1_SSI;
/* Disable RX DMA. */