mt8173: memlayout: Create DRAM DMA region for NOR flash DMA read.
NOR flash has a hardware limitation that it can't access SRAM region
after 4GB mode is enabled. We add a DRAM DMA region after 0x40000000
for NOR flash driver. So that the NOR flash driver can use this region
after 4GB mode is enabled.
BRANCH=none
BUG=chormoe-os-partner:49229
TEST=Boot to kernel on rev4 w/ 2GB ram and rev3 w/ 4GB ram.
And check /proc/meminfo.
Change-Id: Ifedc9e2dfba5d294297b3a28134997ac1dd38f94
Signed-off-by: Yidi Lin <yidi.lin@mediatek.com>
Reviewed-on: https://chromium-review.googlesource.com/327962
Reviewed-by: Julius Werner <jwerner@chromium.org>
diff --git a/src/soc/mediatek/mt8173/flash_controller.c b/src/soc/mediatek/mt8173/flash_controller.c
index 5ffc300..1bfc2a7 100644
--- a/src/soc/mediatek/mt8173/flash_controller.c
+++ b/src/soc/mediatek/mt8173/flash_controller.c
@@ -30,6 +30,7 @@
#include <symbols.h>
#include <timer.h>
#include <soc/flash_controller.h>
+#include <soc/mmu_operations.h>
#define get_nth_byte(d, n) ((d >> (8 * n)) & 0xff)
@@ -116,21 +117,22 @@
return min(65535, buf_len);
}
-static int dma_read(u32 addr, u8 *buf, u32 len)
+static int dma_read(u32 addr, u8 *buf, u32 len, uintptr_t dma_buf,
+ size_t dma_buf_len)
{
struct stopwatch sw;
assert(IS_ALIGNED((uintptr_t)buf, SFLASH_DMA_ALIGN) &&
IS_ALIGNED(len, SFLASH_DMA_ALIGN) &&
- len <= _dma_coherent_size);
+ len <= dma_buf_len);
/* do dma reset */
write32(&mt8173_nor->fdma_ctl, SFLASH_DMA_SW_RESET);
write32(&mt8173_nor->fdma_ctl, SFLASH_DMA_WDLE_EN);
/* flash source address and dram dest address */
write32(&mt8173_nor->fdma_fadr, addr);
- write32(&mt8173_nor->fdma_dadr, ((uintptr_t)_dma_coherent ));
- write32(&mt8173_nor->fdma_end_dadr, ((uintptr_t)_dma_coherent + len));
+ write32(&mt8173_nor->fdma_dadr, dma_buf);
+ write32(&mt8173_nor->fdma_end_dadr, (dma_buf + len));
/* start dma */
write32(&mt8173_nor->fdma_ctl, SFLASH_DMA_TRIGGER | SFLASH_DMA_WDLE_EN);
@@ -142,7 +144,7 @@
}
}
- memcpy(buf, _dma_coherent, len);
+ memcpy(buf, (const void *)dma_buf, len);
return 0;
}
@@ -164,6 +166,9 @@
u32 next;
size_t done = 0;
+ uintptr_t dma_buf;
+ size_t dma_buf_len;
+
if (!IS_ALIGNED((uintptr_t)buf, SFLASH_DMA_ALIGN)) {
next = MIN(ALIGN_UP((uintptr_t)buf, SFLASH_DMA_ALIGN) -
(uintptr_t)buf, len);
@@ -171,10 +176,20 @@
return -1;
done += next;
}
+
+ if (ENV_BOOTBLOCK || ENV_VERSTAGE) {
+ dma_buf = (uintptr_t)_dma_coherent;
+ dma_buf_len = _dma_coherent_size;
+ } else {
+ dma_buf = (uintptr_t)_dram_dma;
+ dma_buf_len = _dram_dma_size;
+ }
+
while (len - done >= SFLASH_DMA_ALIGN) {
- next = MIN(_dma_coherent_size, ALIGN_DOWN(len - done,
+ next = MIN(dma_buf_len, ALIGN_DOWN(len - done,
SFLASH_DMA_ALIGN));
- if (dma_read(addr + done, buf + done, next))
+ if (dma_read(addr + done, buf + done, next, dma_buf,
+ dma_buf_len))
return -1;
done += next;
}
diff --git a/src/soc/mediatek/mt8173/include/soc/memlayout.ld b/src/soc/mediatek/mt8173/include/soc/memlayout.ld
index f41ce34..496b980 100644
--- a/src/soc/mediatek/mt8173/include/soc/memlayout.ld
+++ b/src/soc/mediatek/mt8173/include/soc/memlayout.ld
@@ -29,6 +29,11 @@
#define SRAM_L2C_START(addr) SYMBOL(sram_l2c, addr)
#define SRAM_L2C_END(addr) SYMBOL(esram_l2c, addr)
+#define DRAM_DMA(addr, size) \
+ REGION(dram_dma, addr, size, 4K) \
+ _ = ASSERT(size % 4K == 0, \
+ "DRAM DMA buffer should be multiple of smallest page size (4K)!");
+
SECTIONS
{
SRAM_L2C_START(0x000C0000)
@@ -48,6 +53,7 @@
SRAM_END(0x00130000)
DRAM_START(0x40000000)
+ DRAM_DMA(0x40000000, 1M)
POSTRAM_CBFS_CACHE(0x40100000, 1M)
RAMSTAGE(0x40200000, 256K)
}
diff --git a/src/soc/mediatek/mt8173/include/soc/mmu_operations.h b/src/soc/mediatek/mt8173/include/soc/mmu_operations.h
index 82393f9..f3abccf 100644
--- a/src/soc/mediatek/mt8173/include/soc/mmu_operations.h
+++ b/src/soc/mediatek/mt8173/include/soc/mmu_operations.h
@@ -33,6 +33,10 @@
extern unsigned char _esram_l2c[];
#define _sram_l2c_size (_esram_l2c - _sram_l2c)
+extern unsigned char _dram_dma[];
+extern unsigned char _edram_dma[];
+#define _dram_dma_size (_edram_dma - _dram_dma)
+
void mt8173_mmu_init(void);
void mt8173_mmu_after_dram(void);
diff --git a/src/soc/mediatek/mt8173/mmu_operations.c b/src/soc/mediatek/mt8173/mmu_operations.c
index d69e6fe..d9a7f2b 100644
--- a/src/soc/mediatek/mt8173/mmu_operations.c
+++ b/src/soc/mediatek/mt8173/mmu_operations.c
@@ -57,6 +57,8 @@
/* TODO: Implement true unmapping, and also use it for the zero-page! */
mmu_config_range(_sram_l2c, _sram_l2c_size, DEV_MEM);
+ mmu_config_range(_dram_dma, _dram_dma_size, UNCACHED_MEM);
+
/* Careful: changing cache geometry while it's active is a bad idea! */
mmu_disable();