v3s传memory
一、uboot是如何确定dram的大小的:
函数调用为:
dram_sunxi_dw.c
sunxi_dram_init 》
mctl_auto_detect_dram_size 》
mctl_auto_detect_dram_size_rank 》
mctl_mem_matches_base 》
static bool mctl_mem_matches_base(u32 offset, ulong base)
{
/* Try to write different values to RAM at two addresses */
writel(0, base);
writel(0xaa55aa55, base + offset);
dsb();
/* Check if the same value is actually observed when reading back */
return readl(base) ==
readl(base + offset);
}
意思是,我在基地址写0,与内存未端写一个数。如果未端超出真实内存,就为0,两都相比就反回1。如果连基地址都不为0,在距离基地址很近的地址的地方,就会出现相等,表示内存出错。
需要返回不相等,来证明该距离在内存范围内。
上一个函数,也就是mctl_auto_detect_dram_size_rank()必然用到了该函数mctl_mem_matches_base()循环检测:
for( i++){
if mctl_mem_matches_base(base+i){
break
}
}
size=i
二、修改设备树
int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
{
。。。省略。。。
/* find or create "/memory" node. */
nodeoffset = fdt_find_or_add_subnode(blob, 0, "memory");
if (nodeoffset < 0)
return nodeoffset;
err = fdt_setprop(blob, nodeoffset, "device_type", "memory",
sizeof("memory"));
if (err < 0) {
printf("WARNING: could not set %s %s.\n", "device_type",
fdt_strerror(err));
return err;
}
for (i = 0; i < banks; i++) {
if (start[i] == 0 && size[i] == 0)
break;
}
banks = i;
if (!banks)
return 0;
len = fdt_pack_reg(blob, tmp, start, size, banks);
err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
if (err < 0) {
printf("WARNING: could not set %s %s.\n",
"reg", fdt_strerror(err));
return err;
}
}
所以是将内存信息,通过修改dtb传递给了kernel。