Linux驱动基础:device tree

Bootloader设置

msm平台为例,在bootloader代码中会根据当前ddr开始的地址,按照一定的offset定义了kernel开始的地址,ramdisk开始地址以及TAG开始的地址。其中kernel代码开始的地址和ramdisk的地址自不必说,这两个不对的话再加载完kernel代码之后跳到kernel代码都会有问题,或者ramdisk的mount都会有问题。Device Tree也一样,这里定义的ABOOT_FORCE_TAGS_ADDR偏移量也要和打包boot.img的时候,dt.img的偏移量保持一致,不然也是找不到dt.img进行device tree内容的初始化的。

//bootloader里边定义了如下内容
#define DDR_START                   get_ddr_start()
#define ABOOT_FORCE_KERNEL_ADDR     DDR_START + 0x8000
#define ABOOT_FORCE_KERNEL64_ADDR   DDR_START + 0x80000
#define ABOOT_FORCE_RAMDISK_ADDR    DDR_START + 0x2000000
#define ABOOT_FORCE_TAGS_ADDR       DDR_START + 0x1E00000

device tree相关的ABOOT_FORCE_TAGS_ADDR,在DDR_START地址为0x80000000的时候加上ABOOT_FORCE_TAGS_ADDR的值为0x81E00000。这个值kernel会保存在__atags_pointer变量中,用来在内核寻找device tree相关的内容。

setup_arch()->setup_machine_fdt(__atags_pointer);

在boot.img编译的时候正确指定devicetree的偏移量,才能在内核运行阶段找到相应的device tree,并初始化device tree的节点等。当然偏移量和上面的__atags_pointer一样。
下面来看一下在boot.img打包的命令,这里可以看到BOARD_KERNEL_TAGS_OFFSET这个值和上面bootloader里边定义的偏移量是一致的。

$MKBOOTIMGTOOL --kernel $KERNEL_ZIMG \ 
--ramdisk $PRODUCT_OUT/ramdisk.img \
--output $PRODUCT_OUT/boot.img \
--cmdline "$BOARD_KERNEL_CMDLINE" \
--base $BOARD_KERNEL_BASE \
--pagesize $BOARD_KERNEL_PAGESIZE \
--ramdisk_offset $BOARD_RAMDISK_OFFSET \
--tags_offset $BOARD_KERNEL_TAGS_OFFSET \
--dt $INSTALLED_DTIMAGE_TARGET"

KERNEL_ZIMG=$BUILD_KERNEL_OUT_DIR/arch/arm/boot/zImage
BOARD_KERNEL_BASE=0x80000000
BOARD_KERNEL_PAGESIZE=2048 
BOARD_KERNEL_TAGS_OFFSET=0x01E00000
BOARD_RAMDISK_OFFSET=0x02000000
BOARD_KERNEL_CMDLINE="console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3 androidboot.bootdevice=7824900.sdhci"

#BOARD_KERNEL_CMDLINE="console=ttyHSL0,115200,n8 androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x37 ehci-hcd.park=3"

#BOARD_KERNEL_CMDLINE="console=ttyHSL0,115200,n8 androidboot.hardware=qcom androidboot.bootdevice=soc.0/7824900.sdhci user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3 video=vfb:640x400,bpp=32,memsize=3072000 earlyprintk"
INSTALLED_DTIMAGE_TARGET=${PRODUCT_OUT}/dt.img
DTBTOOL=$BUILD_KERNEL_DIR/tools/dtbTool

ABOOT_FORCE_KERNEL_ADDR开始的地址偏移量是0x8000,就是说kernel code开始的地址,
也就是和_text的值一样是0x8000。
0x8000以下放了一些东西,比如偏移0x4000的地方放了swapper_pg_dir(page table)。
ABOOT_FORCE_TAGS_ADDR这个地址通过__atags_pointer这个值被传到kernel,来进行device tree的读取并初始化platform_device等操作。
也就是说__atags_pointer等于ABOOT_FORCE_TAGS_ADDR的值,也等于BOARD_KERNEL_TAGS_OFFSET这个值。还有__atags_pointer这个值在内核dump文件里边是找不到的,因为这个值定义成了
unsigned int __atags_pointer __initdata; //这里带了__initdata!!,后面会被释放掉
初始化用完之后都被释放掉了。

内核中的初始化

device tree的初始化开始的函数是:

setup_machine_fdt(__atags_pointer) =>
const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
{}

dts文件中定义的名字和board-xx.c文件中定义的DT_MACHINE_START名字需要对应。
这里写图片描述

这里写图片描述

Device Tree的优点

使能了device tree(menuconfig → boot options → flattened device tree)之后,可以不用添加很多board-xxx.c文件去定义platform device。device tree会在machine_init()的时候初始化所有的platform device。
Platform device相关的device tree:
- of_platform_populate()会根据在&soc{}里边定义的所有内容去初始化所有的platform device
- 在每个node里边必须包含compatible项,这样才能在platform driver初始化的时候找到相应的platform device。
- For creating platform devices for sub-nodes, provide a list
of all root nodes (second parameter)????

Platform驱动里的用法

需要添加device tree的内容以定义platform device,然后在platform driver里边读出来的步骤如下:
1. 添加一个node到device tree文件中
这里写图片描述
2. 在platform驱动文件中添加如下内容,让驱动可以找到上面定义的platform device的内容
这里写图片描述
3. 使用of_property_read_u32()等接口读取device tree节点里的内容
这里写图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值