stm32mp2: initial support

Add initial support for STM32MP2 SoCs family.

SoCs information are available here :
https://www.st.com/content/st_com/en/campaigns/microprocessor-stm32mp2.html

Migrate all MP1 related code into stm32mp1/ directory
Create stm32mp2 directory dedicated for STM32MP2 SoCs.

Common code to MP1, MP13 and MP25 is kept into
arch/arm/mach-stm32/mach-stm32mp directory :
  - boot_params.c
  - bsec
  - cmd_stm32key
  - cmd_stm32prog
  - dram_init.c
  - syscon.c
  - ecdsa_romapi.c

For STM32MP2, it also :
  - adds memory region description needed for ARMv8 MMU.
  - enables early data cache before relocation.
    During the transition before/after relocation, the MMU, initially setup
    at the beginning of DDR, must be setup again at a correct address after
    relocation. This is done in enables_caches() by disabling cache, force
    arch.tlb_fillptr to NULL which will force the MMU to be setup again but
    with a new value for gd->arch.tlb_addr. gd->arch.tlb_addr has been
    updated after relocation in arm_reserve_mmu().

Signed-off-by: Patrice Chotard <patrice.chotard@foss.st.com>
Reviewed-by: Patrick Delaunay <patrick.delaunay@foss.st.com>
diff --git a/arch/arm/mach-stm32mp/stm32mp2/Makefile b/arch/arm/mach-stm32mp/stm32mp2/Makefile
new file mode 100644
index 0000000..b579ce5
--- /dev/null
+++ b/arch/arm/mach-stm32mp/stm32mp2/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+#
+# Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+#
+
+obj-y += cpu.o
+obj-y += arm64-mmu.o
+obj-$(CONFIG_OF_SYSTEM_SETUP) += fdt.o
+obj-$(CONFIG_STM32MP25X) += stm32mp25x.o
diff --git a/arch/arm/mach-stm32mp/stm32mp2/arm64-mmu.c b/arch/arm/mach-stm32mp/stm32mp2/arm64-mmu.c
new file mode 100644
index 0000000..a203eeb
--- /dev/null
+++ b/arch/arm/mach-stm32mp/stm32mp2/arm64-mmu.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+#include <asm/system.h>
+#include <asm/armv8/mmu.h>
+
+#define MP2_MEM_MAP_MAX 10
+
+#if (CONFIG_TEXT_BASE < STM32_DDR_BASE) || \
+	(CONFIG_TEXT_BASE > (STM32_DDR_BASE + STM32_DDR_SIZE))
+#error "invalid CONFIG_TEXT_BASE value"
+#endif
+
+struct mm_region stm32mp2_mem_map[MP2_MEM_MAP_MAX] = {
+	{
+		/* PCIe */
+		.virt = 0x10000000UL,
+		.phys = 0x10000000UL,
+		.size = 0x10000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* LPSRAMs, VDERAM, RETRAM, SRAMs, SYSRAM: alias1 */
+		.virt = 0x20000000UL,
+		.phys = 0x20000000UL,
+		.size = 0x00200000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* Peripherals: alias1 */
+		.virt = 0x40000000UL,
+		.phys = 0x40000000UL,
+		.size = 0x10000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/* OSPI and FMC: memory-map area */
+		.virt = 0x60000000UL,
+		.phys = 0x60000000UL,
+		.size = 0x20000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		/*
+		 * DDR = STM32_DDR_BASE / STM32_DDR_SIZE
+		 * the beginning of DDR (before CONFIG_TEXT_BASE) is not
+		 * mapped, protected by RIF and reserved for other firmware
+		 * (OP-TEE / TF-M / Cube M33)
+		 */
+		.virt = CONFIG_TEXT_BASE,
+		.phys = CONFIG_TEXT_BASE,
+		.size = STM32_DDR_SIZE - (CONFIG_TEXT_BASE - STM32_DDR_BASE),
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = stm32mp2_mem_map;
diff --git a/arch/arm/mach-stm32mp/stm32mp2/cpu.c b/arch/arm/mach-stm32mp/stm32mp2/cpu.c
new file mode 100644
index 0000000..5bfeab1
--- /dev/null
+++ b/arch/arm/mach-stm32mp/stm32mp2/cpu.c
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ */
+
+#define LOG_CATEGORY LOGC_ARCH
+
+#include <common.h>
+#include <clk.h>
+#include <cpu_func.h>
+#include <debug_uart.h>
+#include <env_internal.h>
+#include <init.h>
+#include <misc.h>
+#include <wdt.h>
+#include <asm/io.h>
+#include <asm/arch/stm32.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/system.h>
+#include <dm/device.h>
+#include <dm/lists.h>
+#include <dm/uclass.h>
+
+/*
+ * early TLB into the .data section so that it not get cleared
+ * with 16kB alignment
+ */
+#define EARLY_TLB_SIZE 0xA000
+u8 early_tlb[EARLY_TLB_SIZE] __section(".data") __aligned(0x4000);
+
+/*
+ * initialize the MMU and activate cache in U-Boot pre-reloc stage
+ * MMU/TLB is updated in enable_caches() for U-Boot after relocation
+ */
+static void early_enable_caches(void)
+{
+	if (CONFIG_IS_ENABLED(SYS_DCACHE_OFF))
+		return;
+
+	if (!(CONFIG_IS_ENABLED(SYS_ICACHE_OFF) && CONFIG_IS_ENABLED(SYS_DCACHE_OFF))) {
+		gd->arch.tlb_size = EARLY_TLB_SIZE;
+		gd->arch.tlb_addr = (unsigned long)&early_tlb;
+	}
+	/* enable MMU (default configuration) */
+	dcache_enable();
+}
+
+/*
+ * Early system init
+ */
+int arch_cpu_init(void)
+{
+	icache_enable();
+	early_enable_caches();
+
+	return 0;
+}
+
+void enable_caches(void)
+{
+	/* deactivate the data cache, early enabled in arch_cpu_init() */
+	dcache_disable();
+	/*
+	 * Force the call of setup_all_pgtables() in mmu_setup() by clearing tlb_fillptr
+	 * to update the TLB location udpated in board_f.c::reserve_mmu
+	 */
+	gd->arch.tlb_fillptr = 0;
+	dcache_enable();
+}
+
+/* used when CONFIG_DISPLAY_CPUINFO is activated */
+int print_cpuinfo(void)
+{
+	char name[SOC_NAME_SIZE];
+
+	get_soc_name(name);
+	printf("CPU: %s\n", name);
+
+	return 0;
+}
+
+int arch_misc_init(void)
+{
+	return 0;
+}
+
+/*
+ * Force data-section, as .bss will not be valid
+ * when save_boot_params is invoked.
+ */
+static uintptr_t nt_fw_dtb __section(".data");
+
+uintptr_t get_stm32mp_bl2_dtb(void)
+{
+	return nt_fw_dtb;
+}
+
+/*
+ * Save the FDT address provided by TF-A in r2 at boot time
+ * This function is called from start.S
+ */
+void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2,
+		      unsigned long r3)
+{
+	nt_fw_dtb = r2;
+
+	save_boot_params_ret();
+}
diff --git a/arch/arm/mach-stm32mp/stm32mp2/fdt.c b/arch/arm/mach-stm32mp/stm32mp2/fdt.c
new file mode 100644
index 0000000..ee57086
--- /dev/null
+++ b/arch/arm/mach-stm32mp/stm32mp2/fdt.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ */
+
+#include <common.h>
+
+/*
+ * This function is called right before the kernel is booted. "blob" is the
+ * device tree that will be passed to the kernel.
+ */
+int ft_system_setup(void *blob, struct bd_info *bd)
+{
+	return 0;
+}
+
diff --git a/arch/arm/mach-stm32mp/stm32mp2/stm32mp25x.c b/arch/arm/mach-stm32mp/stm32mp2/stm32mp25x.c
new file mode 100644
index 0000000..7d2dab2
--- /dev/null
+++ b/arch/arm/mach-stm32mp/stm32mp2/stm32mp25x.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
+/*
+ * Copyright (C) 2023, STMicroelectronics - All Rights Reserved
+ */
+
+#define LOG_CATEGORY LOGC_ARCH
+
+#include <common.h>
+#include <log.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/stm32.h>
+#include <asm/arch/sys_proto.h>
+
+/* SYSCFG register */
+#define SYSCFG_DEVICEID_OFFSET		0x6400
+#define SYSCFG_DEVICEID_DEV_ID_MASK	GENMASK(11, 0)
+#define SYSCFG_DEVICEID_DEV_ID_SHIFT	0
+#define SYSCFG_DEVICEID_REV_ID_MASK	GENMASK(31, 16)
+#define SYSCFG_DEVICEID_REV_ID_SHIFT	16
+
+/* Device Part Number (RPN) = OTP9 */
+#define RPN_SHIFT	0
+#define RPN_MASK	GENMASK(31, 0)
+
+/* Package = bit 0:2 of OTP122 => STM32MP25_PKG defines
+ * - 000: Custom package
+ * - 011: TFBGA361 => AL = 10x10, 361 balls pith 0.5mm
+ * - 100: TFBGA424 => AK = 14x14, 424 balls pith 0.5mm
+ * - 101: TFBGA436 => AI = 18x18, 436 balls pith 0.5mm
+ * - others: Reserved
+ */
+#define PKG_SHIFT	0
+#define PKG_MASK	GENMASK(2, 0)
+
+static u32 read_deviceid(void)
+{
+	void *syscfg = syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
+
+	return readl(syscfg + SYSCFG_DEVICEID_OFFSET);
+}
+
+u32 get_cpu_dev(void)
+{
+	return (read_deviceid() & SYSCFG_DEVICEID_DEV_ID_MASK) >> SYSCFG_DEVICEID_DEV_ID_SHIFT;
+}
+
+u32 get_cpu_rev(void)
+{
+	return (read_deviceid() & SYSCFG_DEVICEID_REV_ID_MASK) >> SYSCFG_DEVICEID_REV_ID_SHIFT;
+}
+
+/* Get Device Part Number (RPN) from OTP */
+u32 get_cpu_type(void)
+{
+	return get_otp(BSEC_OTP_RPN, RPN_SHIFT, RPN_MASK);
+}
+
+/* Get Package options from OTP */
+u32 get_cpu_package(void)
+{
+	return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK);
+}
+
+int get_eth_nb(void)
+{
+	int nb_eth;
+
+	switch (get_cpu_type()) {
+	case CPU_STM32MP257Fxx:
+		fallthrough;
+	case CPU_STM32MP257Dxx:
+		fallthrough;
+	case CPU_STM32MP257Cxx:
+		fallthrough;
+	case CPU_STM32MP257Axx:
+		nb_eth = 5; /* dual ETH with TSN support */
+		break;
+	case CPU_STM32MP253Fxx:
+		fallthrough;
+	case CPU_STM32MP253Dxx:
+		fallthrough;
+	case CPU_STM32MP253Cxx:
+		fallthrough;
+	case CPU_STM32MP253Axx:
+		nb_eth = 2; /* dual ETH */
+		break;
+	case CPU_STM32MP251Fxx:
+		fallthrough;
+	case CPU_STM32MP251Dxx:
+		fallthrough;
+	case CPU_STM32MP251Cxx:
+		fallthrough;
+	case CPU_STM32MP251Axx:
+		nb_eth = 1; /* single ETH */
+		break;
+	default:
+		nb_eth = 0;
+		break;
+	}
+
+	return nb_eth;
+}
+
+void get_soc_name(char name[SOC_NAME_SIZE])
+{
+	char *cpu_s, *cpu_r, *package;
+
+	cpu_s = "????";
+	cpu_r = "?";
+	package = "??";
+	if (get_cpu_dev() == CPU_DEV_STM32MP25) {
+		switch (get_cpu_type()) {
+		case CPU_STM32MP257Fxx:
+			cpu_s = "257F";
+			break;
+		case CPU_STM32MP257Dxx:
+			cpu_s = "257D";
+			break;
+		case CPU_STM32MP257Cxx:
+			cpu_s = "257C";
+			break;
+		case CPU_STM32MP257Axx:
+			cpu_s = "257A";
+			break;
+		case CPU_STM32MP255Fxx:
+			cpu_s = "255F";
+			break;
+		case CPU_STM32MP255Dxx:
+			cpu_s = "255D";
+			break;
+		case CPU_STM32MP255Cxx:
+			cpu_s = "255C";
+			break;
+		case CPU_STM32MP255Axx:
+			cpu_s = "255A";
+			break;
+		case CPU_STM32MP253Fxx:
+			cpu_s = "253F";
+			break;
+		case CPU_STM32MP253Dxx:
+			cpu_s = "253D";
+			break;
+		case CPU_STM32MP253Cxx:
+			cpu_s = "253C";
+			break;
+		case CPU_STM32MP253Axx:
+			cpu_s = "253A";
+			break;
+		case CPU_STM32MP251Fxx:
+			cpu_s = "251F";
+			break;
+		case CPU_STM32MP251Dxx:
+			cpu_s = "251D";
+			break;
+		case CPU_STM32MP251Cxx:
+			cpu_s = "251C";
+			break;
+		case CPU_STM32MP251Axx:
+			cpu_s = "251A";
+			break;
+		default:
+			cpu_s = "25??";
+			break;
+		}
+		/* REVISION */
+		switch (get_cpu_rev()) {
+		case CPU_REV1:
+			cpu_r = "A";
+			break;
+		default:
+			break;
+		}
+		/* PACKAGE */
+		switch (get_cpu_package()) {
+		case STM32MP25_PKG_CUSTOM:
+			package = "XX";
+			break;
+		case STM32MP25_PKG_AL_TBGA361:
+			package = "AL";
+			break;
+		case STM32MP25_PKG_AK_TBGA424:
+			package = "AK";
+			break;
+		case STM32MP25_PKG_AI_TBGA436:
+			package = "AI";
+			break;
+		default:
+			break;
+		}
+	}
+
+	snprintf(name, SOC_NAME_SIZE, "STM32MP%s%s Rev.%s", cpu_s, package, cpu_r);
+}