summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2014-12-22 17:58:11 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-08 22:36:31 +0000
commit61d50195e1fb568327d2cdce5b5a5095f1be6e05 (patch)
treea17bd73885baa3fbec53c11a56b1bc6a8629c40b
parent3c292e0398e066279124ced299e860585890e4c6 (diff)
downloadchrome-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.c11
-rw-r--r--chip/stm32/dma.c10
-rw-r--r--chip/stm32/registers.h5
-rw-r--r--common/system.c6
-rw-r--r--include/dma.h3
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
*