PMON分析(1)- ROM阶段

PMON的运行过程分为两个阶段:第一阶段是在ROM FLASH中运行,主要进行基本硬件初始化,如:初始化核的一些配置寄存器,其中包括cpu状态和原因寄存器、pcie的配置寄存器、GPIO、sata、cache、tlb、内存控制器和串口初始化等;第二阶段在内存中执行,主要完成环境变量和基本数据结构的初始化、PCI总线扫描和设备初始化,网络协议和设备初始化,并对搜索到的PCI总线上的设备进行驱动程序的加载与配置等,最后引导内核启动。

一、第一阶段

1、配置cpu状态

_start开始执行pmon的入口,也就是mips cpu取指的第一条地址0xbfc00000.

  bal     ls2k_version

     nop

     bnez    v0,2f

     nop

     .set    mips32

     mfc0    t0, $15, 1      #EBASE  Exception Base and cpunum

     .set    mips3

     andi    t0, t0, 0x3ff

     bnez    t0, 2f

     nop

读取PRId 寄存器获取并判断版本是否正常

     lui     t0, 0xba00

     lui     t1, 0x1fe0

       sw      t1, 0x1010(t0) /* config bar for APB * //*((int *))0xba001010 = 1fe00000

lw      t2, 0x1004(t0) //t2 = *(*(int *))

     ori     t2, t2, 0x2

     sw      t2, 0x1004(t0) //enable

设置APB总线控制器的配置空间

     li t0,0xbfe0700c

     lw t1,0x0(t0)

     and t2,t1,(1 << 11)

     beqz  t2,2f

     nop

     li t0,0xbfe0700c

     lw t1, 0x0(t0)

     sw t1,0x0(t0)

     li t2,0x3c00

     li t0,0xbfe07014

     sw t2,0x0(t0)

bal watchdog_close

     nop

关闭看门狗。

/* NOTE!! Not more that 16 instructions here!!! Right now it's FULL! */

mtc0    zero, COP_0_STATUS_REG //cuckoo

mtc0    zero, COP_0_CAUSE_REG

li      t0, SR_BOOT_EXC_VEC     //0x400000 //bit22(BEV)

mtc0    t0, COP_0_STATUS_REG //cuckoo

 

bal     initregs

nop

将状态寄存器和原因寄存器清零,禁用所有的中断和异常检测, 并使当前状态处于内核模式。清零$1~$30寄存器,

mfc0    t0, CP0_STATUS

li      t1, 0x64000000|SR_KX|SR_SX|SR_UX|SR_BOOT_EXC_VEC

or      t0, t0, t1

  mtc0    t0, CP0_STATUS

la      sp, stack

la      gp, _gp

jr      ra

nop

使能32位浮点寄存器模式,使能协处理器可用,使能32 位浮点寄存器,初始化堆栈指针和全局指针。

  .set    mips32

      mfc0    t0, $16, 6              #Store fill

      .set    mips3

      li      t1, 0xfffffeff

      and     t0, t1, t0

      .set    mips32

      mtc0    t0, $16, 6              #Store fill

     .set    mips3

设置GSConfig 寄存器,禁止处理器 store 操作自动写合并功能。

/* spi speedup */

li  t0, 0xbfe00220      //SPI 的 IO 寄存器的基地址 0x1fff0220

li  t1, 0x07

sb  t1, 0x4(t0)

设置spi参数控制寄存器,读使能、支持连续地址读、支持快速读模式。

bal     locate                  /* Get current execute address */

locate:

la      s0, start

subu    s0, ra, s0

and     s0, 0xffff0000

bal 这条指令是一个 pc 相对跳转指令, 跳转的目的是把 ra 寄存器和 0xa0000000 相或,将 cpu 的执行地址映射到 unmapped uncached 段。

mfc0    t0, CP0_STATUS

        li  t1, 0x64000000|SR_KX|SR_SX|SR_UX|SR_BOOT_EXC_VEC      # {cu3,cu2,cu1,cu0}<={0110, status_fr<=1,0xe0 to enable 64bit space

        or      t0, t0, t1

        mtc0    t0, CP0_STATUS

        mtc0    zero, COP_0_CAUSE_REG

设置状态寄存器的BEV位,清零原因寄存器。

cp0_main:

        .set    mips32

        mfc0    t0, $15, 1      #EBASE REG

        .set    mips3

        andi    t0, t0, 0x3ff

        bnez    t0, wait_for_smp

nop

wait_for_smp:

        mfc0    t1, CP0_CONFIG

        ori     t1, t1, 0x3

        mtc0    t1, CP0_CONFIG

        la      t1, 1f

        addu    t1, s0

        li      v0, 0x9fffffff

        and     t1, v0

        jr      t1

        nop

