S5PV210的DDR初始化

S5PV210中DDR的初始化在数据手册中已经说明了步骤,总共27步。本人借助手册进行简单翻译和用代码描述。

ddr时间相关的参数是根据我自己的开发板的ddr设置的,如果想用比较通用的参数,可以参考三星的原版uboot,里面的参数范围比较通用。

S5PV210的DDR初始化_第1张图片

S5PV210的DDR初始化_第2张图片

1. 为了提供稳定的电源给控制器和内存设备,控制器必须确保CKE维持低电平。然后提供一个稳定的时钟。注意:XDDR2SEL需保持高来维持CKE为低.

通常板子都会直接把XDDR2SEL接为高电平


/* 2.根据时钟设置PhyControl0.ctrl_start_point和PhyControl0.ctrl_inc位域以校正值
* 频率。将PhyControl0.ctrl_dll_on位域设置为'1'以打开PHY DLL。
*/
__REG(APB_DMC_0_BASE+DMC_PHYCONTROL0) = (0x10 << 16)|(0x10 << 8)|(1 << 1);


/* 3.DQS清理:将PhyControl1.ctrl_shiftc和PhyControl1.ctrl_offsetc位域设置为正确的值
* 根据时钟频率和存储器tAC参数。
*/
__REG(APB_DMC_0_BASE+DMC_PHYCONTROL1) = (0 << 8)|(8 << 4)|(6 << 0);

/* 4.将PhyControl0.ctrl_start位域设置为'1'。
*/
__REG(APB_DMC_0_BASE+DMC_PHYCONTROL0) |= (1 << 0);

/* 5.设置ConControl 此时,应该关闭自动刷新计数器。 */
__REG(APB_DMC_0_BASE+DMC_CONCONTROL) &= ~(1 << 5);

__REG(APB_DMC_0_BASE+DMC_CONCONTROL) |= (2 << 12);


/* 6.设置MemControl。此时,所有关机模式都应关闭bit16:  0代表1片   1代表2片*/
__REG(APB_DMC_0_BASE+DMC_MEMCONTROL) = (2 << 20)|(0 << 16)|(2 << 12)|(4 << 8);


/* 7.设置MemConfig0寄存器。如果有两个外部存储器芯片,请设置MemConfig1寄存器
*  大于bit 24 选择存储基地址 0x20 ->0x20000000    0x30 ->0x30000000  0x40->0x4000000 */
__REG(APB_DMC_0_BASE+DMC_MEMCONFIG0) = (0x20 << 24)|(0xf0 << 16)|(1 << 12)|(3 << 8)|(2 << 4)|(3 << 0);
//__REG(APB_DMC_0_BASE+DMC_MEMCONFIG1) = (0x40 << 24)|(0xf0 << 16)|(1 << 12)|(3 << 8)|(2 << 4)|(3 << 0);

/* 8.设置PrechConfig和PwrdnConfig寄存器。 */
__REG(APB_DMC_0_BASE+DMC_PRECHCONFIG) = 0xff000000;
__REG(APB_DMC_0_BASE+DMC_PWRDNCONFIG) = 0xffff00ff;

/* 9.根据内存AC设置TimingAref,TimingRow,TimingData和TimingPower寄存器参数。 
* TimingAref = 200 * 7.8
*/
__REG(APB_DMC_0_BASE+DMC_TIMINGAREF) = (1560 << 0);
__REG(APB_DMC_0_BASE+DMC_TIMINGROW) = (0x28 << 24)|(2 << 20)|(3 << 16)|(3 << 12)|(12 << 6)|(7 <<  0);
__REG(APB_DMC_0_BASE+DMC_TIMINGDATA) = (2 << 28)|(3 << 24)|(3 << 20)|(4 << 16)|(4 << 8)|(5 << 0);
__REG(APB_DMC_0_BASE+DMC_TIMINGPOWER) = (10 << 24)|(200 << 16)|(3 << 8)|(3 << 4)|(2 << 0);


/* 10.如果需要QoS方案,请设置QosControl0?15和QosConfig0?15寄存器 */


/* 11.等待DLL lock */
while(0x07 != (__REG(APB_DMC_0_BASE+DMC_PHYSTATUS) & 0x07));


