Device Tree --- Linux Kernel Implementation Appreciation

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

Device Tree goals

write picture description here

Well, let's see how Linux knows the memory size of the system when it starts up

write picture description here
write picture description here

/*
    该函数做了一下事情
             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;
}

Figure A
write picture description here

uboot optionally passes the dtb address to the kernel

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325962117&siteId=291194637