meta-st-stm32mp/recipes-bsp/u-boot/u-boot-stm32mp/0007-ARM-v2020.01-stm32mp-r...

530 lines
16 KiB
Diff

From 84a856108aaf180a2cfda252a9b952b55062442e Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
Date: Tue, 27 Oct 2020 11:48:20 +0100
Subject: [PATCH 07/10] ARM-v2020.01-stm32mp-r2-MACHINE
---
Makefile | 2 +-
arch/arm/Kconfig | 28 ++++++++++
arch/arm/include/asm/iproc-common/configs.h | 1 -
arch/arm/include/asm/system.h | 11 ++++
arch/arm/lib/cache-cp15.c | 29 +++++++---
arch/arm/lib/cache.c | 13 +++--
arch/arm/mach-stm32mp/Kconfig | 13 +++++
.../mach-stm32mp/cmd_stm32prog/stm32prog.c | 2 +-
arch/arm/mach-stm32mp/cpu.c | 53 ++++++++++++++++---
arch/arm/mach-stm32mp/fdt.c | 14 +++--
.../mach-stm32mp/include/mach/stm32mp1_smc.h | 48 ++++++++++++-----
.../arm/mach-stm32mp/include/mach/sys_proto.h | 2 +
arch/arm/mach-stm32mp/spl.c | 20 +++++++
13 files changed, 197 insertions(+), 39 deletions(-)
diff --git a/Makefile b/Makefile
index 8b390bc5a3..64b0560af5 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
VERSION = 2020
PATCHLEVEL = 01
SUBLEVEL =
-EXTRAVERSION = -stm32mp-r1
+EXTRAVERSION = -stm32mp-r2
NAME =
# *DOCUMENTATION*
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 36c9c2fecd..f04c37c88c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -329,6 +329,34 @@ config SYS_CACHELINE_SIZE
default 64 if SYS_CACHE_SHIFT_6
default 32 if SYS_CACHE_SHIFT_5
+choice
+ prompt "Select the ARM data write cache policy"
+ default SYS_ARM_CACHE_WRITETHROUGH if TARGET_BCMCYGNUS || \
+ TARGET_BCMNSP || CPU_PXA || RZA1
+ default SYS_ARM_CACHE_WRITEBACK
+
+config SYS_ARM_CACHE_WRITEBACK
+ bool "Write-back (WB)"
+ help
+ A write updates the cache only and marks the cache line as dirty.
+ External memory is updated only when the line is evicted or explicitly
+ cleaned.
+
+config SYS_ARM_CACHE_WRITETHROUGH
+ bool "Write-through (WT)"
+ help
+ A write updates both the cache and the external memory system.
+ This does not mark the cache line as dirty.
+
+config SYS_ARM_CACHE_WRITEALLOC
+ bool "Write allocation (WA)"
+ help
+ A cache line is allocated on a write miss. This means that executing a
+ store instruction on the processor might cause a burst read to occur.
+ There is a linefill to obtain the data for the cache line, before the
+ write is performed.
+endchoice
+
config ARCH_CPU_INIT
bool "Enable ARCH_CPU_INIT"
help
diff --git a/arch/arm/include/asm/iproc-common/configs.h b/arch/arm/include/asm/iproc-common/configs.h
index 96c4f54f4a..4733c0793c 100644
--- a/arch/arm/include/asm/iproc-common/configs.h
+++ b/arch/arm/include/asm/iproc-common/configs.h
@@ -10,7 +10,6 @@
/* Architecture, CPU, chip, etc */
#define CONFIG_IPROC
-#define CONFIG_SYS_ARM_CACHE_WRITETHROUGH
/* Memory Info */
#define CONFIG_SYS_SDRAM_BASE 0x61000000
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index a1a5e35ef6..9fd3b321fc 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -447,6 +447,7 @@ static inline void set_dacr(unsigned int val)
/* options available for data cache on each page */
enum dcache_option {
+ INVALID_ENTRY = 0,
DCACHE_OFF = TTB_SECT | TTB_SECT_MAIR(0) | TTB_SECT_XN_MASK,
DCACHE_WRITETHROUGH = TTB_SECT | TTB_SECT_MAIR(1),
DCACHE_WRITEBACK = TTB_SECT | TTB_SECT_MAIR(2),
@@ -468,6 +469,7 @@ enum dcache_option {
/* options available for data cache on each page */
enum dcache_option {
+ INVALID_ENTRY = 0,
DCACHE_OFF = TTB_SECT_DOMAIN(0) | TTB_SECT_XN_MASK | TTB_SECT,
DCACHE_WRITETHROUGH = DCACHE_OFF | TTB_SECT_C_MASK,
DCACHE_WRITEBACK = DCACHE_WRITETHROUGH | TTB_SECT_B_MASK,
@@ -477,6 +479,7 @@ enum dcache_option {
#define TTB_SECT_AP (3 << 10)
/* options available for data cache on each page */
enum dcache_option {
+ INVALID_ENTRY = 0,
DCACHE_OFF = 0x12,
DCACHE_WRITETHROUGH = 0x1a,
DCACHE_WRITEBACK = 0x1e,
@@ -484,6 +487,14 @@ enum dcache_option {
};
#endif
+#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
+#define DCACHE_DEFAULT_OPTION DCACHE_WRITETHROUGH
+#elif defined(CONFIG_SYS_ARM_CACHE_WRITEALLOC)
+#define DCACHE_DEFAULT_OPTION DCACHE_WRITEALLOC
+#elif defined(CONFIG_SYS_ARM_CACHE_WRITEBACK)
+#define DCACHE_DEFAULT_OPTION DCACHE_WRITEBACK
+#endif
+
/* Size of an MMU section */
enum {
#ifdef CONFIG_ARMV7_LPAE
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
index f8d20960da..16067cf8da 100644
--- a/arch/arm/lib/cache-cp15.c
+++ b/arch/arm/lib/cache-cp15.c
@@ -6,6 +6,7 @@
#include <common.h>
#include <cpu_func.h>
+#include <lmb.h>
#include <asm/system.h>
#include <asm/cache.h>
#include <linux/compiler.h>
@@ -61,8 +62,11 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
unsigned long startpt, stoppt;
unsigned long upto, end;
- end = ALIGN(start + size, MMU_SECTION_SIZE) >> MMU_SECTION_SHIFT;
+ /* div by 2 before start + size to avoid phys_addr_t overflow */
+ end = ALIGN((start / 2) + (size / 2), MMU_SECTION_SIZE / 2)
+ >> (MMU_SECTION_SHIFT - 1);
start = start >> MMU_SECTION_SHIFT;
+
#ifdef CONFIG_ARMV7_LPAE
debug("%s: start=%pa, size=%zu, option=%llx\n", __func__, &start, size,
option);
@@ -89,20 +93,29 @@ void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size,
__weak void dram_bank_mmu_setup(int bank)
{
bd_t *bd = gd->bd;
+ struct lmb lmb;
int i;
+ /* bd->bi_dram is available only after relocation */
+ if ((gd->flags & GD_FLG_RELOC) == 0)
+ return;
+
+ /*
+ * don't allow cache on reserved memory tagged 'no-map' in DT
+ * => avoid speculative access to "secure" data
+ */
+ lmb_init_and_reserve(&lmb, bd, (void *)gd->fdt_blob);
+
debug("%s: bank: %d\n", __func__, bank);
for (i = bd->bi_dram[bank].start >> MMU_SECTION_SHIFT;
i < (bd->bi_dram[bank].start >> MMU_SECTION_SHIFT) +
(bd->bi_dram[bank].size >> MMU_SECTION_SHIFT);
i++) {
-#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
- set_section_dcache(i, DCACHE_WRITETHROUGH);
-#elif defined(CONFIG_SYS_ARM_CACHE_WRITEALLOC)
- set_section_dcache(i, DCACHE_WRITEALLOC);
-#else
- set_section_dcache(i, DCACHE_WRITEBACK);
-#endif
+ if (lmb_is_reserved_flags(&lmb, i << MMU_SECTION_SHIFT,
+ LMB_NOMAP))
+ set_section_dcache(i, INVALID_ENTRY);
+ else
+ set_section_dcache(i, DCACHE_DEFAULT_OPTION);
}
}
diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c
index 007d4ebc49..7f3cfb407c 100644
--- a/arch/arm/lib/cache.c
+++ b/arch/arm/lib/cache.c
@@ -73,6 +73,15 @@ static unsigned long noncached_start;
static unsigned long noncached_end;
static unsigned long noncached_next;
+void noncached_set_region(void)
+{
+#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
+ mmu_set_region_dcache_behaviour(noncached_start,
+ noncached_end - noncached_start,
+ DCACHE_OFF);
+#endif
+}
+
void noncached_init(void)
{
phys_addr_t start, end;
@@ -89,9 +98,7 @@ void noncached_init(void)
noncached_end = end;
noncached_next = start;
-#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
- mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF);
-#endif
+ noncached_set_region();
}
phys_addr_t noncached_alloc(size_t size, size_t align)
diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig
index f9f79437e4..c24717d36d 100644
--- a/arch/arm/mach-stm32mp/Kconfig
+++ b/arch/arm/mach-stm32mp/Kconfig
@@ -103,6 +103,19 @@ config SYS_TEXT_BASE
config NR_DRAM_BANKS
default 1
+config DDR_CACHEABLE_SIZE
+ hex "Size of the DDR marked cacheable in pre-reloc stage"
+ default 0x10000000 if TFABOOT
+ default 0x40000000
+ help
+ Define the size of the DDR marked as cacheable in U-Boot
+ pre-reloc stage.
+ This option can be useful to avoid speculatif access
+ to secured area of DDR used by TF-A or OP-TEE before U-Boot
+ initialization.
+ The areas marked "no-map" in device tree should be located
+ before this limit: STM32_DDR_BASE + DDR_CACHEABLE_SIZE.
+
config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2
hex "Partition on MMC2 to use to load U-Boot from"
depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
index f2f9ed9f36..531df60404 100644
--- a/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
+++ b/arch/arm/mach-stm32mp/cmd_stm32prog/stm32prog.c
@@ -560,7 +560,7 @@ static int init_device(struct stm32prog_data *data,
#ifdef CONFIG_MMC
case STM32PROG_MMC:
mmc = find_mmc_device(dev->dev_id);
- if (mmc_init(mmc)) {
+ if (!mmc || mmc_init(mmc)) {
stm32prog_err("mmc device %d not found", dev->dev_id);
return -ENODEV;
}
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c
index 305534f2ba..aee0f2bf81 100644
--- a/arch/arm/mach-stm32mp/cpu.c
+++ b/arch/arm/mach-stm32mp/cpu.c
@@ -76,6 +76,12 @@
#define PKG_SHIFT 27
#define PKG_MASK GENMASK(2, 0)
+/*
+ * early TLB into the .data section so that it not get cleared
+ * with 16kB allignment (see TTBR0_BASE_ADDR_MASK)
+ */
+u8 early_tlb[PGTABLE_SIZE] __section(".data") __aligned(0x4000);
+
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
#ifndef CONFIG_STM32MP1_TRUSTED
static void security_init(void)
@@ -142,17 +148,17 @@ static void security_init(void)
/*
* Debug init
*/
-static void dbgmcu_init(void)
+void dbgmcu_init(void)
{
- setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
-
/*
* Freeze IWDG2 if Cortex-A7 is in debug mode
* done in TF-A for TRUSTED boot and
* DBGMCU access is controlled by BSEC_DENABLE.DBGSWENABLE
*/
- if (!CONFIG_IS_ENABLED(STM32MP1_TRUSTED) && bsec_dbgswenable())
+ if (!IS_ENABLED(CONFIG_STM32MP1_TRUSTED) && bsec_dbgswenable()) {
+ setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
setbits_le32(DBGMCU_APB4FZ1, DBGMCU_APB4FZ1_IWDG2);
+ }
}
#endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */
@@ -192,6 +198,33 @@ u32 get_bootmode(void)
TAMP_BOOT_MODE_SHIFT;
}
+/*
+ * initialize the MMU and activate cache in SPL or in U-Boot pre-reloc stage
+ * MMU/TLB is updated in enable_caches() for U-Boot after relocation
+ * or is deactivated in U-Boot entry function start.S::cpu_init_cp15
+ */
+static void early_enable_caches(void)
+{
+ /* I-cache is already enabled in start.S: cpu_init_cp15 */
+
+ if (CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+ return;
+
+ gd->arch.tlb_size = PGTABLE_SIZE;
+ gd->arch.tlb_addr = (unsigned long)&early_tlb;
+
+ dcache_enable();
+
+ if (IS_ENABLED(CONFIG_SPL_BUILD))
+ mmu_set_region_dcache_behaviour(STM32_SYSRAM_BASE,
+ STM32_SYSRAM_SIZE,
+ DCACHE_DEFAULT_OPTION);
+ else
+ mmu_set_region_dcache_behaviour(STM32_DDR_BASE,
+ CONFIG_DDR_CACHEABLE_SIZE,
+ DCACHE_DEFAULT_OPTION);
+}
+
/*
* Early system init
*/
@@ -199,11 +232,12 @@ int arch_cpu_init(void)
{
u32 boot_mode;
+ early_enable_caches();
+
/* early armv7 timer init: needed for polling */
timer_init();
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
- dbgmcu_init();
#ifndef CONFIG_STM32MP1_TRUSTED
security_init();
update_bootmode();
@@ -231,7 +265,14 @@ int arch_cpu_init(void)
void enable_caches(void)
{
- /* Enable D-cache. I-cache is already enabled in start.S */
+ /* I-cache is already enabled in start.S: icache_enable() not needed */
+
+ /* deactivate the data cache, early enabled in arch_cpu_init() */
+ dcache_disable();
+ /*
+ * update MMU after relocation and enable the data cache
+ * warning: the TLB location udpated in board_f.c::reserve_mmu
+ */
dcache_enable();
}
diff --git a/arch/arm/mach-stm32mp/fdt.c b/arch/arm/mach-stm32mp/fdt.c
index 21b5f09728..8d9a58186d 100644
--- a/arch/arm/mach-stm32mp/fdt.c
+++ b/arch/arm/mach-stm32mp/fdt.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
- * Copyright (C) 2019, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2019-2020, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
@@ -223,19 +223,23 @@ static void stm32_fdt_disable_optee(void *blob)
{
int off, node;
+ /* Delete "optee" firmware node */
off = fdt_node_offset_by_compatible(blob, -1, "linaro,optee-tz");
if (off >= 0 && fdtdec_get_is_enabled(blob, off))
- fdt_status_disabled(blob, off);
+ fdt_del_node(blob, off);
- /* Disabled "optee@..." reserved-memory node */
+ /* Delete "optee@..." reserved-memory node */
off = fdt_path_offset(blob, "/reserved-memory/");
if (off < 0)
return;
for (node = fdt_first_subnode(blob, off);
node >= 0;
node = fdt_next_subnode(blob, node)) {
- if (!strncmp(fdt_get_name(blob, node, NULL), "optee@", 6))
- fdt_status_disabled(blob, node);
+ if (strncmp(fdt_get_name(blob, node, NULL), "optee@", 6))
+ continue;
+
+ if (fdt_del_node(blob, node))
+ printf("Failed to remove optee reserved-memory node\n");
}
}
diff --git a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
index dea5b4a6b4..d72747ca31 100644
--- a/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
+++ b/arch/arm/mach-stm32mp/include/mach/stm32mp1_smc.h
@@ -8,27 +8,53 @@
#include <linux/arm-smccc.h>
+/* SMC service generic return codes */
+#define STM32_SMC_OK 0x00000000U
+#define STM32_SMC_NOT_SUPPORTED 0xFFFFFFFFU
+#define STM32_SMC_FAILED 0xFFFFFFFEU
+#define STM32_SMC_INVALID_PARAMS 0xFFFFFFFDU
+
/*
- * SMC function IDs for STM32 Service queries
+ * SMC function IDs for STM32 Service queries.
* STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
* like this is defined in SMC calling Convention by ARM
- * for SiP (silicon Partner)
- * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
+ * for SiP (silicon Partner).
+ * https://developer.arm.com/docs/den0028/latest
*/
-#define STM32_SMC_VERSION 0x82000000
/* Secure Service access from Non-secure */
-#define STM32_SMC_RCC 0x82001000
+
+/*
+ * SMC function STM32_SMC_PWR.
+ *
+ * Argument a0: (input) SMCC ID.
+ * (output) Status return code.
+ * Argument a1: (input) Service ID (STM32_SMC_REG_xxx).
+ * Argument a2: (input) Register offset or physical address.
+ * (output) Register read value, if applicable.
+ * Argument a3: (input) Register target value if applicable.
+ */
#define STM32_SMC_PWR 0x82001001
-#define STM32_SMC_RTC 0x82001002
+
+/*
+ * SMC functions STM32_SMC_BSEC.
+ *
+ * Argument a0: (input) SMCC ID.
+ * (output) Status return code.
+ * Argument a1: (input) Service ID (STM32_SMC_READ_xxx/_PROG_xxx/_WRITE_xxx).
+ * (output) OTP read value, if applicable.
+ * Argument a2: (input) OTP index.
+ * Argument a3: (input) OTP value if applicable.
+ */
#define STM32_SMC_BSEC 0x82001003
-/* Register access service use for RCC/RTC/PWR */
+/* Service ID for STM32_SMC_PWR */
+#define STM32_SMC_REG_READ 0x0
#define STM32_SMC_REG_WRITE 0x1
#define STM32_SMC_REG_SET 0x2
#define STM32_SMC_REG_CLEAR 0x3
-/* Service for BSEC */
+/* Service ID for STM32_SMC_BSEC */
#define STM32_SMC_READ_SHADOW 0x01
#define STM32_SMC_PROG_OTP 0x02
#define STM32_SMC_WRITE_SHADOW 0x03
@@ -37,12 +63,6 @@
#define STM32_SMC_WRITE_ALL 0x06
#define STM32_SMC_WRLOCK_OTP 0x07
-/* SMC error codes */
-#define STM32_SMC_OK 0x0
-#define STM32_SMC_NOT_SUPPORTED -1
-#define STM32_SMC_FAILED -2
-#define STM32_SMC_INVALID_PARAMS -3
-
#define stm32_smc_exec(svc, op, data1, data2) \
stm32_smc(svc, op, data1, data2, NULL)
diff --git a/arch/arm/mach-stm32mp/include/mach/sys_proto.h b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
index b6ad3c67ae..c5cab9f21b 100644
--- a/arch/arm/mach-stm32mp/include/mach/sys_proto.h
+++ b/arch/arm/mach-stm32mp/include/mach/sys_proto.h
@@ -52,3 +52,5 @@ int setup_mac_address(void);
/* board power management : configure vddcore according OPP */
void board_vddcore_init(u32 voltage_mv);
int board_vddcore_set(void);
+
+void dbgmcu_init(void);
diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c
index f4b4c3bd82..41f3fd4b7c 100644
--- a/arch/arm/mach-stm32mp/spl.c
+++ b/arch/arm/mach-stm32mp/spl.c
@@ -4,6 +4,7 @@
*/
#include <common.h>
+#include <cpu_func.h>
#include <dm.h>
#include <spl.h>
#include <asm/io.h>
@@ -123,4 +124,23 @@ void board_init_f(ulong dummy)
printf("DRAM init failed: %d\n", ret);
hang();
}
+
+ /*
+ * activate cache on DDR only when DDR is fully initialized
+ * to avoid speculative access and issue in get_ram_size()
+ */
+ if (!CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+ mmu_set_region_dcache_behaviour(STM32_DDR_BASE,
+ CONFIG_DDR_CACHEABLE_SIZE,
+ DCACHE_DEFAULT_OPTION);
+}
+
+void spl_board_prepare_for_boot(void)
+{
+ dcache_disable();
+}
+
+void spl_board_prepare_for_boot_linux(void)
+{
+ dcache_disable();
}
--
2.17.1