PMON分析(3)- 内存初始化

内存初始化:

loongson3_ddr2_config.S文件

大致过程分为个阶段:

  1. 检测四个DIMM插槽的mc0/1,将信息存在s1中(PROBE_NODE_DIMM)。
  2. 使用PROBE_NODE_DIMM,根据上一步获取的信息检测对应内存大小
  3. 配置内存控制器(mc_init)
  4. 配置L2 X-bar,s1中的MC*_ONLY位决定是否使用这个MC,然后根据s1中的MC*_MEMSIZE位决定内存大小以及如何配置L2 X-bar窗口。

注:目前仅使用一个内存控制器时,支持内存大小:512M、1G、2G、3G、4G;当使用mc0和mc1时,每个控制器只支持1G、2G或4G内存大小。

  1. 获取内存信息保存在s1中

叶子函数PROBE_NODE_DIMM

input:s1[31:16] ----- MC0的slot id信息 s1 = 0x00000000__ff100004

output:s1[31: 8] ------MC0 DIMM info s1 = 0x00000000__f0a31004

PROBE_NODE_DIMM代码流程:

move    t8, ra

move    t1, s1 //t1 = 0x00000000__ff100004

bal     i2cinit //初始化i2c

nop

 

GET_MC0_ONLY //通过s1(ff100004)状态

bnez    a1, 11f

nop

11:

//detect MC0 if not define MC1_ONLY

    GET_MC1_ONLY

    bnez    a1, 12f

    nop

    //do auto probe DIMM

    PRINTSTR("\r\nProbing DDR MC0 SLOT: ");

    PRINTSTR("\r\nProbe MC0 slot 0.");

    dli     a1, 0xff

    and     s1, s1, a1 s1 = 0x4

    GET_MC0_SLOT0_ID 获取slot0的id号

    dli     a0, 0x8

    bgeu    a1, a0, 1f  //invalidate device id --- a1=0

    nop

    dsll    a1, a1, 1

    ori     a0, a1, 0xa1

    bal     PROBE_DIMM;

    nop;

/* 读取mc0的slot0后,获得slot0的dimm信息记录在s1中,s1 = 0x00000010__f0a30004 */

1:

    //store slot 0 DIMM infor in t3

    move    t3, s1

    PRINTSTR("\r\nProbe MC0 slot 1.");

    dli     a1, 0xff

    and     s1, s1, a1

    GET_MC0_SLOT1_ID

    dli     a0, 0x8

    bgeu    a1, a0, 1f  //invalidate device id

    nop

    dsll    a1, a1, 1

    ori     a0, a1, 0xa1

    bal     PROBE_DIMM;

    nop;

/* 读取mc0的slot1后,没有dimm,s1 = 0x00000000__00000004 */

1:

//store slot 1 DIMM infor in t4

    move    t4, s1

    //compare the two slot DIMM infor and merge the CS_MAP and MC0_MEMSIZE if necessary

    move    s1, t3

    GET_SDRAM_TYPE

    beqz    a1, 1f //a1 = 0x3, 不跳转

    nop

    move    s1, t4

    GET_SDRAM_TYPE

    beqz    a1, 2f //a0 = 0.

    nop

2:

//no DIMM in slot 1 and slot 0 has DIMM

    move    s1, t3

    b       4f

    nop

 

4:  //move DIMM_MEMSIZE to MC0_MEMSIZE

    GET_DIMM_MEMSIZE //a1 = 0x10

    dsll    a1, a1, MC0_MEMSIZE_OFFSET //MC0_MEMSIZE_OFFSET = 8

    dli     a0, MC_MEMSIZE_MASK //MC_MEMSIZE_MASK = 0x7f

    dsll    a0, a0, MC0_MEMSIZE_OFFSET

    not     a0, a0

    and     s1, s1, a0

    or      s1, s1, a1 //s1 = 0x00000010__f0a31004

    b       3f

    nop

3:

//merge MC1 and MC0 DIMM infor to s1

    dli     a1, 0xffffff0000000000 //t0 = 0x00000000__00000004

    and     t0, t0, a1

    dli     a1, 0xffffffff

    and     s1, s1, a1

    or      s1, s1, t0 //s1 = 0x00000000__f0a31004