/* 12. PHY DLL补偿由过程,电压和温度(PVT)引起的延迟量的变化,
 * 记忆操作期间的变化。因此,PHY DLL不应该关闭以实现可靠的操作。它可以关闭
 * 除了以低频运行。如果使用关闭模式,请将PhyControl0.ctrl_force位域设置为正确的值
 * 根据PhyStatus0.ctrl_lock_value [9:2]位域来确定延迟量。清除
 * PhyControl0.ctrl_dll_on位域关闭PHY DLL。 
 */
/* 把PhyStatus0.ctrl_lock_value [9:2]数据写到 PhyControl0.ctrl_force里面*/
__REG(APB_DMC_0_BASE+DMC_PHYCONTROL0) |= ((__REG(APB_DMC_0_BASE+DMC_PHYSTATUS)&0x3fc0)<<18); 


/* 13.开机后至少200us确认是否有稳定的时钟
*/
        delay_ms(1);

/* 14.使用DirectCmd寄存器发出NOP命令来断言并将CKE保持为逻辑高电平 */ 
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (7 << 24);


/* 15.等待至少400ns */
        delay_ms(1);

/* 
  *  16.使用DirectCmd寄存器发出PALL命令。
* 17.使用DirectCmd寄存器发出EMRS2命令来编程操作参数。
* 18.使用DirectCmd寄存器发出EMRS3命令来编程操作参数。
* 19.使用DirectCmd寄存器发出EMRS命令以启用内存DLL。
* 20.使用DirectCmd寄存器发出MRS命令以重置内存DLL。
* 21.使用DirectCmd寄存器发出PALL命令。
* 22.使用DirectCmd寄存器发出两个自动刷新命令。
* 23.使用DirectCmd寄存器发出MRS命令来编程操作参数而不需要重新设置内存DLL
*/
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (1 << 24);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (2 << 16);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (3 << 16);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (1 << 16)|(1 << 10);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (0x542 << 0);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (1 << 24);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (5 << 24);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (5 << 24);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (0x442 << 0);


/* 24.等待至少200个时钟周期
*
*/
    delay_ms(1);

/* 25.使用DirectCmd寄存器发出EMRS命令来编程操作参数。如果强迫症
* 不使用校准,发出EMRS命令来设置OCD校准默认值。之后,发布EMRS
* 命令退出OCD校准模式并编程操作参数。
*
*/
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = 0x00010780;
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = 0x00010400;


/* 26.如果有两个外部存储器芯片,请对chip1存储器设备执行步骤14~25
*
*/
/* 14.使用DirectCmd寄存器发出NOP命令来断言并将CKE保持为逻辑高电平*/ 

__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (7 << 24)|(1 << 20);


/* 15.等待至少400ns */

                delay_ms(1);

/* 
*  16.使用DirectCmd寄存器发出PALL命令。
* 17.使用DirectCmd寄存器发出EMRS2命令来编程操作参数。
* 18.使用DirectCmd寄存器发出EMRS3命令来编程操作参数。
* 19.使用DirectCmd寄存器发出EMRS命令以启用内存DLL。
* 20.使用DirectCmd寄存器发出MRS命令以重置内存DLL。
* 21.使用DirectCmd寄存器发出PALL命令。
* 22.使用DirectCmd寄存器发出两个自动刷新命令。
* 23.使用DirectCmd寄存器发出MRS命令来编程操作参数而不需要重新设置内存DLL
*/
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (1 << 24)|(1 << 20);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (2 << 16)|(1 << 20);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (3 << 16)|(1 << 20);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (1 << 16)|(1 << 20)|(1 << 10);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (0x542 << 0)|(1 << 20);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (1 << 24)|(1 << 20);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (5 << 24)|(1 << 20);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (5 << 24)|(1 << 20);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = (0x442 << 0)|(1 << 20);


/* 24.等待至少200个时钟周期 */

   delay_ms(1);


/* 25.使用DirectCmd寄存器发出EMRS命令来编程操作参数。如果强迫症
* 不使用校准,发出EMRS命令来设置OCD校准默认值。之后,发布EMRS
* 命令退出OCD校准模式并编程操作参数。 */
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = 0x00010780|(1 << 20);
__REG(APB_DMC_0_BASE+DMC_DIRECTCMD) = 0x00010400|(1 << 20);


     /*  27.将ConControl设置为打开自动刷新计数器。 */
__REG(APB_DMC_0_BASE+DMC_CONCONTROL) |= (1 << 5);

/* 28.如果需要省电模式,请设置
* MemControl寄存器
*/
        
}


你可能感兴趣的:(嵌入式)