[U-Boot] [PATCH v4 0/4] RPi one binary for RPi3/4 and RPi1/2

From: Matthias Brugger mbrugger@suse.com
In this series we prepare the RaspberryPi source code to be able to build one binary for RPi[3,4] and one for RPi[1,2]. To achieve this we need to set the IO base address on runtime. Apart from that, for arm64 we also need to set memory region correctly.
This patches fix this stuff. With this we could create one binary for each armv7 and armv8 based RPis. There is still some work to do to create a unified config, which will be done in a later patch series.
Changes in v4: - use gcc attribute instead of random assignment - read IO base from device-tree - call rpi_update_mem_map only for ARM64 - get rid of struct pdata
Changes in v3: - fix armv7 build
Changes in v2: - push fw_dtb_pointer into the .data section - fix register access in reset_cpu() - rename BCM2838 to BCM2711 in the correct patch - push rpi_bcm283x_base into the .data section - Move mem_map out of assembly file - push mem_map into the .data section - update the members of mem_map instead of the pointer
Matthias Brugger (4): rpi: push fw_dtb_pointer in the .data section ARM: bcm283x: Move BCM283x_BASE to a global variable ARM: bcm283x: Set rpi_bcm283x_base at run-time ARM: bcm283x: Set memory map at run-time
arch/arm/mach-bcm283x/Kconfig | 6 -- arch/arm/mach-bcm283x/include/mach/base.h | 11 ++ arch/arm/mach-bcm283x/include/mach/mbox.h | 4 +- arch/arm/mach-bcm283x/include/mach/sdhci.h | 5 +- arch/arm/mach-bcm283x/include/mach/timer.h | 7 +- arch/arm/mach-bcm283x/include/mach/wdog.h | 5 +- arch/arm/mach-bcm283x/init.c | 116 +++++++++++++++++++++ arch/arm/mach-bcm283x/mbox.c | 1 + arch/arm/mach-bcm283x/reset.c | 20 +++- board/raspberrypi/rpi/lowlevel_init.S | 12 +-- board/raspberrypi/rpi/rpi.c | 52 +-------- include/configs/rpi.h | 4 + 12 files changed, 171 insertions(+), 72 deletions(-) create mode 100644 arch/arm/mach-bcm283x/include/mach/base.h

