下面教程的源代码见此链接,点击打开链接http://download.csdn.net/download/qq_15015097/10043644,
一、添加单板信息
1、
cp -r board/samsung/smdkc100 board/samsung/smdkv210
2、进入smdkv210下
cd board/samsung/smdkv210/
mv smdkc100.c smdkv210.c
3、修改Kconfig
if TARGET_SMDKV210
config SYS_BOARD
default "smdkv210"
config SYS_VENDOR
default "samsung"
config SYS_SOC
default "s5pv2xx"
config SYS_CONFIG_NAME
default "smdkv210"
endif
4、修改MAINTAINERS
SMDKV210 BOARD
M: Minkyu Kang <mk7.kang@samsung.com>
S: Maintained
F: board/samsung/smdkv210/
F: include/configs/smdkv210.h
F: configs/smdkv210_defconfig
5、修改Makefile
obj-y := smdkv210.o
obj-$(CONFIG_SAMSUNG_ONENAND) += onenand.o
obj-y += lowlevel_init.o
6、根据MAINTAINERS修改includ/configs/smdkv210.h 和configs/smdkv210_defconfig
cp include/configs/smdkc100.h include/configs/smdkv210.h
cp configs/smdkc100_defconfig configs/smdkv210_defconfig
7、修改smdkv210_defconfig
CONFIG_ARM=y
CONFIG_ARCH_S5PV2XX=y
CONFIG_TARGET_SMDKV210=y
CONFIG_IDENT_STRING=" for SMDKV210"
CONFIG_DEFAULT_DEVICE_TREE="s5pv2xx-smdkv210"
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="root=/dev/mtdblock5 ubi.mtd=4 rootfstype=cramfs console=ttySAC0,115200n8 mem=128M mtdparts=s3c-onenand:256k(bootloader),128k@0x40000(params),3m@0x60000(kernel),16m@0x360000(test),-(UBI)"
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="SMDKV210 # "
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_ONENAND=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_CACHE=y
CONFIG_CMD_FAT=y
CONFIG_CMD_MTDPARTS=y
CONFIG_ENV_IS_IN_ONENAND=y
# CONFIG_MMC is not set
8、修改smdkv210.h
#define CONFIG_SAMSUNG 1 /* in a SAMSUNG core */
#define CONFIG_S5P 1 /* which is in a S5P Family */
#define CONFIG_S5PV210 1 /* which is in a S5PV210 */
#define CONFIG_SMDKV210 1 /* working with SMDKV210 */
/* DRAM Base */
#define CONFIG_SYS_SDRAM_BASE 0x20000000
/* Text Base */
#define CONFIG_SYS_TEXT_BASE 0x20000000
#define PHYS_SDRAM_1_SIZE (1024 << 20) /*1024 MB Bank #1 */
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + PHYS_SDRAM_1_SIZE)
二、添加S5PV210信息
1、进入arch/arn目录下
cd arch/arm
vim Kconfig
/*add by xcl*/
config ARCH_S5PV2XX
bool "Samsung S5PV2XX"
select CPU_V7
select DM
select DM_SERIAL
select DM_GPIO
select DM_I2C
/*add by xcl*/
source "arch/arm/mach-s5pv2xx/Kconfig"
2、修改Makefile
vim Makefile
/*add by xcl*/
machine-$(CONFIG_ARCH_S5PV2XX) += s5pv2xx
3、复制mach-s5pc1xx
cp -r mach-s5pc1xx mach-s5pv2xx
4、修改mach-s5pv210目录下Kconfig
cd mach-s5pv210/
vim Kconfig
if ARCH_S5PV2XX
choice
prompt "S5PV2XX board select"
optional
config TARGET_SMDKV210
bool "Support smdkv210 board"
select OF_CONTROL
endchoice
config SYS_SOC
default "s5pv2xx"
source "board/samsung/smdkv210/Kconfig"
endif
5、修改cpu.h
cd include/mach
vim cpu.h
#ifndef _S5PV210_CPU_H
#define _S5PV210_CPU_H
#define S5P_CPU_NAME "S5P"
#define S5PV210_ADDR_BASE 0xE0000000
/* S5PV210 */
#define S5PV210_PRO_ID 0xE0000000
#define S5PV210_CLOCK_BASE 0xE0100000
#define S5PV210_GPIO_BASE 0xE0200000
#define S5PV210_PWMTIMER_BASE 0xE2500000
#define S5PV210_WATCHDOG_BASE 0xE2700000
#define S5PV210_UART_BASE 0xE2900000
#define S5PV210_MMC_BASE 0xEB000000
#define S5PV210_SROMC_BASE 0xE8000000
#define S5PV210_DMC0_BASE 0xF0000000
#define S5PV210_DMC1_BASE 0xF1400000
#define S5PV210_VIC0_BASE 0xF2000000
#define S5PV210_VIC1_BASE 0xF2100000
#define S5PV210_VIC2_BASE 0xF2200000
#define SPPV210_VIC3_BASE 0xF2300000
#define S5PV210_NAND_BASE 0xB0E00000
/*modified by xcl*/
static inline void s5p_set_cpu_id(void)
{
int id = 0;
s5p_cpu_id = readl(S5PV210_PRO_ID);
s5p_cpu_rev = s5p_cpu_id & 0x000000FF;
id = (s5p_cpu_id & 0xFFFFF000) >> 12;
if (id == 0x43110) {
id = s5p_cpu_id & 0x0F;
switch (id){
case 0x00:
s5p_cpu_id = 0x56210;
break;
case 0x01:
s5p_cpu_id = 0xc110;
break;
case 0x02:
s5p_cpu_id = 0xc111;
break;
default :
break;
}
}
}
/*add by xcl*/
IS_SAMSUNG_TYPE(s5pv210, 0x56210)
/*modified by xcl*/
#define SAMSUNG_BASE(device, base) \
static inline unsigned int samsung_get_base_##device(void) \
{ \
if (cpu_is_s5pc100()) \
return S5PC100_##base; \
else if (cpu_is_s5pc110()) \
return S5PC110_##base; \
else if (cpu_is_s5pv210())\
return S5PV210_##base;\
else\
return 0; \
}
5、修改board/samsung/smdkv210/lowlevel_init.S 将里面S5PC100全部替换为S5PV210
6、添加soc
cd arch/arm/cpu/armv7
vim Makefile
/*modified by xcl*/
ifneq (,$(filter s5pv2xx s5pc1xx exynos,$(SOC)))
obj-y += s5p-common/
endif
7、添加设备树
cd arch/arm/dts/
cp s5pc1xx-smdkc100.dts s5pv2xx-smdkv210.dts
cp s5pc110-pinctrl.dtsi s5pv210-pinctrl.dtsi
8、修改Makefile
vim Makefile
/*add by xcl*/
dtb-$(CONFIG_S5PV210) += s5pv2xx-smdkv210.dtb
9、修改设备树
vim s5pv2xx-smdkv210.dts
#include "skeleton.dtsi"
#include "s5pv210-pinctrl.dtsi"
/ {
model = "Samsung SMDKV210 based on S5PV210";
compatible = "samsung,smdkv210", "samsung,s5pv210";
aliases {
serial0 = "/serial@e2900000";
console = "/serial@e2900000";
pinctrl0 = &pinctrl0;
};
pinctrl0: pinctrl@e0200000 {
compatible = "samsung,s5pv210-pinctrl";
reg = <0xe0200000 0x1000>;
};
serial@e2900000 {
compatible = "samsung,exynos4210-uart";
reg = <0xe2900000 0x100>;
interrupts = <0 51 0>;
id = <0>;
};
};
这样基本就算添加了单板信息,回到uboot主目录,为了支持SPL故修改
vim common/spl/Kconfig
config SUPPORT_SPL
bool "enable spl"
help
add by xcl
执行make smdkv210_defconfig
make menuconfig将SPL编译选项选上
make
将上面编译生成的u-boot.bin下载到开发板发现没有现象,然后我通过点灯调试发现问题出现了
common/board_f.c的函数数组static const init_fnc_t init_sequence_f[]里面的timer_init函数
于是继续跟踪到arch/arm/mach-s5pv2xx/clock.c的s5pc1xx_get_pwm_clk函数,发现这个函数是这样的
static unsigned long s5pc1xx_get_pwm_clk(void)
{
if (cpu_is_s5pc110())
return s5pc110_get_pclk();
else
return s5pc100_get_pclk();
}
很明显返回的是s5pc100_get_pclk(),所以有问题;类似的函数还有很多个修改的方法有两个。
方法1:把刚开始修改的arch/arm/mach-s5pv2xx/include/mach/cpu.h里面的s5p_set_cpu_id()
修改成u-boot原来的样子,然后再修改arch/arm/mach-s5pv2xx/include/mach/cpu.h的
#define SAMSUNG_BASE(device, base) \
static inline unsigned int samsung_get_base_##device(void) \
{ \
return S5PV210_##base;\
}
方法2:
修改arch/arm/mach-s5pv2xx/clock.c
改为:
/*
* Copyright (C) 2009 Samsung Electronics
* Minkyu Kang <mk7.kang@samsung.com>
* Heungjun Kim <riverful.kim@samsung.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
#include <asm/arch/clk.h>
#define CLK_M 0
#define CLK_D 1
#define CLK_P 2
#ifndef CONFIG_SYS_CLK_FREQ_C100
#define CONFIG_SYS_CLK_FREQ_C100 12000000
#endif
#ifndef CONFIG_SYS_CLK_FREQ_C110
#define CONFIG_SYS_CLK_FREQ_C110 24000000
#endif
/*add by xcl*/
#ifndef CONFIG_SYS_CLK_FREQ_V210
#define CONFIG_SYS_CLK_FREQ_V210 24000000
#endif
/* s5pc110: return pll clock frequency */
static unsigned long s5pc100_get_pll_clk(int pllreg)
{
struct s5pc100_clock *clk =
(struct s5pc100_clock *)samsung_get_base_clock();
unsigned long r, m, p, s, mask, fout;
unsigned int freq;
switch (pllreg) {
case APLL:
r = readl(&clk->apll_con);
break;
case MPLL:
r = readl(&clk->mpll_con);
break;
case EPLL:
r = readl(&clk->epll_con);
break;
case HPLL:
r = readl(&clk->hpll_con);
break;
default:
printf("Unsupported PLL (%d)\n", pllreg);
return 0;
}
/*
* APLL_CON: MIDV [25:16]
* MPLL_CON: MIDV [23:16]
* EPLL_CON: MIDV [23:16]
* HPLL_CON: MIDV [23:16]
*/
if (pllreg == APLL)
mask = 0x3ff;
else
mask = 0x0ff;
m = (r >> 16) & mask;
/* PDIV [13:8] */
p = (r >> 8) & 0x3f;
/* SDIV [2:0] */
s = r & 0x7;
/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
freq = CONFIG_SYS_CLK_FREQ_C100;
fout = m * (freq / (p * (1 << s)));
return fout;
}
/* s5pc100: return pll clock frequency */
static unsigned long s5pc110_get_pll_clk(int pllreg)
{
struct s5pc110_clock *clk =
(struct s5pc110_clock *)samsung_get_base_clock();
unsigned long r, m, p, s, mask, fout;
unsigned int freq;
switch (pllreg) {
case APLL:
r = readl(&clk->apll_con);
break;
case MPLL:
r = readl(&clk->mpll_con);
break;
case EPLL:
r = readl(&clk->epll_con);
break;
case VPLL:
r = readl(&clk->vpll_con);
break;
default:
printf("Unsupported PLL (%d)\n", pllreg);
return 0;
}
/*
* APLL_CON: MIDV [25:16]
* MPLL_CON: MIDV [25:16]
* EPLL_CON: MIDV [24:16]
* VPLL_CON: MIDV [24:16]
*/
if (pllreg == APLL || pllreg == MPLL)
mask = 0x3ff;
else
mask = 0x1ff;
m = (r >> 16) & mask;
/* PDIV [13:8] */
p = (r >> 8) & 0x3f;
/* SDIV [2:0] */
s = r & 0x7;
freq = CONFIG_SYS_CLK_FREQ_C110;
if (pllreg == APLL) {
if (s < 1)
s = 1;
/* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
fout = m * (freq / (p * (1 << (s - 1))));
} else
/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
fout = m * (freq / (p * (1 << s)));
return fout;
}
/* s5pc100: return pll clock frequency(add by xcl) */
static unsigned long s5pv210_get_pll_clk(int pllreg)
{
struct s5pv210_clock *clk =
(struct s5pv210_clock *)samsung_get_base_clock();
unsigned long r, m, p, s, mask, fout;
unsigned int freq;
switch (pllreg) {
case APLL:
r = readl(&clk->apll_con);
break;
case MPLL:
r = readl(&clk->mpll_con);
break;
case EPLL:
r = readl(&clk->epll_con);
break;
case VPLL:
r = readl(&clk->vpll_con);
break;
default:
printf("Unsupported PLL (%d)\n", pllreg);
return 0;
}
/*
* APLL_CON: MIDV [25:16]
* MPLL_CON: MIDV [25:16]
* EPLL_CON: MIDV [24:16]
* VPLL_CON: MIDV [24:16]
*/
if (pllreg == APLL || pllreg == MPLL)
mask = 0x3ff;
else
mask = 0x1ff;
m = (r >> 16) & mask;
/* PDIV [13:8] */
p = (r >> 8) & 0x3f;
/* SDIV [2:0] */
s = r & 0x7;
freq = CONFIG_SYS_CLK_FREQ_V210;
if (pllreg == APLL) {
if (s < 1)
s = 1;
/* FOUT = MDIV * FIN / (PDIV * 2^(SDIV - 1)) */
fout = m * (freq / (p * (1 << (s - 1))));
} else
/* FOUT = MDIV * FIN / (PDIV * 2^SDIV) */
fout = m * (freq / (p * (1 << s)));
return fout;
}
/* s5pc110: return ARM clock frequency */
static unsigned long s5pc110_get_arm_clk(void)
{
struct s5pc110_clock *clk =
(struct s5pc110_clock *)samsung_get_base_clock();
unsigned long div;
unsigned long dout_apll, armclk;
unsigned int apll_ratio;
div = readl(&clk->div0);
/* APLL_RATIO: [2:0] */
apll_ratio = div & 0x7;
dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
armclk = dout_apll;
return armclk;
}
/* s5pv210: return ARM clock frequency (add by xcl)*/
static unsigned long s5pv210_get_arm_clk(void)
{
struct s5pv210_clock *clk =
(struct s5pv210_clock *)samsung_get_base_clock();
unsigned long div;
unsigned long dout_apll, armclk;
unsigned int apll_ratio;
div = readl(&clk->div0);
/* APLL_RATIO: [2:0] */
apll_ratio = div & 0x7;
dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
armclk = dout_apll;
return armclk;
}
/* s5pc100: return ARM clock frequency */
static unsigned long s5pc100_get_arm_clk(void)
{
struct s5pc100_clock *clk =
(struct s5pc100_clock *)samsung_get_base_clock();
unsigned long div;
unsigned long dout_apll, armclk;
unsigned int apll_ratio, arm_ratio;
div = readl(&clk->div0);
/* ARM_RATIO: [6:4] */
arm_ratio = (div >> 4) & 0x7;
/* APLL_RATIO: [0] */
apll_ratio = div & 0x1;
dout_apll = get_pll_clk(APLL) / (apll_ratio + 1);
armclk = dout_apll / (arm_ratio + 1);
return armclk;
}
/* s5pc100: return HCLKD0 frequency */
static unsigned long get_hclk(void)
{
struct s5pc100_clock *clk =
(struct s5pc100_clock *)samsung_get_base_clock();
unsigned long hclkd0;
uint div, d0_bus_ratio;
div = readl(&clk->div0);
/* D0_BUS_RATIO: [10:8] */
d0_bus_ratio = (div >> 8) & 0x7;
hclkd0 = get_arm_clk() / (d0_bus_ratio + 1);
return hclkd0;
}
/* s5pc100: return PCLKD1 frequency */
static unsigned long get_pclkd1(void)
{
struct s5pc100_clock *clk =
(struct s5pc100_clock *)samsung_get_base_clock();
unsigned long d1_bus, pclkd1;
uint div, d1_bus_ratio, pclkd1_ratio;
div = readl(&clk->div0);
/* D1_BUS_RATIO: [14:12] */
d1_bus_ratio = (div >> 12) & 0x7;
/* PCLKD1_RATIO: [18:16] */
pclkd1_ratio = (div >> 16) & 0x7;
/* ASYNC Mode */
d1_bus = get_pll_clk(MPLL) / (d1_bus_ratio + 1);
pclkd1 = d1_bus / (pclkd1_ratio + 1);
return pclkd1;
}
/* s5pc110: return HCLKs frequency */
static unsigned long get_hclk_sys(int dom)
{
struct s5pc110_clock *clk =
(struct s5pc110_clock *)samsung_get_base_clock();
unsigned long hclk;
unsigned int div;
unsigned int offset;
unsigned int hclk_sys_ratio;
if (dom == CLK_M)
return get_hclk();
div = readl(&clk->div0);
/*
* HCLK_MSYS_RATIO: [10:8]
* HCLK_DSYS_RATIO: [19:16]
* HCLK_PSYS_RATIO: [27:24]
*/
offset = 8 + (dom << 0x3);
hclk_sys_ratio = (div >> offset) & 0xf;
hclk = get_pll_clk(MPLL) / (hclk_sys_ratio + 1);
return hclk;
}
/* s5pc110: return PCLKs frequency */
static unsigned long get_pclk_sys(int dom)
{
struct s5pc110_clock *clk =
(struct s5pc110_clock *)samsung_get_base_clock();
unsigned long pclk;
unsigned int div;
unsigned int offset;
unsigned int pclk_sys_ratio;
div = readl(&clk->div0);
/*
* PCLK_MSYS_RATIO: [14:12]
* PCLK_DSYS_RATIO: [22:20]
* PCLK_PSYS_RATIO: [30:28]
*/
offset = 12 + (dom << 0x3);
pclk_sys_ratio = (div >> offset) & 0x7;
pclk = get_hclk_sys(dom) / (pclk_sys_ratio + 1);
return pclk;
}
/* s5pc110: return peripheral clock frequency */
static unsigned long s5pc110_get_pclk(void)
{
return get_pclk_sys(CLK_P);
}
/* s5pc110: return peripheral clock frequency */
static unsigned long s5pv210_get_pclk(void)
{
return get_pclk_sys(CLK_P);
}
/* s5pc100: return peripheral clock frequency */
static unsigned long s5pc100_get_pclk(void)
{
return get_pclkd1();
}
/* s5pc1xx: return uart clock frequency (modified by xcl)*/
static unsigned long s5pc1xx_get_uart_clk(int dev_index)
{
if (cpu_is_s5pc110())
return s5pc110_get_pclk();
else if (cpu_is_s5pv210())
return s5pv210_get_pclk();
else
return s5pc100_get_pclk();
}
/* s5pc1xx: return pwm clock frequency (modified by xcl) */
static unsigned long s5pc1xx_get_pwm_clk(void)
{
if (cpu_is_s5pc110())
return s5pc110_get_pclk();
else if(cpu_is_s5pv210())
return s5pv210_get_pclk();
else
return s5pc100_get_pclk();
}
/* (modified by xcl) */
unsigned long get_pll_clk(int pllreg)
{
if (cpu_is_s5pc110())
return s5pc110_get_pll_clk(pllreg);
else if(cpu_is_s5pv210())
return s5pv210_get_pll_clk(pllreg);
else
return s5pc100_get_pll_clk(pllreg);
}
/* (modified by xcl) */
unsigned long get_arm_clk(void)
{
if (cpu_is_s5pc110())
return s5pc110_get_arm_clk();
else if(cpu_is_s5pv210())
return s5pv210_get_arm_clk();
else
return s5pc100_get_arm_clk();
}
unsigned long get_pwm_clk(void)
{
return s5pc1xx_get_pwm_clk();
}
unsigned long get_uart_clk(int dev_index)
{
return s5pc1xx_get_uart_clk(dev_index);
}
void set_mmc_clk(int dev_index, unsigned int div)
{
/* Do NOTHING */
}
在arch/arm/mach-s5pv2xx/clock.h添加
struct s5pv210_clock {
unsigned int apll_lock;
unsigned char res1[0x4];
unsigned int mpll_lock;
unsigned char res2[0x4];
unsigned int epll_lock;
unsigned char res3[0xc];
unsigned int vpll_lock;
unsigned char res4[0xdc];
unsigned int apll_con;
unsigned char res5[0x4];
unsigned int mpll_con;
unsigned char res6[0x4];
unsigned int epll_con;
unsigned char res7[0xc];
unsigned int vpll_con;
unsigned char res8[0xdc];
unsigned int src0;
unsigned int src1;
unsigned int src2;
unsigned int src3;
unsigned char res9[0xf0];
unsigned int div0;
unsigned int div1;
unsigned int div2;
unsigned int div3;
unsigned int div4;
unsigned char res10[0x1ec];
unsigned int gate_d00;
unsigned int gate_d01;
unsigned int gate_d02;
unsigned char res11[0x54];
unsigned int gate_sclk0;
unsigned int gate_sclk1;
};
这样修改后在timer_init函数就没有错误了。
接着在common/board_f.c的函数数组static const init_fnc_t init_sequence_f[]
里面的env_init函数出错,一直跟踪到env/env.c里面的env_get_default_location
函数出错,这个函数看上去像是u-boot环境变量出发介质的选择。然后我就去配置看
看能不能解决这个问题直接make menuconfig然后依次选择下去environment->select the location of the environment->
environment is not stord,保存编译,
然后用tftp下载到内存:tftp 20000000 u-boot.bin
去执行:go 20000000
哇!!!!!!!!打印出信息了
说明:我这儿用tftp下载bin文件,大家可能感觉奇怪,怎么移植uboot就有tftp下载了呢?
其实我这儿只是学习,所以我现在在移植uboot的时候开发板是从SD卡启动的,SD卡里面下载了开发板
厂家提供的移植好了的uboot,我用这个u-boot就能直接下载裸机程序到内存去运行,感觉比用dnw方便
快捷一些。值得注意的一点是现在现在进去的u-boot.bin是没有进行内存初始化的,如果通过这种方式
下载的裸机程序是不能进行内存初始化,不然会挂掉,所以我是将内存初始化放在SPL代码里面去进行的。