Patrick Williams | b2e6a9b | 2017-02-23 20:31:26 -0600 | [diff] [blame] | 1 | From ade243a211d62327e9ebadce27bbbff7981e37f0 Mon Sep 17 00:00:00 2001 |
| 2 | From: =?UTF-8?q?C=C3=A9dric=20Schieli?= <cschieli@gmail.com> |
| 3 | Date: Fri, 11 Nov 2016 11:59:07 +0100 |
| 4 | Subject: [PATCH] rpi: passthrough of the firmware provided FDT blob |
| 5 | MIME-Version: 1.0 |
| 6 | Content-Type: text/plain; charset=UTF-8 |
| 7 | Content-Transfer-Encoding: 8bit |
| 8 | |
| 9 | Raspberry firmware used to pass a FDT blob at a fixed address (0x100), |
| 10 | but this is not true anymore. The address now depends on both the |
| 11 | memory size and the blob size [1]. |
| 12 | |
| 13 | If one wants to passthrough this FDT blob to the kernel, the most |
| 14 | reliable way is to save its address from the r2/x0 register in the |
| 15 | U-Boot entry point and expose it in a environment variable for |
| 16 | further processing. |
| 17 | |
| 18 | This 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 | |
| 22 | There are many different ways to use it. One can, for example, use |
| 23 | the following script which will extract from the tree the command |
| 24 | line built by the firmware, then hand over the blob to a previously |
| 25 | loaded kernel: |
| 26 | |
| 27 | fdt addr ${fdt_addr} |
| 28 | fdt get value bootargs /chosen bootargs |
| 29 | bootz ${kernel_addr_r} - ${fdt_addr} |
| 30 | |
| 31 | Alternatively, users relying on sysboot/pxe can simply omit any FDT |
| 32 | statement 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 | |
| 37 | Upstream-Status: Backport |
| 38 | |
| 39 | Signed-off-by: Cédric Schieli <cschieli@gmail.com> |
| 40 | Acked-by: Stephen Warren <swarren@nvidia.com> |
| 41 | Signed-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 | |
| 49 | diff --git a/board/raspberrypi/rpi/Makefile b/board/raspberrypi/rpi/Makefile |
| 50 | index 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 |
| 58 | diff --git a/board/raspberrypi/rpi/lowlevel_init.S b/board/raspberrypi/rpi/lowlevel_init.S |
| 59 | new file mode 100644 |
| 60 | index 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 |
| 100 | diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c |
| 101 | index 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 | -- |
| 155 | 2.10.2 |
| 156 | |