diff options
Diffstat (limited to 'arch/arm/mach-stm32mp/cpu.c')
-rw-r--r-- | arch/arm/mach-stm32mp/cpu.c | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c new file mode 100644 index 00000000000..f9f3bf9050e --- /dev/null +++ b/arch/arm/mach-stm32mp/cpu.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause + */ +#include <common.h> +#include <clk.h> +#include <asm/io.h> +#include <asm/arch/stm32.h> +#include <asm/arch/sys_proto.h> +#include <dm/uclass.h> + +/* RCC register */ +#define RCC_TZCR (STM32_RCC_BASE + 0x00) +#define RCC_DBGCFGR (STM32_RCC_BASE + 0x080C) +#define RCC_BDCR (STM32_RCC_BASE + 0x0140) +#define RCC_MP_APB5ENSETR (STM32_RCC_BASE + 0x0208) +#define RCC_BDCR_VSWRST BIT(31) +#define RCC_BDCR_RTCSRC GENMASK(17, 16) +#define RCC_DBGCFGR_DBGCKEN BIT(8) + +/* Security register */ +#define ETZPC_TZMA1_SIZE (STM32_ETZPC_BASE + 0x04) +#define ETZPC_DECPROT0 (STM32_ETZPC_BASE + 0x10) + +#define TZC_GATE_KEEPER (STM32_TZC_BASE + 0x008) +#define TZC_REGION_ATTRIBUTE0 (STM32_TZC_BASE + 0x110) +#define TZC_REGION_ID_ACCESS0 (STM32_TZC_BASE + 0x114) + +#define TAMP_CR1 (STM32_TAMP_BASE + 0x00) + +#define PWR_CR1 (STM32_PWR_BASE + 0x00) +#define PWR_CR1_DBP BIT(8) + +/* DBGMCU register */ +#define DBGMCU_IDC (STM32_DBGMCU_BASE + 0x00) +#define DBGMCU_APB4FZ1 (STM32_DBGMCU_BASE + 0x2C) +#define DBGMCU_APB4FZ1_IWDG2 BIT(2) +#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0) +#define DBGMCU_IDC_DEV_ID_SHIFT 0 +#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16) +#define DBGMCU_IDC_REV_ID_SHIFT 16 + +/* boot interface from Bootrom + * - boot instance = bit 31:16 + * - boot device = bit 15:0 + */ +#define BOOTROM_PARAM_ADDR 0x2FFC0078 +#define BOOTROM_MODE_MASK GENMASK(15, 0) +#define BOOTROM_MODE_SHIFT 0 +#define BOOTROM_INSTANCE_MASK GENMASK(31, 16) +#define BOOTROM_INSTANCE_SHIFT 16 + +#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) +static void security_init(void) +{ + /* Disable the backup domain write protection */ + /* the protection is enable at each reset by hardware */ + /* And must be disable by software */ + setbits_le32(PWR_CR1, PWR_CR1_DBP); + + while (!(readl(PWR_CR1) & PWR_CR1_DBP)) + ; + + /* If RTC clock isn't enable so this is a cold boot then we need + * to reset the backup domain + */ + if (!(readl(RCC_BDCR) & RCC_BDCR_RTCSRC)) { + setbits_le32(RCC_BDCR, RCC_BDCR_VSWRST); + while (!(readl(RCC_BDCR) & RCC_BDCR_VSWRST)) + ; + clrbits_le32(RCC_BDCR, RCC_BDCR_VSWRST); + } + + /* allow non secure access in Write/Read for all peripheral */ + writel(GENMASK(25, 0), ETZPC_DECPROT0); + + /* Open SYSRAM for no secure access */ + writel(0x0, ETZPC_TZMA1_SIZE); + + /* enable TZC1 TZC2 clock */ + writel(BIT(11) | BIT(12), RCC_MP_APB5ENSETR); + + /* Region 0 set to no access by default */ + /* bit 0 / 16 => nsaid0 read/write Enable + * bit 1 / 17 => nsaid1 read/write Enable + * ... + * bit 15 / 31 => nsaid15 read/write Enable + */ + writel(0xFFFFFFFF, TZC_REGION_ID_ACCESS0); + /* bit 30 / 31 => Secure Global Enable : write/read */ + /* bit 0 / 1 => Region Enable for filter 0/1 */ + writel(BIT(0) | BIT(1) | BIT(30) | BIT(31), TZC_REGION_ATTRIBUTE0); + + /* Enable Filter 0 and 1 */ + setbits_le32(TZC_GATE_KEEPER, BIT(0) | BIT(1)); + + /* RCC trust zone deactivated */ + writel(0x0, RCC_TZCR); + + /* TAMP: deactivate the internal tamper + * Bit 23 ITAMP8E: monotonic counter overflow + * Bit 20 ITAMP5E: RTC calendar overflow + * Bit 19 ITAMP4E: HSE monitoring + * Bit 18 ITAMP3E: LSE monitoring + * Bit 16 ITAMP1E: RTC power domain supply monitoring + */ + writel(0x0, TAMP_CR1); +} + +/* + * Debug init + */ +static void dbgmcu_init(void) +{ + setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); + + /* Freeze IWDG2 if Cortex-A7 is in debug mode */ + setbits_le32(DBGMCU_APB4FZ1, DBGMCU_APB4FZ1_IWDG2); +} +#endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */ + +static u32 get_bootmode(void) +{ + u32 boot_mode; +#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) + u32 bootrom_itf = readl(BOOTROM_PARAM_ADDR); + u32 bootrom_device, bootrom_instance; + + bootrom_device = + (bootrom_itf & BOOTROM_MODE_MASK) >> BOOTROM_MODE_SHIFT; + bootrom_instance = + (bootrom_itf & BOOTROM_INSTANCE_MASK) >> BOOTROM_INSTANCE_SHIFT; + boot_mode = + ((bootrom_device << BOOT_TYPE_SHIFT) & BOOT_TYPE_MASK) | + ((bootrom_instance << BOOT_INSTANCE_SHIFT) & + BOOT_INSTANCE_MASK); + + /* save the boot mode in TAMP backup register */ + clrsetbits_le32(TAMP_BOOT_CONTEXT, + TAMP_BOOT_MODE_MASK, + boot_mode << TAMP_BOOT_MODE_SHIFT); +#else + /* read TAMP backup register */ + boot_mode = (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >> + TAMP_BOOT_MODE_SHIFT; +#endif + return boot_mode; +} + +/* + * Early system init + */ +int arch_cpu_init(void) +{ + /* early armv7 timer init: needed for polling */ + timer_init(); + +#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) + dbgmcu_init(); + + security_init(); +#endif + /* get bootmode from BootRom context: saved in TAMP register */ + get_bootmode(); + + return 0; +} + +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} + +static u32 read_idc(void) +{ + setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN); + + return readl(DBGMCU_IDC); +} + +u32 get_cpu_rev(void) +{ + return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT; +} + +u32 get_cpu_type(void) +{ + return (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + char *cpu_s, *cpu_r; + + switch (get_cpu_type()) { + case CPU_STMP32MP15x: + cpu_s = "15x"; + break; + default: + cpu_s = "?"; + break; + } + + switch (get_cpu_rev()) { + case CPU_REVA: + cpu_r = "A"; + break; + case CPU_REVB: + cpu_r = "B"; + break; + default: + cpu_r = "?"; + break; + } + + printf("CPU: STM32MP%s.%s\n", cpu_s, cpu_r); + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ + +static void setup_boot_mode(void) +{ + char cmd[60]; + u32 boot_ctx = readl(TAMP_BOOT_CONTEXT); + u32 boot_mode = + (boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT; + int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1; + + pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d\n", + __func__, boot_ctx, boot_mode, instance); + + switch (boot_mode & TAMP_BOOT_DEVICE_MASK) { + case BOOT_SERIAL_UART: + sprintf(cmd, "%d", instance); + env_set("boot_device", "uart"); + env_set("boot_instance", cmd); + break; + case BOOT_SERIAL_USB: + env_set("boot_device", "usb"); + env_set("boot_instance", "0"); + break; + case BOOT_FLASH_SD: + case BOOT_FLASH_EMMC: + sprintf(cmd, "%d", instance); + env_set("boot_device", "mmc"); + env_set("boot_instance", cmd); + break; + case BOOT_FLASH_NAND: + env_set("boot_device", "nand"); + env_set("boot_instance", "0"); + break; + case BOOT_FLASH_NOR: + env_set("boot_device", "nor"); + env_set("boot_instance", "0"); + break; + default: + pr_debug("unexpected boot mode = %x\n", boot_mode); + break; + } +} + +int arch_misc_init(void) +{ + setup_boot_mode(); + + return 0; +} |