ARM: arch-meson: build memory banks using reported memory from registers
authorNeil Armstrong <narmstrong@baylibre.com>
Mon, 27 Nov 2017 09:35:46 +0000 (10:35 +0100)
committerTom Rini <trini@konsulko.com>
Mon, 4 Dec 2017 15:17:29 +0000 (10:17 -0500)
As discussed at [1], the Amlogic Meson GX SoCs can embed a BL31 firmware
and a secondary BL32 firmware.
Since mid-2017, the reserved memory address of the BL31 firmware was moved
and grown for security reasons.

But mainline U-Boot and Linux has the old address and size fixed.

These SoCs have a register interface to get the two firmware reserved
memory start and sizes.

This patch adds a dynamic reservation of the memory zones in the device tree bootmem
reserved memory zone used by the kernel in early boot.
To be complete, the memory zones are also added to the EFI reserved zones.

Depends on patchset "Add support for Amlogic GXL Based SBCs" at [2].

[1] http://lists.infradead.org/pipermail/linux-amlogic/2017-October/004860.html
[2] http://lists.infradead.org/pipermail/linux-amlogic/2017-November/005410.html

Changes since v1:
- switched the #if to if(IS_ENABLED()) to compile all code paths
- renamed function to meson_board_add_reserved_memory()
- added a mem.h header with comment
- updated all boards ft_board_setup()

Changes since RFC v2:
- reduced preprocessor load
- kept Odroid-C2 static memory mapping as exception

Changes since RFC v1:
- switch to fdt rsv mem table and efi reserve memory
- replaced in_le32 by readl()

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
[trini: Fix warning on khadas-vim over missing <asm/arch/mem.h>
Signed-off-by: Tom Rini <trini@konsulko.com>
12 files changed:
arch/arm/include/asm/arch-meson/gxbb.h
arch/arm/include/asm/arch-meson/mem.h [new file with mode: 0644]
arch/arm/mach-meson/board.c
board/amlogic/khadas-vim/khadas-vim.c
board/amlogic/libretech-cc/libretech-cc.c
board/amlogic/odroid-c2/odroid-c2.c
board/amlogic/p212/p212.c
configs/khadas-vim_defconfig
configs/libretech-cc_defconfig
configs/odroid-c2_defconfig
configs/p212_defconfig
include/configs/meson-gxbb-common.h

index 95a6fe6998e249b2baed5e743bc3eecc82543e61..ef63dea44964d2be1ea80b1166d838bf2d30ac90 100644 (file)
@@ -7,10 +7,27 @@
 #ifndef __GXBB_H__
 #define __GXBB_H__
 
+#define GXBB_FIRMWARE_MEM_SIZE 0x1000000
+
+#define GXBB_AOBUS_BASE                0xc8100000
 #define GXBB_PERIPHS_BASE      0xc8834400
 #define GXBB_HIU_BASE          0xc883c000
 #define GXBB_ETH_BASE          0xc9410000
 
+/* Always-On Peripherals registers */
+#define GXBB_AO_ADDR(off)      (GXBB_AOBUS_BASE + ((off) << 2))
+
+#define GXBB_AO_SEC_GP_CFG0    GXBB_AO_ADDR(0x90)
+#define GXBB_AO_SEC_GP_CFG3    GXBB_AO_ADDR(0x93)
+#define GXBB_AO_SEC_GP_CFG4    GXBB_AO_ADDR(0x94)
+#define GXBB_AO_SEC_GP_CFG5    GXBB_AO_ADDR(0x95)
+
+#define GXBB_AO_MEM_SIZE_MASK  0xFFFF0000
+#define GXBB_AO_MEM_SIZE_SHIFT 16
+#define GXBB_AO_BL31_RSVMEM_SIZE_MASK  0xFFFF0000
+#define GXBB_AO_BL31_RSVMEM_SIZE_SHIFT 16
+#define GXBB_AO_BL32_RSVMEM_SIZE_MASK  0xFFFF
+
 /* Peripherals registers */
 #define GXBB_PERIPHS_ADDR(off) (GXBB_PERIPHS_BASE + ((off) << 2))
 
diff --git a/arch/arm/include/asm/arch-meson/mem.h b/arch/arm/include/asm/arch-meson/mem.h
new file mode 100644 (file)
index 0000000..86a8417
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __MESON_MEM_H__
+#define __MESON_MEM_H__
+
+/* Configure the reserved memory zones exported by the secure registers
+ * into EFI and DTB reserved memory entries.
+ */
+void meson_gx_init_reserved_memory(void *fdt);
+
+#endif /* __MESON_MEM_H__ */
index e89c6aace98d6e021ee5b86030ac7529623aafc5..908a0cae5607a09798ecc281d34800b15056d4a7 100644 (file)
@@ -11,6 +11,9 @@
 #include <asm/arch/sm.h>
 #include <asm/armv8/mmu.h>
 #include <asm/unaligned.h>
+#include <linux/sizes.h>
+#include <efi_loader.h>
+#include <asm/io.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -34,15 +37,70 @@ int dram_init(void)
        return 0;
 }
 
