【TINY4412】U-BOOT移植笔记:(7)SDRAM驱动
宿主机 : 虚拟机 Ubuntu 16.04 LTS / X64
目标板[底板]: Tiny4412SDK - 1506
目标板[核心板]: Tiny4412 - 1412
U-BOOT版本: 2017.03
交叉编译器: gcc-arm-none-eabi-5_4-2016q3
日期: 2017-4-23 23:36:06
作者: SY
背景介绍
- DDR SDRAM全名叫做:双倍数据率同步动态随机存取存储器
- SDRAM在一个时钟周期内只传输一次数据,它是在时钟的上升期进行数据传输
- DDR SDRAM则是一个时钟周期内传输两次数据,它能够在时钟的上升期和下降期各传输一次数据
- DDR SDRAM芯片的时钟频率一般为DMC控制芯片频率的2倍
开发板SDRAM
- 内存芯片:2片512MB的三星1600Mb/sec/pin内存颗粒,总内存大小为1GB
- 型号:K4B4G1646D-BCK0
- 手册:K4B4G1646D-BCK0.pdf
- 自动刷新周期:Average Refresh Period 7.8us at lower than TCASE 85C, 3.9us at 85C < TCASE < 95 C
- 外部时钟[主芯片提供给内存颗粒的时钟]:800MHz,主芯片需要提供给内存颗粒2个差分的
时钟信号,CK、CK/,详见内存芯片手册P27 - 内部时钟[DMC时钟]:400MHz
- 自动刷新周期TIMINGAREF:24MHz * 7.8us(查看内存手册) = 187.2 = 0xBB
- TIMINGROW:查看内存手册可知,
参数 | 数值 |
---|---|
t_ras | 35 |
t_rc | 48.75 |
t_rcd | 13.75 |
t_rp | 13.75 |
t_rrd | 6 |
t_rfc | 208 |
代码移植
修改文件:arch/arm/mach-exynos/exynos4412_setup.h
root@ubuntu:/opt/u-boot-2017.03# git diff ../temp/
u-boot-2017.03/arch/arm/mach-exynos/exynos4_setup.h
arch/arm/mach-exynos/exynos4412_setup.h
diff --git a/../temp/u-boot-2017.03/arch/arm/mach-exynos/
exynos4_setup.h b/arch/arm/mach-exynos/exynos4412_setup.h
index 9f29d94..3befa95 100644
--- a/../temp/u-boot-2017.03/arch/arm/mach-exynos/exynos4_setup.h
+++ b/arch/arm/mach-exynos/exynos4412_setup.h
@@ -6,8 +6,8 @@
* SPDX-License-Identifier: GPL-2.0+
*/
-#ifndef _ORIGEN_SETUP_H
-#define _ORIGEN_SETUP_H
+#ifndef _EXYNOS4412_SETUP_H
+#define _EXYNOS4412_SETUP_H
#include <config.h>
#include <asm/arch/cpu.h>
@@ -434,7 +434,7 @@ struct mem_timings {
#define ABP_SFR_SLV1_SINGLE_ADDRMAP_START_OFFSET 0x828
#define ABP_SFR_SLV1_SINGLE_ADDRMAP_END_OFFSET 0x830
-#ifdef CONFIG_ORIGEN
+#ifdef CONFIG_TINY4412
/* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */
#define APB_SFR_INTERLEAVE_CONF_VAL 0x20001507
#define APB_SFR_ARBRITATION_CONF_VAL 0x00000001
@@ -470,10 +470,10 @@ struct mem_timings {
#define CTRL_ZQ_MODE_NOTERM (0x1 << 0)
#define CTRL_ZQ_START (0x1 << 1)
#define CTRL_ZQ_DIV (0 << 4)
-#define CTRL_ZQ_MODE_DDS (0x7 << 8)
-#define CTRL_ZQ_MODE_TERM (0x2 << 11)
+#define CTRL_ZQ_MODE_DDS (0x4 << 8)
+#define CTRL_ZQ_MODE_TERM (0x1 << 11)
#define CTRL_ZQ_FORCE_IMPN (0x5 << 14)
-#define CTRL_ZQ_FORCE_IMPP (0x6 << 17)
+#define CTRL_ZQ_FORCE_IMPP (0x2 << 17)
#define CTRL_DCC (0xE38 << 20)
#define ZQ_CONTROL_VAL (CTRL_ZQ_MODE_NOTERM | CTRL_ZQ_START\
| CTRL_ZQ_DIV | CTRL_ZQ_MODE_DDS\
@@ -506,7 +506,7 @@ struct mem_timings {
#define ADD_LAT_PALL (1 << 6)
#define MEM_TYPE_DDR3 (0x6 << 8)
#define MEM_WIDTH_32 (0x2 << 12)
-#define NUM_CHIP_2 (1 << 16)
+#define NUM_CHIP_2 (0 << 16)
#define BL_8 (0x3 << 20)
#define MEMCONTROL_VAL (CLK_STOP_DISABLE | DPWRDN_DISABLE\
| DPWRDN_TYPE | TP_DISABLE | DSREF_DIABLE\
@@ -515,20 +515,20 @@ struct mem_timings {
#define CHIP_BANK_8 (0x3 << 0)
-#define CHIP_ROW_14 (0x2 << 4)
+#define CHIP_ROW_15 (0x3 << 4)
#define CHIP_COL_10 (0x3 << 8)
#define CHIP_MAP_INTERLEAVED (1 << 12)
-#define CHIP_MASK (0xe0 << 16)
+#define CHIP_MASK (0xC0 << 16)
#ifdef CONFIG_MIU_LINEAR
#define CHIP0_BASE (0x40 << 24)
#define CHIP1_BASE (0x60 << 24)
#else
-#define CHIP0_BASE (0x20 << 24)
-#define CHIP1_BASE (0x40 << 24)
+#define CHIP0_BASE (0x40 << 24)
+#define CHIP1_BASE (0x80 << 24)
#endif
-#define MEMCONFIG0_VAL (CHIP_BANK_8 | CHIP_ROW_14 | CHIP_COL_10\
+#define MEMCONFIG0_VAL (CHIP_BANK_8 | CHIP_ROW_15 | CHIP_COL_10\
| CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP0_BASE)
-#define MEMCONFIG1_VAL (CHIP_BANK_8 | CHIP_ROW_14 | CHIP_COL_10\
+#define MEMCONFIG1_VAL (CHIP_BANK_8 | CHIP_ROW_15 | CHIP_COL_10\
| CHIP_MAP_INTERLEAVED | CHIP_MASK | CHIP1_BASE)
#define TP_CNT (0xff << 24)
@@ -556,11 +556,11 @@ struct mem_timings {
#define CONTROL2_VAL 0x00000000
-#ifdef CONFIG_ORIGEN
-#define TIMINGREF_VAL 0x000000BB
-#define TIMINGROW_VAL 0x4046654f
-#define TIMINGDATA_VAL 0x46400506
-#define TIMINGPOWER_VAL 0x52000A3C
+#ifdef CONFIG_TINY4412
+ #define TIMINGREF_VAL 0x000000BB
+ #define TIMINGROW_VAL 0x6946654f
+ #define TIMINGDATA_VAL 0x46460506
+ #define TIMINGPOWER_VAL 0x5200183c
#else
#define TIMINGREF_VAL 0x000000BC
#ifdef DRAM_CLK_330
(END)
修改文件:/arch/arm/mach-exynos/dmc_init_exynos4412.c
root@ubuntu:/opt/u-boot-2017.03# git diff ../temp/u-
boot-2017.03/arch/arm/mach-exynos/dmc_init_exynos4.c
arch/arm/mach-exynos/dmc_init_exynos4412.c
diff --git a/../temp/u-boot-2017.03/arch/arm/mach-exynos/
dmc_init_exynos4.c b/arch/arm/mach-exynos/dmc_init_exynos4412.c
index ecddc72..938348a 100644
--- a/../temp/u-boot-2017.03/arch/arm/mach-exynos/dmc_init_exynos4.c
+++ b/arch/arm/mach-exynos/dmc_init_exynos4412.c
@@ -1,5 +1,5 @@
/*
- * Memory setup for board based on EXYNOS4210
+ * Memory setup for board based on EXYNOS4412
*
* Copyright (C) 2013 Samsung Electronics
* Rajeshwari Shinde <rajeshwari.s@samsung.com>
@@ -26,7 +26,8 @@
#include <config.h>
#include <asm/arch/dmc.h>
#include "common_setup.h"
-#include "exynos4_setup.h"
+#include <debug_uart.h>
+#include "exynos4412_setup.h"
struct mem_timings mem = {
.direct_cmd_msr = {
@@ -124,6 +125,10 @@ static void dmc_init(struct exynos4_dmc *dmc)
writel(mem.memconfig0, &dmc->memconfig0);
writel(mem.memconfig1, &dmc->memconfig1);
+#ifdef CONFIG_TINY4412
+ writel(0x8000001f, &dmc->ivcontrol);
+#endif
+
/* Config Precharge Policy */
writel(mem.prechconfig, &dmc->prechconfig);
/*
@@ -175,39 +180,106 @@ void mem_ctrl_init(int reset)
* 0: full_sync
*/
writel(1, ASYNC_CONFIG);
-#ifdef CONFIG_ORIGEN
- /* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */
- writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE +
- APB_SFR_INTERLEAVE_CONF_OFFSET);
- /* Update MIU Configuration */
- writel(APB_SFR_ARBRITATION_CONF_VAL, EXYNOS4_MIU_BASE +
- APB_SFR_ARBRITATION_CONF_OFFSET);
-#else
- writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE +
- APB_SFR_INTERLEAVE_CONF_OFFSET);
- writel(INTERLEAVE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE +
- ABP_SFR_INTERLEAVE_ADDRMAP_START_OFFSET);
- writel(INTERLEAVE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE +
- ABP_SFR_INTERLEAVE_ADDRMAP_END_OFFSET);
- writel(INTERLEAVE_ADDR_MAP_EN, EXYNOS4_MIU_BASE +
- ABP_SFR_SLV_ADDRMAP_CONF_OFFSET);
-#ifdef CONFIG_MIU_LINEAR
- writel(SLAVE0_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE +
- ABP_SFR_SLV0_SINGLE_ADDRMAP_START_OFFSET);
- writel(SLAVE0_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE +
- ABP_SFR_SLV0_SINGLE_ADDRMAP_END_OFFSET);
- writel(SLAVE1_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE +
- ABP_SFR_SLV1_SINGLE_ADDRMAP_START_OFFSET);
- writel(SLAVE1_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE +
- ABP_SFR_SLV1_SINGLE_ADDRMAP_END_OFFSET);
- writel(APB_SFR_SLV_ADDR_MAP_CONF_VAL, EXYNOS4_MIU_BASE +
- ABP_SFR_SLV_ADDRMAP_CONF_OFFSET);
-#endif
+
+#ifndef CONFIG_TINY4412
+ #ifdef CONFIG_ORIGEN
+ /* Interleave: 2Bit, Interleave_bit1: 0x15, Interleave_bit0: 0x7 */
+ writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE +
+ APB_SFR_INTERLEAVE_CONF_OFFSET);
+ /* Update MIU Configuration */
+ writel(APB_SFR_ARBRITATION_CONF_VAL, EXYNOS4_MIU_BASE +
+ APB_SFR_ARBRITATION_CONF_OFFSET);
+ #else
+ writel(APB_SFR_INTERLEAVE_CONF_VAL, EXYNOS4_MIU_BASE +
+ APB_SFR_INTERLEAVE_CONF_OFFSET);
+ writel(INTERLEAVE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE +
+ ABP_SFR_INTERLEAVE_ADDRMAP_START_OFFSET);
+ writel(INTERLEAVE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE +
+ ABP_SFR_INTERLEAVE_ADDRMAP_END_OFFSET);
+ writel(INTERLEAVE_ADDR_MAP_EN, EXYNOS4_MIU_BASE +
+ ABP_SFR_SLV_ADDRMAP_CONF_OFFSET);
+ #ifdef CONFIG_MIU_LINEAR
+ writel(SLAVE0_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE +
+ ABP_SFR_SLV0_SINGLE_ADDRMAP_START_OFFSET);
+ writel(SLAVE0_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE +
+ ABP_SFR_SLV0_SINGLE_ADDRMAP_END_OFFSET);
+ writel(SLAVE1_SINGLE_ADDR_MAP_START_ADDR, EXYNOS4_MIU_BASE +
+ ABP_SFR_SLV1_SINGLE_ADDRMAP_START_OFFSET);
+ writel(SLAVE1_SINGLE_ADDR_MAP_END_ADDR, EXYNOS4_MIU_BASE +
+ ABP_SFR_SLV1_SINGLE_ADDRMAP_END_OFFSET);
+ writel(APB_SFR_SLV_ADDR_MAP_CONF_VAL, EXYNOS4_MIU_BASE +
+ ABP_SFR_SLV_ADDRMAP_CONF_OFFSET);
+ #endif
+ #endif
#endif
- /* DREX0 */
+
+ printascii("[SPL] DDR3 SDRAM配置:\n");
+ printascii("timingref "); printhex8(mem.timingref); printascii("\n");
+ printascii("timingrow "); printhex8(mem.timingrow); printascii("\n");
+ printascii("timingdata "); printhex8(mem.timingdata); printascii("\n");
+ printascii("timingpower "); printhex8(mem.timingpower); printascii("\n");
+ printascii("zqcontrol "); printhex8(mem.zqcontrol); printascii("\n");
+ printascii("control0 "); printhex8(mem.control0); printascii("\n");
+ printascii("control1 "); printhex8(mem.control1); printascii("\n");
+ printascii("control2 "); printhex8(mem.control2); printascii("\n");
+ printascii("concontrol "); printhex8(mem.concontrol); printascii("\n");
+ printascii("prechconfig "); printhex8(mem.prechconfig); printascii("\n");
+ printascii("memcontrol "); printhex8(mem.memcontrol); printascii("\n");
+ printascii("memconfig0 "); printhex8(mem.memconfig0); printascii("\n");
+ printascii("memconfig1 "); printhex8(mem.memconfig1); printascii("\n");
+ printascii("dll_resync "); printhex8(mem.dll_resync); printascii("\n");
+ printascii("dll_on "); printhex8(mem.dll_on); printascii("\n");
+
+ /* DMC0 */
dmc = (struct exynos4_dmc *)samsung_get_base_dmc_ctrl();
dmc_init(dmc);
+
+ /* DMC1 */
dmc = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl()
+ DMC_OFFSET);
dmc_init(dmc);
+
+{
+ printascii("[SPL] DDR3 SDRAM测试:\n");
+
+ void Test_SDRAM(unsigned long addr, unsigned long value);
+ Test_SDRAM(0x40000000, 0x12121212);
+ Test_SDRAM(0x40000004, 0x12121213);
+ Test_SDRAM(0x40000008, 0x12121214);
+ Test_SDRAM(0x4000000C, 0x12121215);
+ Test_SDRAM(0x40000010, 0x12121216);
+
+ Test_SDRAM(0x41000000, 0x23232325);
+ Test_SDRAM(0x42000000, 0x23232326);
+
+ Test_SDRAM(0x42345530, 0x23232323);
+ Test_SDRAM(0x42345534, 0x23232324);
+ Test_SDRAM(0x42345538, 0x23232325);
+ Test_SDRAM(0x4234553C, 0x23232326);
+ Test_SDRAM(0x50000000, 0x34343434);
+ Test_SDRAM(0x58494940, 0x45454545);
+ Test_SDRAM(0x60000008, 0x56565656);
+ Test_SDRAM(0x6FFFFFFC, 0x67676767);
+ Test_SDRAM(0x70000000, 0x78787878);
+ Test_SDRAM(0x7FFFFFFC, 0x89898989);
+
+ printascii("测试结束\n");
+}
}
+
+void Test_SDRAM(unsigned long addr, unsigned long value)
+{
+
+ printascii("写入地址 = ");
+ printhex8(addr);
+
+ printascii(" 写入值 = ");
+ printhex8(value);
+ writel(value, addr);
+
+ printascii(" 读取值 = ");
+ printhex8(readl(addr));
+ printascii("\n");
+}
+
+
(END)
测试结果:
[SPL] DDR3 SDRAM配置:
timingref 000000bb
timingrow 6946654f
timingdata 46460506
timingpower 5200183c
zqcontrol e3854c03
control0 71101008
control1 e0000086
control2 00000000
concontrol 0fff301a
prechconfig ff000000
memcontrol 00302640
memconfig0 40c01333
memconfig1 80c01333
dll_resync 00000003
dll_on 00000001
[SPL] DDR3 SDRAM测试:
写入地址 = 40000000 写入值 = 12121212 读取值 = 12121212
写入地址 = 40000004 写入值 = 12121213 读取值 = 12121213
写入地址 = 40000008 写入值 = 12121214 读取值 = 12121214
写入地址 = 4000000c 写入值 = 12121215 读取值 = 12121215
写入地址 = 40000010 写入值 = 12121216 读取值 = 12121216
写入地址 = 41000000 写入值 = 23232325 读取值 = 23232325
写入地址 = 42000000 写入值 = 23232326 读取值 = 23232326
写入地址 = 42345530 写入值 = 23232323 读取值 = 23232323
写入地址 = 42345534 写入值 = 23232324 读取值 = 23232324
写入地址 = 42345538 写入值 = 23232325 读取值 = 23232325
写入地址 = 4234553c 写入值 = 23232326 读取值 = 23232326
写入地址 = 50000000 写入值 = 34343434 读取值 = 34343434
写入地址 = 58494940 写入值 = 45454545 读取值 = 45454545
写入地址 = 60000008 写入值 = 56565656 读取值 = 56565656
写入地址 = 6ffffffc 写入值 = 67676767 读取值 = 67676767
写入地址 = 70000000 写入值 = 78787878 读取值 = 78787878
写入地址 = 7ffffffc 写入值 = 89898989 读取值 = 89898989