单龙芯3A3000-7A1000PMON研究学习-(30)撸起袖子干-再来一杯代码11-内存初始化3-mc_init

这部分留给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.暂停休息。。。。。后面有时间再看吧。。。真的太长了。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大智兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值