DM3730 x-loader 分析 七 DDR

时间:2022-04-14 01:44:35

本文所涉及的DDR型号MT29C4G96MAZAPCJA-5IT,512MB,32/IO,4bank,200MHz

先放源码,根据cpu_family() 只看红色部分。

void config_3430sdram_ddr(void)
{
/* reset sdrc controller */
__raw_writel(SOFTRESET, SDRC_SYSCONFIG);

//__raw_writel(1<<1, 0x6D000010);   

//寄存器SDRC_SYSCONFIG赋值0x00000002  含义 Software reset activated//
wait_on_value(BIT0, BIT0, SDRC_STATUS, 12000000);// 这个函数的具体分析见下//

//wait_on_value(1<<0, 1<<0, 0x6D000014, 12000000)//

//寄存器SDRC_SYSSTATUS 赋值0x001 含义 Resetcompleted- The module is readyto be used//
__raw_writel(0, SDRC_SYSCONFIG);

// 寄存器SDRC_SYSCONFIG 赋值0x00 含义 Normal mode//

/* setup sdrc to ball mux */
__raw_writel(SDP_SDRC_SHARING, SDRC_SHARING);

//__raw_writel(0x00000100, 0x6D000044); 

//寄存器 SDRC_SHARING 赋值0x00000100 含义 使用CS0,CS1 32-bit SDRAM on Datalane [31:0]//


switch (get_cpu_family()) {
case CPU_OMAP34XX: /* Micron 1286MB/256MB, 1/2 banks of 128MB */
__raw_writel(0x1, SDRC_CS_CFG); /* 128MB/bank */
__raw_writel(SDP_SDRC_MDCFG_0_DDR, SDRC_MCFG_0);
__raw_writel(SDP_SDRC_MDCFG_0_DDR, SDRC_MCFG_1);
__raw_writel(MICRON_V_ACTIMA_165, SDRC_ACTIM_CTRLA_0);
__raw_writel(MICRON_V_ACTIMB_165, SDRC_ACTIM_CTRLB_0);
__raw_writel(MICRON_V_ACTIMA_165, SDRC_ACTIM_CTRLA_1);
__raw_writel(MICRON_V_ACTIMB_165, SDRC_ACTIM_CTRLB_1);
__raw_writel(SDP_3430_SDRC_RFR_CTRL_165MHz, SDRC_RFR_CTRL_0);
__raw_writel(SDP_3430_SDRC_RFR_CTRL_165MHz, SDRC_RFR_CTRL_1);
break;
case CPU_OMAP36XX: /* Hynix 256MB/512MB, 1/2 banks of 256MB */
__raw_writel(0x2, SDRC_CS_CFG); /* 256MB/bank */
__raw_writel(SDP_SDRC_MDCFG_0_DDR_HYNIX, SDRC_MCFG_0);
__raw_writel(SDP_SDRC_MDCFG_0_DDR_HYNIX, SDRC_MCFG_1);
__raw_writel(HYNIX_V_ACTIMA_200, SDRC_ACTIM_CTRLA_0);
__raw_writel(HYNIX_V_ACTIMA_200, SDRC_ACTIM_CTRLB_0);
__raw_writel(HYNIX_V_ACTIMA_200, SDRC_ACTIM_CTRLA_1);
__raw_writel(HYNIX_V_ACTIMA_200, SDRC_ACTIM_CTRLB_1);
__raw_writel(SDP_3430_SDRC_RFR_CTRL_200MHz, SDRC_RFR_CTRL_0);
__raw_writel(SDP_3430_SDRC_RFR_CTRL_200MHz, SDRC_RFR_CTRL_1);
break;

          default:

__raw_writel(0x1, SDRC_CS_CFG); /* 128MB/bank */
__raw_writel(SDP_SDRC_MDCFG_0_DDR, SDRC_MCFG_0);
__raw_writel(SDP_SDRC_MDCFG_0_DDR, SDRC_MCFG_1);
__raw_writel(MICRON_V_ACTIMA_165, SDRC_ACTIM_CTRLA_0);
__raw_writel(MICRON_V_ACTIMB_165, SDRC_ACTIM_CTRLB_0);
__raw_writel(MICRON_V_ACTIMA_165, SDRC_ACTIM_CTRLA_1);
__raw_writel(MICRON_V_ACTIMB_165, SDRC_ACTIM_CTRLB_1);
__raw_writel(SDP_3430_SDRC_RFR_CTRL_165MHz, SDRC_RFR_CTRL_0);
__raw_writel(SDP_3430_SDRC_RFR_CTRL_165MHz, SDRC_RFR_CTRL_1);
}

__raw_writel(SDP_SDRC_POWER_POP, SDRC_POWER);

/* init sequence for mDDR/mSDR using manual commands (DDR is different) */
__raw_writel(CMD_NOP, SDRC_MANUAL_0);
__raw_writel(CMD_NOP, SDRC_MANUAL_1);

delay(5000);

__raw_writel(CMD_PRECHARGE, SDRC_MANUAL_0);
__raw_writel(CMD_PRECHARGE, SDRC_MANUAL_1);

__raw_writel(CMD_AUTOREFRESH, SDRC_MANUAL_0);
__raw_writel(CMD_AUTOREFRESH, SDRC_MANUAL_1);

__raw_writel(CMD_AUTOREFRESH, SDRC_MANUAL_0);
__raw_writel(CMD_AUTOREFRESH, SDRC_MANUAL_1);

/* set mr0 */
__raw_writel(SDP_SDRC_MR_0_DDR, SDRC_MR_0);
__raw_writel(SDP_SDRC_MR_0_DDR, SDRC_MR_1);

/* set up dll */
__raw_writel(SDP_SDRC_DLLAB_CTRL, SDRC_DLLA_CTRL);
delay(0x2000);/* give time to lock */

}
#endif /* CFG_3430SDRAM_DDR */

