您的位置:首页 > 其它

u-boot-2016.11移植uboot-spl.bin

2016-11-28 08:10 246 查看
一、时钟初始化
1、修改clock.h
cd arch/arm/mach-s5pv210/include/mach/
vim clock.h
/* add by Sourcelink */
struct s5pv210_clock {
unsigned int    apll_lock;
unsigned char   res1[0x04];
unsigned int    mpll_lock;
unsigned char   res2[0x04];
unsigned int    epll_lock;
unsigned char   res3[0x0c];
unsigned int    vpll_lock;
unsigned char   res4[0xdc];
unsigned int    apll_con0;
unsigned int    apll_con1;
unsigned int    mpll_con;
unsigned char   res5[0x04];
unsigned int    epll_con0;
unsigned int    epll_con1;
unsigned char   res6[0x08];
unsigned int    vpll_con;
unsigned char   res7[0xdc];
unsigned int    clk_src0;
unsigned int    clk_src1;
unsigned int    clk_src2;
unsigned int    clk_src3;
unsigned int    clk_src4;
unsigned int    clk_src5;
unsigned int    clk_src6;
unsigned char   res8[0x64];
unsigned int    clk_src_mask0;
unsigned int    clk_src_mask1;
unsigned char   res9[0x78];
unsigned int    clk_div0;
unsigned int    clk_div1;
unsigned int    clk_div2;
unsigned int    clk_div3;
unsigned int    clk_div4;
unsigned int    clk_div5;
unsigned int    clk_div6;
unsigned int    clk_div7;
unsigned char   res10[0x24];
unsigned int    clk_gate_sclk;
unsigned char   res11[0x18];
unsigned int    clk_gate_ip0;
unsigned int    clk_gate_ip1;
unsigned int    clk_gate_ip2;
unsigned int    clk_gate_ip3;
unsigned int    clk_gate_ip4;
unsigned char   res12[0x0c];
unsigned int    clk_gate_block;
unsigned int    clk_gate_ip5;
};

2、增加clock初始化函数
cd board/samsung/smdkv210/
vim smdkv210.c
void clock_init(void)
{
u32 val = 0;

struct s5pv210_clock *const clock = (struct s5pv210_clock *)samsung_get_base_clock();

/* 1.设置PLL锁定值 */
writel(0xFFFF, &clock->apll_lock);
writel(0xFFFF, &clock->mpll_lock);
writel(0xFFFF, &clock->epll_lock);
writel(0xFFFF, &clock->vpll_lock);

/* 2.设置PLL的PMS值(使用芯片手册推荐的值),并使能PLL */
/*              P                   M                     S                  EN */
writel((3  << 8) | (125 << 16) | (1 << 0) | (1 << 31), &clock->apll_con0);      /* FOUT_APLL = 1000MHz */
writel((12 << 8) | (667 << 16) | (1 << 0) | (1 << 31), &clock->mpll_con);       /* FOUT_MPLL = 667MHz */
writel((3  << 8) | (48  << 16) | (2 << 0) | (1 << 31), &clock->epll_con0);      /* FOUT_EPLL = 96MHz */
writel((6  << 8) | (108 << 16) | (3 << 0) | (1 << 31), &clock->vpll_con);       /* FOUT_VPLL = 54MHz */

/* 3.等待PLL锁定 */
while (!(readl(&clock->apll_con0) & (1 << 29)));
while (!(readl(&clock->mpll_con) & (1 << 29)));
while (!(readl(&clock->apll_con0) & (1 << 29)));
while (!(readl(&clock->epll_con0) & (1 << 29)));
while (!(readl(&clock->vpll_con) & (1 << 29)));

/*
** 4.设置系统时钟源,选择PLL为时钟输出 */
/* MOUT_MSYS = SCLKAPLL = FOUT_APLL = 1000MHz
** MOUT_DSYS = SCLKMPLL = FOUT_MPLL = 667MHz
** MOUT_PSYS = SCLKMPLL = FOUT_MPLL = 667MHz
** ONENAND = HCLK_PSYS
*/

writel((1 << 0) | (1 << 4) | (1 << 8) | (1 << 12), &clock->clk_src0);

/* 4.设置其他模块的时钟源 */

/* 6.设置系统时钟分频值 */
val =   (0 << 0)  |     /* APLL_RATIO = 0, freq(ARMCLK) = MOUT_MSYS / (APLL_RATIO + 1) = 1000MHz */
(4 << 4)  |     /* A2M_RATIO = 4, freq(A2M) = SCLKAPLL / (A2M_RATIO + 1) = 200MHz */
(4 << 8)  |     /* HCLK_MSYS_RATIO = 4, freq(HCLK_MSYS) = ARMCLK / (HCLK_MSYS_RATIO + 1) = 200MHz */
(1 << 12) |     /* PCLK_MSYS_RATIO = 1, freq(PCLK_MSYS) = HCLK_MSYS / (PCLK_MSYS_RATIO + 1) = 100MHz */
(3 << 16) | /* HCLK_DSYS_RATIO = 3, freq(HCLK_DSYS) = MOUT_DSYS / (HCLK_DSYS_RATIO + 1) = 166MHz */
(1 << 20) | /* PCLK_DSYS_RATIO = 1, freq(PCLK_DSYS) = HCLK_DSYS / (PCLK_DSYS_RATIO + 1) = 83MHz */
(4 << 24) |     /* HCLK_PSYS_RATIO = 4, freq(HCLK_PSYS) = MOUT_PSYS / (HCLK_PSYS_RATIO + 1) = 133MHz */
(1 << 28);      /* PCLK_PSYS_RATIO = 1, freq(PCLK_PSYS) = HCLK_PSYS / (PCLK_PSYS_RATIO + 1) = 66MHz */
writel(val, &clock->clk_div0);

/* 7.设置其他模块的时钟分频值 */
}

