rpi: Use the U-Boot control FDT for fdt_addr
authorSimon Glass <sjg@chromium.org>
Sat, 27 Sep 2025 11:30:15 +0000 (05:30 -0600)
committerPeter Robinson <pbrobinson@gmail.com>
Tue, 25 Nov 2025 09:22:12 +0000 (09:22 +0000)
The fdt_addr variable is used in extlinux as a fallback devicetree if
none is provided by the boot command. Otherwise the only use in U-Boot
seems to me efi_install_fdt() when the internal FDT is required.

The existing mechanism uses the devicetree provided to U-Boot, but in
its original, unrelocated position. In my testing on an rpi_4, this ends
up at 2b35ef00 which is not a convenient place in memory, if the ramdisk
is large.

U-Boot already deals with this sort of problem by relocating the FDT
to a safe address.

So use the control-FDT address instead.

Remove the existing comment, which is confusing, since the FDT is not
actually passed unmodified to the kernel: U-Boot adds various things
using its FDT-fixup mechanism.

Note that board_get_usable_ram_top() reduces the RAM top for boards with
less RAM. This behaviour is left unchanged as there is no other
mechanism for U-Boot to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Christopher Obbard <christopher.obbard@linaro.org>
Tested-by: Christopher Obbard <christopher.obbard@linaro.org> # CM4 1G
board/raspberrypi/rpi/rpi.c

index 1b0b664..6f96c1e 100644 (file)
@@ -3,6 +3,8 @@
  * (C) Copyright 2012-2016 Stephen Warren
  */
 
+#define LOG_CATEGORY   LOGC_BOARD
+
 #include <config.h>
 #include <dm.h>
 #include <env.h>
@@ -354,15 +356,13 @@ static void set_fdtfile(void)
 }
 
 /*
- * If the firmware provided a valid FDT at boot time, let's expose it in
- * ${fdt_addr} so it may be passed unmodified to the kernel.
+ * Allow U-Boot to use its control FDT with extlinux if one is not provided.
+ * This will then go through the usual fixups that U-Boot does, before being
+ * handed off to Linux
  */
 static void set_fdt_addr(void)
 {
-       if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC)
-               return;
-
-       env_set_hex("fdt_addr", fw_dtb_pointer);
+       env_set_hex("fdt_addr", (ulong)gd->fdt_blob);
 }
 
 /*
@@ -608,7 +608,10 @@ int ft_board_setup(void *blob, struct bd_info *bd)
 {
        int node;
 
-       update_fdt_from_fw(blob, (void *)fw_dtb_pointer);
+       if (blob == gd->fdt_blob)
+               log_debug("Same FDT: nothing to do\n");
+       else
+               update_fdt_from_fw(blob, (void *)gd->fdt_blob);
 
        if (CONFIG_IS_ENABLED(FDT_SIMPLEFB)) {
                node = fdt_node_offset_by_compatible(blob, -1, "simple-framebuffer");