UBOOT1.3.1代码导读(2)-lowlevel_init.S

本文详细介绍了如何使用AT91RM9200 DK板初始化系统时钟、Flash和SDRAM的过程,包括寄存器配置和代码实现。

这个文件主要是设置系统时钟,初始化flash,以及SDRAM。。。
..\u-boot-1.3.1\cpu\arm920t\at91rm9200\lowlevel_init.S
#include
#include
//CONFIG_SKIP_LOWLEVEL_INIT定义见..\u-boot-1.3.1\include\configs\at91rm9200dk.h
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*
* some parameters for the board
*
* This is based on rm9200dk.cfg for the BDI2000 from ABATRON which in
* turn is based on the boot.bin code from ATMEL
*
*/
//flash相关寄存器
/* flash */
#define MC_PUIA        0xFFFFFF10
#define MC_PUP        0xFFFFFF50
#define MC_PUER        0xFFFFFF54
#define MC_ASR        0xFFFFFF04
#define MC_AASR        0xFFFFFF08
#define EBI_CFGR    0xFFFFFF64
#define SMC2_CSR    0xFFFFFF70
//系统时钟相关寄存器
/* clocks */
#define PLLAR        0xFFFFFC28
#define PLLBR        0xFFFFFC2C
#define MCKR        0xFFFFFC30
#define AT91C_BASE_CKGR 0xFFFFFC20
#define CKGR_MOR 0
//sdram相关寄存器
/* sdram */
#define PIOC_ASR    0xFFFFF870
#define PIOC_BSR    0xFFFFF874
#define PIOC_PDR    0xFFFFF804
#define EBI_CSA        0xFFFFFF60
#define SDRC_CR        0xFFFFFF98
#define SDRC_MR        0xFFFFFF90
#define SDRC_TR        0xFFFFFF94
_MTEXT_BASE:
#undef START_FROM_MEM//从flash,还是从sdram启动,这里定义从sdram启动
#ifdef START_FROM_MEM
    .word    TEXT_BASE-PHYS_FLASH_1
#else
    .word    TEXT_BASE//TEXT_BASE在..\u-boot-1.3.1\board\at91rm9200dk\config.mk
#endif
.globl lowlevel_init
lowlevel_init:
    /* Get the CKGR Base Address */
    ldr     r1, =AT91C_BASE_CKGR //初始化系统时钟
    /* Main oscillator Enable register */
#ifdef CFG_USE_MAIN_OSCILLATOR
    ldr     r0, =0x0000FF01        /* Enable main oscillator,  OSCOUNT = 0xFF */
#else
    ldr     r0, =0x0000FF00        /* Disable main oscillator, OSCOUNT = 0xFF */
