Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1152670
  • 博文数量: 241
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 2279
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-27 19:53
个人简介

JustForFun

文章分类

全部博文(241)

文章存档

2023年(8)

2022年(2)

2021年(3)

2020年(30)

2019年(11)

2018年(27)

2017年(54)

2016年(83)

2015年(23)

我的朋友

分类: LINUX

2020-10-05 23:36:30

代码平台Android7.1.2  硬件RK3288  ROC-RK3288-CC
Android7.1.2/ROC-RK3328-CC_Android7.1.2_git_20171204/kernel/arch/arm64/mach-rockchip

dts文件为板级设备描述文件,被编译后为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 // sp



ENTRY(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 processor
ENDPROC(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 << 29)   // x0 = 0x40000000 = 512M
    add    x0, x0, x24         // 判断device tree的物理地址是否在kernel起始的512M内存空间内部
    cmp    x21, x0
    b.ge    1f
    ret
1:
    mov    x21, #0
    ret
ENDPROC(__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_SIZE
1:    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 << 21) - 1)    // 2MB aligned  // x3= x3 & 0xffffffffffe00000 // 2MB对齐
    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 << 29) - 1)        // within 512MB? // 是否小于512MB
    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 << 21        // 2MB for the FDT blob
    sub    x6, x6, #1            // inclusive range
    create_block_map x0, x7, x3, x5, x6      
                                    // 创建pud页表,x0是pud的基地址,x7是flag,x3是需要创建pud页表的内存地址 // 2MB block
1:
    /*
     * 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.c

phys_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 = <2>;        #size-cells = <2>;这样的信息

    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.c

arch_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;
}




///////////////////

阅读(1625) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~