代码平台Android7.1.2  硬件RK3288  ROC-RK3288-CCAndroid7.1.2/ROC-RK3328-CC_Android7.1.2_git_20171204/kernel/arch/arm64/mach-rockchipdts文件为板级设备描述文件,被编译后为dtb,由bootloader读入,并作为参数传递给linux kernel,入口地址为__fdt_pointer,定义在汇编文件head.S (arch\arm64\kernel)中/ /        arch/arm64/kernel/head.S__switch_data:    .quad    __mmap_switched    .quad    __bss_start            // x6    .quad    __bss_stop            // x7    .quad    processor_id            // x4    .quad    __fdt_pointer            // x5    .quad    memstart_addr            // x6    .quad    init_thread_union + THREAD_START_SP // spENTRY(stext)    mov    x21, x0                // x21=FDT   //FDT代表设备树    bl    el2_setup            // Drop to EL1, w20=cpu_boot_mode    bl    __calc_phys_offset        // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET    bl    set_cpu_boot_mode_flag    mrs    x22, midr_el1            // x22=cpuid    mov    x0, x22    bl    lookup_processor_type    mov    x23, x0                // x23=current cpu_table    cbz    x23, __error_p            // invalid processor (x23=0)?    bl    __vet_fdt                   // 检查device tree的合法性    bl    __create_page_tables        // x25=TTBR0, x26=TTBR1    /*     * The following calls CPU specific code in a position independent     * manner. See arch/arm64/mm/proc.S for details. x23 = base of     * cpu_info structure selected by lookup_processor_type above.     * On return, the CPU will be ready for the MMU to be turned on and     * the TCR will have been set.     */    ldr    x27, __switch_data        // address to jump to after                        // MMU has been enabled    adr    lr, __enable_mmu        // return (PIC) address    ldr    x12, [x23, #CPU_INFO_SETUP]    add    x12, x12, x28            // __virt_to_phys    br    x12                // initialise processorENDPROC(stext)/ /        arch/arm64/kernel/head.S * Determine validity of the x21 FDT pointer. * The dtb must be 8-byte aligned and live in the first 512M of memory. */__vet_fdt:   // 检查device tree的合法性    tst    x21, #0x7  // 是否字节对齐    b.ne    1f            // 不对齐直接跳转到标号1处,将x21清0,并返回    cmp    x21, x24   // x21保存的是device tree的物理地址,x24保存的是kernel起始的物理内存地址    b.lt    1f               // 当device tree的物理地址小于kernel起始的物理地址时,直接跳转到标号1处,将x21清0,并返回    mov    x0, #(1    add    x0, x0, x24         // 判断device tree的物理地址是否在kernel起始的512M内存空间内部    cmp    x21, x0    b.ge    1f    ret1:    mov    x21, #0    retENDPROC(__vet_fdt)/ /        arch/arm64/kernel/head.S/* * Setup the initial page tables. We only setup the barest amount which is * required to get the kernel running. The following sections are required: *   - identity mapping to enable the MMU (low address, TTBR0) *   - first few MB of the kernel linear mapping to jump to once the MMU has *     been enabled, including the FDT blob (TTBR1) *   - pgd entry for fixed mappings (TTBR1) */__create_page_tables:    pgtbl    x25, x26, x28            // idmap_pg_dir and swapper_pg_dir addresses    mov    x27, lr    /*     * Invalidate the idmap and swapper page tables to avoid potential     * dirty cache lines being evicted.     */    mov    x0, x25    add    x1, x26, #SWAPPER_DIR_SIZE    bl    __inval_cache_range    /*     * Clear the idmap and swapper page tables.     */    mov    x0, x25    add    x6, x26, #SWAPPER_DIR_SIZE1:    stp    xzr, xzr, [x0], #16    stp    xzr, xzr, [x0], #16    stp    xzr, xzr, [x0], #16    stp    xzr, xzr, [x0], #16    cmp    x0, x6    b.lo    1b    ldr    x7, =MM_MMUFLAGS    /*     * Create the identity mapping.     */    add    x0, x25, #PAGE_SIZE        // section table address    ldr    x3, =KERNEL_START    add    x3, x3, x28            // __pa(KERNEL_START)    create_pgd_entry x25, x0, x3, x5, x6    ldr    x6, =KERNEL_END    mov    x5, x3                // __pa(KERNEL_START)    add    x6, x6, x28            // __pa(KERNEL_END)    create_block_map x0, x7, x3, x5, x6    /*     * Map the kernel image (starting with PHYS_OFFSET).     */    add    x0, x26, #PAGE_SIZE        // section table address    mov    x5, #PAGE_OFFSET    create_pgd_entry x26, x0, x5, x3, x6    ldr    x6, =KERNEL_END    mov    x3, x24                // phys offset    create_block_map x0, x7, x3, x5, x6    /*     * Map the FDT blob (maximum 2MB; must be within 512MB of     * PHYS_OFFSET).     */    mov    x3, x21                // FDT phys address      // x21保存的是device tree的物理地址    and    x3, x3, #~((1    mov    x6, #PAGE_OFFSET                 // PAGE_OFFSET等于0xffffffc000000000   PAGE_OFFSET是Linux内核空间的虚拟起始地址    sub    x5, x3, x24            // subtract PHYS_OFFSET  // x5等于device tree相对于kernel起始的物理内存地址的偏移                                                //// x24 = PHYS_OFFSET  PHYS_OFFSET是物理内存的起始地址    tst    x5, #~((1    csel    x21, xzr, x21, ne        // zero the FDT pointer    // 如果x5大于512MB,则将x21清0    b.ne    1f                                 // 如果x5大于512MB,跳转到标号1处    add    x5, x5, x6            // __va(FDT blob) // x5等于device tree的虚拟内存地址    add    x6, x5, #1    sub    x6, x6, #1            // inclusive range    create_block_map x0, x7, x3, x5, x6                                          // 创建pud页表,x0是pud的基地址,x7是flag,x3是需要创建pud页表的内存地址 // 2MB block1:    /*     * Since the page tables have been populated with non-cacheable     * accesses (MMU disabled), invalidate the idmap and swapper page     * tables again to remove any speculatively loaded cache lines.     */    mov    x0, x25    add    x1, x26, #SWAPPER_DIR_SIZE    bl    __inval_cache_range   // 再次将idmap和swapper对应的cacheline设为无效    mov    lr, x27   // 恢复lr    ret         //返回ENDPROC(__create_page_tables)//////////////////////////////////////////////////////////////////////////////////arch/arm64/kernel/setup.cphys_addr_t  __fdt_pointer  __initdata;void __init setup_arch(char **cmdline_p){    setup_processor();    setup_machine_fdt(__fdt_pointer);    unflatten_device_tree();}static void __init setup_machine_fdt(phys_addr_t dt_phys){    struct boot_param_header *devtree;    unsigned long dt_root;    cpuinfo_store_cpu();    /* Check we have a non-NULL DT pointer */    if (!dt_phys) {        early_print("\n"            "Error: NULL or invalid device tree blob\n"            "The dtb must be 8-byte aligned and passed in the first 512MB of memory\n"            "\nPlease check your bootloader.\n");        while (true)            cpu_relax();    }    devtree = phys_to_virt(dt_phys);    /* Check device tree validity */    if (be32_to_cpu(devtree->magic) != OF_DT_HEADER) {        early_print("\n"            "Error: invalid device tree blob at physical address 0x%p (virtual address 0x%p)\n"            "Expected 0x%x, found 0x%x\n"            "\nPlease check your bootloader.\n",            dt_phys, devtree, OF_DT_HEADER,            be32_to_cpu(devtree->magic));        while (true)            cpu_relax();    }    initial_boot_params = devtree;    dt_root = of_get_flat_dt_root();    machine_name = of_get_flat_dt_prop(dt_root, "model", NULL);    if (!machine_name)        machine_name = of_get_flat_dt_prop(dt_root, "compatible", NULL);    if (!machine_name)        machine_name = "";    pr_info("Machine: %s\n", machine_name);    /* Retrieve various information from the /chosen node */    of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);    /* Initialize {size,address}-cells info */    // 解析   #address-cells = ;        #size-cells = ;这样的信息    of_scan_flat_dt(early_init_dt_scan_root, NULL);    /* Setup memory, calling early_init_dt_add_memory_arch */    of_scan_flat_dt(early_init_dt_scan_memory, NULL);}////////////////////////////////////////////////////////////////////////////////////Android7.1.2/ROC-RK3328-CC_Android7.1.2_git_20171204/kernel/arch/arm64/mach-rockchip/rk322xh.carch_initcall(rk322xh_dt_init);static __init int rk322xh_dt_init(void){    struct device_node *node, *gp, *cp;    int avs_delta = -5;    node = of_find_compatible_node(NULL, NULL, "rockchip,rk322xh-grf");    if (node) {        grf = of_iomap(node, 0);        if (!grf) {            pr_err("%s: could not map grf registers\n", __func__);            return -ENXIO;        }    } else {        pr_err("%s: could not find grf dt node\n", __func__);        return -ENODEV;    }    rockchip_pmu_ops.set_idle_request = rk322xh_set_idle_request;    node = of_find_compatible_node(NULL, NULL, "rockchip,avs");    if (node)        of_property_read_u32(node, "avs-delta", &avs_delta);    rockchip_avs_delta = avs_delta;    node = of_find_compatible_node(NULL, NULL, "rockchip,cpu_axi_bus");    if (!node)        return -ENODEV;#define MAP(name)                            \    do {                                \        cp = of_get_child_by_name(gp, #name);            \        if (cp)                            \            name##_qos_base = of_iomap(cp, 0);        \        if (!name##_qos_base)                    \            pr_err("%s: could not map qos %s register\n",    \                   __func__, #name);            \    } while (0)    gp = of_get_child_by_name(node, "qos");    if (gp) {        MAP(cpu);        MAP(gpu0);        MAP(gpu1);        MAP(emmc);        MAP(gmac2io);        MAP(sdio);        MAP(sdmmc);        MAP(usbhost0);        MAP(usb3otg);        MAP(usbotg);        MAP(gmac2phy);        MAP(sdmmc_ext);        MAP(dma);        MAP(crypto);        MAP(tsp);        MAP(rkvdec_r);        MAP(rkvdec_w);        MAP(hdcp);        MAP(vop);        MAP(iep);        MAP(vip);        MAP(rga_r);        MAP(rga_w);        MAP(h265);        MAP(h264);        MAP(vpu);    }#undef MAP    return 0;}/////////////////////////设备树在 RK3288/Android7.1.2/ROC-RK3328-CC_Android7.1.2_git_20171204/kernel/arch/arm64/boot/dts/rk3328-roc-cc.dts/// kernel/drivers/of/fdt.c/** * early_init_dt_scan_root - fetch the top level address and size cells */int __init early_init_dt_scan_root(unsigned long node, const char *uname,                   int depth, void *data){    const __be32 *prop;    if (depth != 0)        return 0;    dt_root_size_cells = OF_ROOT_NODE_SIZE_CELLS_DEFAULT;    dt_root_addr_cells = OF_ROOT_NODE_ADDR_CELLS_DEFAULT;    prop = of_get_flat_dt_prop(node, "#size-cells", NULL);    if (prop)        dt_root_size_cells = be32_to_cpup(prop);    pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);    prop = of_get_flat_dt_prop(node, "#address-cells", NULL);    if (prop)        dt_root_addr_cells = be32_to_cpup(prop);    pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);    /* break now */    return 1;}///////////////////
10-15 11:32
查看更多