#endif
    str     r0, [r1, #CKGR_MOR]
    /* Add loop to compensate Main Oscillator startup time */
    ldr     r0, =0x00000010//这个地方相当与一段延时,保证系统时钟设置正常
LoopOsc:
    subs    r0, r0, #1
    bhi     LoopOsc
    /* memory control configuration *///初始化flash
    /* this isn't very elegant, but     what the heck */
    ldr    r0, =SMRDATA  //将标号SMRDATA所标识的地址写入r0
    ldr    r1, _MTEXT_BASE  //将标号_MTEXT_BASE处的数据写入r1
    sub    r0, r0, r1   //得到相对起始地址   我总觉得这个地方有些问题,可很多人认为没有问题。。。。有待深究,是不是我多了呢?
    add    r2, r0, #80  //得到相对结束地址
0:
    /* the address */ 
    //不仔细的看,你还真发现不了这个地方的妙处,哈哈,想法挺好。。。。
    //需要配合下面的表一起看,估计你就能明白了。
    ldr    r1, [r0], #4  //R1←[R0],R0←R0+4
    /* the value */
    ldr    r3, [r0], #4
    str    r3, [r1]
    cmp    r2, r0
    bne    0b
    /* delay - this is all done by guess */
    ldr    r0, =0x00010000
1:
    subs    r0, r0, #1
    bhi    1b
    ldr    r0, =SMRDATA1//初始化sdram
    ldr    r1, _MTEXT_BASE
    sub    r0, r0, r1
    add    r2, r0, #176
2:
    /* the address */
    ldr    r1, [r0], #4
    /* the value */
    ldr    r3, [r0], #4
    str    r3, [r1]
    cmp    r2, r0
    bne    2b
    /* switch from FastBus to Asynchronous clock mode */
    //结合datasheet看,有详细的描述
    mrc    p15, 0, r0, c1, c0, 0  //将读出的数据放到r0中
    orr    r0, r0, #0xC0000000    @ set bit 31 (iA) and 30 (nF)
  //主要是设置C1,异步模式;C0是只读的
    mcr    p15, 0, r0, c1, c0, 0
    /* everything is fine now */
    mov    pc, lr
    .ltorg
SMRDATA:
    .word MC_PUIA
    .word MC_PUIA_VAL//..\u-boot-1.3.1\include\configs\at91rm9200dk.h有定义
    .word MC_PUP
    .word MC_PUP_VAL
    .word MC_PUER
    .word MC_PUER_VAL
    .word MC_ASR
    .word MC_ASR_VAL
    .word MC_AASR
    .word MC_AASR_VAL
    .word EBI_CFGR
    .word EBI_CFGR_VAL
    .word SMC2_CSR
    .word SMC2_CSR_VAL
    .word PLLAR
    .word PLLAR_VAL
    .word PLLBR
    .word PLLBR_VAL
    .word MCKR
    .word MCKR_VAL
    /* SMRDATA is 80 bytes long */
    /* here there's a delay of 100 */
SMRDATA1:
    .word PIOC_ASR
    .word PIOC_ASR_VAL
    .word PIOC_BSR
    .word PIOC_BSR_VAL
    .word PIOC_PDR
    .word PIOC_PDR_VAL
    .word EBI_CSA
    .word EBI_CSA_VAL
    .word SDRC_CR
    .word SDRC_CR_VAL
    .word SDRC_MR
    .word SDRC_MR_VAL
    .word SDRAM
    .word SDRAM_VAL
    .word SDRC_MR
    .word SDRC_MR_VAL1
    .word SDRAM
    .word SDRAM_VAL
    .word SDRAM
    .word SDRAM_VAL
    .word SDRAM
    .word SDRAM_VAL
    .word SDRAM
    .word SDRAM_VAL
    .word SDRAM
    .word SDRAM_VAL
    .word SDRAM
    .word SDRAM_VAL
    .word SDRAM
    .word SDRAM_VAL
    .word SDRAM
    .word SDRAM_VAL
    .word SDRC_MR
    .word SDRC_MR_VAL2
    .word SDRAM1
    .word SDRAM_VAL
    .word SDRC_TR
    .word SDRC_TR_VAL
    .word SDRAM
    .word SDRAM_VAL
    .word SDRC_MR
    .word SDRC_MR_VAL3
    .word SDRAM
    .word SDRAM_VAL
    /* SMRDATA1 is 176 bytes long */
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

void sdram_init(void) { /*获取最高频点*/ u32 train_high_point = 2133;/*Training High freq point*/ /*开机频点,在/bsp/bootloader/chipram/include/configs/xxxx.h中配置*/ u32 target_ddr_clk = (mcu_clk_para.ddr_freq.value)/1000000; /*ddr_mode bit[15:8]代表F7~F0 8个频点,bit0为0开DFS,表示变频;bit0为1关DFS,表示定频*/ u32 ddr_mode = mcu_clk_para.ddr_mode.value | 2; //bit1 close pub_dvs //release io pmu_apb_state_set(); #ifdef DDR_SCAN_ENABLE pub_soft_reset(); #endif pll_clk_cfg(2132, 1);//2132M = 26M * 0x52 analog_dpll_cfg(); #if defined(AUTO_SLT_EN) REG32(UART1_TX_BUF_ADDR + 0x24) = 0xa94; print_string("\r\nREV:QogirL8_ASLT_A100 \r\n"); #endif /*ddr init start*/ #ifndef DDR_SCAN_ENABLE print_string("ddr init start!!!\r\n"); #endif #ifdef PUB_DVFS_EN //L8 not support /*not enable PUB_DVFS_EN, chipram using 750mv to training all freq, *best timing paras at 750mv */ pub_top_dvfs_cfg(); print_string("pub vol cfg to 700mv\n"); pub_dvfs_voltage_cfg(700); print_string("pub vol cfg to 600mv\n"); pub_dvfs_voltage_cfg(600); #endif /*axi port clk always on*/ pub_axi_port_lowpower_close(); #ifdef DDR_SCAN_ENABLE u32 freq_index; /*if scan use fdl1 with 384, set default freq to a higher freq. if need 384 scan delete this code*/ if(target_ddr_clk < DDR_CLK_533M) target_ddr_clk = DDR_CLK_1066M; scan_target_clk = target_ddr_clk; /*control CA scan call sdram_init() with mask such freq training --this project not efficient now, ddrc_train_flow() has not check ddr_mode, so all freq need training. reserved code for future use here*/ if (first_init == 2) { dmc_freq_sel_search(target_ddr_clk, &freq_index); if (target_ddr_clk >= DDR_CLK_533M) ddr_mode = 0xFF00 & (~(1 << (freq_index + 8))); if (target_ddr_clk == DDR_CLK_1866M) ddr_mode = 0xEFFF & ddr_mode; } #endif /*dram type setting*/ /*通过获取的ADC值判断DRAM类型,并根据DRAM类型选择PINMUX配置,用于单软多硬配置*/ dram_type_pinmux_auto_detect(); /*watchdog reset entry into sre*/ //关闭watchdog,避免硬件不能及时刷新数据 wdg_rst_keep_sre(); /*ZQC阻值校验实现对DDR PHY IO上240Ω电阻精度的校准操作,需外接一个精密的240Ω对比电阻*/ /*zq calibration--PHY1 using PHY0 zqc result*/ ddrc_zqc_seq();//ZQC阻值校准 /*pinmux setting*/ ddrc_phy_pinmux_set();//配置对应DRAM类型的PINMUX值 /*dram init at a low frequency*/ /*低频点初始化,配置ODT及驱动能力,使DDR颗粒可读写,在dram_support.h中配置*/ dram_init_from_low_freq(BOOT_FREQ_POINT); /*rfm config*/ //dmc_rfm_set();//todo //loop_get_tdqs2dq(); /*dram size auto-detect and include Manual setting mode */ /*根据MR8的值,获取DDR容量等信息,training时需要;部分开机问题也需要读取MR8值进行适配*/ /*根据DDR size重新配置DDRC控制参数*/ /*根据串口Log显示的DRAM Type值,在dram_support.c和dram_support.h中配置DDR容量组合信息*/ dram_size_auto_detect(); //可以读取DDR内部寄存器MR8的值 /*DFS pre setting, f0--f7 clk,voltage setting*/ /*config pub top*/ ddrc_pub_apb_cfg(); sw_dfs_pre_cfg(); sw_dfs_mode(); /*According MR5,MR6,MR7(Manufacturer ID) limit Top freq(variable:train_high_point) */ dram_freq_auto_detect(&train_high_point); //close dbi ddrc_dbi_close(); //dmc_phy_train_pre_set(); //training flow--Change freq and training //ddr mode:bit8~bit15 map fn0 ~ fn7 training enable flag (0:Enable 1:Disable)*/ /*跑测 training ,模式定频或者从最低到最高频*/ ddrc_train_flow(ddr_mode, train_high_point); /*target frequency point*/ /*设置开机频点和最高频点*/ ddrc_target_point_set(target_ddr_clk, train_high_point); /*ssc cfg Extended frequency*/ #if defined(CONFIG_NAND_SPL) && defined(SSC_CFG) pll_ssc_cfg(target_ddr_clk,(ddr_mode>>16)&0xff); #endif /*enable auto refresh*/ ddrc_auto_refresh_open(); #ifdef DDR_SCAN_ENABLE if(first_init == 0) first_init = 1; else return ; ddr_scan_offline_r3p5(target_ddr_clk); #endif /*dbi setting*/ ddrc_dbi_set(target_ddr_clk); /* *ddr init end *1.ddrc lowpower *3.mr4 function *4.dfs function *5.auto cpst *6.auto zqc */ ddrc_dmc_post_set(); /*bist test*/ ddrc_bist_test(reset_key); /*pub_sys clk auto gate*/ //pub_lowpower_set(); /*reason: prevent conflict between cm4 config and apcpu access pub cfg*/ reg_bit_set(AON_APB_PUB_EARLY_RESP, 0, 1, 1); //shorten the delay of writing pub register /*set pub_acc_rdy to make other subsys access*/ pub_acc_rdy_set(); #ifdef DDR_MINICODE_ENABLE dram_feature_test(train_high_point); #endif #ifdef DDR_POWER_TEST //power_consumption_measure_entry(); #endif #ifdef DRAM_MEM_TEST /***memtest***/ dram_mem_test(0x80000000,0xc0000000); #endif /****send ddr size to kernel ****/ dmc_update_param_for_uboot(); //将DDR容量信息等参数上报到U-Boot #if defined(CONFIG_NAND_SPL) /*ddr debug mode---AON IRAM Addr*/ /*Send kernel and dfs information through iram*/ ddrc_iram_init(); /*发送DRAM信息到Kernel、根据ddr_mode的值确认是否关闭DFS、将参数传到IRAM*/ ddrc_debug_mode(ddr_mode, train_high_point); #endif ddr_init_pass(); ddrc_lock(); #if defined(CONFIG_NAND_SPL) && defined(WDG_TEST) /*watch dog reset*/ ddrc_reboot_cnt(); start_watchdog(5); while(1); #endif }根据这个init函数给我一个init流程,以及介绍这些流程分别做了什么。
最新发布
11-01
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值