-int dram_init_banksize(void)
+phys_size_t get_effective_memsize(void)
 {
-       /* Reserve first 16 MiB of RAM for firmware */
-       gd->bd->bi_dram[0].start = 0x1000000;
-       gd->bd->bi_dram[0].size  = 0xf000000;
-       /* Reserve 2 MiB for ARM Trusted Firmware (BL31) */
-       gd->bd->bi_dram[1].start = 0x10000000;
-       gd->bd->bi_dram[1].size  = gd->ram_size - 0x10200000;
-       return 0;
+       /* Size is reported in MiB, convert it in bytes */
+       return ((readl(GXBB_AO_SEC_GP_CFG0) & GXBB_AO_MEM_SIZE_MASK)
+                       >> GXBB_AO_MEM_SIZE_SHIFT) * SZ_1M;
+}
+
+static void meson_board_add_reserved_memory(void *fdt, u64 start, u64 size)
+{
+       int ret;
+
+       ret = fdt_add_mem_rsv(fdt, start, size);
+       if (ret)
+               printf("Could not reserve zone @ 0x%llx\n", start);
+
+       if (IS_ENABLED(CONFIG_EFI_LOADER)) {
+               efi_add_memory_map(start,
+                                  ALIGN(size, EFI_PAGE_SIZE) >> EFI_PAGE_SHIFT,
+                                  EFI_RESERVED_MEMORY_TYPE, false);
+       }
+}
+
+void meson_gx_init_reserved_memory(void *fdt)
+{
+       u64 bl31_size, bl31_start;
+       u64 bl32_size, bl32_start;
+       u32 reg;
+
+       /*
+        * Get ARM Trusted Firmware reserved memory zones in :
+        * - AO_SEC_GP_CFG3: bl32 & bl31 size in KiB, can be 0
+        * - AO_SEC_GP_CFG5: bl31 physical start address, can be NULL
+        * - AO_SEC_GP_CFG4: bl32 physical start address, can be NULL
+        */
+
+       reg = readl(GXBB_AO_SEC_GP_CFG3);
+
+       bl31_size = ((reg & GXBB_AO_BL31_RSVMEM_SIZE_MASK)
+                       >> GXBB_AO_BL31_RSVMEM_SIZE_SHIFT) * SZ_1K;
+       bl32_size = (reg & GXBB_AO_BL32_RSVMEM_SIZE_MASK) * SZ_1K;
+
+       bl31_start = readl(GXBB_AO_SEC_GP_CFG5);
+       bl32_start = readl(GXBB_AO_SEC_GP_CFG4);
+
+       /*
+        * Early Meson GXBB Firmware revisions did not provide the reserved
+        * memory zones in the registers, keep fixed memory zone handling.
+        */
+       if (IS_ENABLED(CONFIG_MESON_GXBB) &&
+           !reg && !bl31_start && !bl32_start) {
+               bl31_start = 0x10000000;
+               bl31_size = 0x200000;
+       }
+
+       /* Add first 16MiB reserved zone */
+       meson_board_add_reserved_memory(fdt, 0, GXBB_FIRMWARE_MEM_SIZE);
+
+       /* Add BL31 reserved zone */
+       if (bl31_start && bl31_size)
+               meson_board_add_reserved_memory(fdt, bl31_start, bl31_size);
+
+       /* Add BL32 reserved zone */
+       if (bl32_start && bl32_size)
+               meson_board_add_reserved_memory(fdt, bl32_start, bl32_size);
 }
 
 void reset_cpu(ulong addr)