1:

        li      t0, 0xbfe11120

        sd      zero, 0(t0)

        sd      t1, 8(t0)

使能Kseg0 段Cache,设置1 号处理器核的 IPI_MailBox0 寄存器

    bal     beep_on

    nop

    li      a0, 0x8000

1:

    addiu   a0, -1

    nop

    bnez    a0, 1b

    nop

    bal     beep_off//mtf

        nop

获取cpu num,将除启动核外其他核睡眠

2、pcie配置

    li      t0, 0xbfe10000 //+0x580 配置 PCIE0 PHY 的控制信号。

    li      t1, 0xc2492331

    sw      t1, 0x580(t0) //PCIE0 配置寄存器 0低32

    sw      t1, 0x5a0(t0) //PCIE1 配置寄存器 0低32位

 

    li      t1, 0xff3ff0a8

        sw      t1, 0x584(t0) //PCIE0 配置寄存器 0高32位

        sw      t1, 0x5a4(t0) //PCIE1 配置寄存器 0高32位

 

        li      t1, 0x27fff

        sw      t1, 0x588(t0) //PCIE0 配置寄存器 1

        sw      t1, 0x5a8(t0) //PCIE1 配置寄存器 1

配置pcie0/1配置寄存器。设置硬件参数,包括阻抗参数,PCIE PHY 发送低摆幅幅值,PCIE PHY PLL 的倍频数。

li      t0, 0xbfe10590 //PCIE0 PHY 配置控制寄存器

        dli     t1, 0x14fff1002

        sd      t1, 0x0(t0)

        sd      t1, 0x20(t0)

 

        dli     t1, 0x14fff1102

        sd      t1, 0x0(t0)

        sd      t1, 0x20(t0)

 

        dli     t1, 0x14fff1202

        sd      t1, 0x0(t0)

        sd      t1, 0x20(t0)

 

        dli     t1, 0x14fff1302

        sd      t1, 0x0(t0)

        sd      t1, 0x20(t0)

 

        li      t0, 0xbfe10430

        lw      t1, 0x0(t0)

        or      t1, t1, 0x30000 //pcie enable

        sw      t1, 0x0(t0)

设置PCIE0/1 PHY 配置控制寄存器,使能PCIE1/0 控制器。

dli     t0, 0x900000fe0800680c //DEV D / Gen2 Control Register 寄存器

        li      t1, 0xfff9ffff

        lw      t2, 0x0(t0)

        and     t1, t1, t2

        or      t1, 0x20000

        sw      t1, 0x0(t0)

        dli     t0, 0x900000fe0700681c

        lw  t2, 0x0(t0)

li  t1, (0x1 << 26)

      or  t2, t1

      sw  t2, 0x0(t0)

 

        dli     t0, 0x900000fe00006800 //PCIE1 Port0 的配置头基址

        li      t1, 0x10000000

        sw      t1, 0x10(t0)

        dli     t0, 0x9000000000000000

        li      t1, 0x10000000

        or      t0, t0, t1

         li  t1, (0x7<<18)|(0x7<<2)

        not t1, t1 

        lw  t2, 0x54(t0)

        and t2, t2, t1 

        sw  t2, 0x54(t0)

        lw  t2, 0x58(t0)

        and t2, t2, t1

        sw  t2, 0x58(t0)

        dli     t1, 0xff204f

        sw      t1, 0x0(t0)

龙芯 2K1000 有两个 PCIE 控制器,其中一个 PCIE 控制器既可以作为一个 X4 的 PCIE端口也可以作为 4 个独立的 X1 PCIE 端口;另一个 PCIE 控制器既可以作为一个 X4 的 PCIE端口也可以作为 2 个独立的 X1 PCIE 端口,作为 X1 端口时,仅 LANE0 和 LANE1 可用,LANE2 和 LANE3 不可用。配置pcie0的port0-3及pcie1的port0-1控制器,并且初始化串口。

3、gmac配置

  li t1,0xbfe10500 //GPIO 方向控制

     li t2,(1 << 2) //34 - 2

     not t2,t2

     lw t3,0x4(t1)

     and t2,t3

     sw t2,0x4(t1)

     li t2,(1 << 2)//34 -2

     lw t3,0x14(t1)

     not t2,t2

     and t2,t3

     sw t2,0x14(t1)

配置gpio的43位输出模式,并且拉低第43位来复位gmac1。

 

#include "loongson3_clksetting.S"

li t1,0xbfe10500

          li t2,(1 << 2) //34 - 2

          lw t3,0x14(t1)

          or t2,t3

          sw t2,0x14(t1)

拉高GPIO,完成gmac1的复位。

4、sata配置

