diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2014-12-22 17:58:11 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-01-08 22:36:31 +0000 |
commit | 61d50195e1fb568327d2cdce5b5a5095f1be6e05 (patch) | |
tree | a17bd73885baa3fbec53c11a56b1bc6a8629c40b | |
parent | 3c292e0398e066279124ced299e860585890e4c6 (diff) | |
download | chrome-ec-61d50195e1fb568327d2cdce5b5a5095f1be6e05.tar.gz |
disable DMA before sysjumping
It's not safe to sysjump with a DMA enabled as it can led to memory
corruption after we have landed in the new image before that piece of
hardware is re-configured.
Implement and call dma_disable_all() on all platforms with generic DMA.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BRANCH=all
BUG=chrome-os-partner:34865
TEST=on various boards, call "sysjump rw".
Change-Id: I2a6b63ff19c2d932a5e31bc375bf468bc8ae5125
Reviewed-on: https://chromium-review.googlesource.com/237340
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Alec Berg <alecaberg@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Commit-Queue: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | chip/mec1322/dma.c | 11 | ||||
-rw-r--r-- | chip/stm32/dma.c | 10 | ||||
-rw-r--r-- | chip/stm32/registers.h | 5 | ||||
-rw-r--r-- | common/system.c | 6 | ||||
-rw-r--r-- | include/dma.h | 3 |
5 files changed, 35 insertions, 0 deletions
diff --git a/chip/mec1322/dma.c b/chip/mec1322/dma.c index 53e09122af..afd76aedc4 100644 --- a/chip/mec1322/dma.c +++ b/chip/mec1322/dma.c @@ -34,6 +34,17 @@ void dma_disable(enum dma_channel channel) chan->act = 0; } +void dma_disable_all(void) +{ + int ch; + + for (ch = 0; ch < MEC1322_DMAC_COUNT; ch++) { + mec1322_dma_chan_t *chan = dma_get_channel(ch); + chan->ctrl &= ~(1 << 0); + chan->act = 0; + } +} + /** * Prepare a channel for use and start it * diff --git a/chip/stm32/dma.c b/chip/stm32/dma.c index d151d3044f..0f2e89bc14 100644 --- a/chip/stm32/dma.c +++ b/chip/stm32/dma.c @@ -58,6 +58,16 @@ void dma_disable(enum dma_channel channel) chan->ccr &= ~STM32_DMA_CCR_EN; } +void dma_disable_all(void) +{ + int ch; + + for (ch = 0; ch < STM32_DMAC_COUNT; ch++) { + stm32_dma_chan_t *chan = dma_get_channel(ch); + chan->ccr &= ~STM32_DMA_CCR_EN; + } +} + /** * Prepare a channel for use and start it * diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index 59d7e16efb..261e9fb26c 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -1217,6 +1217,7 @@ enum dma_channel { STM32_DMAC_I2C2_RX = STM32_DMAC_CH5, STM32_DMAC_USART1_TX = STM32_DMAC_CH4, STM32_DMAC_USART1_RX = STM32_DMAC_CH5, +#if !defined(CHIP_VARIANT_STM32F03X) && !defined(CHIP_VARIANT_STM32F05X) STM32_DMAC_USART2_RX = STM32_DMAC_CH6, STM32_DMAC_USART2_TX = STM32_DMAC_CH7, STM32_DMAC_I2C1_TX = STM32_DMAC_CH6, @@ -1233,6 +1234,10 @@ enum dma_channel { /* Only DMA1 (with 7 channels) is present on STM32F100 and STM32L151x */ STM32_DMAC_COUNT = 7, + +#else /* stm32f03x and stm32f05x have only 5 channels */ + STM32_DMAC_COUNT = 5, +#endif }; /* Registers for a single channel of the DMA controller */ diff --git a/common/system.c b/common/system.c index b31ab43015..de3000ccd1 100644 --- a/common/system.c +++ b/common/system.c @@ -7,6 +7,7 @@ #include "clock.h" #include "common.h" #include "console.h" +#include "dma.h" #include "flash.h" #include "gpio.h" #include "hooks.h" @@ -421,6 +422,11 @@ static void jump_to_image(uintptr_t init_addr) /* Disable interrupts before jump */ interrupt_disable(); +#ifdef CONFIG_DMA + /* Disable all DMA channels to avoid memory corruption */ + dma_disable_all(); +#endif /* CONFIG_DMA */ + /* Fill in preserved data between jumps */ jdata->reserved0 = 0; jdata->magic = JUMP_DATA_MAGIC; diff --git a/include/dma.h b/include/dma.h index e63d03a232..5e5553a794 100644 --- a/include/dma.h +++ b/include/dma.h @@ -65,6 +65,9 @@ void dma_start_rx(const struct dma_option *option, unsigned count, */ void dma_disable(enum dma_channel channel); +/* Stop transfers on all DMA channels */ +void dma_disable_all(void); + /** * Get the number of bytes available to read, or number of bytes written * |