二、ddr初始化
1、增加dmc寄存器
cd arch/arm/mach-s5pv210/include/mach/
vim dmc.h

/* add by Sourcelink */

#ifndef __ASM_ARM_ARCH_DRAM_H_
#define __ASM_ARM_ARCH_DRAM_H_

#ifndef __ASSEMBLY__

struct s5pv210_dmc0 {
unsigned int    concontrol;
unsigned int    memcontrol;
unsigned int    memconfig0;
unsigned int    memconfig1;
unsigned int    directcmd;
unsigned int    prechconfig;
unsigned int    phycontrol0;
unsigned int    phycontrol1;
unsigned char   res1[0x08];
unsigned int    pwrdnconfig;
unsigned char   res2[0x04];
unsigned int    timingaref;
unsigned int    timingrow;
unsigned int    timingdata;
unsigned int    timingpower;
unsigned int    phystatus;
unsigned int    chip0status;
unsigned int    chip1status;
unsigned int    arefstatus;
unsigned int    mrstatus;
unsigned int    phytest0;
unsigned int    phytest1;
};

struct s5pv210_dmc1 {
unsigned int    concontrol;
unsigned int    memcontrol;
unsigned int    memconfig0;
unsigned int    memconfig1;
unsigned int    directcmd;
unsigned int    prechconfig;
unsigned int    phycontrol0;
unsigned int    phycontrol1;
unsigned char   res1[0x08];
unsigned int    pwrdnconfig;
unsigned char   res2[0x04];
unsigned int    timingaref;
unsigned int    timingrow;
unsigned int    timingdata;
unsigned int    timingpower;
unsigned int    phystatus;
unsigned int    chip0status;
unsigned int    chip1status;
unsigned int    arefstatus;
unsigned int    mrstatus;
unsigned int    phytest0;
unsigned int    phytest1;
};

#endif

#endif