From: Matthias Brugger mbrugger@suse.com
The fw_dtb_pointer was defined in the assembly code, which makes him live in section .text_rest Put that's not necessary, we can push the variable in the .data section.
This will prevent relocation errors like: board/raspberrypi/rpi/rpi.c:317:(.text.board_get_usable_ram_top+0x8): relocation truncated to fit: R_AARCH64_LDST64_ABS_LO12_NC against symbol `fw_dtb_pointer' defined in .text section in board/raspberrypi/rpi/built-in.o
Signed-off-by: Matthias Brugger mbrugger@suse.com
---
Changes in v4: - use gcc attribute instead of random assignment
Changes in v3: - fix armv7 build
Changes in v2: - push fw_dtb_pointer into the .data section
board/raspberrypi/rpi/lowlevel_init.S | 12 ++---------- board/raspberrypi/rpi/rpi.c | 7 +++++-- 2 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/board/raspberrypi/rpi/lowlevel_init.S b/board/raspberrypi/rpi/lowlevel_init.S index 435eed521f..8c39b3e12e 100644 --- a/board/raspberrypi/rpi/lowlevel_init.S +++ b/board/raspberrypi/rpi/lowlevel_init.S @@ -6,15 +6,6 @@
#include <config.h>
-.align 8 -.global fw_dtb_pointer -fw_dtb_pointer: -#ifdef CONFIG_ARM64 - .dword 0x0 -#else - .word 0x0 -#endif - /* * Routine: save_boot_params (called after reset from start.S) * Description: save ATAG/FDT address provided by the firmware at boot time @@ -28,7 +19,8 @@ save_boot_params: adr x8, fw_dtb_pointer str x0, [x8] #else - str r2, fw_dtb_pointer + ldr r8, =fw_dtb_pointer + str r2, [r8] #endif
/* Returns */ diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 9e0abdda31..e84a1db14a 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -27,8 +27,11 @@
DECLARE_GLOBAL_DATA_PTR;
-/* From lowlevel_init.S */ -extern unsigned long fw_dtb_pointer; +/* Assigned in lowlevel_init.S + * Push the variable into the .data section so that it + * does not get cleared later. + */ +unsigned long __section(".data") fw_dtb_pointer;
/* TODO(sjg@chromium.org): Move these to the msg.c file */ struct msg_get_arm_mem {

From: Matthias Brugger mbrugger@suse.com
We move the per SOC define BCM283x_BASE to a global variable. This is a first step to provide a single binary for several bcm283x SoCs.
Signed-off-by: Matthias Brugger mbrugger@suse.com
---
Changes in v4: None Changes in v3: None Changes in v2: - fix register access in reset_cpu()
arch/arm/mach-bcm283x/include/mach/base.h | 11 +++++++++++ arch/arm/mach-bcm283x/include/mach/mbox.h | 4 +++- arch/arm/mach-bcm283x/include/mach/sdhci.h | 5 ++++- arch/arm/mach-bcm283x/include/mach/timer.h | 7 ++++++- arch/arm/mach-bcm283x/include/mach/wdog.h | 5 ++++- arch/arm/mach-bcm283x/init.c | 8 ++++++++ arch/arm/mach-bcm283x/mbox.c | 1 + arch/arm/mach-bcm283x/reset.c | 20 +++++++++++++++----- include/configs/rpi.h | 4 ++++ 9 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 arch/arm/mach-bcm283x/include/mach/base.h
diff --git a/arch/arm/mach-bcm283x/include/mach/base.h b/arch/arm/mach-bcm283x/include/mach/base.h new file mode 100644 index 0000000000..c4ae39852f --- /dev/null +++ b/arch/arm/mach-bcm283x/include/mach/base.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * (C) Copyright 2019 Matthias Brugger + */ + +#ifndef _BCM283x_BASE_H_ +#define _BCM283x_BASE_H_ + +extern unsigned long rpi_bcm283x_base; + +#endif diff --git a/arch/arm/mach-bcm283x/include/mach/mbox.h b/arch/arm/mach-bcm283x/include/mach/mbox.h index 0b6c2543d5..60e226ce1d 100644 --- a/arch/arm/mach-bcm283x/include/mach/mbox.h +++ b/arch/arm/mach-bcm283x/include/mach/mbox.h @@ -7,6 +7,7 @@ #define _BCM2835_MBOX_H
#include <linux/compiler.h> +#include <asm/arch/base.h>
/* * The BCM2835 SoC contains (at least) two CPUs; the VideoCore (a/k/a "GPU") @@ -37,7 +38,8 @@
/* Raw mailbox HW */
-#define BCM2835_MBOX_PHYSADDR (CONFIG_BCM283x_BASE + 0x0000b880) +#define BCM2835_MBOX_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \ + rpi_bcm283x_base + 0x0000b880; })
struct bcm2835_mbox_regs { u32 read; diff --git a/arch/arm/mach-bcm283x/include/mach/sdhci.h b/arch/arm/mach-bcm283x/include/mach/sdhci.h index b443c379d8..7323690687 100644 --- a/arch/arm/mach-bcm283x/include/mach/sdhci.h +++ b/arch/arm/mach-bcm283x/include/mach/sdhci.h @@ -6,7 +6,10 @@ #ifndef _BCM2835_SDHCI_H_ #define _BCM2835_SDHCI_H_
-#define BCM2835_SDHCI_BASE (CONFIG_BCM283x_BASE + 0x00300000) +#include <asm/arch/base.h> + +#define BCM2835_SDHCI_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \ + rpi_bcm283x_base + 0x00300000; })
int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq);
diff --git a/arch/arm/mach-bcm283x/include/mach/timer.h b/arch/arm/mach-bcm283x/include/mach/timer.h index 61beb1aba1..01c0ebad64 100644 --- a/arch/arm/mach-bcm283x/include/mach/timer.h +++ b/arch/arm/mach-bcm283x/include/mach/timer.h @@ -6,7 +6,12 @@ #ifndef _BCM2835_TIMER_H #define _BCM2835_TIMER_H
-#define BCM2835_TIMER_PHYSADDR (CONFIG_BCM283x_BASE + 0x00003000) +#ifndef __ASSEMBLY__ +#include <asm/arch/base.h> +#endif + +#define BCM2835_TIMER_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \ + rpi_bcm283x_base + 0x00003000; })
#define BCM2835_TIMER_CS_M3 (1 << 3) #define BCM2835_TIMER_CS_M2 (1 << 2) diff --git a/arch/arm/mach-bcm283x/include/mach/wdog.h b/arch/arm/mach-bcm283x/include/mach/wdog.h index 8292b3cf1f..9942666720 100644 --- a/arch/arm/mach-bcm283x/include/mach/wdog.h +++ b/arch/arm/mach-bcm283x/include/mach/wdog.h @@ -6,7 +6,10 @@ #ifndef _BCM2835_WDOG_H #define _BCM2835_WDOG_H
-#define BCM2835_WDOG_PHYSADDR (CONFIG_BCM283x_BASE + 0x00100000) +#include <asm/arch/base.h> + +#define BCM2835_WDOG_PHYSADDR ({ BUG_ON(!rpi_bcm283x_base); \ + rpi_bcm283x_base + 0x00100000; })
struct bcm2835_wdog_regs { u32 unknown0[7]; diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c index 97414415a6..d36017e823 100644 --- a/arch/arm/mach-bcm283x/init.c +++ b/arch/arm/mach-bcm283x/init.c @@ -8,6 +8,8 @@
#include <common.h>
+unsigned long rpi_bcm283x_base; + int arch_cpu_init(void) { icache_enable(); @@ -15,6 +17,12 @@ int arch_cpu_init(void) return 0; }
+int mach_cpu_init(void) +{ + rpi_bcm283x_base = CONFIG_BCM283x_BASE; + + return 0; +} #ifdef CONFIG_ARMV7_LPAE void enable_caches(void) { diff --git a/arch/arm/mach-bcm283x/mbox.c b/arch/arm/mach-bcm283x/mbox.c index 3c67f68c17..467d0d5fba 100644 --- a/arch/arm/mach-bcm283x/mbox.c +++ b/arch/arm/mach-bcm283x/mbox.c @@ -5,6 +5,7 @@
#include <common.h> #include <asm/io.h> +#include <asm/arch/base.h> #include <asm/arch/mbox.h> #include <phys2bus.h>
diff --git a/arch/arm/mach-bcm283x/reset.c b/arch/arm/mach-bcm283x/reset.c index b3da0c7cd6..cd8138d702 100644 --- a/arch/arm/mach-bcm283x/reset.c +++ b/arch/arm/mach-bcm283x/reset.c @@ -8,6 +8,7 @@
#include <common.h> #include <asm/io.h> +#include <asm/arch/base.h> #include <asm/arch/wdog.h> #include <efi_loader.h>
@@ -25,10 +26,10 @@
void hw_watchdog_disable(void) {}
-__efi_runtime_data struct bcm2835_wdog_regs *wdog_regs = - (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR; +__efi_runtime_data struct bcm2835_wdog_regs *wdog_regs;
-void __efi_runtime reset_cpu(ulong ticks) +static void __efi_runtime +__reset_cpu(struct bcm2835_wdog_regs *wdog_regs, ulong ticks) { uint32_t rstc, timeout;
@@ -46,6 +47,14 @@ void __efi_runtime reset_cpu(ulong ticks) writel(BCM2835_WDOG_PASSWORD | rstc, &wdog_regs->rstc); }
+void reset_cpu(ulong ticks) +{ + struct bcm2835_wdog_regs *regs = + (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR; + + __reset_cpu(regs, 0); +} + #ifdef CONFIG_EFI_LOADER
void __efi_runtime EFIAPI efi_reset_system( @@ -58,7 +67,7 @@ void __efi_runtime EFIAPI efi_reset_system( if (reset_type == EFI_RESET_COLD || reset_type == EFI_RESET_WARM || reset_type == EFI_RESET_PLATFORM_SPECIFIC) { - reset_cpu(0); + __reset_cpu(wdog_regs, 0); } else if (reset_type == EFI_RESET_SHUTDOWN) { /* * We set the watchdog hard reset bit here to distinguish this reset @@ -69,7 +78,7 @@ void __efi_runtime EFIAPI efi_reset_system( val |= BCM2835_WDOG_PASSWORD; val |= BCM2835_WDOG_RSTS_RASPBERRYPI_HALT; writel(val, &wdog_regs->rsts); - reset_cpu(0); + __reset_cpu(wdog_regs, 0); }
while (1) { } @@ -77,6 +86,7 @@ void __efi_runtime EFIAPI efi_reset_system(
efi_status_t efi_reset_system_init(void) { + wdog_regs = (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR; return efi_add_runtime_mmio(&wdog_regs, sizeof(*wdog_regs)); }
diff --git a/include/configs/rpi.h b/include/configs/rpi.h index 77d2d5458a..69b09f3f72 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -9,6 +9,10 @@ #include <linux/sizes.h> #include <asm/arch/timer.h>
+#ifndef __ASSEMBLY__ +#include <asm/arch/base.h> +#endif + #if defined(CONFIG_TARGET_RPI_2) || defined(CONFIG_TARGET_RPI_3_32B) #define CONFIG_SKIP_LOWLEVEL_INIT #endif

From: Matthias Brugger mbrugger@suse.com
As part of the effort to create one binary for several bcm83x SoCs we read the IO base address from device-tree.
Signed-off-by: Matthias Brugger mbrugger@suse.com
---
Changes in v4: - read IO base from device-tree
Changes in v3: None Changes in v2: - rename BCM2838 to BCM2711 in the correct patch - push rpi_bcm283x_base into the .data section
arch/arm/mach-bcm283x/Kconfig | 6 ------ arch/arm/mach-bcm283x/init.c | 20 ++++++++++++++++++-- 2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-bcm283x/Kconfig b/arch/arm/mach-bcm283x/Kconfig index b08275f598..e8e0ff0eb4 100644 --- a/arch/arm/mach-bcm283x/Kconfig +++ b/arch/arm/mach-bcm283x/Kconfig @@ -202,10 +202,4 @@ config SYS_SOC config SYS_CONFIG_NAME default "rpi"
-config BCM283x_BASE - hex - default "0x20000000" if BCM2835 - default "0x3f000000" if BCM2836 || BCM2837 - default "0xfe000000" if BCM2711 - endmenu diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c index d36017e823..b3f3dfabea 100644 --- a/arch/arm/mach-bcm283x/init.c +++ b/arch/arm/mach-bcm283x/init.c @@ -7,8 +7,10 @@ */
#include <common.h> +#include <dm/device.h> +#include <fdt_support.h>
-unsigned long rpi_bcm283x_base; +unsigned long rpi_bcm283x_base = 0x3f000000;
int arch_cpu_init(void) { @@ -19,10 +21,24 @@ int arch_cpu_init(void)
int mach_cpu_init(void) { - rpi_bcm283x_base = CONFIG_BCM283x_BASE; + int ret, soc_offset; + u64 io_base, size; + + /* Get IO base from device tree */ + soc_offset = fdt_path_offset(gd->fdt_blob, "/soc"); + if (soc_offset < 0) + return soc_offset; + + ret = fdt_read_range((void *)gd->fdt_blob, soc_offset, 0, NULL, + &io_base, &size); + if (ret) + return ret; + + rpi_bcm283x_base = io_base;
return 0; } + #ifdef CONFIG_ARMV7_LPAE void enable_caches(void) {

From: Matthias Brugger mbrugger@suse.com
For bcm283x based on arm64 we also have to change the mm_region. Add assign this in mach_cpu_init() so we can create now one binary for RPi3 and RPi4.
Signed-off-by: Matthias Brugger mbrugger@suse.com
---
Changes in v4: - call rpi_update_mem_map only for ARM64 - get rid of struct pdata
Changes in v3: None Changes in v2: - Move mem_map out of assembly file - push mem_map into the .data section - update the members of mem_map instead of the pointer
arch/arm/mach-bcm283x/init.c | 92 ++++++++++++++++++++++++++++++++++++ board/raspberrypi/rpi/rpi.c | 45 ------------------ 2 files changed, 92 insertions(+), 45 deletions(-)
diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c index b3f3dfabea..6fb41a99b2 100644 --- a/arch/arm/mach-bcm283x/init.c +++ b/arch/arm/mach-bcm283x/init.c @@ -10,6 +10,96 @@ #include <dm/device.h> #include <fdt_support.h>
+#ifdef CONFIG_ARM64 +#include <asm/armv8/mmu.h> + +static struct mm_region bcm283x_mem_map[] = { + { + .virt = 0x00000000UL, + .phys = 0x00000000UL, + .size = 0x3f000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0x3f000000UL, + .phys = 0x3f000000UL, + .size = 0x01000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* List terminator */ + 0, + } +}; + +static struct mm_region bcm2711_mem_map[] = { + { + .virt = 0x00000000UL, + .phys = 0x00000000UL, + .size = 0xfe000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0xfe000000UL, + .phys = 0xfe000000UL, + .size = 0x01800000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = bcm283x_mem_map; + +/* + * I/O address space varies on different chip versions. + * We set the base address by inspecting the DTB. + */ +static const struct udevice_id board_ids[] = { + { .compatible = "brcm,bcm2837", .data = (ulong)&bcm283x_mem_map}, + { .compatible = "brcm,bcm2838", .data = (ulong)&bcm2711_mem_map}, + { .compatible = "brcm,bcm2711", .data = (ulong)&bcm2711_mem_map}, + { }, +}; + +static void _rpi_update_mem_map(struct mm_region *pd) +{ + int i; + + for (i = 0; i < 2; i++) { + mem_map[i].virt = pd[i].virt; + mem_map[i].phys = pd[i].phys; + mem_map[i].size = pd[i].size; + mem_map[i].attrs = pd[i].attrs; + } +} + +static void rpi_update_mem_map(void) +{ + int ret; + struct mm_region *mm; + const struct udevice_id *of_match = board_ids; + + while (of_match->compatible) { + ret = fdt_node_check_compatible(gd->fdt_blob, 0, + of_match->compatible); + if (!ret) { + mm = (struct mm_region *)of_match->data; + _rpi_update_mem_map(mm); + break; + } + + of_match++; + } +} +#else +static void rpi_update_mem_map(void) {} +#endif + unsigned long rpi_bcm283x_base = 0x3f000000;
int arch_cpu_init(void) @@ -24,6 +114,8 @@ int mach_cpu_init(void) int ret, soc_offset; u64 io_base, size;
+ rpi_update_mem_map(); + /* Get IO base from device tree */ soc_offset = fdt_path_offset(gd->fdt_blob, "/soc"); if (soc_offset < 0) diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index e84a1db14a..3d4afaf653 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -251,51 +251,6 @@ static uint32_t rev_scheme; static uint32_t rev_type; static const struct rpi_model *model;
-#ifdef CONFIG_ARM64 -#ifndef CONFIG_BCM2711 -static struct mm_region bcm283x_mem_map[] = { - { - .virt = 0x00000000UL, - .phys = 0x00000000UL, - .size = 0x3f000000UL, - .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | - PTE_BLOCK_INNER_SHARE - }, { - .virt = 0x3f000000UL, - .phys = 0x3f000000UL, - .size = 0x01000000UL, - .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | - PTE_BLOCK_NON_SHARE | - PTE_BLOCK_PXN | PTE_BLOCK_UXN - }, { - /* List terminator */ - 0, - } -}; -#else -static struct mm_region bcm283x_mem_map[] = { - { - .virt = 0x00000000UL, - .phys = 0x00000000UL, - .size = 0xfe000000UL, - .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | - PTE_BLOCK_INNER_SHARE - }, { - .virt = 0xfe000000UL, - .phys = 0xfe000000UL, - .size = 0x01800000UL, - .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | - PTE_BLOCK_NON_SHARE | - PTE_BLOCK_PXN | PTE_BLOCK_UXN - }, { - /* List terminator */ - 0, - } -}; -#endif -struct mm_region *mem_map = bcm283x_mem_map; -#endif - int dram_init(void) { ALLOC_CACHE_ALIGN_BUFFER(struct msg_get_arm_mem, msg, 1);
participants (1)
-
matthias.bgg@kernel.org