我是靠谱客的博主 俏皮蜜粉,最近开发中收集的这篇文章主要介绍s3c2440 linux系统移植(五)使用device tree,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

linux3.10 默认不打开device tree,但现在linux驱动的开发基本都使用device tree来描述device,所以这边也学习下device tree的使用。3.10内核里面没有找到s3c24xx 系列的dts,从高版本的内核中可以找到相关的dts,这边下载了4.19.5的内核,发现里面有s3c24xx 的dts文件,把相关dts,dtsi,以及头文件都拷贝过来,(s3c24xx.dtsi,s3c2416.dtsi,s3c2416-pinctrl.dtsi,s3c2416-smdk2416.dts,s3c2443.h,samsung.h)放到arch/arm/boot/dts/ 目录下面,重命名s3c2416-smdk2416.dts 为smdk2440.dts,并且修改该目录下的makefile:

加入smdk2440.dtb。

然后修改smdk2440.dts的compatible id:

model = "SMDK2440";
compatible = "samsung,SMDK2440";

同时可以把dts中关于uart3的配置给去掉,2440只有3个串口

配置kernel device support:

在这边uboot 把dts的地址放在0x33ffb000 上面,并使用r2 寄存器传给linux,这边强制在arch/arm/kernel/head.S中把这个地址写死:

#ifdef CONFIG_ARM_VIRT_EXT
	bl	__hyp_stub_install
#endif
	@ ensure svc mode and all interrupts masked
	safe_svcmode_maskall r9

	mrc	p15, 0, r9, c0, c0		@ get processor id
	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
	#ldr r2,=0x30000100
	ldr r2,=0x33ffb000
	ldr r1,=0x16a
	movs	r10, r5	

在uboot代码中,arch/arm/lib/bootm.c 中可以看到:

static void boot_jump_linux(bootm_headers_t *images, int flag)
{

	unsigned long machid = gd->bd->bi_arch_number;
	char *s;
	void (*kernel_entry)(int zero, int arch, uint params);
	unsigned long r2;
	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);

	kernel_entry = (void (*)(int, int, uint))images->ep;

	s = getenv("machid");
	if (s) {
		if (strict_strtoul(s, 16, &machid) < 0) {
			debug("strict_strtoul failed!n");
			return;
		}
		printf("Using machid 0x%lx from environmentn", machid);
	}
	
	debug("## Transferring control to Linux (at address %08lx)" 
		"...n", (ulong) kernel_entry);
	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
	announce_and_cleanup(fake);

	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
		r2 = (unsigned long)images->ft_addr;
	else
		r2 = gd->bd->bi_boot_params;
	printf("r2 =%lxn",r2);
	if (!fake) {
#ifdef CONFIG_ARMV7_NONSEC
		if (armv7_boot_nonsec()) {
			armv7_init_nonsec();
			secure_ram_addr(_do_nonsec_entry)(kernel_entry,
							  0, machid, r2);
		} else
#endif
	debug("machid =%x n",machid);
			kernel_entry(0, machid, r2);
	}

}

定义了 IMAGE_ENABLE_OF_LIBFDT ,就会把dts的地址传给r2,否则就把boot args传给r2,这边未知bug导致在启动kernel的时候r2的值丢失,所以写死。

在启动kernel的时候:

start_kernel
    ------>setup_arch
        -------->setup_machine_fdt
            -------->for_each_machine_desc(mdesc) {
		
		    score = of_flat_dt_match(dt_root, mdesc->dt_compat);
		    if (score > 0 && score < mdesc_score) {
			    mdesc_best = mdesc;
			    mdesc_score = score;
		    }

会寻找 定义的machine的mdesc->dt_compat,dt_compat中包含的是machine的compatible,在dts中已经定义的compatible为samsung,SMDK2440,所以要在kernel中加入这个compatible,找到arch/arm/mach-s3c24xx/mach-smdk2440.c

做如下修改:

/*MACHINE_START(S3C2440, "SMDK2440")

	.atag_offset	= 0x100,

	.init_irq	= s3c2440_init_irq,
	.map_io		= smdk2440_map_io,
	.init_machine	= smdk2440_machine_init,
	.init_time	= samsung_timer_init,
	.restart	= s3c244x_restart,
MACHINE_END*/
static const char *const s3c2440_dt_compat[] __initconst = {
    "samsung,SMDK2440",
    NULL
};
DT_MACHINE_START(S3C2440, "SMDK2440")

	.atag_offset	= 0x100,
	.dt_compat    = s3c2440_dt_compat,
	.init_irq	= s3c2440_init_irq,
	.map_io		= smdk2440_map_io,
	.init_machine	= smdk2440_machine_init,
	.init_time	= samsung_timer_init,
	.restart	= s3c244x_restart,
MACHINE_END

然后make,编译kernel ,生成smdk2440.dtb文件和uImage文件。

接下来配置uboot,把device tree相关的配置给选上:

修改arch/arm/lib/bootm.c文件:

void arch_lmb_reserve(struct lmb *lmb)
{
	ulong sp;

	/*
	 * Booting a (Linux) kernel image
	 *
	 * Allocate space for command line and board info - the
	 * address should be as high as possible within the reach of
	 * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
	 * memory, which means far enough below the current stack
	 * pointer.
	 */
	sp = get_sp();
	debug("## Current stack ends at 0x%08lx ", sp);

	/* adjust sp by 4K to be safe */
	sp -= 4096;
	//lmb_reserve(lmb, sp,
	//	    gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size - sp);
	lmb_reserve(lmb, sp,
		    0x10000);
}

这边这个函数会检测堆栈的位置,防止在reload dts的时候覆盖到这边地址,可能是gd->bd->bi_dram[0].start + gd->bd->bi_dram[0].size这个值前面没初始化好,导致size太大了,怎么算都会overlay,reload 失败,所以强制写大小为0x10000,至要这个值安全就好,实际会reload 到ram的最高地址,我这边reload 地址为0x33ffb000,然后重新编译uboot,然后烧写uboot,并如下命令加载kernel 和dtb

tftp uImage 0x31000000

tftp smdk2440.dtb 0x32000000

bootm 0x31000000 - 0x32000000

uboot 会把第一个参数当做kernel 地址,第二个参数当做dtb,最终系统启动成功,相比之前几章花的时间,移植dts竟然出乎意料的顺利,后面就要开始驱动的移植了,继续加油。

最后

以上就是俏皮蜜粉为你收集整理的s3c2440 linux系统移植(五)使用device tree的全部内容,希望文章能够帮你解决s3c2440 linux系统移植(五)使用device tree所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部