Tiny210(S5PV210) U-BOOT(十一)----DDR2初始化源码分析

1.u-boot关于DDR的源码分析在mem_setup.S中,一点一点来,先看第一段

   /* 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, =0x00002AAA
    str    r1, [r0, #MP1_8DRV_SR_OFFSET]
首先在初始化DDR之前,引入一个关于DRAM Drive Strength的概念----DRAM Drive Strength(也被称为:driving strength),表示“DRAM驱动强度”。这个参数用来控制内存数据总线的信号强度,数值越高代表信号强度越高,增加信号强度可以提高超频的稳定性。但是并非信号强度高就一定好。
所以,这里我们需要配置这个Drive Striegth,DDR2内存的所有线都需要配置,这里我们从地址线开始看,我们的内存是挂载在Memory Port1(以下简称MP1)上,所以,先在S5PV210的芯片手册搜索Xm1ADDR。
Tiny210(S5PV210) U-BOOT(十一)----DDR2初始化源码分析_第1张图片
在P63页,找到MP1的各个pin脚的描述,继续向下搜索。
Tiny210(S5PV210) U-BOOT(十一)----DDR2初始化源码分析_第2张图片
在P107页,Pin脚复用的描述表里找到他的GPIO口定义
Tiny210(S5PV210) U-BOOT(十一)----DDR2初始化源码分析_第3张图片
Xm1ADDR[0]~[7]的GPIO的MP1_0[0]~7是复用的,OK,搜索MP1_0。

在P122页最终找到MP1_0DRV,在这个寄存器的描述中,显示这个寄存器就是用来配置我们的内存的Drive Strength的寄存器,搜索MP1_0DRV。


找到MP1_0DRV的寄存器的配置表,这里给出的初始值是AAAA,我总共是0-7,8根线,每根线我配的值都是10,也就是2x,符合我们上面介绍DRAM Driver Strength的描述,OK,到这里我们的MP1_0寄存器----Xm1ADDR[0]~[7]的Driver Strength配置完毕。剩下的就按照上面的方法,再把剩下的线全部配好,初始均按芯片手册的参考值配为2x,也就是10。现在再回过头来看上面的初始化代码,清楚多了,整个这么一长串代码,其实只做了一件事,就是给MP1上接的内存的每一根线都配置Driver Strength的值为2x,这里有一个地方,需要注意一下,最后一个MP1_8他的参考配置为0x2AAA。照样的,再配置DM1,把Memory Port2也配置完毕,这里我们没有用到MP2,不配置,应该也没有关系。继续看下一段代码:

/* DMC0 initialization at single Type*/
    ldr    r0, =APB_DMC_0_BASE

    ldr    r1, =0x00101000                @PhyControl0 DLL parameter setting, manual 0x00101000
    str    r1, [r0, #DMC_PHYCONTROL0]

    ldr    r1, =0x00000086                @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
    str    r1, [r0, #DMC_PHYCONTROL1]

    ldr    r1, =0x00101002                @PhyControl0 DLL on
    str    r1, [r0, #DMC_PHYCONTROL0]

    ldr    r1, =0x00101003                @PhyControl0 DLL start
    str    r1, [r0, #DMC_PHYCONTROL0]

根据芯片手册给出的参考步骤,第2步如下:

2.依照时钟频率正确配置PhyControl0.ctrl_start_point和PhyControl0.ctrl_inc bit-fields的值。配置的PhyControl0.ctrl_dll_on值为'1'以打开PHY DLL。

那开始配置PhyControl0的相关位,P614页找到DRAM的寄存器配置表,找到有关PhyControl0的寄存器为PHYCONTROL0

OK,我们需要正确配置PhyControl0寄存器的ctrl_start_pointctrl_inc这两个位的值,OK,查看寄存器的描述

Tiny210(S5PV210) U-BOOT(十一)----DDR2初始化源码分析_第4张图片

ctrl_start_point和ctrl_inc这两位芯片手册上给的参考值为0x10,先配这两位,则为:
ctrl_start_point: 0x10 ---- 10000(二进制)
ctrl_inc:  0x10 ---- 10000(二进制)
其余的位全部配成0,最终为 10000 00010000 00000000 ---- 0x00101000,代码如下:
    ldr    r0, =APB_DMC_0_BASE

    ldr    r1, =0x00101000                @PhyControl0 DLL parameter setting, manual 0x00101000
    str    r1, [r0, #DMC_PHYCONTROL0]
第2步配置完成,接着往下看第3步--3.DQS Cleaning:依照时钟频率和内存的tAC参数正确设置PhyControl1.ctrl_shiftc and PhyControl1.ctrl_offsetc bit-fields位的值。

查看PhyControl1的ctrl_shiftcctrl_offsetc这两位的描述
Tiny210(S5PV210) U-BOOT(十一)----DDR2初始化源码分析_第5张图片
我们的内存是DDR2-800,所以ctrl_shiftc配置为0x6 ---- 110,ctrl_offsetc的配置暂时参考三星的裸板参数配置为0,ctrl_ref配置为1000,整理代码如下:

 ldr    r1, =0x00000086                @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
 str    r1, [r0, #DMC_PHYCONTROL1]
按照第2步的要求,打开PLL,将 PhyControl0.ctrl_dll_on配置为1
    ldr    r1, =0x00101002                @PhyControl0 DLL on
    str    r1, [r0, #DMC_PHYCONTROL0]
继续第4步-- 4.配置 PhyControl0.ctrl_start 的值为'1'
    ldr    r1, =0x00101003                @PhyControl0 DLL start
    str    r1, [r0, #DMC_PHYCONTROL0]
后面的步骤,全部是按照三星的芯片手册上的那28步来一步一步的在操作寄存器,没有一步有漏掉,所以,对比着芯片手册上的那28步一行一行的查看代码就OK了。有一点,在配置完 16-25步后,到第26步时--配置第26步--26.如果有两组DDR芯片,重复14-25步配置chip1的内存,刚刚配置的是chip0,也就是第一组内存芯片。这里就把第16-25步重新再做一次,初始化chip1就OK了。代码太多,这里就不详细重复了,我这里参考的是三星的裸板的DDR源码。至此,DDR的源码也分析完成,下面,应该可以开始将这些移植进一个新的u-boot中去了。

你可能感兴趣的:(u-boot)