上次的uboot的BL1是自己实现的,今天就来让uboot-2012-10支持SPL功能,但不是完全用的uboot本身的代码,也不知道这样是好还是坏。
1.分析顶层目录的Makefile可以知道,需要添加CONFIG_SPL配置,这在前面的已经说过了,跟踪start.S代码,得知编译需要arch/arm/lib/spl.c文件,查看arch/arm/lib/Makefile得知,需要添加CONFIG_SPL_FRAMEWORK配置,所以include/configs/smdkv210.h +70添加
/* SPL */ #define CONFIG_SPL #define CONFIG_SPL_FRAMEWORK
2.因为SPL不需要BSS清零,所以修改arch/arm/cpu/armv7/start.S +128
#ifndef CONFIG_SPL_BUILD //by ZheGao clear bss ldr r0, =__bss_start ldr r1, =__bss_end__ mov r2, #0x0 1: str r2, [r0], #4 cmp r0, r1 bne 1b //end of clear bss bl save_boot_params #endif
3.因为BL1需要初始化memory,所以在lowlevel_init中添加,board/samsung/smdkv210/lowlevel_init.S +43
#ifdef CONFIG_SPL_BUILD bl mem_ctrl_asm_init #endif
4.mem_ctrl_asm_init在同目录下的mem_setup.S文件中,修改board/samsung/smdkv210/mem_setup.S 添加memory的配置
#define ELFIN_GPIO_BASE 0xE0200000 #define MP1_0DRV_SR_OFFSET 0x3CC #define MP1_1DRV_SR_OFFSET 0x3EC #define MP1_2DRV_SR_OFFSET 0x40C #define MP1_3DRV_SR_OFFSET 0x42C #define MP1_4DRV_SR_OFFSET 0x44C #define MP1_5DRV_SR_OFFSET 0x46C #define MP1_6DRV_SR_OFFSET 0x48C #define MP1_7DRV_SR_OFFSET 0x4AC #define MP1_8DRV_SR_OFFSET 0x4CC #define MP2_0DRV_SR_OFFSET 0x4EC #define MP2_1DRV_SR_OFFSET 0x50C #define MP2_2DRV_SR_OFFSET 0x52C #define MP2_3DRV_SR_OFFSET 0x54C #define MP2_4DRV_SR_OFFSET 0x56C #define MP2_5DRV_SR_OFFSET 0x58C #define MP2_6DRV_SR_OFFSET 0x5AC #define MP2_7DRV_SR_OFFSET 0x5CC #define MP2_8DRV_SR_OFFSET 0x5EC #define APB_DMC_0_BASE 0xF0000000 #define APB_DMC_1_BASE 0xF1400000 #define ASYNC_MSYS_DMC0_BASE 0xF1E00000 #define DMC_CONCONTROL 0x00 #define DMC_MEMCONTROL 0x04 #define DMC_MEMCONFIG0 0x08 #define DMC_MEMCONFIG1 0x0C #define DMC_DIRECTCMD 0x10 #define DMC_PRECHCONFIG 0x14 #define DMC_PHYCONTROL0 0x18 #define DMC_PHYCONTROL1 0x1C #define DMC_RESERVED 0x20 #define DMC_PWRDNCONFIG 0x28 #define DMC_TIMINGAREF 0x30 #define DMC_TIMINGROW 0x34 #define DMC_TIMINGDATA 0x38 #define DMC_TIMINGPOWER 0x3C #define DMC_PHYSTATUS 0x40 #define DMC_CHIP0STATUS 0x48 #define DMC_CHIP1STATUS 0x4C #define DMC_AREFSTATUS 0x50 #define DMC_MRSTATUS 0x54 #define DMC_PHYTEST0 0x58 #define DMC_PHYTEST1 0x5C #define DMC_QOSCONTROL0 0x60 #define DMC_QOSCONFIG0 0x64 #define DMC_QOSCONTROL1 0x68 #define DMC_QOSCONFIG1 0x6C #define DMC_QOSCONTROL2 0x70 #define DMC_QOSCONFIG2 0x74 #define DMC_QOSCONTROL3 0x78 #define DMC_QOSCONFIG3 0x7C #define DMC_QOSCONTROL4 0x80 #define DMC_QOSCONFIG4 0x84 #define DMC_QOSCONTROL5 0x88 #define DMC_QOSCONFIG5 0x8C #define DMC_QOSCONTROL6 0x90 #define DMC_QOSCONFIG6 0x94 #define DMC_QOSCONTROL7 0x98 #define DMC_QOSCONFIG7 0x9C #define DMC_QOSCONTROL8 0xA0 #define DMC_QOSCONFIG8 0xA4 #define DMC_QOSCONTROL9 0xA8 #define DMC_QOSCONFIG9 0xAC #define DMC_QOSCONTROL10 0xB0 #define DMC_QOSCONFIG10 0xB4 #define DMC_QOSCONTROL11 0xB8 #define DMC_QOSCONFIG11 0xBC #define DMC_QOSCONTROL12 0xC0 #define DMC_QOSCONFIG12 0xC4 #define DMC_QOSCONTROL13 0xC8 #define DMC_QOSCONFIG13 0xCC #define DMC_QOSCONTROL14 0xD0 #define DMC_QOSCONFIG14 0xD4 #define DMC_QOSCONTROL15 0xD8 #define DMC_QOSCONFIG15 0xDC #define DMC0_MEMCONFIG_0 0x20E01323 // MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed #define DMC0_MEMCONFIG_1 0x40F01323 // MemConfig1 #define DMC0_TIMINGA_REF 0x00000618 // TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E) #define DMC0_TIMING_ROW 0x28233287 // TimingRow for @200MHz #define DMC0_TIMING_DATA 0x23240304 // TimingData CL=3 #define DMC0_TIMING_PWR 0x09C80232 // TimingPower #define DMC1_MEMCONTROL 0x00202400 // MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off #define DMC1_MEMCONFIG_0 0x40C01323 // MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed #define DMC1_MEMCONFIG_1 0x00E01323 // MemConfig1 #define DMC1_TIMINGA_REF 0x00000618 // TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4 #define DMC1_TIMING_ROW 0x28233289 // TimingRow for @200MHz #define DMC1_TIMING_DATA 0x23240304 // TimingData CL=3 #define DMC1_TIMING_PWR 0x08280232 // TimingPower .globl mem_ctrl_asm_init mem_ctrl_asm_init: #if 0 ldr r6, =S5PC100_DMC_BASE @ 0xE6000000 /* DLL parameter setting */ ldr r1, =0x50101000 str r1, [r6, #0x018] @ PHYCONTROL0 ldr r1, =0xf4 str r1, [r6, #0x01C] @ PHYCONTROL1 ldr r1, =0x0 str r1, [r6, #0x020] @ PHYCONTROL2 /* DLL on */ ldr r1, =0x50101002 str r1, [r6, #0x018] @ PHYCONTROL0 /* DLL start */ ldr r1, =0x50101003 str r1, [r6, #0x018] @ PHYCONTROL0 /* Force value locking for DLL off */ str r1, [r6, #0x018] @ PHYCONTROL0 /* DLL off */ ldr r1, =0x50101001 str r1, [r6, #0x018] @ PHYCONTROL0 /* auto refresh off */ ldr r1, =0xff001010 str r1, [r6, #0x000] @ CONCONTROL /* * Burst Length 4, 2 chips, 32-bit, LPDDR * OFF: dynamic self refresh, force precharge, dynamic power down off */ ldr r1, =0x00212100 str r1, [r6, #0x004] @ MEMCONTROL /* * Note: * If Bank0 has OneDRAM we place it at 0x2800'0000 * So finally Bank1 should address start at at 0x2000'0000 */ mov r4, #0x0 swap_memory: /* * Bank0 * 0x30 -> 0x30000000 * 0xf8 -> 0x37FFFFFF * [15:12] 0: Linear * [11:8 ] 2: 9 bits * [ 7:4 ] 2: 14 bits * [ 3:0 ] 2: 4 banks */ ldr r1, =0x30f80222 /* if r4 is 1, swap the bank */ cmp r4, #0x1 orreq r1, r1, #0x08000000 str r1, [r6, #0x008] @ MEMCONFIG0 /* * Bank1 * 0x38 -> 0x38000000 * 0xf8 -> 0x3fFFFFFF * [15:12] 0: Linear * [11:8 ] 2: 9 bits * [ 7:4 ] 2: 14 bits * [ 3:0 ] 2: 4 banks */ ldr r1, =0x38f80222 /* if r4 is 1, swap the bank */ cmp r4, #0x1 biceq r1, r1, #0x08000000 str r1, [r6, #0x00c] @ MEMCONFIG1 ldr r1, =0x20000000 str r1, [r6, #0x014] @ PRECHCONFIG /* * FIXME: Please verify these values * 7.8us * 166MHz %LE %LONG1294(0x50E) * 7.8us * 133MHz %LE %LONG1038(0x40E), * 7.8us * 100MHz %LE %LONG780(0x30C), * 7.8us * 20MHz %LE %LONG156(0x9C), * 7.8us * 10MHz %LE %LONG78(0x4E) */ ldr r1, =0x0000050e str r1, [r6, #0x030] @ TIMINGAREF /* 166 MHz */ ldr r1, =0x0c233287 str r1, [r6, #0x034] @ TIMINGROW /* twtr=3 twr=2 trtp=3 cl=3 wl=3 rl=3 */ ldr r1, =0x32330303 str r1, [r6, #0x038] @ TIMINGDATA /* tfaw=4 sxsr=0x14 txp=0x14 tcke=3 tmrd=3 */ ldr r1, =0x04141433 str r1, [r6, #0x03C] @ TIMINGPOWER /* chip0 Deselect */ ldr r1, =0x07000000 str r1, [r6, #0x010] @ DIRECTCMD /* chip0 PALL */ ldr r1, =0x01000000 str r1, [r6, #0x010] @ DIRECTCMD /* chip0 REFA */ ldr r1, =0x05000000 str r1, [r6, #0x010] @ DIRECTCMD /* chip0 REFA */ str r1, [r6, #0x010] @ DIRECTCMD /* chip0 MRS, CL%LE %LONG3, BL%LE %LONG4 */ ldr r1, =0x00000032 str r1, [r6, #0x010] @ DIRECTCMD /* chip1 Deselect */ ldr r1, =0x07100000 str r1, [r6, #0x010] @ DIRECTCMD /* chip1 PALL */ ldr r1, =0x01100000 str r1, [r6, #0x010] @ DIRECTCMD /* chip1 REFA */ ldr r1, =0x05100000 str r1, [r6, #0x010] @ DIRECTCMD /* chip1 REFA */ str r1, [r6, #0x010] @ DIRECTCMD /* chip1 MRS, CL%LE %LONG3, BL%LE %LONG4 */ ldr r1, =0x00100032 str r1, [r6, #0x010] @ DIRECTCMD /* auto refresh on */ ldr r1, =0xff002030 str r1, [r6, #0x000] @ CONCONTROL /* PwrdnConfig */ ldr r1, =0x00100002 str r1, [r6, #0x028] @ PWRDNCONFIG /* BL%LE %LONG */ ldr r1, =0xff212100 str r1, [r6, #0x004] @ MEMCONTROL /* Try to test memory area */ cmp r4, #0x1 beq 1f mov r4, #0x1 ldr r1, =0x37ffff00 str r4, [r1] str r4, [r1, #0x4] @ dummy write ldr r0, [r1] cmp r0, r4 bne swap_memory #endif /* DMC0 Drive Strength (Setting 2X) */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x0000AAAA str r1, [r0, #MP1_0DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_1DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_2DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_3DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_4DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_5DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_6DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP1_7DRV_SR_OFFSET] ldr r1, =0x00002AAA str r1, [r0, #MP1_8DRV_SR_OFFSET] /* DMC1 Drive Strength (Setting 2X) */ ldr r0, =ELFIN_GPIO_BASE ldr r1, =0x0000AAAA str r1, [r0, #MP2_0DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_1DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_2DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_3DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_4DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_5DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_6DRV_SR_OFFSET] ldr r1, =0x0000AAAA str r1, [r0, #MP2_7DRV_SR_OFFSET] ldr r1, =0x00002AAA str r1, [r0, #MP2_8DRV_SR_OFFSET] /* DMC0 initialization at single Type*/ ldr r0, =APB_DMC_0_BASE ldr r1, =0x00101000 @PhyControl0 DLL parameter setting, manual 0x00101000 str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00000086 @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case str r1, [r0, #DMC_PHYCONTROL1] ldr r1, =0x00101002 @PhyControl0 DLL on str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00101003 @PhyControl0 DLL start str r1, [r0, #DMC_PHYCONTROL0] find_lock_val: ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value and r2, r1, #0x7 cmp r2, #0x7 @Loop until DLL is locked bne find_lock_val and r1, #0x3fc0 mov r2, r1, LSL #18 orr r2, r2, #0x100000 orr r2 ,r2, #0x1000 orr r1, r2, #0x3 @Force Value locking str r1, [r0, #DMC_PHYCONTROL0] #if 0 /* Memory margin test 10.01.05 */ orr r1, r2, #0x1 @DLL off str r1, [r0, #DMC_PHYCONTROL0] #endif /* setting DDR2 */ ldr r1, =0x0FFF2010 @ConControl auto refresh off str r1, [r0, #DMC_CONCONTROL] ldr r1, =0x00212400 @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] ldr r1, =DMC0_MEMCONFIG_0 @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed str r1, [r0, #DMC_MEMCONFIG0] ldr r1, =DMC0_MEMCONFIG_1 @MemConfig1 str r1, [r0, #DMC_MEMCONFIG1] ldr r1, =0xFF000000 @PrechConfig str r1, [r0, #DMC_PRECHCONFIG] ldr r1, =DMC0_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E) str r1, [r0, #DMC_TIMINGAREF] ldr r1, =DMC0_TIMING_ROW @TimingRow for @200MHz str r1, [r0, #DMC_TIMINGROW] ldr r1, =DMC0_TIMING_DATA @TimingData CL=3 str r1, [r0, #DMC_TIMINGDATA] ldr r1, =DMC0_TIMING_PWR @TimingPower str r1, [r0, #DMC_TIMINGPOWER] ldr r1, =0x07000000 @DirectCmd chip0 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00020000 @DirectCmd chip0 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00030000 @DirectCmd chip0 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x07100000 @DirectCmd chip1 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00120000 @DirectCmd chip1 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00130000 @DirectCmd chip1 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x0FF02030 @ConControl auto refresh on str r1, [r0, #DMC_CONCONTROL] ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG] ldr r1, =0x00202400 @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] /* DMC1 initialization */ ldr r0, =APB_DMC_1_BASE ldr r1, =0x00101000 @Phycontrol0 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00000086 @Phycontrol1 DLL parameter setting str r1, [r0, #DMC_PHYCONTROL1] ldr r1, =0x00101002 @PhyControl0 DLL on str r1, [r0, #DMC_PHYCONTROL0] ldr r1, =0x00101003 @PhyControl0 DLL start str r1, [r0, #DMC_PHYCONTROL0] find_lock_val1: ldr r1, [r0, #DMC_PHYSTATUS] @Load Phystatus register value and r2, r1, #0x7 cmp r2, #0x7 @Loop until DLL is locked bne find_lock_val1 and r1, #0x3fc0 mov r2, r1, LSL #18 orr r2, r2, #0x100000 orr r2, r2, #0x1000 orr r1, r2, #0x3 @Force Value locking str r1, [r0, #DMC_PHYCONTROL0] #if 0 /* Memory margin test 10.01.05 */ orr r1, r2, #0x1 @DLL off str r1, [r0, #DMC_PHYCONTROL0] #endif /* settinf fot DDR2 */ ldr r0, =APB_DMC_1_BASE ldr r1, =0x0FFF2010 @auto refresh off str r1, [r0, #DMC_CONCONTROL] ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] ldr r1, =DMC1_MEMCONFIG_0 @MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed str r1, [r0, #DMC_MEMCONFIG0] ldr r1, =DMC1_MEMCONFIG_1 @MemConfig1 str r1, [r0, #DMC_MEMCONFIG1] ldr r1, =0xFF000000 str r1, [r0, #DMC_PRECHCONFIG] ldr r1, =DMC1_TIMINGA_REF @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4 str r1, [r0, #DMC_TIMINGAREF] ldr r1, =DMC1_TIMING_ROW @TimingRow for @200MHz str r1, [r0, #DMC_TIMINGROW] ldr r1, =DMC1_TIMING_DATA @TimingData CL=3 str r1, [r0, #DMC_TIMINGDATA] ldr r1, =DMC1_TIMING_PWR @TimingPower str r1, [r0, #DMC_TIMINGPOWER] ldr r1, =0x07000000 @DirectCmd chip0 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00020000 @DirectCmd chip0 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00030000 @DirectCmd chip0 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000542 @DirectCmd chip0 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01000000 @DirectCmd chip0 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05000000 @DirectCmd chip0 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00000442 @DirectCmd chip0 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010780 @DirectCmd chip0 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00010400 @DirectCmd chip0 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x07100000 @DirectCmd chip1 Deselect str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00120000 @DirectCmd chip1 EMRS2 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00130000 @DirectCmd chip1 EMRS3 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110440 @DirectCmd chip1 EMRS1 (MEM DLL on, DQS# disable) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100542 @DirectCmd chip1 MRS (MEM DLL reset) CL=4, BL=4 str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x01100000 @DirectCmd chip1 PALL str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x05100000 @DirectCmd chip1 REFA str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00100442 @DirectCmd chip1 MRS (MEM DLL unreset) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110780 @DirectCmd chip1 EMRS1 (OCD default) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x00110400 @DirectCmd chip1 EMRS1 (OCD exit) str r1, [r0, #DMC_DIRECTCMD] ldr r1, =0x0FF02030 @ConControl auto refresh on str r1, [r0, #DMC_CONCONTROL] ldr r1, =0xFFFF00FF @PwrdnConfig str r1, [r0, #DMC_PWRDNCONFIG] ldr r1, =DMC1_MEMCONTROL @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off str r1, [r0, #DMC_MEMCONTROL] mov pc, lr
5.修改board/samsung/smdkv210/Makefile 添加对mem_setup.S的选则编译,uboot里就不需要编译了,因为BL1已经初始化过了,在执行一次也没问题的
ifndef CONFIG_SPL_BUILD SOBJS := lowlevel_init.o endif ifdef CONFIG_SPL_BUILD SOBJS := lowlevel_init.o mem_setup.o endif
6.修改arch/arm/lib/spl.c 的 board_init_f 函数
void __weak board_init_f(ulong dummy) { __attribute__((noreturn)) void (*uboot)(void); #if 0 /* Set the stack pointer. */ asm volatile("mov sp, %0\n" : : "r"(CONFIG_SPL_STACK)); /* Clear the BSS. */ memset(__bss_start, 0, __bss_end__ - __bss_start); /* Set global data pointer. */ gd = &gdata; board_init_r(NULL, 0); #endif /* // test #define GPH0CON (*(volatile unsigned int *)0xE0200C00) #define GPH0DAT (*(volatile unsigned int *)0xE0200C04) GPH0CON = (1<<0) | (1<<4) | (1<<8) | (1<<12); GPH0DAT = 10; */ uart_init(); copy_uboot_to_ram(); //printf ("jump to u-boot image\r\n"); /* Jump to U-Boot image */ uboot = (void *)CONFIG_SYS_TEXT_BASE; (*uboot)(); }
7.在arch/arm/lib/spl.c 中添加串口的初始化和从sd卡拷贝uboot到ddr2内存里的函数
//UART #define ULCON0 (*(volatile unsigned int *)0xE2900000) #define UCON0 (*(volatile unsigned int *)0xE2900004) #define UTRSTAT0 (*(volatile unsigned int *)0xE2900010) #define UTXH0 (*(volatile unsigned char *)0xE2900020) #define URXH0 (*(volatile unsigned char *)0xE2900024) #define UBRDIV0 (*(volatile unsigned int *)0xE2900028) #define UDIVSLOT0 (*(volatile unsigned int *)0xE290002C) //GPA0 #define GPA0CON (*(volatile unsigned int *)0xE0200000) typedef u32(*copy_sd_mmc_to_mem) (u32 channel, u32 start_block, u16 block_size, u32 *trg, u32 init); /* Pointer to as well as the global data structure for SPL */ DECLARE_GLOBAL_DATA_PTR; gd_t gdata __attribute__ ((section(".data"))); void uart_init (void) { //配置GPA0_0 - GPA0_1管脚为串口0功能管脚 GPA0CON = (2<<0) | (2<<4); /** * 传送模式: 0:普通模式 * 校验位: 0无校验 * 停止位: 1 * 数据位: 8 */ ULCON0 = (0<<6) | (0<<3) | (0<<2) | (3<<0); /** * 时钟选则: 0 = PCLK = 66M: * 发送模式:01 = Interrupt request or polling mode */ UCON0 = (0<<10) | (1<<2) | (1<<0); /** * DIV_VAL = UBRDIVn + (num of 1's in UDIVSLOTn)/16 * DIV_VAL = (PCLK / (bps x 16)) - 1 * DIV_VAL = (66000000 / (115200 * 16)) - 1 = 34.8 * UBRDIV0 = 34 * (num of 1's in UDIVSLOTn)/16 = 0.8 * (num of 1's in UDIVSLOTn) = 12 * 查表得 UDIVSLOT0 = 0xDDDD */ UBRDIV0 = 34; UDIVSLOT0 = 0xDDDD; } void copy_uboot_to_ram(void) { ulong ch; ch = *(volatile u32 *)(0xD0037488); copy_sd_mmc_to_mem copy_bl2 = (copy_sd_mmc_to_mem) (*(u32 *) (0xD0037F98)); u32 ret; //printf ("boot mmc chanel: %x\r\n", ch); if (ch == 0xEB000000) { ret = copy_bl2(0, 49, 1024, CONFIG_SYS_TEXT_BASE, 0); } if (ret == 0) { //printf ("copy error\r\n"); while (1); } else return; }
8.arch/arm/include/asm/spl.h +27
//#include <asm/arch/spl.h>
9.分析spl/Makefile得知,在tools/下没有mk$(BOARD)spl这个工具,我暂时对这个工具不熟悉,就用自己的吧,我的工具是mkv210_image,用来制作BL1头信息的
ifdef CONFIG_SAMSUNG $(obj)$(BOARD)-spl.bin: $(obj)u-boot-spl.bin $(OBJTREE)/tools/mk$(BOARD)spl \ $(obj)u-boot-spl.bin $(obj)$(BOARD)-spl.bin endif
10.修改spl/Makefile,然后拷贝mkv210_image.c到tools/下
ifdef CONFIG_SAMSUNG $(obj)$(BOARD)-spl.bin: $(obj)u-boot-spl.bin $(HOSTCC) $(TOPDIR)/tools/mkv210_image.c -o $(TOPDIR)/tools/mkv210_image $(OBJTREE)/tools/mkv210_image \ $(obj)u-boot-spl.bin $(obj)$(BOARD)-spl.bin endif
11.make,插入SD卡,使用下面的命令烧写SPL和uboot.bin到SD卡上
dd iflag=dsync oflag=dsync if=spl/smdkv210-spl.bin of=/dev/sdb seek=1
dd iflag=dsync oflag=dsync if=u-boot.bin of=/dev/sdb seek=49
12.把SD卡插到开发板上,上电,就可以在控制台上打印出
//#define PHYS_SDRAM_1_SIZE (128 << 20) /* 0x8000000, 128 MB Bank #1 */ #define PHYS_SDRAM_1_SIZE (0x40000000) /* 0x8000000, 128 MB Bank #1 */