arm64: versal2: Add support for AMD Versal Gen 2

Add support for AMD Versal Gen 2. SoC is based on Cortex-a78ae 4 cluster/2
cpu core each. A lot of IPs are shared with previous families. There are
couple of new IP blocks where the most interesting from user point of view
is UFS.

Signed-off-by: Michal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/bc2b70831ce1031bd0fac32357bff84936e1310f.1716994063.git.michal.simek@amd.com
diff --git a/arch/arm/mach-versal2/Kconfig b/arch/arm/mach-versal2/Kconfig
new file mode 100644
index 0000000..3f18e33
--- /dev/null
+++ b/arch/arm/mach-versal2/Kconfig
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0
+
+if ARCH_VERSAL2
+
+config SYS_BOARD
+	string "Board name"
+	default "versal2"
+
+config SYS_VENDOR
+	string "Vendor name"
+	default "amd"
+
+config SYS_SOC
+	default "versal2"
+
+config SYS_CONFIG_NAME
+	string "Board configuration name"
+	default "amd_versal2"
+	help
+	  This option contains information about board configuration name.
+	  Based on this option include/configs/<CONFIG_SYS_CONFIG_NAME>.h header
+	  will be used for board configuration.
+
+config COUNTER_FREQUENCY
+	int "Timer clock frequency"
+	default 0
+	help
+	  Setup time clock frequency for certain platform
+
+config IOU_SWITCH_DIVISOR0
+	hex "IOU switch divisor0"
+	default 0x20
+	help
+	  Setup time clock divisor for input clock.
+
+config SYS_MEM_RSVD_FOR_MMU
+	bool "Reserve memory for MMU Table"
+	help
+	  If defined this option is used to setup different space for
+	  MMU table than the one which will be allocated during
+	  relocation.
+
+config GICV3
+	def_bool y
+
+config SYS_MALLOC_LEN
+	default 0x2000000
+
+config ZYNQ_SDHCI_MAX_FREQ
+	default 200000000
+
+source "board/xilinx/Kconfig"
+source "board/amd/versal2/Kconfig"
+
+endif
diff --git a/arch/arm/mach-versal2/Makefile b/arch/arm/mach-versal2/Makefile
new file mode 100644
index 0000000..96497b1
--- /dev/null
+++ b/arch/arm/mach-versal2/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2021 - 2022, Xilinx, Inc.
+# Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
+#
+# Michal Simek <michal.simek@amd.com>
+#
+
+obj-y	+= clk.o
+obj-y	+= cpu.o
diff --git a/arch/arm/mach-versal2/clk.c b/arch/arm/mach-versal2/clk.c
new file mode 100644
index 0000000..e73ae9a
--- /dev/null
+++ b/arch/arm/mach-versal2/clk.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016 - 2022,  Xilinx, Inc.
+ * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
+ *
+ * Michal Simek <michal.simek@amd.com>
+ */
+
+#include <init.h>
+#include <time.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_CLOCKS
+/**
+ * set_cpu_clk_info - Initialize clock framework
+ *
+ * Return: 0 always.
+ *
+ * This function is called from common code after relocation and sets up the
+ * clock framework. The framework must not be used before this function had been
+ * called.
+ */
+int set_cpu_clk_info(void)
+{
+	gd->cpu_clk = get_tbclk();
+
+	gd->bd->bi_arm_freq = gd->cpu_clk / 1000000;
+	gd->bd->bi_dsp_freq = 0;
+
+	return 0;
+}
+#endif
diff --git a/arch/arm/mach-versal2/cpu.c b/arch/arm/mach-versal2/cpu.c
new file mode 100644
index 0000000..2dfcadb
--- /dev/null
+++ b/arch/arm/mach-versal2/cpu.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 - 2022, Xilinx, Inc.
+ * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
+ *
+ * Michal Simek <michal.simek@amd.com>
+ */
+
+#include <init.h>
+#include <asm/armv8/mmu.h>
+#include <asm/cache.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/cache.h>
+#include <dm/platdata.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define VERSAL2_MEM_MAP_USED	5
+
+#define DRAM_BANKS CONFIG_NR_DRAM_BANKS
+
+/* +1 is end of list which needs to be empty */
+#define VERSAL2_MEM_MAP_MAX (VERSAL2_MEM_MAP_USED + DRAM_BANKS + 1)
+
+static struct mm_region versal2_mem_map[VERSAL2_MEM_MAP_MAX] = {
+	{
+		.virt = 0x80000000UL,
+		.phys = 0x80000000UL,
+		.size = 0x70000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.virt = 0xf0000000UL,
+		.phys = 0xf0000000UL,
+		.size = 0x0fe00000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.virt = 0x400000000UL,
+		.phys = 0x400000000UL,
+		.size = 0x200000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}, {
+		.virt = 0x600000000UL,
+		.phys = 0x600000000UL,
+		.size = 0x800000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	}, {
+		.virt = 0xe00000000UL,
+		.phys = 0xe00000000UL,
+		.size = 0xf200000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE |
+			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
+	}
+};
+
+void mem_map_fill(void)
+{
+	int banks = VERSAL2_MEM_MAP_USED;
+
+	for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		/* Zero size means no more DDR that's this is end */
+		if (!gd->bd->bi_dram[i].size)
+			break;
+
+		versal2_mem_map[banks].virt = gd->bd->bi_dram[i].start;
+		versal2_mem_map[banks].phys = gd->bd->bi_dram[i].start;
+		versal2_mem_map[banks].size = gd->bd->bi_dram[i].size;
+		versal2_mem_map[banks].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+					      PTE_BLOCK_INNER_SHARE;
+		banks = banks + 1;
+	}
+}
+
+struct mm_region *mem_map = versal2_mem_map;
+
+u64 get_page_table_size(void)
+{
+	return 0x14000;
+}
+
+U_BOOT_DRVINFO(soc_amd_versal2) = {
+	.name = "soc_amd_versal2",
+};
diff --git a/arch/arm/mach-versal2/include/mach/hardware.h b/arch/arm/mach-versal2/include/mach/hardware.h
new file mode 100644
index 0000000..42e3061
--- /dev/null
+++ b/arch/arm/mach-versal2/include/mach/hardware.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016 - 2022, Xilinx, Inc.
+ * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
+ */
+
+#ifndef __ASSEMBLY__
+#include <linux/bitops.h>
+#endif
+
+struct crlapb_regs {
+	u32 reserved0[67];
+	u32 cpu_r5_ctrl;
+	u32 reserved;
+	u32 iou_switch_ctrl; /* 0x114 */
+	u32 reserved1[13];
+	u32 timestamp_ref_ctrl; /* 0x14c */
+	u32 reserved3[108];
+	u32 rst_cpu_r5;
+	u32 reserved2[17];
+	u32 rst_timestamp; /* 0x348 */
+};
+
+struct iou_scntrs_regs {
+	u32 counter_control_register; /* 0x0 */
+	u32 reserved0[7];
+	u32 base_frequency_id_register; /* 0x20 */
+};
+
+struct crp_regs {
+	u32 reserved0[128];
+	u32 boot_mode_usr;	/* 0x200 */
+};
+
+#define VERSAL2_CRL_APB_BASEADDR		0xEB5E0000
+#define VERSAL2_CRP_BASEADDR			0xF1260000
+#define VERSAL2_IOU_SCNTR_SECURE		0xEC920000
+
+#define CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT	BIT(25)
+#define IOU_SWITCH_CTRL_CLKACT_BIT		BIT(25)
+#define IOU_SWITCH_CTRL_DIVISOR0_SHIFT		8
+#define IOU_SCNTRS_CONTROL_EN			1
+
+#define crlapb_base ((struct crlapb_regs *)VERSAL2_CRL_APB_BASEADDR)
+#define crp_base ((struct crp_regs *)VERSAL2_CRP_BASEADDR)
+#define iou_scntr_secure ((struct iou_scntrs_regs *)VERSAL2_IOU_SCNTR_SECURE)
+
+#define PMC_TAP	0xF11A0000
+
+#define PMC_TAP_IDCODE		(PMC_TAP + 0)
+#define PMC_TAP_VERSION		(PMC_TAP + 0x4)
+# define PMC_VERSION_MASK	GENMASK(7, 0)
+# define PS_VERSION_MASK	GENMASK(15, 8)
+# define PS_VERSION_PRODUCTION	0x20
+# define RTL_VERSION_MASK	GENMASK(23, 16)
+# define PLATFORM_MASK		GENMASK(27, 24)
+# define PLATFORM_VERSION_MASK	GENMASK(31, 28)
+#define PMC_TAP_USERCODE	(PMC_TAP + 0x8)
+
+/* Bootmode setting values */
+#define BOOT_MODES_MASK	0x0000000F
+#define QSPI_MODE_24BIT	0x00000001
+#define QSPI_MODE_32BIT	0x00000002
+#define SD_MODE		0x00000003 /* sd 0 */
+#define SD_MODE1	0x00000005 /* sd 1 */
+#define EMMC_MODE	0x00000006
+#define USB_MODE	0x00000007
+#define OSPI_MODE	0x00000008
+#define SELECTMAP_MODE	0x0000000A
+#define SD1_LSHFT_MODE	0x0000000E /* SD1 Level shifter */
+#define JTAG_MODE	0x00000000
+#define BOOT_MODE_USE_ALT	0x100
+#define BOOT_MODE_ALT_SHIFT	12
+
+enum versal2_platform {
+	VERSAL2_SILICON = 0,
+	VERSAL2_SPP = 1,
+	VERSAL2_EMU = 2,
+	VERSAL2_QEMU = 3,
+	VERSAL2_SPP_MMD = 5,
+	VERSAL2_EMU_MMD = 6,
+};
+
+#define VERSAL2_SLCR_BASEADDR	0xF1060000
+#define VERSAL_AXI_MUX_SEL	(VERSAL2_SLCR_BASEADDR + 0x504)
+#define VERSAL_OSPI_LINEAR_MODE	BIT(1)
+
+#define FLASH_RESET_GPIO	0xc
+#define WPROT_CRP	0xF126001C
+#define RST_GPIO	0xF1260318
+#define WPROT_LPD_MIO	0xFF080728
+#define WPROT_PMC_MIO	0xF1060828
+#define BOOT_MODE_DIR	0xF1020204
+#define BOOT_MODE_OUT	0xF1020208
+#define MIO_PIN_12	0xF1060030
+#define BANK0_OUTPUT	0xF1020040
+#define BANK0_TRI	0xF1060200
diff --git a/arch/arm/mach-versal2/include/mach/sys_proto.h b/arch/arm/mach-versal2/include/mach/sys_proto.h
new file mode 100644
index 0000000..7b1726a
--- /dev/null
+++ b/arch/arm/mach-versal2/include/mach/sys_proto.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2021 - 2022, Xilinx, Inc.
+ * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
+ */
+
+#include <linux/build_bug.h>
+
+void mem_map_fill(void);