2、增加ddr初始化函数
cd board/samsung/smdkv210/
vim smdkv210.c
void ddr_init(void)
{
struct s5pv210_dmc0 *const dmc0 = (struct s5pv210_dmc0 *)samsung_get_base_dmc0();
struct s5pv210_dmc1 *const dmc1 = (struct s5pv210_dmc1 *)samsung_get_base_dmc1();

/* DMC0 */
writel(0x00101000, &dmc0->phycontrol0);
writel(0x00101002, &dmc0->phycontrol0);                 /* DLL on */
writel(0x00000086, &dmc0->phycontrol1);
writel(0x00101003, &dmc0->phycontrol0);                 /* DLL start */

while ((readl(&dmc0->phystatus) & 0x7) != 0x7);         /* wait DLL locked */

writel(0x0FFF2350, &dmc0->concontrol);                  /* Auto Refresh Counter should be off */
writel(0x00202430, &dmc0->memcontrol);                  /* Dynamic power down should be off */
writel(0x20E01323, &dmc0->memconfig0);

writel(0xFF000000, &dmc0->prechconfig);
writel(0xFFFF00FF, &dmc0->pwrdnconfig);

writel(0x00000618, &dmc0->timingaref);                  /* 7.8us * 200MHz = 1560 = 0x618  */
writel(0x19233309, &dmc0->timingrow);
writel(0x23240204, &dmc0->timingdata);
writel(0x09C80232, &dmc0->timingpower);

writel(0x07000000, &dmc0->directcmd);                   /* NOP */
writel(0x01000000, &dmc0->directcmd);                   /* PALL */
writel(0x00020000, &dmc0->directcmd);                   /* EMRS2 */
writel(0x00030000, &dmc0->directcmd);                   /* EMRS3 */
writel(0x00010400, &dmc0->directcmd);                   /* EMRS enable DLL */
writel(0x00000542, &dmc0->directcmd);                   /* DLL reset */
writel(0x01000000, &dmc0->directcmd);                   /* PALL */
writel(0x05000000, &dmc0->directcmd);                   /* auto refresh */
writel(0x05000000, &dmc0->directcmd);                   /* auto refresh */
writel(0x00000442, &dmc0->directcmd);                   /* DLL unreset */
writel(0x00010780, &dmc0->directcmd);                   /* OCD default */
writel(0x00010400, &dmc0->directcmd);                   /* OCD exit */

writel(0x0FF02030, &dmc0->concontrol);                  /* auto refresh on */
writel(0xFFFF00FF, &dmc0->pwrdnconfig);
writel(0x00202400, &dmc0->memcontrol);

/* DMC1 */
writel(0x00101000, &dmc1->phycontrol0);
writel(0x00101002, &dmc1->phycontrol0);                 /* DLL on */
writel(0x00000086, &dmc1->phycontrol1);
writel(0x00101003, &dmc1->phycontrol0);                 /* DLL start */

while ((readl(&dmc1->phystatus) & 0x7) != 0x7);         /* wait DLL locked */

writel(0x0FFF2350, &dmc1->concontrol);                  /* Auto Refresh Counter should be off */
writel(0x00202430, &dmc1->memcontrol);                  /* Dynamic power down should be off */
writel(0x40E01323, &dmc1->memconfig0);

writel(0xFF000000, &dmc1->prechconfig);
writel(0xFFFF00FF, &dmc1->pwrdnconfig);

writel(0x00000618, &dmc1->timingaref);                  /* 7.8us * 200MHz = 1560 = 0x618  */
writel(0x19233309, &dmc1->timingrow);
writel(0x23240204, &dmc1->timingdata);
writel(0x09C80232, &dmc1->timingpower);

writel(0x07000000, &dmc1->directcmd);                   /* NOP */
writel(0x01000000, &dmc1->directcmd);                   /* PALL */
writel(0x00020000, &dmc1->directcmd);                   /* EMRS2 */
writel(0x00030000, &dmc1->directcmd);                   /* EMRS3 */
writel(0x00010400, &dmc1->directcmd);                   /* EMRS enable DLL */
writel(0x00000542, &dmc1->directcmd);                   /* DLL reset */
writel(0x01000000, &dmc1->directcmd);                   /* PALL */
writel(0x05000000, &dmc1->directcmd);                   /* auto refresh */
writel(0x05000000, &dmc1->directcmd);                   /* auto refresh */
writel(0x00000442, &dmc1->directcmd);                   /* DLL unreset */
writel(0x00010780, &dmc1->directcmd);                   /* OCD default */
writel(0x00010400, &dmc1->directcmd);                   /* OCD exit */

writel(0x0FF02030, &dmc1->concontrol);                  /* auto refresh on */
writel(0xFFFF00FF, &dmc1->pwrdnconfig);
writel(0x00202400, &dmc1->memcontrol);
}
三、初始化sd卡copy函数
void copy_bl2_to_ram(void)
{
/*
** ch:  通道
** sb:  起始块
** bs:  块大小
** dst: 目的地
** i:   是否初始化
*/
#iefine CopySDMMCtoMem(ch, sb, bs, dst, i) \
(((unsigned char(*)(int, unsigned int, unsigned short, unsigned int*, unsigned char))\
(*((unsigned int *)0xD0037F98)))(ch, sb, bs, dst, i))

unsigned int V210_SDMMC_BASE = *(volatile unsigned int *)(0xD0037488);  // V210_SDMMC_BASE
unsigned char ch = 0;

/* 参考S5PV210手册7.9.1 SD/MMC REGISTER MAP */
if (V210_SDMMC_BASE == 0xEB000000)              // 通道0
ch = 0;
else if (V210_SDMMC_BASE == 0xEB200000) // 通道2
ch = 2;

CopySDMMCtoMem(ch, 32, 10, (unsigned int *)CONFIG_SYS_SDRAM_BASE, 0);
}

