Linux驱动基础:device tree

    xiaoxiao2021-03-26  91

    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节点里的内容

    转载请注明原文地址: https://ju.6miu.com/read-662272.html

    最新回复(0)