From 81146c46f620ba83008d700698be708c813e811e Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Sun, 17 Jan 2021 02:11:32 +0000 Subject: [PATCH] fdt: Use proper #address-cells and #size-cells for reserved-memory The devicetree binding document[1] for the /reserved-memory node demands that the number of address and size-cells in the reserved-memory node must match those values in the root node. So far we were forcing a 64-bit address along with a 32-bit size. Adjust the code to query the cells values from the root node, and populate the newly created /reserved-memory node accordingly. This fixes the fdt_add_reserved_memory() function when called on a devicetree which does not use the 2/1 pair. Linux is picky about this and will bail out the parsing routine, effectively ignoring the reserved-memory node: [ 0.000000] OF: fdt: Reserved memory: unsupported node format, ignoring [1] Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt in the Linux kernel source tree Change-Id: Ie126ebab4f3fedd48e12c9ed4bd8fa123acc86d3 Signed-off-by: Andre Przywara --- common/fdt_fixup.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/common/fdt_fixup.c b/common/fdt_fixup.c index e88a55008..46606fb6e 100644 --- a/common/fdt_fixup.c +++ b/common/fdt_fixup.c @@ -188,6 +188,8 @@ int dt_add_psci_cpu_enable_methods(void *fdt) * * See reserved-memory/reserved-memory.txt in the (Linux kernel) DT binding * documentation for details. + * According to this binding, the address-cells and size-cells must match + * those of the root node. * * Return: 0 on success, a negative error value otherwise. ******************************************************************************/ @@ -195,23 +197,37 @@ int fdt_add_reserved_memory(void *dtb, const char *node_name, uintptr_t base, size_t size) { int offs = fdt_path_offset(dtb, "/reserved-memory"); - uint32_t addresses[3]; + uint32_t addresses[4]; + int ac, sc; + unsigned int idx = 0; + ac = fdt_address_cells(dtb, 0); + sc = fdt_size_cells(dtb, 0); if (offs < 0) { /* create if not existing yet */ offs = fdt_add_subnode(dtb, 0, "reserved-memory"); - if (offs < 0) + if (offs < 0) { return offs; - fdt_setprop_u32(dtb, offs, "#address-cells", 2); - fdt_setprop_u32(dtb, offs, "#size-cells", 1); + } + fdt_setprop_u32(dtb, offs, "#address-cells", ac); + fdt_setprop_u32(dtb, offs, "#size-cells", sc); fdt_setprop(dtb, offs, "ranges", NULL, 0); } - addresses[0] = cpu_to_fdt32(HIGH_BITS(base)); - addresses[1] = cpu_to_fdt32(base & 0xffffffff); - addresses[2] = cpu_to_fdt32(size & 0xffffffff); + if (ac > 1) { + addresses[idx] = cpu_to_fdt32(HIGH_BITS(base)); + idx++; + } + addresses[idx] = cpu_to_fdt32(base & 0xffffffff); + idx++; + if (sc > 1) { + addresses[idx] = cpu_to_fdt32(HIGH_BITS(size)); + idx++; + } + addresses[idx] = cpu_to_fdt32(size & 0xffffffff); + idx++; offs = fdt_add_subnode(dtb, offs, node_name); fdt_setprop(dtb, offs, "no-map", NULL, 0); - fdt_setprop(dtb, offs, "reg", addresses, 12); + fdt_setprop(dtb, offs, "reg", addresses, idx * sizeof(uint32_t)); return 0; }