四、更改base地址
在进行clock初始化和ddr初始化时用到了.h中的寄存器地址
struct s5pv210_clock *const clock = (struct s5pv210_clock *)samsung_get_base_clock();
定义了这个结构体变量 需要修改cpu.h
cd arch/arm/mach-s5pv210/include/mach/
vim cpu.h
/* add by Sourcelink */
IS_SAMSUNG_TYPE(s5pv210, 0x56210)
/* modif by Sourcelink */
#define SAMSUNG_BASE(device, base)                              \
static inline unsigned int samsung_get_base_##device(void)      \
{               						\
if(cpu_is_s5pv210())                            \
return S5PV210_##base;                  \
else if(cpu_is_s5pc100())			\
return S5PC100_##base;			\
}
一开始这么写发现执行都是S5PC100的寄存器基地址,现在还没有发现原因。s5pv210的id函数在上一节有贴出来。希望知道的朋友告知。最后改成了如下:
/* modif by Sourcelink */
#define SAMSUNG_BASE(device, base)                              \
static inline unsigned int samsung_get_base_##device(void)      \
{                                                               \
return S5PV210_##base;                          \
}

/* add by Sourcelink */
SAMSUNG_BASE(dmc0,DMC0_BASE)
SAMSUNG_BASE(dmc1,DMC1_BASE)

五、添加宏CONFIG_SPL
编译 u-boot-spl.bin 时,spl/Makefile 会导出一个宏 CONFIG_SPL_BUILD,我们通过这个宏来控制代码是否被编译,下面列出修改后的框架
#ifdef CONFIG_SPL_BUILD
六、硬件初始化
cd board/samsung/smdkv210/
vim lowlevel_init.S
/* modif by Sourcelink */

.globl lowlevel_init
lowlevel_init:
mov     r9, lr

#ifdef CONFIG_SPL_BUILD
bl clock_init           /* 时钟初始化 */
bl ddr_init             /* DDR初始化 */
#endif
mov     pc, r9          /* 返回 */
七、修改_main函数
cd arch/arm/lib
vim crt0.S
ENTRY(_main)

/*
* Set up initial C runtime environment and call board_init_f(0).
*/

/* modied by Sourcelink */
#if !defined(CONFIG_SPL_BUILD)
ldr     sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic     sp, sp, #7      /* 8-byte alignment for ABI compliance */
sub     sp, sp, #GD_SIZE        /* allocate one GD above SP */
bic     sp, sp, #7      /* 8-byte alignment for ABI compliance */
mov     r9, sp          /* GD is above SP */
mov     r0, #0
#endif
/* modied by Sourcelink */
#ifdef CONFIG_SPL_BUILD
bl copy_bl2_to_ram                       /* 拷贝BL2到DDR */
ldr pc, =CONFIG_SYS_SDRAM_BASE          /* 跳转到DDR的起始地址执行BL2 */
#else
bl      board_init_f
#endif

八、修改ddr基地址

vim include/configs/smdkv210.h
/* DRAM Base */
#define CONFIG_SYS_SDRAM_BASE           0x20000000      /* modif by Sourcelink */

/* Text Base */
#define CONFIG_SYS_TEXT_BASE            0x20000000

九、增加宏
vim configs/smdkv210_defconfig
# add by Sourcelink
CONFIG_SPL=y

十、添加增加头信息的可执行文件
在做完前面九步后进行编译会提示mkexynosspl:Command not find 这是个可执行文件是在make时自动增加头信息用的
分析scripts/Makefile.spl

vim scripts/Makefile.spl

# modif by Sourcelink
$(obj)/$(BOARD)-spl.bin: $(obj)/u-boot-spl.bin
$(if $(wildcard $(objtree)/spl/board/samsung/$(BOARD)/tools/mk$(BOARD)spl),\
$(objtree)/spl/board/samsung/$(BOARD)/tools/mk$(BOARD)spl,\
$(objtree)/tools/mksource210spl) $(VAR_SIZE_PARAM) $< $@
endif
把自己编译好的可执行文件Source210 更改成mksource210spl 放到tools目录下

十一、编译和烧写
make smdkv210_defconfig
make spl/u-boot-spl.bin

编译完成后把spl目录下的smdkv210-spl.bin 烧写到sd卡扇区1,再烧写一个其他可运行bin文件到sd卡扇区32
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: