Use Shikra fixed pre-DDR memory map when enabling caches in SPL. Allocate page tables from the early malloc-F heap and select the board map through a common Qualcomm hook.
Signed-off-by: Abhilash V <[email protected]> --- arch/arm/mach-snapdragon/mem_map.c | 24 ++++- arch/arm/mach-snapdragon/qcom-priv.h | 4 + board/qualcomm/shikra/spl-shikra.c | 140 +++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-snapdragon/mem_map.c b/arch/arm/mach-snapdragon/mem_map.c index 17c18e5096a..9df522f7a4e 100644 --- a/arch/arm/mach-snapdragon/mem_map.c +++ b/arch/arm/mach-snapdragon/mem_map.c @@ -28,6 +28,19 @@ static struct mm_region rbx_mem_map[CONFIG_NR_DRAM_BANKS + 2] = { { 0 } }; struct mm_region *mem_map = rbx_mem_map; +#if defined(CONFIG_SPL_BUILD) +enum qcom_memmap_source qcom_memmap_source __section(".data") = 0; +#endif + +/* + * SPL platforms whose pre-DRAM address map differs from the common Qualcomm + * map may override this hook. + */ +struct mm_region *__weak qcom_spl_mem_map(void) +{ + return NULL; +} + static void build_mem_map(void) { int i, j; @@ -65,10 +78,12 @@ static void build_mem_map(void) #endif } +#if !defined(CONFIG_SPL_BUILD) u64 get_page_table_size(void) { return SZ_1M; } +#endif struct mem_resource_attrs { fdt_addr_t start; @@ -185,6 +200,7 @@ static void configure_reserved_memory(void) */ void enable_caches(void) { + struct mm_region *spl_mem_map; u64 tlb_addr = gd->arch.tlb_addr; u64 tlb_size = gd->arch.tlb_size; u64 pt_size; @@ -192,7 +208,11 @@ void enable_caches(void) gd->arch.tlb_fillptr = tlb_addr; - build_mem_map(); + spl_mem_map = qcom_spl_mem_map(); + if (spl_mem_map) + mem_map = spl_mem_map; + else + build_mem_map(); icache_enable(); @@ -223,4 +243,4 @@ void enable_caches(void) debug("carveout time: %lums\n", get_timer(carveout_start)); } dcache_enable(); -} \ No newline at end of file +} diff --git a/arch/arm/mach-snapdragon/qcom-priv.h b/arch/arm/mach-snapdragon/qcom-priv.h index 27e5c54e512..c267c0d9aec 100644 --- a/arch/arm/mach-snapdragon/qcom-priv.h +++ b/arch/arm/mach-snapdragon/qcom-priv.h @@ -5,6 +5,8 @@ #include <stdbool.h> +struct mm_region; + /** * enum qcom_boot_source - Track where we got loaded from. * Used for capsule update logic. @@ -40,4 +42,6 @@ static inline void qcom_configure_capsule_updates(void) {} int qcom_parse_memory(const void *fdt, bool fdt_is_internal); +struct mm_region *qcom_spl_mem_map(void); + #endif /* __QCOM_PRIV_H__ */ diff --git a/board/qualcomm/shikra/spl-shikra.c b/board/qualcomm/shikra/spl-shikra.c index b967b0137b1..9bab677cce5 100644 --- a/board/qualcomm/shikra/spl-shikra.c +++ b/board/qualcomm/shikra/spl-shikra.c @@ -3,15 +3,107 @@ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ #include <blk.h> +#include <cpu_func.h> #include <asm/io.h> +#include <asm/sections.h> +#include <asm/system.h> +#include <asm/armv8/mmu.h> #include <dm/uclass.h> +#include <init.h> #include <linux/err.h> +#include <linux/sizes.h> #include <linux/string.h> +#include <malloc.h> #include <mach/qclib.h> #include <mach/spl.h> #include <part.h> #include <spl.h> +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_SPL_BUILD) +/* + * The SPL device tree does not describe the complete early physical layout, + * so use Shikra's fixed map when enabling the MMU. + */ +#define SHIKRA_SPL_DEVICE_REG_LOW_BASE 0x00000000UL +#define SHIKRA_SPL_SYSTEM_IMEM_BASE 0x0c100000UL +#define SHIKRA_SPL_SYSTEM_IMEM_SIZE 0x00020000UL +#define SHIKRA_SPL_BOOTIMEM_BASE 0x0c200000UL +#define SHIKRA_SPL_BOOTIMEM_SIZE 0x001c0000UL +#define SHIKRA_SPL_DEVICE_REG_HIGH_BASE (SHIKRA_SPL_BOOTIMEM_BASE + \ + SHIKRA_SPL_BOOTIMEM_SIZE) +#define SHIKRA_SPL_DDR_BASE 0x80000000UL +#define SHIKRA_SPL_DDR_SIZE 0x80000000UL +#define SHIKRA_SPL_DDR2_BASE 0x880000000ULL +#define SHIKRA_SPL_DDR2_SIZE (SZ_32G - SZ_2G) +#define SHIKRA_SPL_DEVICE_REG_LOW_SIZE (SHIKRA_SPL_SYSTEM_IMEM_BASE - \ + SHIKRA_SPL_DEVICE_REG_LOW_BASE) +#define SHIKRA_SPL_DEVICE_REG_HIGH_SIZE (SHIKRA_SPL_DDR_BASE - \ + SHIKRA_SPL_DEVICE_REG_HIGH_BASE) + +static struct mm_region shikra_spl_mem_map[] = { + { + .virt = SHIKRA_SPL_DEVICE_REG_LOW_BASE, + .phys = SHIKRA_SPL_DEVICE_REG_LOW_BASE, + .size = SHIKRA_SPL_DEVICE_REG_LOW_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE, + }, { + .virt = SHIKRA_SPL_SYSTEM_IMEM_BASE, + .phys = SHIKRA_SPL_SYSTEM_IMEM_BASE, + .size = SHIKRA_SPL_SYSTEM_IMEM_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { + /* SPL and QCLIB execute directly from BOOT_IMEM. */ + .virt = SHIKRA_SPL_BOOTIMEM_BASE, + .phys = SHIKRA_SPL_BOOTIMEM_BASE, + .size = SHIKRA_SPL_BOOTIMEM_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { + .virt = SHIKRA_SPL_DEVICE_REG_HIGH_BASE, + .phys = SHIKRA_SPL_DEVICE_REG_HIGH_BASE, + .size = SHIKRA_SPL_DEVICE_REG_HIGH_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE, + }, { + .virt = SHIKRA_SPL_DDR_BASE, + .phys = SHIKRA_SPL_DDR_BASE, + .size = SHIKRA_SPL_DDR_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | + PTE_BLOCK_INNER_SHARE, + }, { + .virt = SHIKRA_SPL_DDR2_BASE, + .phys = SHIKRA_SPL_DDR2_BASE, + .size = SHIKRA_SPL_DDR2_SIZE, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | + PTE_BLOCK_INNER_SHARE, + }, { + 0, + } +}; + +struct mm_region *qcom_spl_mem_map(void) +{ + return shikra_spl_mem_map; +} + +int arm_reserve_mmu(void) +{ +#if !(CONFIG_IS_ENABLED(SYS_ICACHE_OFF) && CONFIG_IS_ENABLED(SYS_DCACHE_OFF)) + mem_map = qcom_spl_mem_map(); + gd->arch.tlb_size = PGTABLE_SIZE; + gd->arch.tlb_addr = (unsigned long)memalign(SZ_64K, gd->arch.tlb_size); + if (!gd->arch.tlb_addr) + return -ENOMEM; +#endif + + return 0; +} +#endif + #define IPQ_SPL_BOOTCFG_REG_ADDR 0x1B46070 #define IPQ_SPL_BOOTCFG_DEV_MASK GENMASK(5, 1) #define IPQ_SPL_BOOTCFG_DEV_SHFT 0x1 @@ -55,6 +147,54 @@ enum { IPQ_SPL_BOOTCFG_DEV_MAX }; +#if defined(CONFIG_SPL_BUILD) +void board_init_f(ulong dummy) +{ + int ret = 0; + + memset(__bss_start, 0, __bss_end - __bss_start); + + qcom_spl_malloc_init_f(); + + ret = spl_early_init(); + if (ret) { + pr_debug("spl_early_init() failed (%d)\n", ret); + goto fail; + } + + event_notify_null(EVT_LAST_STAGE_INIT); + + preloader_console_init(); + +#if !(CONFIG_IS_ENABLED(SYS_ICACHE_OFF) && CONFIG_IS_ENABLED(SYS_DCACHE_OFF)) + ret = arm_reserve_mmu(); + if (ret) { + pr_debug("arm_reserve_mmu() failed (%d)\n", ret); + goto fail; + } + + enable_caches(); +#endif + + ret = qcom_spl_loader_pre_ddr(spl_boot_device()); + if (ret) { + pr_debug("qcom_spl_loader_pre_ddr() failed (%d)\n", ret); + goto fail; + } + + ret = qcom_spl_invoke_qclib(); + if (ret) { + pr_debug("qcom_spl_invoke_qclib() failed (%d)\n", ret); + goto fail; + } + + board_init_r(NULL, 0); + +fail: + if (ret) + reset_cpu(); +} +#endif int qcom_spl_soc_qclib_override(struct interface_table *table, const void *fit, int images_node) { -- 2.34.1
