uboot源码学习(9)DDR初始化程序分析之一

本文分析S5PV210板的DDR初始化程序。
一、IO部分配置。从下图管脚定义表来看,Xm1管脚只有单个功能Func0,所以不用配置管脚复用功能。
在这里插入图片描述
memory.S文件,20行-40行

mem_init:
	//1、设置DMC0 Drive Strength (Setting 2X)
	ldr r0,=ELFIN_GPIO_BASE
	ldr r1,0x0000AAAA
	str r1,[r0,#MP1_0DRV_SR_OFFSET]
	ldr r1,0x0000AAAA
	str r1,[r0,#MP1_1DRV_SR_OFFSET]
	ldr r1,0x0000AAAA
	str r1,[r0,#MP1_2DRV_SR_OFFSET]
	ldr r1,0x0000AAAA
	str r1,[r0,#MP1_3DRV_SR_OFFSET]
	ldr r1,0x0000AAAA
	str r1,[r0,#MP1_4DRV_SR_OFFSET]
	ldr r1,0x0000AAAA
	str r1,[r0,#MP1_5DRV_SR_OFFSET]
	ldr r1,0x0000AAAA
	str r1,[r0,#MP1_6DRV_SR_OFFSET]
	ldr r1,0x0000AAAA
	str r1,[r0,#MP1_7DRV_SR_OFFSET]
	ldr r1,0x0000AAAA
	str r1,[r0,#MP1_8DRV_SR_OFFSET]

其中,宏定义都在s5pv210.h文件中:

#defineELFIN_GPIO_BASE 0xE020_0000
#defineELFIN_GPIO_BASE 0x3CC

将DMC0的驱动能力设置为2X。

二、从此开始,按照手册的27步开始配置:
step1:To provide stable power for controller and memory device, the controller must assert and hold CKE to a logic high level. Then apply stable clock. Note: XDDR2SEL should be Low level to hold CKE to high.
为了提供稳定的电源给控制器和内存设备,控制器必须确保CKE维持低电平,提供一个稳定的时钟。
在这里插入图片描述
step2:Set the PhyControl0.ctrl_start_point and PhyControl0.ctrl_inc bit-fields to correct value according to clock frequency. Set the PhyControl0.ctrl_dll_on bit-field to ‘1’ to activate the PHY DLL.

此步配置DMC端DLL。

DMC端DLL的作用是将DQS信号相移90°,以消减从DDR数据总线有数据时到数据传送到CPU的延时(rd_fetch)。
在这里插入图片描述
在这里插入图片描述
rd_fetch计算公式如下:
在这里插入图片描述
配置代码:

//2、初始化PHY DLL
ldr r0,=APB_DMC_0_BASE 
//step3:PhyControl0 parameter setting,manual 0x00101000
ldr r1,= 0x00101000
str r1,[r0,#DMC_PYHCONTROL0]
//PhyControl1 parameter setting,LPDDR/LPDDR2 Case
ldr r1,= 0x00000086
str r1,[r0,#DMC_PYHCONTROL1 ]
#define APB_DMC_0_BASE 0xF000000
#define DMC_PYHCONTROL0 0x18
#define DMC_PYHCONTROL1 0x1C

在这里插入图片描述
上图中:ctrl_inc,表示DLL从0到90°相移过程中,每次相移的度数。推荐值为0x10;
ctrl_start_point:表示DLL从0到90°相移过程中,起点位置,推荐值为0x10;
ctrl_dll_on:DLL总开关;此时先配置为0,在后面的步骤中再打开。
ctrl_start:DLL待机开关。先打开ctrl_dll_on,再打开ctrl_start。
ctrl_dfdqs:DQS差分或者单端选择信号;
ctrl_half:DLL低速或告诉选择信号。此处配置为0。
在这里插入图片描述
step3:DQS Cleaning: Set the PhyControl1.ctrl_shiftc and PhyControl1.ctrl_offsetc bit-fields to the correct value according to clock frequency and memory tAC parameters.
在这里插入图片描述
其中,ctrl_shiftc是DQS Cleaning 相移粗调,在DDR2@200MHz时推荐是0x6(T/2)。
ctrl_offsetc是DQS Cleaning相移精调。
fp_resync是DLL重新同步,一般用不到,置0;
ctrl_ref是DLL同步后还要等待若干个周期锁定,初始值为4,程序中设为8。
drv_type是设置双向空闲引脚状态,设为0或者下拉。一般设为0比较省电。
ctrl_offsetd主要用于debug用。保持默认值即可。

DQS Cleaning示意图如下:
在这里插入图片描述
DQS Cleaning就是在DMC中将DQS的信号延时标记出来,如PCB布线、焊点等的延时。
step4:. Set the PhyControl0.ctrl_start bit-field to ‘1’.

//step2:PhyControl0 DLL on
ldr r1,=0x00101002
str r1,[r0,#DMC_PYHCONTROL0]
//step4:PhyControl0 DLL start
ldr r1,=0x00101003
str r1,[r0,#DMC_PYHCONTROL0]

此两步是将DLL on 和DLL start开关打开。
在这里插入图片描述

find_lock_val:
	//Loop until DLL is locked 
	ldr r1,[r0,#DMC_PHYSTATUS]
	and r2,r1,#0x7
	cmp r2,#0x7
	bne find_lock_val
	
	//force value locking
	and r1,0x3fc0
	mov r2,r1,LSL,#18
	orr r2,r2,#0x100000
	orr r2,r2,#0x1000
	orr r1,r2,#0x03
	str r1,[r0,#DMC_PYHCONTROL0]

此步是将step11、step12提前:
step11:Wait for the PhyStatus0.ctrl_locked bit-fields to change to ‘1’. Check whether PHY DLL is locked.
step12:PHY DLL compensates the changes of delay amount caused by Process, Voltage and Temperature (PVT) variation during memory operation. Therefore, it should not be off for reliable operation. PHY DLL can be off if frequency is low. If off mode is used, set the PhyControl0.ctrl_force bit-field to the correct value according to the PhyStatus0.ctrl_lock_value[9:2] bit-field for fix delay amount. Clear the PhyControl0.ctrl_dll_on bit- field to turn off PHY DLL.

step12的含义是:因为DLL电路是模拟电路,工作的时候会很耗电。在DLL稳定的时候,会把CLK和DQS之间的差值存到PhyControl0.ctrl_force寄存器中,待DDR在IDLE状态下直接使用,而关闭DLL电路。
等待PHYSTATUS寄存器中的值为0x7的时候表示DLL锁定完成:
在这里插入图片描述
//force value locking 部分代码是将PHYSTATUS寄存器中ctrl_lock_value中的值存入到PYHCONTROL0寄存器中的ctrl_force中。
在这里插入图片描述
step5:Set the ConControl. At this moment, an auto refresh counter should be off.

//初始化DMC0
//step5:ConControl auto refresh off
ldr r1,=0x0FFF2010
str r1,[r0,#DMC_CONCONTROL]

在这里插入图片描述
在这里插入图片描述
out_of:乱序执行。使能后可以提高DDR工作效率;
aref_en:自动刷新计数器,根据step5,此计数器此时需要置0;
ctc_rtr_gap_en:两个不同型号的DDR芯片时,读周期之间的延迟。置为0;
drv_en:当置0时,禁用PHYCONTROL1中的drv_type功能。置为0;
chip0_empty:为只读。0表示在Rank1中的命令队列不为空。1为空。chip1_empty同理。
dq_swap;DQ[31]<–>DQ[0],将这两个数颠倒一下。一般不用,置为0;
qos_fast_en:Qos功能未开启,置为0;
timeout_cnt:超时时间。配置为默认值0xFFF。
rd_fetch:在读数据过程中,当数据出现在DDR数据总线上之后,再传输到DMC的FIFO中的过程中,必然会有一定的延时,rd_fetch即表示此延时的大小,一般为1或者2。设为2比较保险。
在这里插入图片描述
step6:Set the MemControl. At this moment, all power down modes should be off.

//step6:MemControl BL=4,1 chip,DDR2 type,dynamic self refresh,force precharge ,dynamic power down off
ldr r1,#DMC0_MEMCONTROL
str r1,[r0,#DMC_MEMCONTROL]
#define DMC0_MEMCONTROL 0x00202400

在这里插入图片描述
在这里插入图片描述
clk_stop_en:表示在IDEL状态下CLK信号是否给出,此时设为0,表示在IDEL状态下CLK一直是打开的;
dpwrdn_en:根据step6的说明,dpwrdn_en需要关闭,置为0;
dpwrdn_type:动态掉电模式选择,此时掉电模式关闭,置为0;
tp_en:预充电倒计时时间,一般不用,置为0;
dsref_en:动态自刷新,此时在配置阶段,暂时不需要,置为0;
add_lat_pall:强制所有的行预充电时额外的延时。此时不需要,置为0;
mem_type:选择Memory类型,DDR2选择0x4;
mem_width:总线宽度,32位选择0x2;
num_chip:rank的数量,此时为1,设置为0x0;
bl:突发写/读长度,一般设置为4,设置为0x2;

在这里插入图片描述

step7:Set the MemConfig0 register. If there are two external memory chips, also set the MemConfig1 register.
**此寄存器很重要,决定着能够使用多大的内存。**此处只用到1个rank,MemConfig1配置无效。

//step7:MemConfig0 256MB config,8 banks,Mapping Method[12:15]0:linear,1:linterleaved,2:Mixed
ldr r1,=DMC0_MEMCONFIG_0
str r1,[r0,#DMC_MEMCONFIG0]
//MemConfig1
ldr r1,=DMC0_MEMCONFIG_1
str r1,[r0,#DMC_MEMCONFIG1]
#define DMC0_MEMCONFIG_0 0x20F00313

在这里插入图片描述
chip_bank:每个Device的bank数,此时为8个banks,设为0x3;
chip_row:行地址的位宽,一般行数大于列数,则原理图中地址线的宽度即为chip_row。此处用14位,设为0x2;
chip_col:列地址的位宽,10位,设为0x3;计算过程:
在这里插入图片描述
chip_map:地址的排布顺序,一般选用Linear线性排布;置为0x0。线性表示:先排布一个bank的8个IO,再按顺序排布同一个row的不同col,当同个row的col排布完后,再接着排布同个bank的下一个row。Interleaved表示,当同个row的col排布完后,跳到下一个bank的row去排布;
chip_mask:地址总线掩码。此处代码中设置位0xF0,可使用内存大小为256M。需要改为0XE0。计算过程如下:
在这里插入图片描述
chip_base:DDR在S5PV210中的起始地址,当设为0x20时,起始地址为0x2000_0000。
在这里插入图片描述
step8:Set the PrechConfig and PwrdnConfig registers.
此步未配置PwrdnConfig ,将set PwrdnConfig 放到了代码最后配置。

//step8:PrechConfig
ldr r1,=0xFF000000
str r1,[r0,#DMC_PRECHCONFIG]

在这里插入图片描述
chip0_policy:rank0打开政策,若置0,则打开页政策,表示每读/写完一个数据后,暂时不关闭该行,若下个数据也在该行,则不用重复打开。置1,则每读/写一个数据就将该行关闭。[7:0]是针对每个bank都可以单独设置。一般都设置为0x0。
chip1_policy:rank1的打开政策。同上。
tp_cnt:当在chip0_policy打开的时候,读/写指令完成之后没有确切的等待周期数,则从数据总线上有数据开始经过tp_cnt个周期后,会自动发送precharge命令关闭该行。一般设置的大一些,此处设为0xFF。
step9:Set the TimingAref, TimingRow, TimingData and TimingPower registers according to memory AC
parameters.

//step9:TimingAref 78.us//133MHz=1038(0x40E),100MHz=780(0x30C),20MHz=156(0x9C),10MHz=78(0x4E)
ldr r1,=DMC0_TIMINGA_REF
str r1,[r0,#DMC_TIMINGAREF]
//TimingRow for 200MHz
ldr r1,=DMC0_TIMING_ROW
str r1,[r0,#DMC_TIMINGROW]
//TimingData CL=4
ldr r1,=DMC0_TIMING_DATA
str r1,[r0,#DMC_TIMINGDATA]
//TimingPower
ldr r1,=DMC0_TIMING_PWR
str r1,[r0,#DMC_TIMINGPOWER]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
TimingAref寄存器:
t_refi:每行数据64ms刷新一次,共有16k行,刷新8k次,则两行刷新时间间隔为64ms/8k≈7.8us。又时钟频率为133MHz,则时钟周期为1/133MHz。则两行刷新时间间隔的时钟周期数为7.8us×133MHz = 1038。配置为0x40E。
133MHz,是通过查手册,在BL1阶段,初始化时钟频率为400MHz,配置给DDR的时钟为133MHz。DEMO程序中给出的值为0x00000618,其对应的频率为200MHz,此时需要将其改为133MHz.
在这里插入图片描述
TimingRow寄存器:
t_rfc:自刷新指令之间的时钟周期数,通过查手册:
在这里插入图片描述
查得tRFC=127.5ns。则t_rfc*T≥tRFC,T=133MHz。计算得t_rfc≥17。设为17=0x11。DEMO中设置为2B,也是可以的。
同理,查得其余参数,得:
在这里插入图片描述
TimingData寄存器:
也是通过查手册得:
其中t_cas必须DMC端和DDR端配置一致。wl和rl只给LPDDR使用,此处不用配置。
在这里插入图片描述
TimingPower寄存器:
t_xsr:表示在退出下电自刷新时,从下电模式上电之后,到第一个有效指令之间需要等待的时钟周期数。查手册得需要≥200个clk。DEMO中设置为220。
t_xp:指退出下电模式后,到下一个有效指令需要等待得时钟周期数。手册中注释此参数≥2,DEMO中为3。
t_cke:表示下电或者上电至少要维持t_cke个时钟周期。手册中注释此参数≥3,DEMO中为4。
t_mrd:表示在发送写MRS或者EMRS寄存器指令后,至少等待t_mrd个时钟周期才可以进入下电模式。手册中注释此参数≥2,DEMO中为3。
在这里插入图片描述
step10:If QoS scheme is required, set the QosControl0~15 and QosConfig0~15 registers.
Qos现在不用,此步跳过。
step11和step12已在step4之后执行了。
step13:Confirm whether stable clock issues minimum 200us after power on.
此步,DEMO未等待200us,因为从上电开始执行到此处,程序执行start.S中的代码以及之前得初始化指令,运行时间已经超过200us,所以此步跳过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值