http://weimenlove.blog.163.com/blog/static/177754732013421103750491/
S3C2410/S3C2440在操作SDRAM时,如果操作的是64M大小,则用来选择4个L-Bank的引脚为ADDR24和ADDR25,但如果操作的SDRAM是128M,则需要使用ADDR25和ADDR26引脚来进行bank选择。如果使用的SDRAM为256M,则需要使用nGCS6和nGCS7两个片选来配合操作,且最大支持的SDRAM为256M。
⒈DDR相关配置
配置DDR芯片的特性:比如row位数,column地址数,CS0和CS1的选择,Bank数等。
TI8148中关于DDR的配置,查看tms320dm8148.pdf,发现有DDR0 Registers和DDR1 Registers地址为:(Table 2-3. L3 Memory Map)
0x4C00_0000 0x4CFF_FFFF 16MB DDR0 Registers
0x4D00_0000 0x4DFF_FFFF 16MB DDR1 Registers
然后查看SPRUGZ8D.pdf中的Table 7-35. DDR2/DDR3 Memory Controller Registers,查得SDRAM Configuration Registe的偏移地址为80H。并查看7.8.1.2 SDRAM Configuration Register(SDRCR)各个位代表的意思。
8h SDRCR SDRAM Configuration Registe
结合开发板使用的MT41J256芯片手册,有如下结论:
①1024 word page requiring 10 column address bits(2~0:010)
②电路图上只使用了CS0(3:0)。
③内部有8个bank(芯片手册)(6~4:011)
④Row使用了A[14:0],即15根线(芯片手册)(9~7:110)
在u-boot源代码中,arch/arm/include/asm/arch-ti81xx/ddr_defs_ti814x.h里对该值进行了定义。根据上面的要求,进行修改。
#define DDR3_EMIF_SDRAM_CONFIG 0x61C011B2
改为:
#define DDR3_EMIF_SDRAM_CONFIG 0x61C01332。
在board/ti/ti8148/evm.c中,将上面的值写入对应的寄存器DDR0 Registers和DDR1 Registers中。
static void config_ti814x_ddr(void)
{
__raw_writel(DDR3_EMIF_SDRAM_CONFIG, EMIF4_0_SDRAM_CONFIG);
__raw_writel(DDR3_EMIF_SDRAM_CONFIG, EMIF4_1_SDRAM_CONFIG);
}
2. DDR DMM配置
配置DDR的大小,是否使用交织访问方式等。
查看tms320dm8148.pdf,发现DDR DMM Registers地址为:(Table 2-3. L3 Memory Map)
0x4E00_0000 0x4FFF_FFFF 32MB DDR DMM Registers
然后查看SPRUGZ8D.pdf中的Table 6-10. DMM/TILER Registers,查得DMM_LISA_MAP_0-3的偏移地址为40H~4CH。并查看Figure 6-60. DMM_LISA_MAP Registers各个位代表的意思。
40h-4Ch DMM_LISA_MAP_0-3
arch/arm/include/asm/arch-ti81xx/ddr_defs_ti814x.h
芯片为PG1_0版本时,修改PG1_0_DMM_LISA_MAP__开头的宏;芯片为PG2_1版本时,修改PG2_1_DMM_LISA_MAP__开头的宏。
ezsdk官方的代码使用的是1G的DDR配置为:
//1G contiguous section with 128-byte interleaving
#define PG2_1_DMM_LISA_MAP__3
0x80640300
使用2G的DDR时配置为:
//2G contiguous section with 128-byte interleaving
#define PG2_1_DMM_LISA_MAP__3
0x80740300
有2G的空间但是只使用高1G的配置为:
//1G Mapped on SDRC1 only (no interleaved)
#define PG2_1_DMM_LISA_MAP__3
0x80600200
在文件arch/arm/include/asm/arch-ti81xx/clocks_ti814x.h中有如下宏定义:
#define DDR_N
19
#define DDR_M
(pg_val_ti814x(666, 800))
#endif
#define DDR_M2
2
#define DDR_CLKCTRL
0x801
其中pg_val_ti814x()的定义如下,在这里 DDR_M的值为800。
u32 pg_val_ti814x(u32 pg1_val, u32 pg2_val)
{
/* PG2.1 devices should read 0x3 as chip rev */
if (PG2_1 == get_cpu_rev())
return pg2_val;
else
return pg1_val;
}
对上述宏的引用过程如下:s_init()->prcm_init()->ddr_pll_config()->pll_config()。
pll_config()的内容如下:
/*
* configure individual ADPLLJ
*/
static void pll_config(u32 base, u32 n, u32 m, u32 m2, u32 clkctrl_val)
{
u32 m2nval, mn2val, read_clkctrl = 0;
m2nval = (m2 << 16) | n;
mn2val = m;
/* by-pass pll */
read_clkctrl = __raw_readl(base + ADPLLJ_CLKCTRL);
__raw_writel((read_clkctrl | 0x00800000), (base + ADPLLJ_CLKCTRL));
while ((__raw_readl(base + ADPLLJ_STATUS) & 0x101) != 0x101);
read_clkctrl = __raw_readl(base + ADPLLJ_CLKCTRL);
__raw_writel((read_clkctrl & 0xfffffffe), (base + ADPLLJ_CLKCTRL));
/*
* ref_clk = 20/(n + 1);
* clkout_dco = ref_clk * m;
* clk_out = clkout_dco/m2;
*/
__raw_writel(m2nval, (base + ADPLLJ_M2NDIV));
__raw_writel(mn2val, (base + ADPLLJ_MN2DIV));
/* Load M2, N2 dividers of ADPLL */
__raw_writel(0x1, (base + ADPLLJ_TENABLEDIV));
__raw_writel(0x0, (base + ADPLLJ_TENABLEDIV));
/* Loda M, N dividers of ADPLL */
__raw_writel(0x1, (base + ADPLLJ_TENABLE));
__raw_writel(0x0, (base + ADPLLJ_TENABLE));
read_clkctrl = __raw_readl(base + ADPLLJ_CLKCTRL);
if (MODENA_PLL_BASE == base)
__raw_writel((read_clkctrl & 0xff7fffff) | clkctrl_val,
base + ADPLLJ_CLKCTRL);
else
__raw_writel((read_clkctrl & 0xff7fe3ff) | clkctrl_val,
base + ADPLLJ_CLKCTRL);
/* Wait for phase and freq lock */
while ((__raw_readl(base + ADPLLJ_STATUS) & 0x600) != 0x600);
}
DDR的输出频率为clk_out= 20/(DDR_N+1)* DDR_M/ DDR_M2 = 20/(19+1)*800/2=400。其中涉及到的寄存器包括:DDRPLL_M2NDIV Register(addr=0x481c52A0)(offset=2A0h);DDRPLL_MN2DIV Regiseter(addr=0x481c52A4)(offset=2A4h);
当需要修改DDR的频率时,可以直接修改DDR_M中的频率值即可。