12:

    move    ra, t8

    jr      ra //返回

    nop

在ls2k/ddr_dir/detect_node_dimm_all.S文件中,首先初始化i2c,调用叶子函数PROBE_DIMM通过i2c获取内存条的spd信息。0x8为DD2,0xB为DDR3。

s1[30]标识SDRAM的type。

s1[29]标识SDRAM的DIMM WIDTH。s1[28]标识SDRAM的DIMM WIDTH。

//s1[2.3]位标识cpu的SEL,s1[0.1]位标识cpu的NODE ID。

#define SDRAM_TYPE_OFFSET   30

#define DIMM_ECC_OFFSET     29

#define DIMM_TYPE_OFFSET    28

#define DIMM_WIDTH_OFFSET   27

#define ROW_SIZE_OFFSET     24

#define EIGHT_BANK_OFFSET   23

#define ADDR_MIRROR_OFFSET  22

#define COL_SIZE_OFFSET     20

#define MC_CS_MAP_OFFSET    16

#define MC1_CS_MAP_OFFSET   48

#define SDRAM_WIDTH_OFFSET  15

#define MC1_SDRAM_WIDTH_OFFSET 47

#define MC_CS_MAP_MASK      (0xf)

#define MC1_MEMSIZE_OFFSET  40

#define MC0_MEMSIZE_OFFSET  8

#define MC_MEMSIZE_MASK     (0x7f)

#define DIMM_MEMSIZE_OFFSET 32

#define DIMM_MEMSIZE_MASK   (0x7f)

在PROBE_DIMM函数中,通过i2c总线获取上述相关信息,保存到s1相应的位。

  1. 校验s1保存的内存信息是否正常

代码流程:

GET_MC_SEL_BITS

    dli     a2, 3

    bne     a1, a2, 1f //获取cpu SEL信息

nop

1:

    PRINTSTR("\r\ncheck NODE mem size\r\n"); //获取内存控制

    GET_MC0_ONLY

    bnez    a1, 1f

    nop

    GET_MC1_ONLY

    bnez    a1, 2f

nop

 

1:  //MC0_ONLY

    GET_MC0_MEMSIZE

    b       5f

nop

5:

    beqz    a1, 89f

    nop

    dli     t5, 0x10

    bgt     a1, t5, 89f

    nop

  1. 配置内存控制器

在mc_init函数(Targets/LS2K/ls2k/ddr_dir/ls3A8_ddr_config.S文件)中,使能内存控制器的配置空间(1MB @0x0ff0,0000)。获取SDRAM类型,按照DDR3类型配置。

获取RDIMM参数地址。跳转到ddr2_config进行内存参数的设置。

 

//t8保存了内存控制器(MC0)的配置空间的基地址。

//a2记录了ddr3_RDIMM_reg_data参数数据地址。

在ddr2_config函数中,将a2中记录的RDIMM寄存器参数拷贝到MC0的配置空间。然后设置tREFI(一般情况下,内存控制器会周期性的发送 AR(Auto-Refresh Command),每两个 AR 直接的时间间隔定义为 tREFI = 64ms / 8192 = 7.8 us。ls2k这里设置12us)、设置tRFC(SDRAM 完成一次刷新操作所需要的时间定义为 tRFC, 这个时间会随着 SDRAM Row 的数量的增加而变大)。

set_tREFI:

        dli      t1, DDR_FREQ

        divu    t1, t1, 10

        dli             a2, 78

        dmulou  a2, a2, t1

        dsrl    a2, a2, 8

//      daddu   a2, a2, 1

        dli             t1, 0x1c8

        or              t1, t1, t8

        sb              a2, 0x3(t1)

=====================================

dli             t1, DDR_FREQ

        dmulou  t5, t5, t1

        divu    t5, t5, 100

        dli             t1, 0x1c8

        or              t1, t1, t8

        sb              t5, 0x2(t1)             //tRFC = 140

未完。。。待续

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值