Device Tree --- Linux Kernel 实现欣赏

有一个无法忽视的事实,基础研发的突破,让这一切成为可能 ,
                                               -------Qualcomm

Device Tree 的目标

这里写图片描述

好,看启动的时候 Linux是如何知道系统的内存大小

这里写图片描述
这里写图片描述

/*
    该函数做了一下事情
             1 : 获取内存 base 和 size
             2 : 将内存信息添加到memblock子系统

    @node:
           1484,  Why ?
           下面会说 
           1 : 这个 node 为什么要定义为 unsigned long 类型
           2 : linuxer在 Code Review 的时候为什么会接受这样的机制
    @uname:
           1 : memory@六0000000

            下面会对该字符串进行校验, 它就是靠名字来决定是否进行下面的工作,
            利用字符串匹配   platform bus 做的很好,

            类似的是 CAN bus 滤波是通过ID匹配来完成的  

            作者说了 we are scanning memory node only,

            其他node这里不是你的坑,return, 走人

            看,每一个 node 就是这样展开的,Linux Kernel这块做的并不是智能,

            Linux Kernel是时候该引入 Artificial intelligence 了 !

    @depth:
    @data:

    好,那么该函数是怎么被调用的呢 ?

    扫描整颗树吧,回调吧,
    有类比的是 sock维护的钩子函数 实现的很优美,主要用于处理消息,后面会单独欣赏

    int __init of_scan_flat_dt()
    {
        .....
        FOR + IF 做决策,   也不看看这是在什么时机,

        心里的“如果”少了,IF也少了

        MSM8937平台 MSM_CCI_IRQ() 该ISR 简直是 IF依赖症了  哈哈.
        它主要是对寄存器的各个位进行判断,

        Register 它底层是通过 D触发器 来实现的 ! 后面单独欣赏D触发器的实现

        上面 code 啰嗦了一大把,严重影响了启动的时间,
        这里回调吧
        rc = it(offset, pathp, depth, data);
    }

    好,下面看一下是谁调用了of_scan_flat_dt.
    见下面的图A
*/ 

int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data)
{
    /*
        读出属性"device_type"的属性值, 
        上面说了这个字符串是 "memory@60000000"
    */
    const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
    const __be32 *reg, *endp;
    int l;

    if (type == NULL) {
        if (!IS_ENABLED(CONFIG_PPC32) || depth != 1 || strcmp(uname, "memory@0") != 0)
            return 0;
    } else if (strcmp(type, "memory") != 0)
        return 0;

    reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
    if (reg == NULL)
        reg = of_get_flat_dt_prop(node, "reg", &l);
    if (reg == NULL)
        return 0;

    endp = reg + (l / sizeof(__be32));

    pr_debug("memory scan node %s, reg size %d, data: %x %x %x %x,\n", uname, l, reg[0], reg[1], reg[2], reg[3]);

    while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
        u64 base, size;
        base = dt_mem_next_cell(dt_root_addr_cells, &reg);
        size = dt_mem_next_cell(dt_root_size_cells, &reg);

        if (size == 0)
            continue;

        pr_debug(" - %llx ,  %llx\n", (unsigned long long)base, (unsigned long long)size);

        early_init_dt_add_memory_arch(base, size);
    }

    return 0;
}

图 A
这里写图片描述

uboot选择性的传递dtb地址给kernel

猜你喜欢

转载自blog.csdn.net/leesagacious/article/details/79266153