这部分留给mc_init(这可能是个大话题。)
1. 这个函数被调用了两次,参数t3分别是0和1
mc_init:
move t7, ra //保存返回值,可能中间要调用其他函数
sync
nop
nop
nop
nop
//t0 = 0x900000003ff00000 两个偏移都是0x10??,配置了同一个窗口??
GET_NODE_ID_a0; //a0=0;s1也传过来了,参数OFFSET,BASE,MASK,MMAP
XBAR_CONFIG_NODE_a0(0x10, \
0x0000000000000000, \
0xfffffffff0000000, \
0x00000000000000f0)
beqz t3, 1f //第一次进来的时候等于0,第二次等于1
nop
GET_NODE_ID_a0;
XBAR_CONFIG_NODE_a0(0x10, \
0x0000000000000000, \
0xfffffffff0000000, \
0x00000000000000f1)
1:
sync
nop
nop
nop
nop
t7 保存了返回值。
a0 = 0.
t0 = 0x900000003ff00000
1.1 展开宏定义,这个已经见过多次了
#define XBAR_CONFIG_NODE_a0(OFFSET, BASE, MASK, MMAP) \
daddiu v0, t0, OFFSET; \
dli v1, BASE; \
or v1, v1, a0; \
sd v1, 0x00(v0); \
dli v1, MASK; \
sd v1, 0x40(v0); \
dli v1, MMAP; \
sd v1, 0x80(v0);
这里配置0x900000003ff00010,是CPU_WIN2的配置
BASE = 0;
MASK= 0xffff,ffff,f000,0000;
MMAP = 0xf0. 允许映射,指向DDR0控制器,范围0~0xfff,ffff (256M)
第一次调用的时候,跳到标号1.
第二次调用的时候。执行下面的语句
配置0x900000003ff00010,是CPU_WIN2的配置,把前面的配置给覆盖了。
BASE = 0;
MASK= 0xffff,ffff,f000,0000;
MMAP = 0xf1. 允许映射,指向DDR1控制器,范围0~0xfff,ffff (256M)
2.继续看代码,有一个跳转
TTYDBG("\r\nEnable register space of MEMORY\r\n")
bal enable_mc_conf_space //1167行。禁止MC
nop
3. 进入enable_mc_conf_space函数
//for 3A8
LEAF(enable_mc_conf_space)
/*********************
pre-condition::
t2: chip configure register address
t3: MC select
*********************/
lw a2, 0x0(t2)
li v1, 0x1
beqz t3, 1f //t3等于0,则跳转
nop
sll v1, v1, 5 //t3等于1时,左移5位
1:
sll v1, v1, DDR_CONFIG_DISABLE_OFFSET //8
not v1, v1 //按位取反
and a2, a2, v1 //t3=0,[8]清零mc0禁止 t3=1,[13]清零mc1禁止
sw a2, 0x0(t2)
sync
jr ra
nop
END(enable_mc_conf_space)
t2 = 0x900000001fe00180
在初始化的时候,先禁止对应的MC控制器??还是使能??
4. 设置t8 = 0x9000,0000,0ff0,0000
GET_NODE_ID_a0;
dli t8, DDR_MC_CONFIG_BASE //0x9000,0000,0ff0,0000
or t8, t8, a0
a0 = 0;
5. 识别DDR类型
GET_SDRAM_TYPE //a1=3,DDR3
dli t1, 0x2
beq t1, a1, 2f //不相等,不跳转
nop
dli t1, 0x3
beq t1, a1, 3f //ddr3,跳128行
nop
//not DDR2 and not DDR3, errors
PRINTSTR("\r\n!!! ERROR: NOT recognized DDR SDRAM TYPE. !!!\r\n");
b 3f
nop
6. 准备DDR内存配置参数
3: //DDR3 //--------------------------------执行这
GET_DIMM_TYPE //dimm buffer register: NO a1 = 0;
bnez a1, 1f
nop
//UDIMM
dla a2, ddr3_reg_data //ddr3_reg_data是个数组,loongson_mc2_param.S(start.S中1818包含)
beqz t3, 21f //第一次t3等于0,跳转,第二次不跳转
nop
dla a2, ddr3_reg_data_mc1 //其实与ddr3_reg_data数据一样
21:
7. 调用函数ddr2_config
b 4f //注意参数 a2 跳到183行
nop
4:
bal ddr2_config //lsmc_config_param.S
nop
8. 在另一个S文件中。这个文件在开始的时候被包含进来。
support lsmc(3A8, 3B5~)
input param:
a2: mc param address
t7(option ARB_LEVEL)--do arb level, 0--not level; 1--do level;
t8: input, Memory Controller config register base
t3: controller select
0: MC0
1: MC1
看一眼注释吧。
a2 已经有了,t8前面已经有了,t3也没问题。t7似乎没用到,反正是0。
9. 将配置信息写入到寄存器,一共写了180个寄存器(64位)
ddr2_config:
daddu a2, a2, s0 //a2是数组的地址,+s0得到的应该是在rom的绝对地址
dli t1, DDR_PARAM_NUM //ddr_param_define.h t1 = 180
daddiu v0, t8, 0x0 t8 = 0x9000,0000,0ff0,0000
//write param registers
1:
ld a1, 0x0(a2) //加载数组中第一个双字(8个字节)
sd a1, 0x0(v0) //写入到配置寄存器
daddiu t1, t1, -1
daddiu a2, a2, 0x8 //数组的指针后移8个字节
daddiu v0, v0, 0x8 //寄存器的指针同步后移8个字节
bnez t1, 1b //t1不等于0,继续循环,应该是循环180次
nop
10.设置刷新周期
set_tREFI: //设置刷新周期
dli t1, DDR_FREQ //DDR_FREQ = 533 频率
divu t1, t1, 10 //除以10 t1 = 53
dli a2, 78
dmulou a2, a2, t1 //乘法,a2 = 78*53 = 4134 = 0x1026
#ifndef TEMP_EXTREME //没定义
dsrl a2, a2, 8 //右移8位,a2 = 0x10
#else
dsrl a2, a2, 9
#endif
// daddu a2, a2, 1
dli t1, 0x1c8
or t1, t1, t8 //t1 = 0x9000,0000,0ff0,01c8
sb a2, 0x3(t1) //写寄存器1个字节,0x9000,0000,0ff0,01cb
寄存器0x0ff0,01cb,没有相关说明。寄存器就是这个。
11.设置RFC
#ifndef NO_AUTO_TRFC //没定义
set_tRFC:
GET_MC0_MEMSIZE //a1 = 16
beqz t3, 1f //t3 第一次为0,跳转,第二次为1,不跳转
nop
GET_MC1_MEMSIZE //第二次的时候,a1=16
1:
move t1, a1 //t1 = 16
GET_MC_CS_MAP //a1=3
beqz t3, 1f //t3 第一次为0,跳转,第二次为1,不跳转
nop
GET_MC1_CS_MAP //a1=3
1:
dli t5, 0x4 //t5 = 4
dli a2, 0x0 //a2 = 0
cal_memsize: //计算内存大小
dsubu t5, t5, 1 //t5-1
beqz t5, 1f //等于0,跳转
nop
and t4, a1, 0x1 //t4 = 1
dsrl a1, a1, 0x1 //a1 右移1位
beqz t4, cal_memsize //等于0 则跳转
nop
daddu a2, a2, 1 //a2 += 1
b cal_memsize
nop
1:
divu a2, t1, a2 //a2=16/2 = 8
GET_SDRAM_WIDTH //a1 = 1 16bits宽度
beqz t3, 1f //t3 第一次为0,跳转,第二次为1,不跳转
nop
GET_MC1_SDRAM_WIDTH //a1 = 1 16bits宽度
1:
dli t5, 0x2 //t5 = 2
beqz a1, x8 //a1等于0则跳转,这不跳转
nop
dli t5, 0x1 //t5 = 1
x8:
divu a2, a2, t5 //a2 = 8/1 = 8
dli t1, 0x1
blt a2, t1, 21f //a2小于1则跳转
dli t5, 0x9 //t5 = 9
dli t1, 0x2
blt a2, t1, 21f //a2小于2则跳转
dli t5, 0xb //t5 = 0xb
dli t1, 0x4
blt a2, t1, 21f //a2小于4则跳转
dli t5, 0x10 //t5 = 0x10
dli t1, 0x8
blt a2, t1, 21f //a2小于8则跳转
dli t5, 0x1a
dli t1, 0x10
blt a2, t1, 21f //a2小于16则跳转
dli t5, 0x23 //t5 = 0x23
PRINTSTR("\r\n memsize wrong \r\n")
b 2f
nop
21:
dli t1, DDR_FREQ //DDR_FREQ =533
dmulou t5, t5, t1 //t5 = 0x23 *533
divu t5, t5, 100 //t5 = t5/100 = 186 =0xBA
dli t1, 0x1c8
or t1, t1, t8
sb t5, 0x2(t1) //写寄存器0x1ca
2:
#endif
12. 设置偏移位0x210的寄存器[9:8],被清零
//for UDIMM 4cs,open 2T mode
GET_DIMM_TYPE //a1 = 0
bnez a1, 1f //不等于0则跳转
nop
//UDIMM
GET_MC_CS_MAP //a1 = 3
dli a2, 0xf
bne a1, a2, 1f //不相等则跳转,不相等
nop
//add cmd_timing ,trddata and tphy_wrlat by one
ld a2, CMD_TIMING(t8)
dli a1, 0x1
dsll a1, a1, CMD_TIMING_OFFSET
daddu a2, a2, a1
sd a2, CMD_TIMING(t8)
ld a2, TRDDATA(t8)
dli a1, 0x1
dsll a1, a1, TRDDATA_OFFSET
daddu a2, a2, a1
sd a2, TRDDATA(t8)
ld a2, TPHY_WRLAT(t8)
dli a1, 0x1
dsll a1, a1, TPHY_WRLAT_OFFSET
daddu a2, a2, a1
sd a2, TPHY_WRLAT(t8)
1:
//for UDIMM 4cs,open 2T mode
GET_DIMM_TYPE //a1 = 0
bnez a1, 1f //不等于0则跳转,不跳转
nop
//UDIMM
GET_MC_CS_MAP //a1= 3
dli a2, 0xf
bne a1, a2, 1f //不相等则跳转,不相等,怎么是重复的???
nop
//add cmd_timing ,trddata and tphy_wrlat by one
ld a2, CMD_TIMING(t8)
dli a1, 0x1
dsll a1, a1, CMD_TIMING_OFFSET
daddu a2, a2, a1
sd a2, CMD_TIMING(t8)
ld a2, TRDDATA(t8)
dli a1, 0x1
dsll a1, a1, TRDDATA_OFFSET
daddu a2, a2, a1
sd a2, TRDDATA(t8)
ld a2, TPHY_WRLAT(t8)
dli a1, 0x1
dsll a1, a1, TPHY_WRLAT_OFFSET
daddu a2, a2, a1
sd a2, TPHY_WRLAT(t8)
1:
//rewrite eight_bank_mode
//rewrite pm_bank_diff_0 and pm_bank
ld a2, EIGHT_BANK_MODE_ADDR(t8) //0x210
dli a1, 0x3
dsll a1, a1, EIGHT_BANK_MODE_OFFSET //3<<8
not a1, a1 //0xffff,ffff,ffff,fcff
and a2, a2, a1 //[9:8]被清零
GET_EIGHT_BANK //a1 =1 8bank
xor a1, a1, 0x1 //a1 = 0
dsll a1, a1, EIGHT_BANK_MODE_OFFSET //a1 = 0
or a2, a2, a1 //[8]
sd a2, EIGHT_BANK_MODE_ADDR(t8) //[9:8]被清零
13.0x168寄存器
//for version 3, pm_bank not used, changed to cs_resync
lw a2, 0x0(t8)
dli a1, 0x3
beq a2, a1, 1f //等于3则跳转。不知道是否跳转?
nop
//rewrite pm_bank
ld a2, BANK_NUM_ADDR(t8) //0x168
dli a1, 0x7
dsll a1, a1, BANK_NUM_OFFSET //24
not a1, a1 //a1 = 0xf8ff,ffff
and a2, a2, a1 //清零[26:24]
dli v0, 0x7
GET_EIGHT_BANK //a1 = 1
xor a1, a1, 0x1 //a1 = 0
dsrl a1, v0, a1 //a1 = 7
dsll a1, a1, BANK_NUM_OFFSET //7<<24
or a2, a2, a1 //[26:24] = 7
sd a2, BANK_NUM_ADDR(t8) //写入0x168
14.暂停休息。。。。。后面有时间再看吧。。。真的太长了。