li          t0, 0xbfe10000

    li      t1, 0x30c31cf9

    sw      t1, 0x454(t0) //sata配置寄存器

    li      t1, 0xf300040f

    sw      t1, 0x450(t0)

PRINTSTR("\r\nUSE internel SATA ref clock\r\n")

        li      t1, 0xbfe10450

        ld      a0, 0x0(t1)

        li      a1, 0x2

        not     a1, a1

        and     a0, a0, a1

        sd      a0, 0x0(t1)

        sync

 

        ld      a0, 0x0(t1)

        li      a1, 0x4

        or  a0, a1

        sd      a0, 0x0(t1)

        sync

        ld      a0, 0x0(t1)

        li      a1, 0x8

        or  a0, a1

        sd      a0, 0x0(t1)

        sync

 

        ld      a0, 0x0(t1)

        bal     hexserial64

        nop

 

li      t0, 0xbfe10000

 

    //assert p0 reset

    lw      t1, 0x450(t0)

    li      t2, (1 << 3)

    not     t2, t2

    and     t1, t1, t2

    sw      t1, 0x450(t0)

 

    //assert phy reset

    lw      t1, 0x450(t0)

    li      t2, (1 << 2)

    not     t2, t2

    and     t1, t1, t2

    sw      t1, 0x450(t0)

 

    //power down phy

    lw      t1, 0x454(t0)

    li      t2, (1 << 31)

    or      t1, t1, t2

    sw      t1, 0x454(t0)

 

    //switch refclk

    lw      t1, 0x450(t0)

    li      t2, (1 << 1)

    not     t2, t2

    and     t1, t1, t2

    sw      t1, 0x450(t0)

 

    //delay a while

    li      t1, 0x1000

1:

    subu    t1, t1, 1

    bnez    t1, 1b

    nop

 

    lw      t1, 0x454(t0)

    li      t2, (1 << 31)

    not     t2, t2

    and     t1, t1, t2

    sw      t1, 0x454(t0)

 

    //deassert phy reset

    lw      t1, 0x450(t0)

    li      t2, (1 << 2)

    or      t1, t1, t2

    sw      t1, 0x450(t0)

 

    //deassert p0 reset

    lw      t1, 0x450(t0)

    li      t2, (1 << 3)

    or      t1, t1, t2

    sw      t1, 0x450(t0)

li      t0, 0xbfe10458

        dli     t1, 0x1403f1002

        sd      t1, 0x0(t0)

设置SATA 配置寄存器。选择内部时钟。配置sata发送信号。

5、初始化pcitlb及cache

li      t0, 0xbfe13800 //PCICFG2_RECFG 寄存器

        dli     a0, 0xffffff0000ffffff

        sd      a0, 0x08(t0)

        li      t0, 0xba001800 //GMAC0配置空间头基地址

        li      a0, 0x0080ff08

        sw      a0, 0x0c(t0)

 

        li      t0, 0xbfe13800 //PCICFG2_RECFG 寄存器

        dli     a0, 0xff00ff0000fffff0

        sd      a0, 0x00(t0)

        sd      a0, 0x08(t0)

        sd      a0, 0x10(t0)

        sd      a0, 0x18(t0)

        sd      a0, 0x20(t0)

        sd      a0, 0x28(t0)

        sd      a0, 0x30(t0)

        sd      a0, 0x38(t0)

        sd      a0, 0x40(t0)

使能 APB 总线控制器的配置头空间的重配置功能,设置对应的字节可写。

PRINTSTR("\r\nPMON2000 MIPS Initializing. Standby...\r\n")

        mfc0    a0, COP_0_CONFIG                /* enable kseg0 cachability */

        ori     a0, a0, 0x3           // ENABLE

        mtc0   a0, COP_0_CONFIG

使能kseg0的cache能力。

#include "pcitlb.S"

 

 

将虚拟地0xc0000000~0xffffffff 映射到物理地址0x40000000~ 0x7fffffff 作为pci mem空间

/* jmp to 0x9fc... */

        lui     t0, 0xdfff ####################### go to 9fc

        ori     t0, t0, 0xffff

        bal     1f

        nop

1:

        and     ra, ra, t0

        addiu   ra, ra, 16

        jr      ra

        nop

验证kseg0的cache是否使能成功

        PRINTSTR("cache enable done\r\n")

 

        li      t0, 0xbfe10430 //通用配置寄存器 2

        lw      a2, 0x0(t0)

        // pcie0 and pcie1

        lui     t1, 0x3

        // enable dvo0 and dvo1 pin output

        ori     t1, t1, 0x12

        or      a2, a2, t1

        sw      a2, 0x0(t0)

