blob: 323b7ab4084d61a659c297d33ef9994ccfc68767 [file] [log] [blame]
Patrick Williamsb2e6a9b2017-02-23 20:31:26 -06001From ade243a211d62327e9ebadce27bbbff7981e37f0 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?C=C3=A9dric=20Schieli?= <cschieli@gmail.com>
3Date: Fri, 11 Nov 2016 11:59:07 +0100
4Subject: [PATCH] rpi: passthrough of the firmware provided FDT blob
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Raspberry firmware used to pass a FDT blob at a fixed address (0x100),
10but this is not true anymore. The address now depends on both the
11memory size and the blob size [1].
12
13If one wants to passthrough this FDT blob to the kernel, the most
14reliable way is to save its address from the r2/x0 register in the
15U-Boot entry point and expose it in a environment variable for
16further processing.
17
18This patch just does this:
19- save the provided address in the global variable fw_dtb_pointer
20- expose it in ${fdt_addr} if it points to a a valid FDT blob
21
22There are many different ways to use it. One can, for example, use
23the following script which will extract from the tree the command
24line built by the firmware, then hand over the blob to a previously
25loaded kernel:
26
27fdt addr ${fdt_addr}
28fdt get value bootargs /chosen bootargs
29bootz ${kernel_addr_r} - ${fdt_addr}
30
31Alternatively, users relying on sysboot/pxe can simply omit any FDT
32statement in their extlinux.conf file, U-Boot will automagically pick
33${fdt_addr} and pass it to the kernel.
34
35[1] https://www.raspberrypi.org/forums//viewtopic.php?f=107&t=134018
36
37Upstream-Status: Backport
38
39Signed-off-by: Cédric Schieli <cschieli@gmail.com>
40Acked-by: Stephen Warren <swarren@nvidia.com>
41Signed-off-by: Jonathan Liu <net147@gmail.com>
42---
43 board/raspberrypi/rpi/Makefile | 1 +
44 board/raspberrypi/rpi/lowlevel_init.S | 36 +++++++++++++++++++++++++++++++++++
45 board/raspberrypi/rpi/rpi.c | 29 ++++++++++++++++++++++++++++
46 3 files changed, 66 insertions(+)
47 create mode 100644 board/raspberrypi/rpi/lowlevel_init.S
48
49diff --git a/board/raspberrypi/rpi/Makefile b/board/raspberrypi/rpi/Makefile
50index 4ce2c98..dcb25ac 100644
51--- a/board/raspberrypi/rpi/Makefile
52+++ b/board/raspberrypi/rpi/Makefile
53@@ -5,3 +5,4 @@
54 #
55
56 obj-y := rpi.o
57+obj-y += lowlevel_init.o
58diff --git a/board/raspberrypi/rpi/lowlevel_init.S b/board/raspberrypi/rpi/lowlevel_init.S
59new file mode 100644
60index 0000000..cdbd8e1
61--- /dev/null
62+++ b/board/raspberrypi/rpi/lowlevel_init.S
63@@ -0,0 +1,36 @@
64+/*
65+ * (C) Copyright 2016
66+ * Cédric Schieli <cschieli@gmail.com>
67+ *
68+ * SPDX-License-Identifier: GPL-2.0+
69+ */
70+
71+#include <config.h>
72+
73+.align 8
74+.global fw_dtb_pointer
75+fw_dtb_pointer:
76+#ifdef CONFIG_ARM64
77+ .dword 0x0
78+#else
79+ .word 0x0
80+#endif
81+
82+/*
83+ * Routine: save_boot_params (called after reset from start.S)
84+ * Description: save ATAG/FDT address provided by the firmware at boot time
85+ */
86+
87+.global save_boot_params
88+save_boot_params:
89+
90+ /* The firmware provided ATAG/FDT address can be found in r2/x0 */
91+#ifdef CONFIG_ARM64
92+ adr x8, fw_dtb_pointer
93+ str x0, [x8]
94+#else
95+ str r2, fw_dtb_pointer
96+#endif
97+
98+ /* Returns */
99+ b save_boot_params_ret
100diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c
101index 6245b36..ffd6d31 100644
102--- a/board/raspberrypi/rpi/rpi.c
103+++ b/board/raspberrypi/rpi/rpi.c
104@@ -25,6 +25,9 @@
105
106 DECLARE_GLOBAL_DATA_PTR;
107
108+/* From lowlevel_init.S */
109+extern unsigned long fw_dtb_pointer;
110+
111 static const struct bcm2835_gpio_platdata gpio_platdata = {
112 .base = BCM2835_GPIO_BASE,
113 };
114@@ -285,6 +288,31 @@ static void set_fdtfile(void)
115 setenv("fdtfile", fdtfile);
116 }
117
118+/*
119+ * If the firmware provided a valid FDT at boot time, let's expose it in
120+ * ${fdt_addr} so it may be passed unmodified to the kernel.
121+ */
122+static void set_fdt_addr(void)
123+{
124+ if (getenv("fdt_addr"))
125+ return;
126+
127+ if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC)
128+ return;
129+
130+ setenv_hex("fdt_addr", fw_dtb_pointer);
131+}
132+
133+/*
134+ * Prevent relocation from stomping on a firmware provided FDT blob.
135+ */
136+unsigned long board_get_usable_ram_top(unsigned long total_size)
137+{
138+ if ((gd->ram_top - fw_dtb_pointer) > SZ_64M)
139+ return gd->ram_top;
140+ return fw_dtb_pointer & ~0xffff;
141+}
142+
143 static void set_usbethaddr(void)
144 {
145 ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_mac_address, msg, 1);
146@@ -356,6 +384,7 @@ static void set_serial_number(void)
147
148 int misc_init_r(void)
149 {
150+ set_fdt_addr();
151 set_fdtfile();
152 set_usbethaddr();
153 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
154--
1552.10.2
156