上面这些寄存器是DM3730 中SDRC(三星处理器中叫DMC)需要配置的,主要涉及一些DDR本身参数,特别是一些时间参数,我用表格1-1说明比较直观

1. 第一列是SDRC中目标寄存器名称以及datasheet对应页码,第二列是写入值,后面32列为了方便分析每个区域bit位的含义

2. 寄存器的顺序与代码执行顺序一致,这个初始化顺序参考sprugn4r.pdf P2272,不过代码的顺序做了调整,具体问什么调整,不必纠结,因为这个是大牛写好的!

3. 其中寄存器SDRC_ACTIM_CTRLA_p(0/1)里面的值是根据DDR芯片本身AC parameters 计算的,如何计算?什么含义?见下表1-2

4. 也就是如果以后要替换DDR 在不改变硬件连接方式的情况下,例如:数据宽度,容量等不变,只更换品牌,DDR频率就参考表1-2更改部分值就可以了。

    如果更换的DDR数据宽度或者容量都不一样,那就需要把表1-1全部重新配置一遍。

5.红色和灰色区域目前还没有理解,理解以后再更新

DM3730 x-loader 分析 七 DDR


DM3730 x-loader 分析 七 DDR

相关函数说明

参数说明:
u32 read_bit_mask 要读取目标寄存器中bit位
u32 match_value   读取的匹配值
u32 read_addr     目标寄存器地址
u32 bound         等待值


这个函数的意思就是要读取目标寄存器某个状态位的值,如果和匹配值相同,就返回1,如果不同就等待bound
直到返回0,结束。


u32 wait_on_value(u32 read_bit_mask, u32 match_value, u32 read_addr, u32 bound)
{
u32 i = 0, val;
do {
++i;
val = __raw_readl(read_addr) & read_bit_mask;


//读取寄存器中的值,& read_bit_mask 就是把需要的bit位保留,其他位清零,赋值给val//


if (val == match_value)
return 1;
//判断读取的值与匹配值是否相同//
if (i == bound)
return 0;
} while (1);
}