From 2514c2d0e6abe98157c1de83bce5c8bb69ac3a77 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 12 Mar 2018 10:46:10 +0100 Subject: arm: stm32: add new architecture for STM32MP family - add new arch stm32mp for STM32 MPU/Soc based on Cortex A - support for stm32mp157 SOC - SPL is used as first boot stage loader - using driver model for all the drivers, even in SPL - all security feature are deactivated (ETZC and TZC) - reused STM32 MCU drivers when it is possible Signed-off-by: Patrick Delaunay --- arch/arm/mach-stm32mp/Kconfig | 41 +++++++++ arch/arm/mach-stm32mp/Makefile | 10 +++ arch/arm/mach-stm32mp/config.mk | 14 +++ arch/arm/mach-stm32mp/cpu.c | 139 +++++++++++++++++++++++++++++ arch/arm/mach-stm32mp/dram_init.c | 34 +++++++ arch/arm/mach-stm32mp/include/mach/gpio.h | 115 ++++++++++++++++++++++++ arch/arm/mach-stm32mp/include/mach/stm32.h | 27 ++++++ arch/arm/mach-stm32mp/spl.c | 60 +++++++++++++ 8 files changed, 440 insertions(+) create mode 100644 arch/arm/mach-stm32mp/Kconfig create mode 100644 arch/arm/mach-stm32mp/Makefile create mode 100644 arch/arm/mach-stm32mp/config.mk create mode 100644 arch/arm/mach-stm32mp/cpu.c create mode 100644 arch/arm/mach-stm32mp/dram_init.c create mode 100644 arch/arm/mach-stm32mp/include/mach/gpio.h create mode 100644 arch/arm/mach-stm32mp/include/mach/stm32.h create mode 100644 arch/arm/mach-stm32mp/spl.c (limited to 'arch/arm/mach-stm32mp') diff --git a/arch/arm/mach-stm32mp/Kconfig b/arch/arm/mach-stm32mp/Kconfig new file mode 100644 index 00000000000..ab94879c423 --- /dev/null +++ b/arch/arm/mach-stm32mp/Kconfig @@ -0,0 +1,41 @@ +if ARCH_STM32MP + +config SPL + select SPL_BOARD_INIT + select SPL_CLK + select SPL_DM + select SPL_DM_SEQ_ALIAS + select SPL_FRAMEWORK + select SPL_GPIO_SUPPORT + select SPL_LIBCOMMON_SUPPORT + select SPL_LIBGENERIC_SUPPORT + select SPL_OF_CONTROL + select SPL_OF_TRANSLATE + select SPL_PINCTRL + select SPL_REGMAP + select SPL_RESET_SUPPORT + select SPL_SERIAL_SUPPORT + select SPL_SYSCON + imply SPL_LIBDISK_SUPPORT + +config SYS_SOC + default "stm32mp" + +config TARGET_STM32MP1 + bool "Support stm32mp1xx" + select CPU_V7 + select PINCTRL_STM32 + select STM32_RESET + help + target STMicroelectronics SOC STM32MP1 family + STMicroelectronics MPU with core ARMv7 + +config SYS_TEXT_BASE + prompt "U-Boot base address" + default 0xC0100000 + help + configure the U-Boot base address + when DDR driver is used: + DDR + 1MB (0xC0100000) + +endif diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile new file mode 100644 index 00000000000..4620869b36d --- /dev/null +++ b/arch/arm/mach-stm32mp/Makefile @@ -0,0 +1,10 @@ +# +# Copyright (C) 2018, STMicroelectronics - All Rights Reserved +# +# SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause +# + +obj-y += cpu.o +obj-y += dram_init.o + +obj-$(CONFIG_SPL_BUILD) += spl.o diff --git a/arch/arm/mach-stm32mp/config.mk b/arch/arm/mach-stm32mp/config.mk new file mode 100644 index 00000000000..34e59c61ac0 --- /dev/null +++ b/arch/arm/mach-stm32mp/config.mk @@ -0,0 +1,14 @@ +# +# Copyright (C) 2018, STMicroelectronics - All Rights Reserved +# +# SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause +# + +ALL-$(CONFIG_SPL_BUILD) += spl/u-boot-spl.stm32 + +MKIMAGEFLAGS_u-boot-spl.stm32 = -T stm32image -a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE) + +spl/u-boot-spl.stm32: MKIMAGEOUTPUT = spl/u-boot-spl.stm32.log + +spl/u-boot-spl.stm32: spl/u-boot-spl.bin FORCE + $(call if_changed,mkimage) diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c new file mode 100644 index 00000000000..7c43dc12941 --- /dev/null +++ b/arch/arm/mach-stm32mp/cpu.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause + */ +#include +#include +#include +#include + +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} + +#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) +/********************************************** + * Security init + *********************************************/ +#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) + +#define RCC_TZCR (STM32_RCC_BASE + 0x00) +#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) + +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 + *********************************************/ +#define RCC_DBGCFGR (STM32_RCC_BASE + 0x080C) +#define RCC_DBGCFGR_DBGCKEN BIT(8) + +#define DBGMCU_APB4FZ1 (STM32_DBGMCU_BASE + 0x2C) +#define DBGMCU_APB4FZ1_IWDG2 BIT(2) + +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) */ + +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 + + return 0; +} + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + printf("CPU: STM32MP15x\n"); + + return 0; +} +#endif /* CONFIG_DISPLAY_CPUINFO */ + +void reset_cpu(ulong addr) +{ +} diff --git a/arch/arm/mach-stm32mp/dram_init.c b/arch/arm/mach-stm32mp/dram_init.c new file mode 100644 index 00000000000..ecb4c988d20 --- /dev/null +++ b/arch/arm/mach-stm32mp/dram_init.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + struct ram_info ram; + struct udevice *dev; + int ret; + + ret = uclass_get_device(UCLASS_RAM, 0, &dev); + if (ret) { + debug("RAM init failed: %d\n", ret); + return ret; + } + ret = ram_get_info(dev, &ram); + if (ret) { + debug("Cannot get RAM size: %d\n", ret); + return ret; + } + debug("RAM init base=%lx, size=%x\n", ram.base, ram.size); + + gd->ram_size = ram.size; + + return 0; +} diff --git a/arch/arm/mach-stm32mp/include/mach/gpio.h b/arch/arm/mach-stm32mp/include/mach/gpio.h new file mode 100644 index 00000000000..59525577928 --- /dev/null +++ b/arch/arm/mach-stm32mp/include/mach/gpio.h @@ -0,0 +1,115 @@ +/* + * (C) Copyright 2016 + * Vikas Manocha, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _STM32_GPIO_H_ +#define _STM32_GPIO_H_ +#include + +enum stm32_gpio_port { + STM32_GPIO_PORT_A = 0, + STM32_GPIO_PORT_B, + STM32_GPIO_PORT_C, + STM32_GPIO_PORT_D, + STM32_GPIO_PORT_E, + STM32_GPIO_PORT_F, + STM32_GPIO_PORT_G, + STM32_GPIO_PORT_H, + STM32_GPIO_PORT_I +}; + +enum stm32_gpio_pin { + STM32_GPIO_PIN_0 = 0, + STM32_GPIO_PIN_1, + STM32_GPIO_PIN_2, + STM32_GPIO_PIN_3, + STM32_GPIO_PIN_4, + STM32_GPIO_PIN_5, + STM32_GPIO_PIN_6, + STM32_GPIO_PIN_7, + STM32_GPIO_PIN_8, + STM32_GPIO_PIN_9, + STM32_GPIO_PIN_10, + STM32_GPIO_PIN_11, + STM32_GPIO_PIN_12, + STM32_GPIO_PIN_13, + STM32_GPIO_PIN_14, + STM32_GPIO_PIN_15 +}; + +enum stm32_gpio_mode { + STM32_GPIO_MODE_IN = 0, + STM32_GPIO_MODE_OUT, + STM32_GPIO_MODE_AF, + STM32_GPIO_MODE_AN +}; + +enum stm32_gpio_otype { + STM32_GPIO_OTYPE_PP = 0, + STM32_GPIO_OTYPE_OD +}; + +enum stm32_gpio_speed { + STM32_GPIO_SPEED_2M = 0, + STM32_GPIO_SPEED_25M, + STM32_GPIO_SPEED_50M, + STM32_GPIO_SPEED_100M +}; + +enum stm32_gpio_pupd { + STM32_GPIO_PUPD_NO = 0, + STM32_GPIO_PUPD_UP, + STM32_GPIO_PUPD_DOWN +}; + +enum stm32_gpio_af { + STM32_GPIO_AF0 = 0, + STM32_GPIO_AF1, + STM32_GPIO_AF2, + STM32_GPIO_AF3, + STM32_GPIO_AF4, + STM32_GPIO_AF5, + STM32_GPIO_AF6, + STM32_GPIO_AF7, + STM32_GPIO_AF8, + STM32_GPIO_AF9, + STM32_GPIO_AF10, + STM32_GPIO_AF11, + STM32_GPIO_AF12, + STM32_GPIO_AF13, + STM32_GPIO_AF14, + STM32_GPIO_AF15 +}; + +struct stm32_gpio_dsc { + enum stm32_gpio_port port; + enum stm32_gpio_pin pin; +}; + +struct stm32_gpio_ctl { + enum stm32_gpio_mode mode; + enum stm32_gpio_otype otype; + enum stm32_gpio_speed speed; + enum stm32_gpio_pupd pupd; + enum stm32_gpio_af af; +}; + +struct stm32_gpio_regs { + u32 moder; /* GPIO port mode */ + u32 otyper; /* GPIO port output type */ + u32 ospeedr; /* GPIO port output speed */ + u32 pupdr; /* GPIO port pull-up/pull-down */ + u32 idr; /* GPIO port input data */ + u32 odr; /* GPIO port output data */ + u32 bsrr; /* GPIO port bit set/reset */ + u32 lckr; /* GPIO port configuration lock */ + u32 afr[2]; /* GPIO alternate function */ +}; + +struct stm32_gpio_priv { + struct stm32_gpio_regs *regs; +}; +#endif /* _STM32_GPIO_H_ */ diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h new file mode 100644 index 00000000000..ffbe0b10347 --- /dev/null +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause + */ + +#ifndef _MACH_STM32_H_ +#define _MACH_STM32_H_ + +/* + * Peripheral memory map + * only address used before device tree parsing + */ +#define STM32_RCC_BASE 0x50000000 +#define STM32_PWR_BASE 0x50001000 +#define STM32_DBGMCU_BASE 0x50081000 +#define STM32_TZC_BASE 0x5C006000 +#define STM32_ETZPC_BASE 0x5C007000 +#define STM32_TAMP_BASE 0x5C00A000 + +#define STM32_SYSRAM_BASE 0x2FFC0000 +#define STM32_SYSRAM_SIZE SZ_256K + +#define STM32_DDR_BASE 0xC0000000 +#define STM32_DDR_SIZE SZ_1G + +#endif /* _MACH_STM32_H_ */ diff --git a/arch/arm/mach-stm32mp/spl.c b/arch/arm/mach-stm32mp/spl.c new file mode 100644 index 00000000000..8f5962a9351 --- /dev/null +++ b/arch/arm/mach-stm32mp/spl.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ BSD-3-Clause + */ + +#include +#include +#include + +u32 spl_boot_device(void) +{ + return BOOT_DEVICE_MMC1; +} + +u32 spl_boot_mode(const u32 boot_device) +{ + return MMCSD_MODE_RAW; +} + +void board_init_f(ulong dummy) +{ + struct udevice *dev; + int ret; + + arch_cpu_init(); + + ret = spl_early_init(); + if (ret) { + debug("spl_early_init() failed: %d\n", ret); + hang(); + } + + ret = uclass_get_device(UCLASS_CLK, 0, &dev); + if (ret) { + debug("Clock init failed: %d\n", ret); + return; + } + + ret = uclass_get_device(UCLASS_RESET, 0, &dev); + if (ret) { + debug("Reset init failed: %d\n", ret); + return; + } + + ret = uclass_get_device(UCLASS_PINCTRL, 0, &dev); + if (ret) { + debug("%s: Cannot find pinctrl device\n", __func__); + return; + } + + /* enable console uart printing */ + preloader_console_init(); + + ret = uclass_get_device(UCLASS_RAM, 0, &dev); + if (ret) { + debug("DRAM init failed: %d\n", ret); + return; + } +} -- cgit v1.2.3