使能DVO0和DVO1管脚,使能 CAMERA 的管脚功能

 

        li      t0, 0xbfe10420 //通用配置寄存器 0

        //sdio

        lw      t2, 0x0(t0)

        lui     t1, 0x10

        //enable pwm0, pwm1, i2c0, i2c1, nand, sata, i2s, gmac1

        //no hda, no ac97

        ori     t1, t1, 0x3f48

        or      t2, t2, t1

        sw      t2, 0x0(t0)

设置一些复用管脚功能,包括GMAC1,HDA,pwm,sata,iac,i2s。

6、初始化内存

TTYDBG("\r\nStart Init Memory, wait a while......\r\n")

        move    msize, $0

       move    s3, $0

//!!!!important--s1 must be correctly set

       TTYDBG("NODE 0 MEMORY CONFIG BEGIN\r\n")

       dli     s1, 0xc1a10404

#include "ddr_dir/loongson3_ddr2_config.S"

内存初始化。主要完成的是内存控制器的配置和窗口地址的路由配置。

       /*judge the node0 whether have memory*/

       and     a0, msize, 0xff

 

//close default internal mapping in ddr controller

        li      t0, 0xbfe10424 //通用配置寄存器 0

        lb      a0, 0x1(t0)

        and     a0, a0, 0xfd //mc_default_reg置零

        sb      a0, 0x1(t0)

        sync

        li      t0, 0xbfe10420

        ld      a0, 0x0(t0)

        move    t6, a0

        dsrl    a0, t6, 32

        bal     hexserial

        nop

        move    a0, t6

        bal     hexserial

        nop

        PRINTSTR("\r\n")

关闭窗口不命中处理

/* test memory */

        li      t0, 0xa0000000 //kseg0段

        dli     a0, 0x5555555555555555

        sd      a0, 0x0(t0)

        dli     a0, 0xaaaaaaaaaaaaaaaa

        sd      a0, 0x8(t0)

        dli     a0, 0x3333333333333333

        sd      a0, 0x10(t0)

        dli     a0, 0xcccccccccccccccc

        sd      a0, 0x18(t0)

        dli     a0, 0x7777777777777777

        sd      a0, 0x20(t0)

        dli     a0, 0x8888888888888888

        sd      a0, 0x28(t0)

        dli     a0, 0x1111111111111111

        sd      a0, 0x30(t0)

        dli     a0, 0xeeeeeeeeeeeeeeee

        sd      a0, 0x38(t0)

        PRINTSTR("The uncache data is:\r\n")

        dli     t1, 8

        dli     t5, 0x9000000000000000

1:

        ld      t6, 0x0(t5)

        move    a0, t5

        and     a0, a0, 0xfff

        bal     hexserial

        nop  

        PRINTSTR(":  ")

        dsrl    a0, t6, 32

        bal     hexserial

        nop  

        move    a0, t6

        bal     hexserial

        nop  

        PRINTSTR("\r\n")

 

        daddiu  t1, t1, -1

        daddiu  t5, t5, 8

        bnez    t1, 1b

        nop  

 

        PRINTSTR("The cached  data is:\r\n")

        dli     t1, 8

        dli     t5, 0x9800000000000000

1:

        ld      t6, 0x0(t5)

        move    a0, t5

        and     a0, a0, 0xfff

        bal     hexserial

        nop  

        PRINTSTR(":  ")

        dsrl    a0, t6, 32

        bal     hexserial

        nop  

        move    a0, t6

        bal     hexserial

        nop  

        PRINTSTR("\r\n")

 

        daddiu  t1, t1, -1

        daddiu  t5, t5, 8

        bnez    t1, 1b

        nop

测试内存,写入内存数据,分别从cache和uncache内存中读出。

la      a0, start

        li      a1, 0xbfc00000

        la      a2, _edata

 

        move    t0, a0

        move    t1, a1

        move    t2, a2

        /* copy text section */

1:      and     t3, t0, 0x0000ffff

        bnez    t3, 2f

        nop

        move    a0, t0

        bal     hexserial

        nop

        li      a0, '\r'

        bal     tgt_putchar

        nop

 

2:      lw      t3, 0(t1)

        sw      t3, 0(t0)

 

        addu    t0, 4

        addu    t1, 4

 

        blt         t0, t2, 1b

        nop

        PRINTSTR("\ncopy text section done.\r\n")

 

        .set noreorder

        /* Clear BSS */

        la      a0, _edata

        la      a2, _end

2:      sw      zero, 0(a0)

        bne     a2, a0, 2b

        addu    a0, 4

        TTYDBG("\nClear BSS done.\r\n")

 

        PRINTSTR("Copy PMON to execute location done.\r\n")

为将pmon拷贝到ram做准备,pmon拷贝到内存中并解压。

move    a0, msize

        la      v0, initmips

        jalr    v0

        nop

至此,在ROM阶段的初始化全部结束,后续代码将搬移到ram来进行初始化。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值