index db9c2924584d948fc9dc2d7f4e21b90208312035..5e198569db40edfc95d19a7203bb595ce5299d70 100644 (file)
@@ -9,6 +9,7 @@
 #include <dm.h>
 #include <asm/io.h>
 #include <asm/arch/gxbb.h>
+#include <asm/arch/mem.h>
 #include <asm/arch/sm.h>
 #include <asm/arch/eth.h>
 
@@ -47,3 +48,10 @@ int misc_init_r(void)
 
        return 0;
 }
+
+int ft_board_setup(void *blob, bd_t *bd)
+{
+       meson_gx_init_reserved_memory(blob);
+
+       return 0;
+}
index 26c0e78a46c0e165c64804f7b3fe493ea20f9652..6be6e2ae93b49a9d215e1ec4883b9f7692faa55a 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/arch/gxbb.h>
 #include <asm/arch/sm.h>
 #include <asm/arch/eth.h>
+#include <asm/arch/mem.h>
 
 #define EFUSE_SN_OFFSET                20
 #define EFUSE_SN_SIZE          16
@@ -51,3 +52,10 @@ int misc_init_r(void)
 
        return 0;
 }
+
+int ft_board_setup(void *blob, bd_t *bd)
+{
+       meson_gx_init_reserved_memory(blob);
+
+       return 0;
+}
index d68d0f134446eff16f39ce73d4576cd279e2b816..0cb571432f0bc46157cc136fc2f7231df369f310 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/arch/gxbb.h>
 #include <asm/arch/sm.h>
 #include <asm/arch/eth.h>
+#include <asm/arch/mem.h>
 
 #define EFUSE_SN_OFFSET                20
 #define EFUSE_SN_SIZE          16
@@ -54,3 +55,10 @@ int misc_init_r(void)
 
        return 0;
 }
+
+int ft_board_setup(void *blob, bd_t *bd)
+{
+       meson_gx_init_reserved_memory(blob);
+
+       return 0;
+}
index 2b6d88ab1b94c9efdbf35e26ece9e9728955ae13..5fde53438ecd5f1f293f1e27f84ed07916f18870 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/arch/gxbb.h>
 #include <asm/arch/sm.h>
 #include <asm/arch/eth.h>
+#include <asm/arch/mem.h>
 
 #define EFUSE_SN_OFFSET                20
 #define EFUSE_SN_SIZE          16
@@ -46,3 +47,10 @@ int misc_init_r(void)
 
        return 0;
 }
+
+int ft_board_setup(void *blob, bd_t *bd)
+{
+       meson_gx_init_reserved_memory(blob);
+
+       return 0;
+}
index dcccc6915a42d83af953bdc7fef3e17fe88b677c..f2a30a83e9b4868b33d6f882c95f38c419fdc091 100644 (file)
@@ -17,6 +17,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_CONTROL=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
index a63e9407616c74bd7c7b1236bc0702e3f41c7af1..6583c43c85559ab8e5ff5b933e888c03a7445f8a 100644 (file)
@@ -17,6 +17,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_CONTROL=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
index 1afd2fc1113302dbc674e50b7ac48c4cbdf3ba83..18d2b6825d539912e34216d2e9ec50badd200527 100644 (file)
@@ -16,6 +16,7 @@ CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_CONTROL=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_NET_RANDOM_ETHADDR=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
index d4b534954ee0397f221eab096d7f600e5fb3673e..b6e788b09898c9d38d076e024ec443da2da22f3c 100644 (file)
@@ -17,6 +17,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_GPIO=y
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_OF_CONTROL=y
+CONFIG_OF_BOARD_SETUP=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_MESON_GX=y
index d88d42de9ac2ff99b7468dc3f054f8bb789a58b0..c2b306ad2e6203142b53134a58bfbf9eca872cdf 100644 (file)
@@ -10,7 +10,7 @@
 
 #define CONFIG_CPU_ARMV8
 #define CONFIG_REMAKE_ELF
-#define CONFIG_NR_DRAM_BANKS           2
+#define CONFIG_NR_DRAM_BANKS           1
 #define CONFIG_ENV_SIZE                        0x2000
 #define CONFIG_SYS_MAXARGS             32
 #define CONFIG_SYS_MALLOC_LEN          (32 << 20)