目錄
-
-
- 1、DDR的注冊
-
- (1)、在dts中定義了DDR(memory)的範圍
- (2)、将DDR位址範圍注冊到linux kernel
- 2、reserved-memory的注冊
-
- (1)、在dts中定義了reserved-memory的範圍
- (2)、将reserved memory資訊告知給linux kernel
-
★★★ 友情連結 : 個人部落格導讀首頁—點選此處 ★★★
1、DDR的注冊
(1)、在dts中定義了DDR(memory)的範圍
[email protected] {
device_type = "memory";
reg = <0x0 0x80000000 0x2 0x0>;
};
(2)、将DDR位址範圍注冊到linux kernel
early_init_dt_scan_memory()
early_init_dt_scan_memory() —> early_init_dt_add_memory_arch(base, size) —> memblock_add(base, size)—>memblock_add_region(base, size, MAX_NUMNODES, 0)
(driver/of/fdt.c)
/**
* early_init_dt_scan_memory - Look for an parse memory nodes
*/
int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
int depth, void *data)
{
const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
const __be32 *reg, *endp;
int l;
/* We are scanning "memory" nodes only */
if (type == NULL) {
/*
* The longtrail doesn't have a device_type on the
* /memory node, so look for the node called /[email protected].
*/
if (!IS_ENABLED(CONFIG_PPC32) || depth != 1 || strcmp(uname, "[email protected]") != 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,\n", uname, l);
while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
u64 base, size;
base = dt_mem_next_cell(dt_root_addr_cells, ®);
size = dt_mem_next_cell(dt_root_size_cells, ®);
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;
}
MAX_NUMNODES表示有幾塊DDR區域(注意是幾塊DDR區域,并不是幾塊DDR),大小為1(1<<0)或和CONFIG_NODES_SHIFT值相關
#define MAX_NUMNODES (1 << NODES_SHIFT)
#ifdef CONFIG_NODES_SHIFT
#define NODES_SHIFT CONFIG_NODES_SHIFT
#else
#define NODES_SHIFT 0
#endif
2、reserved-memory的注冊
(1)、在dts中定義了reserved-memory的範圍
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
/* global autoconfigured region for contiguous allocations */
linux,cma {
compatible = "shared-dma-pool";
reusable;
size = <0x4000000>;
alignment = <0x2000>;
linux,cma-default;
};
display_reserved: framebuffer@78000000 {
reg = <0x78000000 0x800000>;
};
multimedia_reserved: multimedia@77000000 {
compatible = "acme,multimedia-memory";
reg = <0x77000000 0x4000000>;
};
};
/* ... */
fb0: video@12300000 {
memory-region = <&display_reserved>;
/* ... */
};
scaler: scaler@12500000 {
memory-region = <&multimedia_reserved>;
/* ... */
};
codec: codec@12600000 {
memory-region = <&multimedia_reserved>;
/* ... */
};
(2)、将reserved memory資訊告知給linux kernel
__fdt_scan_reserved_mem()
__fdt_scan_reserved_mem() —> __reserved_mem_reserve_reg() —> early_init_dt_reserve_memory_arch(base, size, nomap)—>memblock_reserve(base, size) —> memblock_reserve_region(base, size, MAX_NUMNODES, 0)
(driver/of/fdt.c)
/**
* fdt_scan_reserved_mem() - scan a single FDT node for reserved memory
*/
static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
int depth, void *data)
{
static int found;
const char *status;
int err;
if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) {
if (__reserved_mem_check_root(node) != 0) {
pr_err("Reserved memory: unsupported node format, ignoring\n");
/* break scan */
return 1;
}
found = 1;
/* scan next node */
return 0;
} else if (!found) {
/* scan next node */
return 0;
} else if (found && depth < 2) {
/* scanning of /reserved-memory has been finished */
return 1;
}
status = of_get_flat_dt_prop(node, "status", NULL);
if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0)
return 0;
err = __reserved_mem_reserve_reg(node, uname);
if (err == -ENOENT && of_get_flat_dt_prop(node, "size", NULL))
fdt_reserved_mem_save_node(node, uname, 0, 0);
/* scan next node */
return 0;
}