Uboot21之DDR初始化
时间:2018.4.5 作者:Tom 工作:HWE 说明:如需转载,请注明出处。已注明转载
bl mem_ctrl_asm_init
2)函数位置在uboot/cpu/s5pc11x/s5pc110/cpu_init.S文件中。
3)该函数和裸机中初始化DDR代码是一样的。实际上裸机中初始化DDR的代码就是从这里抄的。配置值也可以从这里抄,但是当时我自己根据理解+抄袭整出来的一份。
4)配置值中其他配置值参考裸机中的解释即可明白,有一个和裸机中讲的不一样。DMC0_MEMCONFIG_0,在裸机中配置值为0x20E01323;在uboot中配置为0x30F01313.这个配置不同就导致结果不同。
在 裸机中DMC0的256MB内存地址范围是0x20000000-0x2FFFFFFF;
在uboot中DMC0的256MB内存地址范围为0x30000000-0x3FFFFFFF。
5)之前在裸机中时配置为2开头的地址,当时并没有说可以配置为3开头。从分析九鼎移植的uboot可以看出:DMC0上允许的地址范围是20000000-3FFFFFFF(一共是512MB),而我们实际只接了256MB物理内存,SoC允许我们给这256MB挑选地址范围。
6)总结一下:在uboot中,可用的物理地址范围为:0x30000000-0x4FFFFFFF。一共512MB,其中30000000-3FFFFFFF为DMC0,40000000-4FFFFFFF为DMC1。
7)我们需要的内存配置值在x210_sd.h的438行到468行之间。分析的时候要注意条件编译的条件,配置头文件中考虑了不同时钟配置下的内存配置值,这个的主要目的是让不同时钟需求的客户都能找到合适自己的内存配置值。
8)在uboot中DMC0和DMC1都工作了,所以在裸机中只要把uboot中的配置值和配置代码全部移植过去,应该是能够让DMC0和DMC1都工作的。
#include <config.h>
#include <s5pc110.h>
.globl mem_ctrl_asm_init
mem_ctrl_asm_init:
#ifndef CONFIG_EVT1
ldr r0, =ASYNC_MSYS_DMC0_BASE
#define ASYNC_MSYS_DMC0_BASE 0xF1E00000
ldr r1, =0x0
str r1, [r0, #0x0]
/* This register is removed at EVT1 of C110. */
ldr r1, =0x0
str r1, [r0, #0xC]
#endif
上述是设置DRAM的同步方式,选择全双工同步模式。
#ifdef CONFIG_MCP_SINGLE
/* DMC0 Drive Strength (Setting 2X) */ 1.设置DMC0 Drive Strength
ldr r0, =ELFIN_GPIO_BASE
#define ELFIN_GPIO_BASE 0xE0200000
ldr r1, =0x0000AAAA
str r1, [r0, #MP1_0DRV_SR_OFFSET]
#define MP1_0DRV_SR_OFFSET 0x3CC
。。。。。。。。。。。。。。
ldr r1, =0x00002AAA
str r1, [r0, #MP1_8DRV_SR_OFFSET]
上述是设置DCM0驱动强度,通用的是2倍的驱动强度
/* DMC1 Drive Strength (Setting 2X) */
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0x0000AAAA
str r1, [r0, #MP2_0DRV_SR_OFFSET]
。。。。。。。。。。。。。。。。。。。
ldr r1, =0x00002AAA
str r1, [r0, #MP2_8DRV_SR_OFFSET]
上述是设置DCM1驱动强度,通用的是2倍的驱动强度
/* DMC0 initialization at single Type*/2.初始化PHY DLL
控制器和芯片端都有DLL,芯片端DLL做的简单不需要配置。控制端的DLL需要配置。
ldr r0, =APB_DMC_0_BASE
#define APB_DMC_0_BASE 0xF0000000
598页
ldr r1, =0x00101000 @PhyControl0 DLL parameter setting, manual 0x00101000
str r1, [r0, #DMC_PHYCONTROL0] 第二步
#define DMC_PHYCONTROL0 0x18
ldr r1, =0x00000086 @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
str r1, [r0, #DMC_PHYCONTROL1] 第三步
#define DMC_PHYCONTROL1 0x1C
ldr r1, =0x00101002 @PhyControl0 DLL on
str r1, [r0, #DMC_PHYCONTROL0] 第三步:DLL打开
ldr r1, =0x00101003 @PhyControl0 DLL start
str r1, [r0, #DMC_PHYCONTROL0] 第四步:DLL开始工作
find_lock_val: 第十二步:等到DLL稳定
ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value
#define DMC_PHYSTATUS 0x40
and r2, r1, #0x7
cmp r2, #0x7 @Loop until DLL is locked
bne find_lock_val
等待DLL锁定CLK,直至完全同步
and r1, #0x3fc0
mov r2, r1, LSL #18
orr r2, r2, #0x100000
orr r2 ,r2, #0x1000
orr r1, r2, #0x3 @Force Value locking
str r1, [r0, #DMC_PHYCONTROL0]
将数据锁至DMC_PHYCONTROL0。
#if 0 /* Memory margin test 10.01.05 */
orr r1, r2, #0x1 @DLL off
str r1, [r0, #DMC_PHYCONTROL0]
#endif
/* setting DDR2 */第五步:初始化DMC0
ldr r1, =0x0FFF2010 @ConControl auto refresh off
str r1, [r0, #DMC_CONCONTROL]
ldr r1, =DMC0_MEMCONTROL @MemControl BL=4, 1 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
#define DMC0_MEMCONTROL 0x00212400
str r1, [r0, #DMC_MEMCONTROL]
ldr r1, =DMC0_MEMCONFIG_0 @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
#define DMC0_MEMCONFIG_0 0x20E01323
16~23位配置决定了我们可用的内存大小,也就是地址范围。与chip_mask取反。
str r1, [r0, #DMC_MEMCONFIG0]
ldr r1, =DMC0_MEMCONFIG_1 @MemConfig1
str r1, [r0, #DMC_MEMCONFIG1]
ldr r1, =0xFF000000 @PrechConfig
str r1, [r0, #DMC_PRECHCONFIG]
ldr r1, =DMC0_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
#define DMC0_TIMINGA_REF 0x40e
str r1, [r0, #DMC_TIMINGAREF]
ldr r1, =DMC0_TIMING_ROW @TimingRow for @200MHz
#define DMC0_TIMING_ROW 0x10233206
str r1, [r0, #DMC_TIMINGROW]
ldr r1, =DMC0_TIMING_DATA @TimingData CL=3
#define DMC0_TIMING_DATA 0x12130005
str r1, [r0, #DMC_TIMINGDATA]
ldr r1, =DMC0_TIMING_PWR @TimingPower
#define DMC0_TIMING_PWR 0x0E100222
str r1, [r0, #DMC_TIMINGPOWER]
下面开始初始化DDR2
ldr r1, =0x07000000 @DirectCmd chip0 Deselect
str r1, [r0, #DMC_DIRECTCMD]
#define DMC_DIRECTCMD 0x10
ldr r1, =0x01000000 @DirectCmd chip0 PALL
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00020000 @DirectCmd chip0 EMRS2
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00030000 @DirectCmd chip0 EMRS3
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x01000000 @DirectCmd chip0 PALL
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x05000000 @DirectCmd chip0 REFA
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit)
str r1, [r0, #DMC_DIRECTCMD]
下面是chip1的配置,一样的:
ldr r1, =0x07100000 @DirectCmd chip1 Deselect
str r1, [r0, #DMC_DIRECTCMD]
。。。。。。。。。。。。。。。。。。。。。。。。。。
ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit)
str r1, [r0, #DMC_DIRECTCMD]
ldr r1, =0x0FF02030 @ConControl auto refresh on
str r1, [r0, #DMC_CONCONTROL]
ldr r1, =0xFFFF00FF @PwrdnConfig
str r1, [r0, #DMC_PWRDNCONFIG]
ldr r1, =0x00202400 @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
str r1, [r0, #DMC_MEMCONTROL]
上面的指令均是主控发给device的指令,用于初始化DDR芯片。
/* DMC1 initialization */
下面过程是同样的。
ldr r0, =APB_DMC_1_BASE
。。。。。。。。。。。。。。。
#else /* CONFIG_MCP_SINGLE */
----------------------------------------------------------------
mov pc, lr
DDR的 控制器和外部DDR芯片初始化完毕!
.ltorg