
This is for new platform enablement for agilex5. Add platform related files to enable new product.
Signed-off-by: Jit Loon Lim jit.loon.lim@intel.com --- arch/arm/mach-socfpga/Kconfig | 37 +++ arch/arm/mach-socfpga/Makefile | 69 ++++- arch/arm/mach-socfpga/board.c | 65 ++++- arch/arm/mach-socfpga/clock_manager_agilex5.c | 82 ++++++ arch/arm/mach-socfpga/firewall.c | 107 ------- arch/arm/mach-socfpga/lowlevel_init_agilex5.S | 61 ++++ arch/arm/mach-socfpga/lowlevel_init_soc64.S | 167 ++++++++++- arch/arm/mach-socfpga/mailbox_s10.c | 21 ++ arch/arm/mach-socfpga/misc.c | 19 +- arch/arm/mach-socfpga/misc_soc64.c | 33 ++- arch/arm/mach-socfpga/mmu-arm64_s10.c | 43 ++- arch/arm/mach-socfpga/reset_manager_s10.c | 271 +++++++++++++++--- arch/arm/mach-socfpga/secure_reg_helper.c | 4 +- arch/arm/mach-socfpga/smmu_agilex5.c | 34 +++ arch/arm/mach-socfpga/smmu_s10.c | 126 ++++++++ arch/arm/mach-socfpga/spl_agilex5.c | 180 ++++++++++++ arch/arm/mach-socfpga/spl_soc64.c | 188 +++++++++++- arch/arm/mach-socfpga/u-boot-spl-soc64.lds | 93 ++++++ arch/arm/mach-socfpga/wrap_handoff_soc64.c | 7 +- 19 files changed, 1429 insertions(+), 178 deletions(-) create mode 100644 arch/arm/mach-socfpga/clock_manager_agilex5.c delete mode 100644 arch/arm/mach-socfpga/firewall.c create mode 100644 arch/arm/mach-socfpga/lowlevel_init_agilex5.S create mode 100644 arch/arm/mach-socfpga/smmu_agilex5.c create mode 100644 arch/arm/mach-socfpga/smmu_s10.c create mode 100644 arch/arm/mach-socfpga/spl_agilex5.c create mode 100644 arch/arm/mach-socfpga/u-boot-spl-soc64.lds
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 503c82d388..562c3796ec 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -44,6 +44,15 @@ config TEXT_BASE default 0x01000040 if TARGET_SOCFPGA_ARRIA10 default 0x01000040 if TARGET_SOCFPGA_GEN5
+config ARMV8_PSCI_NR_CPUS + default 4 if TARGET_SOCFPGA_SOC64 + +config ARMV8_SECURE_BASE + default 0x00001000 if TARGET_SOCFPGA_SOC64 && ARMV8_PSCI + +config SYS_HAS_ARMV8_SECURE_BASE + default y if TARGET_SOCFPGA_SOC64 && ARMV8_PSCI + config TARGET_SOCFPGA_AGILEX bool select ARMV8_MULTIENTRY @@ -51,10 +60,31 @@ config TARGET_SOCFPGA_AGILEX select BINMAN if SPL_ATF select CLK select FPGA_INTEL_SDM_MAILBOX + select GICV2 + select NCORE_CACHE + select SPL_CLK if SPL + select TARGET_SOCFPGA_SOC64 + +config TARGET_SOCFPGA_AGILEX5 + bool + select BINMAN if SPL_ATF + select CLK + select FPGA_INTEL_SDM_MAILBOX + select GICV3 select NCORE_CACHE select SPL_CLK if SPL select TARGET_SOCFPGA_SOC64
+config TARGET_SOCFPGA_AGILEX5_EMU + bool "Enable build that bootable only on Agilex5 Emulator" + help + This is to use for Agilex5 Emulator. + +config TARGET_SOCFPGA_AGILEX5_SIMICS + bool "Enable build that bootable only on Agilex5 Simics platform" + help + This is to use for Agilex5 Simics. + config TARGET_SOCFPGA_ARRIA5 bool select TARGET_SOCFPGA_GEN5 @@ -126,6 +156,10 @@ config TARGET_SOCFPGA_AGILEX_SOCDK bool "Intel SOCFPGA SoCDK (Agilex)" select TARGET_SOCFPGA_AGILEX
+config TARGET_SOCFPGA_AGILEX5_SOCDK + bool "Intel SOCFPGA SoCDK (Agilex5)" + select TARGET_SOCFPGA_AGILEX5 + config TARGET_SOCFPGA_ARIES_MCVEVK bool "Aries MCVEVK (Cyclone V)" select TARGET_SOCFPGA_CYCLONE5 @@ -199,6 +233,7 @@ config TARGET_SOCFPGA_TERASIC_SOCKIT endchoice
config SYS_BOARD + default "agilex5-socdk" if TARGET_SOCFPGA_AGILEX5_SOCDK default "agilex-socdk" if TARGET_SOCFPGA_AGILEX_SOCDK default "arria5-socdk" if TARGET_SOCFPGA_ARRIA5_SOCDK default "arria10-socdk" if TARGET_SOCFPGA_ARRIA10_SOCDK @@ -220,6 +255,7 @@ config SYS_BOARD default "vining_fpga" if TARGET_SOCFPGA_SOFTING_VINING_FPGA
config SYS_VENDOR + default "intel" if TARGET_SOCFPGA_AGILEX5_SOCDK default "intel" if TARGET_SOCFPGA_AGILEX_SOCDK default "intel" if TARGET_SOCFPGA_N5X_SOCDK default "altera" if TARGET_SOCFPGA_ARRIA5_SOCDK @@ -242,6 +278,7 @@ config SYS_SOC default "socfpga"
config SYS_CONFIG_NAME + default "socfpga_agilex5_socdk" if TARGET_SOCFPGA_AGILEX5_SOCDK default "socfpga_agilex_socdk" if TARGET_SOCFPGA_AGILEX_SOCDK default "socfpga_arria5_secu1" if TARGET_SOCFPGA_ARRIA5_SECU1 default "socfpga_arria5_socdk" if TARGET_SOCFPGA_ARRIA5_SOCDK diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index ec38b64dd4..771e7ce77d 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -35,10 +35,22 @@ obj-y += mailbox_s10.o obj-y += misc_soc64.o obj-y += mmu-arm64_s10.o obj-y += reset_manager_s10.o +obj-y += smmu_s10.o obj-y += system_manager_soc64.o obj-y += timer_s10.o obj-y += wrap_handoff_soc64.o obj-y += wrap_pll_config_soc64.o +ifndef CONFIG_SPL_BUILD +obj-y += rsu.o +obj-y += rsu_ll_qspi.o +obj-y += rsu_misc.o +obj-y += rsu_s10.o +obj-$(CONFIG_ARMV8_PSCI) += psci.o +obj-$(CONFIG_ARMV8_PSCI) += smc_ecc_dbe_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_fpga_reconfig_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_registers_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_rsu_s10.o +endif endif
ifdef CONFIG_TARGET_SOCFPGA_AGILEX @@ -49,11 +61,46 @@ obj-y += misc_soc64.o obj-y += mmu-arm64_s10.o obj-y += reset_manager_s10.o obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH) += secure_vab.o +obj-y += smmu_s10.o obj-y += system_manager_soc64.o obj-y += timer_s10.o obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH) += vab.o obj-y += wrap_handoff_soc64.o obj-y += wrap_pll_config_soc64.o +ifndef CONFIG_SPL_BUILD +obj-y += rsu.o +obj-y += rsu_ll_qspi.o +obj-y += rsu_misc.o +obj-y += rsu_s10.o +obj-$(CONFIG_ARMV8_PSCI) += psci.o +obj-$(CONFIG_ARMV8_PSCI) += smc_ecc_dbe_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_fpga_reconfig_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_registers_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_rsu_s10.o +endif +endif + +ifdef CONFIG_TARGET_SOCFPGA_AGILEX5 +obj-y += clock_manager_agilex5.o +obj-y += lowlevel_init_agilex5.o +obj-y += mailbox_s10.o +obj-y += misc_soc64.o +obj-y += mmu-arm64_s10.o +obj-y += reset_manager_s10.o +obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH) += secure_vab.o +obj-y += smmu_agilex5.o +obj-y += system_manager_soc64.o +obj-y += timer_s10.o +obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH) += vab.o +obj-y += wrap_handoff_soc64.o +obj-y += wrap_pll_config_soc64.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_ARMV8_PSCI) += psci.o +obj-$(CONFIG_ARMV8_PSCI) += smc_ecc_dbe_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_fpga_reconfig_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_registers_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_rsu_s10.o +endif endif
ifdef CONFIG_TARGET_SOCFPGA_N5X @@ -64,11 +111,22 @@ obj-y += misc_soc64.o obj-y += mmu-arm64_s10.o obj-y += reset_manager_s10.o obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH) += secure_vab.o +obj-y += smmu_s10.o obj-y += system_manager_soc64.o obj-y += timer_s10.o obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH) += vab.o obj-y += wrap_handoff_soc64.o obj-y += wrap_pll_config_soc64.o +ifndef CONFIG_SPL_BUILD +obj-y += rsu.o +obj-y += rsu_ll_qspi.o +obj-y += rsu_misc.o +obj-y += rsu_s10.o +obj-$(CONFIG_ARMV8_PSCI) += psci.o +obj-$(CONFIG_ARMV8_PSCI) += smc_ecc_dbe_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_registers_s10.o +obj-$(CONFIG_ARMV8_PSCI) += smc_rsu_s10.o +endif endif
ifdef CONFIG_SPL_BUILD @@ -79,21 +137,24 @@ obj-y += wrap_iocsr_config.o obj-y += wrap_pinmux_config.o obj-y += wrap_sdram_config.o endif -ifdef CONFIG_TARGET_SOCFPGA_SOC64 -obj-y += firewall.o -obj-y += spl_soc64.o -endif ifdef CONFIG_TARGET_SOCFPGA_ARRIA10 obj-y += spl_a10.o endif ifdef CONFIG_TARGET_SOCFPGA_STRATIX10 obj-y += spl_s10.o +obj-y += spl_soc64.o endif ifdef CONFIG_TARGET_SOCFPGA_AGILEX obj-y += spl_agilex.o +obj-y += spl_soc64.o endif ifdef CONFIG_TARGET_SOCFPGA_N5X obj-y += spl_n5x.o +obj-y += spl_soc64.o +endif +ifdef CONFIG_TARGET_SOCFPGA_AGILEX5 +obj-y += spl_agilex5.o +obj-y += spl_soc64.o endif else obj-$(CONFIG_SPL_ATF) += secure_reg_helper.o diff --git a/arch/arm/mach-socfpga/board.c b/arch/arm/mach-socfpga/board.c index 09e09192fb..140a520ab7 100644 --- a/arch/arm/mach-socfpga/board.c +++ b/arch/arm/mach-socfpga/board.c @@ -7,9 +7,11 @@
#include <common.h> #include <asm/arch/clock_manager.h> +#include <asm/arch/mailbox_s10.h> #include <asm/arch/misc.h> #include <asm/arch/reset_manager.h> #include <asm/arch/secure_vab.h> +#include <asm/arch/smc_api.h> #include <asm/global_data.h> #include <asm/io.h> #include <errno.h> @@ -23,6 +25,8 @@
DECLARE_GLOBAL_DATA_PTR;
+#define DEFAULT_JTAG_USERCODE 0xFFFFFFFF + void s_init(void) { #ifndef CONFIG_ARM64 /* @@ -46,7 +50,7 @@ void s_init(void) { int board_init(void) { /* Address of boot parameters for ATAG (if ATAG is used) */ - gd->bd->bi_boot_params = CFG_SYS_SDRAM_BASE + 0x100; + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
return 0; } @@ -92,13 +96,55 @@ int g_dnl_board_usb_cable_connected(void) } #endif
-#ifdef CONFIG_SPL_BUILD -__weak int board_fit_config_name_match(const char *name) +u8 socfpga_get_board_id(void) { - /* Just empty function now - can't decide what to choose */ - debug("%s: %s\n", __func__, name); + u8 board_id = 0; + u32 jtag_usercode; + int err;
- return 0; +#if !IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_SPL_ATF) + err = smc_get_usercode(&jtag_usercode); +#else + u32 resp_len = 1; + + err = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_GET_USERCODE, MBOX_CMD_DIRECT, 0, + NULL, 0, &resp_len, &jtag_usercode); +#endif + + if (err) { + puts("Fail to read JTAG Usercode. Default Board ID to 0\n"); + return board_id; + } + + debug("Valid JTAG Usercode: %u\n", jtag_usercode); + + if (jtag_usercode == DEFAULT_JTAG_USERCODE) { + debug("JTAG Usercode is not set. Default Board ID to 0\n"); + } else if (jtag_usercode >= 0 && jtag_usercode <= 255) { + board_id = jtag_usercode; + debug("Valid JTAG Usercode. Set Board ID to %u\n", board_id); + } else { + puts("Board ID is not in range 0 to 255\n"); + } + + return board_id; +} + +#if IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_SOCFPGA_SOC64) +int board_fit_config_name_match(const char *name) +{ + char board_name[10]; + +#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS) || \ +IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU) + sprintf(board_name, "board_%u", 0); /* Hardcoded board ID since Simics no support */ +#else + sprintf(board_name, "board_%u", socfpga_get_board_id()); +#endif + + debug("Board name: %s\n", board_name); + + return strcmp(name, board_name); } #endif
@@ -116,6 +162,8 @@ void board_fit_image_post_process(const void *fit, int node, void **p_image, #if !IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_FIT) void board_prep_linux(struct bootm_headers *images) { + bool use_fit = false; + if (!images->fit_uname_cfg) { if (IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH) && !IS_ENABLED(CONFIG_SOCFPGA_SECURE_VAB_AUTH_ALLOW_NON_FIT_IMAGE)) { @@ -127,14 +175,17 @@ void board_prep_linux(struct bootm_headers *images) hang(); } } else { + use_fit = true; /* Update fdt_addr in enviroment variable */ env_set_hex("fdt_addr", (ulong)images->ft_addr); debug("images->ft_addr = 0x%08lx\n", (ulong)images->ft_addr); }
- if (IS_ENABLED(CONFIG_CADENCE_QSPI)) { + if (use_fit && IS_ENABLED(CONFIG_CADENCE_QSPI)) { if (env_get("linux_qspi_enable")) run_command(env_get("linux_qspi_enable"), 0); + if (env_get("rsu_status")) + run_command(env_get("rsu_status"), 0); } } #endif diff --git a/arch/arm/mach-socfpga/clock_manager_agilex5.c b/arch/arm/mach-socfpga/clock_manager_agilex5.c new file mode 100644 index 0000000000..46b6bc5d40 --- /dev/null +++ b/arch/arm/mach-socfpga/clock_manager_agilex5.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019-2022 Intel Corporation <www.intel.com> + * + */ + +#include <clk.h> +#include <common.h> +#include <dm.h> +#include <log.h> +#include <malloc.h> +#include <asm/arch/clock_manager.h> +#include <asm/arch/system_manager.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <dt-bindings/clock/agilex5-clock.h> + +DECLARE_GLOBAL_DATA_PTR; + +static ulong cm_get_rate_dm(u32 id) +{ + struct udevice *dev; + struct clk clk; + ulong rate; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_CLK, + DM_DRIVER_GET(socfpga_agilex5_clk), + &dev); + if (ret) + return 0; + + clk.id = id; + ret = clk_request(dev, &clk); + if (ret < 0) + return 0; + + rate = clk_get_rate(&clk); + + clk_free(&clk); + + if ((rate == (unsigned long)-ENOSYS) || + (rate == (unsigned long)-ENXIO) || + (rate == (unsigned long)-EIO)) { + debug("%s id %u: clk_get_rate err: %ld\n", + __func__, id, rate); + return 0; + } + + return rate; +} + +static u32 cm_get_rate_dm_khz(u32 id) +{ + return cm_get_rate_dm(id) / 1000; +} + +unsigned long cm_get_mpu_clk_hz(void) +{ + return cm_get_rate_dm(AGILEX5_MPU_CLK); +} + +unsigned int cm_get_l4_sys_free_clk_hz(void) +{ + return cm_get_rate_dm(AGILEX5_L4_SYS_FREE_CLK); +} + +void cm_print_clock_quick_summary(void) +{ + printf("MPU %10d kHz\n", + cm_get_rate_dm_khz(AGILEX5_MPU_CLK)); + printf("L4 Main %8d kHz\n", + cm_get_rate_dm_khz(AGILEX5_L4_MAIN_CLK)); + printf("L4 sys free %8d kHz\n", + cm_get_rate_dm_khz(AGILEX5_L4_SYS_FREE_CLK)); + printf("L4 MP %8d kHz\n", + cm_get_rate_dm_khz(AGILEX5_L4_MP_CLK)); + printf("L4 SP %8d kHz\n", + cm_get_rate_dm_khz(AGILEX5_L4_SP_CLK)); + printf("SDMMC %8d kHz\n", + cm_get_rate_dm_khz(AGILEX5_SDMMC_CLK)); +} diff --git a/arch/arm/mach-socfpga/firewall.c b/arch/arm/mach-socfpga/firewall.c deleted file mode 100644 index 69229dc651..0000000000 --- a/arch/arm/mach-socfpga/firewall.c +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2016-2019 Intel Corporation <www.intel.com> - * - */ - -#include <asm/io.h> -#include <common.h> -#include <asm/arch/firewall.h> -#include <asm/arch/system_manager.h> - -static void firewall_l4_per_disable(void) -{ - const struct socfpga_firwall_l4_per *firwall_l4_per_base = - (struct socfpga_firwall_l4_per *)SOCFPGA_FIREWALL_L4_PER; - u32 i; - const u32 *addr[] = { - &firwall_l4_per_base->nand, - &firwall_l4_per_base->nand_data, - &firwall_l4_per_base->usb0, - &firwall_l4_per_base->usb1, - &firwall_l4_per_base->spim0, - &firwall_l4_per_base->spim1, - &firwall_l4_per_base->emac0, - &firwall_l4_per_base->emac1, - &firwall_l4_per_base->emac2, - &firwall_l4_per_base->sdmmc, - &firwall_l4_per_base->gpio0, - &firwall_l4_per_base->gpio1, - &firwall_l4_per_base->i2c0, - &firwall_l4_per_base->i2c1, - &firwall_l4_per_base->i2c2, - &firwall_l4_per_base->i2c3, - &firwall_l4_per_base->i2c4, - &firwall_l4_per_base->timer0, - &firwall_l4_per_base->timer1, - &firwall_l4_per_base->uart0, - &firwall_l4_per_base->uart1 - }; - - /* - * The following lines of code will enable non-secure access - * to nand, usb, spi, emac, sdmmc, gpio, i2c, timers and uart. This - * is needed as most OS run in non-secure mode. Thus we need to - * enable non-secure access to these peripherals in order for the - * OS to use these peripherals. - */ - for (i = 0; i < ARRAY_SIZE(addr); i++) - writel(FIREWALL_L4_DISABLE_ALL, addr[i]); -} - -static void firewall_l4_sys_disable(void) -{ - const struct socfpga_firwall_l4_sys *firwall_l4_sys_base = - (struct socfpga_firwall_l4_sys *)SOCFPGA_FIREWALL_L4_SYS; - u32 i; - const u32 *addr[] = { - &firwall_l4_sys_base->dma_ecc, - &firwall_l4_sys_base->emac0rx_ecc, - &firwall_l4_sys_base->emac0tx_ecc, - &firwall_l4_sys_base->emac1rx_ecc, - &firwall_l4_sys_base->emac1tx_ecc, - &firwall_l4_sys_base->emac2rx_ecc, - &firwall_l4_sys_base->emac2tx_ecc, - &firwall_l4_sys_base->nand_ecc, - &firwall_l4_sys_base->nand_read_ecc, - &firwall_l4_sys_base->nand_write_ecc, - &firwall_l4_sys_base->ocram_ecc, - &firwall_l4_sys_base->sdmmc_ecc, - &firwall_l4_sys_base->usb0_ecc, - &firwall_l4_sys_base->usb1_ecc, - &firwall_l4_sys_base->clock_manager, - &firwall_l4_sys_base->io_manager, - &firwall_l4_sys_base->reset_manager, - &firwall_l4_sys_base->system_manager, - &firwall_l4_sys_base->watchdog0, - &firwall_l4_sys_base->watchdog1, - &firwall_l4_sys_base->watchdog2, - &firwall_l4_sys_base->watchdog3 - }; - - for (i = 0; i < ARRAY_SIZE(addr); i++) - writel(FIREWALL_L4_DISABLE_ALL, addr[i]); -} - -static void firewall_bridge_disable(void) -{ - /* disable lwsocf2fpga and soc2fpga bridge security */ - writel(FIREWALL_BRIDGE_DISABLE_ALL, SOCFPGA_FIREWALL_SOC2FPGA); - writel(FIREWALL_BRIDGE_DISABLE_ALL, SOCFPGA_FIREWALL_LWSOC2FPGA); -} - -void firewall_setup(void) -{ - firewall_l4_per_disable(); - firewall_l4_sys_disable(); - firewall_bridge_disable(); - - /* disable SMMU security */ - writel(FIREWALL_L4_DISABLE_ALL, SOCFPGA_FIREWALL_TCU); - - /* enable non-secure interface to DMA330 DMA and peripherals */ - writel(SYSMGR_DMA_IRQ_NS | SYSMGR_DMA_MGR_NS, - socfpga_get_sysmgr_addr() + SYSMGR_SOC64_DMA); - writel(SYSMGR_DMAPERIPH_ALL_NS, - socfpga_get_sysmgr_addr() + SYSMGR_SOC64_DMA_PERIPH); -} diff --git a/arch/arm/mach-socfpga/lowlevel_init_agilex5.S b/arch/arm/mach-socfpga/lowlevel_init_agilex5.S new file mode 100644 index 0000000000..15e5066767 --- /dev/null +++ b/arch/arm/mach-socfpga/lowlevel_init_agilex5.S @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2022-2023 Intel Corporation <www.intel.com> + * + */ + +#include <asm-offsets.h> +#include <config.h> +#include <linux/linkage.h> +#include <asm/macro.h> +#include <asm/arch/reset_manager_soc64.h> + +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_ARMV8_PSCI) +.align 3 +_el3_exception_vectors: + .quad el3_exception_vectors; +#endif + +ENTRY(lowlevel_init) + mov x29, lr /* Save LR */ + +#ifdef CONFIG_SPL_BUILD + branch_if_slave x0, 3f + + /* Check rstmgr.stat for warm reset status */ + ldr w1, =SOCFPGA_RSTMGR_ADDRESS + ldr w0, [x1] + /* Check whether any L4 watchdogs or SDM had triggered warm reset */ + ldr x2, =RSTMGR_L4WD_MPU_WARMRESET_MASK + ands x0, x0, x2 + /* + * If current Reset Manager's status is warm reset just reload the + * .data section by copying the data from data preserve section. + * Otherwise, copy the .data section to the data preserve section to + * keep an original copy of .data section. This ensure SPL is + * reentrant after warm reset. + */ + b.ne reload_data_section + /* Copy from .data to preserved .data to backup the SPL state */ + ldr x0, =__data_start + ldr x1, =__preserve_data_start + ldr x2, =__preserve_data_end + b copy_loop +reload_data_section: + /* Copy from preserved .data to .data to restore the SPL state */ + ldr x0, =__preserve_data_start + ldr x1, =__data_start + ldr x2, =__data_end +copy_loop: + ldr w3, [x0] + add x0, x0, #4 + str w3, [x1] + add x1, x1, #4 + cmp x1, x2 + b.ne copy_loop +3: +#endif + + mov lr, x29 /* Restore LR */ + ret +ENDPROC(lowlevel_init) diff --git a/arch/arm/mach-socfpga/lowlevel_init_soc64.S b/arch/arm/mach-socfpga/lowlevel_init_soc64.S index 875927cc4d..5680553f68 100644 --- a/arch/arm/mach-socfpga/lowlevel_init_soc64.S +++ b/arch/arm/mach-socfpga/lowlevel_init_soc64.S @@ -1,7 +1,7 @@ -/* - * Copyright (C) 2020 Intel Corporation. All rights reserved +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2022-2023 Intel Corporation <www.intel.com> * - * SPDX-License-Identifier: GPL-2.0 */
#include <asm-offsets.h> @@ -9,11 +9,101 @@ #include <linux/linkage.h> #include <asm/macro.h>
+#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_ARMV8_PSCI) +.align 3 +_el3_exception_vectors: + .quad el3_exception_vectors; +#endif + ENTRY(lowlevel_init) mov x29, lr /* Save LR */
+#ifdef CONFIG_SPL_BUILD + /* Check for L2 reset magic word */ + ldr x4, =L2_RESET_DONE_REG + ldr x5, [x4] + ldr x1, =L2_RESET_DONE_STATUS + cmp x1, x5 + /* No L2 reset, skip warm reset */ + b.ne skipwarmreset + /* Put all slaves CPUs into WFI mode */ + branch_if_slave x0, put_cpu_in_wfi + /* L2 reset completed */ + str xzr, [x4] + /* Clear previous CPU release address */ + ldr x4, =CPU_RELEASE_ADDR + str wzr, [x4] + /* Master CPU (CPU0) request for warm reset */ + mrs x1, rmr_el3 + orr x1, x1, #0x02 + msr rmr_el3, x1 + isb + dsb sy +put_cpu_in_wfi: + wfi + b put_cpu_in_wfi +skipwarmreset: +#endif + #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3) #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) + + /* + * In ATF flow, need to clear the old CPU address when cold reset + * being triggered, but shouldn't clear CPU address if it is reset + * by CPU-ON, so that the core can correctly jump to ATF code after + * reset by CPU-ON. CPU-ON trigger the reset via mpumodrst. + * + * Hardware will set 1 to core*_irq in mpurststat register in + * reset manager if the core is reset by mpumodrst. + * + * The following code will check the mpurststat to identify if the + * core is reset by mpumodrst, and it will skip CPU address clearing + * if the core is reset by mpumodrst. At last, the code need to clear + * the core*_irq by set it to 1. So that it can reflect the correct + * and latest status in next reset. + */ + + /* Check if it is a master core off/on from kernel using boot scratch + * cold register 8 bit 19. This bit is set by ATF. + */ + ldr x4, =BOOT_SCRATCH_COLD8 + ldr x5, [x4] + and x6, x5, #0x80000 + cbnz x6, wait_for_atf_master + + /* Retrieve mpurststat register in reset manager */ + ldr x4, =SOCFPGA_RSTMGR_ADDRESS + ldr w5, [x4, #0x04] + + /* Set mask based on current core id */ + mrs x0, mpidr_el1 + and x1, x0, #0xF + ldr x2, =0x00000100 + lsl x2, x2, x1 + + /* Skip if core*_irq register is set */ + and x6, x5, x2 + cbnz x6, skip_clear_cpu_address + + /* + * Reach here means core*_irq is 0, means the core is + * reset by cold, warm or watchdog reset. + * Clear previous CPU release address + */ + ldr x4, =CPU_RELEASE_ADDR + str wzr, [x4] + b skip_clear_core_irq + +skip_clear_cpu_address: + /* Clear core*_irq register by writing 1 */ + ldr x4, =SOCFPGA_RSTMGR_ADDRESS + str w2, [x4, #0x04] + +skip_clear_core_irq: + /* Master CPU (CPU0) does not need to wait for atf */ + branch_if_master x0, master_cpu + wait_for_atf: ldr x4, =CPU_RELEASE_ADDR ldr x5, [x4] @@ -21,6 +111,16 @@ wait_for_atf: br x5 slave_wait_atf: branch_if_slave x0, wait_for_atf + +wait_for_atf_master: + ldr x4, =CPU_RELEASE_ADDR + ldr x5, [x4] + cbz x5, master_wait_atf + br x5 +master_wait_atf: + branch_if_master x0, wait_for_atf_master + +master_cpu: #else branch_if_slave x0, 1f #endif @@ -52,6 +152,18 @@ slave_wait_atf: bl gic_wait_for_interrupt #endif
+#if defined(CONFIG_SPL_BUILD) && !defined(CONFIG_SPL_ATF) + /* + * Read the u-boot's PSCI exception handler's vector base + * address from the sysmgr.boot_scratch_cold6 & 7 and update + * their VBAR_EL3 respectively. + */ +wait_vbar_el3: + ldr x4, =VBAR_EL3_BASE_ADDR + ldr x5, [x4] + cbz x5, wait_vbar_el3 + msr vbar_el3, x5 +#endif /* * All slaves will enter EL2 and optionally EL1. */ @@ -71,6 +183,55 @@ lowlevel_in_el1: #endif /* CONFIG_ARMV8_MULTIENTRY */
2: +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_ARMV8_PSCI) + /* + * Write the u-boot PSCI exception handler's vector base address + * into a sysmgr.boot_scratch_cold6 & 7 so that other slave cpus + * are able to get the vector base address and update their VBAR_EL3 + * respectively. + */ + adr x0, _el3_exception_vectors + ldr x5, [x0] + ldr x4, =VBAR_EL3_BASE_ADDR + str x5, [x4] +#endif + +#ifdef CONFIG_SPL_BUILD + branch_if_slave x0, 3f + + /* Check rstmgr.stat for warm reset status */ + ldr x1, =SOCFPGA_RSTMGR_ADDRESS + ldr x0, [x1] + /* Check whether any L4 watchdogs or MPUs had triggered warm reset */ + ldr x2, =0x000F0F00 + ands x0, x0, x2 + /* + * If current Reset Manager's status is warm reset just reload the + * .data section by copying the data from data preserve section. + * Otherwise, copy the .data section to the data preserve section to + * keep an original copy of .data section. This ensure SPL is + * reentrant after warm reset. + */ + b.ne reload_data_section + /* Copy from .data to preserved .data to backup the SPL state */ + ldr x0, =__data_start + ldr x1, =__preserve_data_start + ldr x2, =__preserve_data_end + b copy_loop +reload_data_section: + /* Copy from preserved .data to .data to restore the SPL state */ + ldr x0, =__preserve_data_start + ldr x1, =__data_start + ldr x2, =__data_end +copy_loop: + ldr w3, [x0] + add x0, x0, #4 + str w3, [x1] + add x1, x1, #4 + cmp x1, x2 + b.ne copy_loop +3: +#endif mov lr, x29 /* Restore LR */ ret ENDPROC(lowlevel_init) diff --git a/arch/arm/mach-socfpga/mailbox_s10.c b/arch/arm/mach-socfpga/mailbox_s10.c index 101af23855..7846596c17 100644 --- a/arch/arm/mach-socfpga/mailbox_s10.c +++ b/arch/arm/mach-socfpga/mailbox_s10.c @@ -7,7 +7,9 @@ #include <common.h> #include <asm/arch/clock_manager.h> #include <asm/arch/mailbox_s10.h> +#include <asm/arch/smc_api.h> #include <asm/arch/system_manager.h> +#include <asm/arch/timer.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/secure.h> @@ -454,6 +456,14 @@ static __always_inline int mbox_get_fpga_config_status_common(u32 cmd) return MBOX_CFGSTAT_STATE_CONFIG; }
+#ifdef CONFIG_ARMV8_PSCI +int __secure mbox_hps_stage_notify_psci(u32 execution_stage) +{ + return mbox_send_cmd_psci(MBOX_ID_UBOOT, MBOX_HPS_STAGE_NOTIFY, + MBOX_CMD_DIRECT, 1, &execution_stage, 0, 0, NULL); +} +#endif + int mbox_get_fpga_config_status(u32 cmd) { return mbox_get_fpga_config_status_common(cmd); @@ -479,6 +489,17 @@ int __secure mbox_send_cmd_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, urgent, resp_buf_len, resp_buf); }
+int mbox_hps_stage_notify(u32 execution_stage) +{ +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) + return smc_send_mailbox(MBOX_HPS_STAGE_NOTIFY, 1, &execution_stage, + 0, 0, NULL); +#else + return mbox_send_cmd(MBOX_ID_UBOOT, MBOX_HPS_STAGE_NOTIFY, + MBOX_CMD_DIRECT, 1, &execution_stage, 0, 0, NULL); +#endif +} + int mbox_send_cmd_only(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg) { return mbox_send_cmd_only_common(id, cmd, is_indirect, len, arg); diff --git a/arch/arm/mach-socfpga/misc.c b/arch/arm/mach-socfpga/misc.c index 5b5a81a255..024b714ecb 100644 --- a/arch/arm/mach-socfpga/misc.c +++ b/arch/arm/mach-socfpga/misc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2012-2017 Altera Corporation <www.altera.com> + * Copyright (C) 2012-2023 Altera Corporation <www.altera.com> */
#include <common.h> @@ -34,7 +34,7 @@ phys_addr_t socfpga_sysmgr_base __section(".data");
#ifdef CONFIG_SYS_L2_PL310 static const struct pl310_regs *const pl310 = - (struct pl310_regs *)CFG_SYS_PL310_BASE; + (struct pl310_regs *)CONFIG_SYS_PL310_BASE; #endif
struct bsel bsel_str[] = { @@ -164,7 +164,10 @@ int arch_cpu_init(void) * timeout value is still active which might too short for Linux * booting. */ +#if !(IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS) || \ +IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU)) hw_watchdog_init(); +#endif #else /* * If the HW watchdog is NOT enabled, make sure it is not running, @@ -208,10 +211,11 @@ static int do_bridge(struct cmd_tbl *cmdtp, int flag, int argc, }
U_BOOT_CMD(bridge, 3, 1, do_bridge, - "SoCFPGA HPS FPGA bridge control", - "enable [mask] - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n" - "bridge disable [mask] - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n" - "" + "SoCFPGA HPS FPGA bridge control", + "enable [mask] - Enable HPS-to-FPGA (Bit 0), LWHPS-to-FPGA (Bit 1), FPGA-to-HPS (Bit 2), F2SDRAM0 (Bit 3), F2SDRAM1 (Bit 4), F2SDRAM2 (Bit 5) bridges \n" + "bridge disable [mask] - Disable HPS-to-FPGA (Bit 0), LWHPS-to-FPGA (Bit 1), FPGA-to-HPS (Bit 2), F2SDRAM0 (Bit 3), F2SDRAM1 (Bit 4), F2SDRAM2 (Bit 5) bridges\n" + "Bit 3, Bit 4 and Bit 5 bridges only available in Stratix 10\n" + "" );
#endif @@ -257,6 +261,9 @@ void socfpga_get_managers_addr(void) #elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X) ret = socfpga_get_base_addr("intel,n5x-clkmgr", &socfpga_clkmgr_base); +#elif IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5) + ret = socfpga_get_base_addr("intel,agilex5-clkmgr", + &socfpga_clkmgr_base); #else ret = socfpga_get_base_addr("altr,clk-mgr", &socfpga_clkmgr_base); #endif diff --git a/arch/arm/mach-socfpga/misc_soc64.c b/arch/arm/mach-socfpga/misc_soc64.c index 2acdfad07b..7dd6f834e1 100644 --- a/arch/arm/mach-socfpga/misc_soc64.c +++ b/arch/arm/mach-socfpga/misc_soc64.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2016-2018 Intel Corporation <www.intel.com> + * Copyright (C) 2016-2023 Intel Corporation <www.intel.com> * */
@@ -18,8 +18,12 @@ #include <log.h> #include <mach/clock_manager.h>
+#define RSU_DEFAULT_LOG_LEVEL 7 + DECLARE_GLOBAL_DATA_PTR;
+u8 socfpga_get_board_id(void); + /* * FPGA programming support for SoC FPGA Stratix 10 */ @@ -47,8 +51,11 @@ static Altera_desc altera_fpga[] = { #if defined(CONFIG_DISPLAY_CPUINFO) int print_cpuinfo(void) { +#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5) + puts("CPU: Intel FPGA SoCFPGA Platform (ARMv8 64bit Cortex-A55/A76)\n"); +#else puts("CPU: Intel FPGA SoCFPGA Platform (ARMv8 64bit Cortex-A53)\n"); - +#endif return 0; } #endif @@ -56,11 +63,26 @@ int print_cpuinfo(void) #ifdef CONFIG_ARCH_MISC_INIT int arch_misc_init(void) { +#if !(IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS) || \ +IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU)) char qspi_string[13]; + char level[4]; + char id[3]; + + snprintf(level, sizeof(level), "%u", RSU_DEFAULT_LOG_LEVEL);
sprintf(qspi_string, "<0x%08x>", cm_get_qspi_controller_clk_hz()); env_set("qspi_clock", qspi_string);
+ /* for RSU, set log level to default if log level is not set */ + if (!env_get("rsu_log_level")) + env_set("rsu_log_level", level); + + /* Export board_id as environment variable */ + sprintf(id, "%u", socfpga_get_board_id()); + env_set("board_id", id); +#endif + return 0; } #endif @@ -87,5 +109,10 @@ void do_bridge_reset(int enable, unsigned int mask) return; }
- socfpga_bridges_reset(enable); + socfpga_bridges_reset(enable, mask); +} + +void arch_preboot_os(void) +{ + mbox_hps_stage_notify(HPS_EXECUTION_STATE_OS); } diff --git a/arch/arm/mach-socfpga/mmu-arm64_s10.c b/arch/arm/mach-socfpga/mmu-arm64_s10.c index a55b7b7cf3..0951233cad 100644 --- a/arch/arm/mach-socfpga/mmu-arm64_s10.c +++ b/arch/arm/mach-socfpga/mmu-arm64_s10.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2016-2018 Intel Corporation <www.intel.com> + * Copyright (C) 2016-2022 Intel Corporation <www.intel.com> * */
@@ -10,6 +10,46 @@
DECLARE_GLOBAL_DATA_PTR;
+#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5) +static struct mm_region socfpga_agilex5_mem_map[] = { + { + /* OCRAM 1MB but available 256KB */ + .virt = 0x00000000UL, + .phys = 0x00000000UL, + .size = 0x00040000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { + /* DEVICE */ + .virt = 0x10808000UL, + .phys = 0x10808000UL, + .size = 0x0F7F8000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN, + }, { + /* FPGA 1.5GB */ + .virt = 0x20000000UL, + .phys = 0x20000000UL, + .size = 0x60000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN, + }, { + /* MEM 2GB */ + .virt = 0x80000000UL, + .phys = 0x80000000UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { + /* List terminator */ + }, +}; + +struct mm_region *mem_map = socfpga_agilex5_mem_map; + +#else static struct mm_region socfpga_stratix10_mem_map[] = { { /* MEM 2GB*/ @@ -70,3 +110,4 @@ static struct mm_region socfpga_stratix10_mem_map[] = { };
struct mm_region *mem_map = socfpga_stratix10_mem_map; +#endif diff --git a/arch/arm/mach-socfpga/reset_manager_s10.c b/arch/arm/mach-socfpga/reset_manager_s10.c index f47fec10a0..1bf6a74648 100644 --- a/arch/arm/mach-socfpga/reset_manager_s10.c +++ b/arch/arm/mach-socfpga/reset_manager_s10.c @@ -1,22 +1,58 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2016-2018 Intel Corporation <www.intel.com> + * Copyright (C) 2016-2023 Intel Corporation <www.intel.com> * */
#include <common.h> +#include <errno.h> #include <hang.h> #include <asm/global_data.h> #include <asm/io.h> +#include <asm/secure.h> #include <asm/arch/reset_manager.h> #include <asm/arch/smc_api.h> #include <asm/arch/system_manager.h> +#include <asm/arch/timer.h> #include <dt-bindings/reset/altr,rst-mgr-s10.h> +#include <exports.h> #include <linux/iopoll.h> #include <linux/intel-smc.h>
DECLARE_GLOBAL_DATA_PTR;
+#define TIMEOUT_300MS 300 + +/* F2S manager registers */ +#define F2SDRAM_SIDEBAND_FLAGINSTATUS0 0x14 +#define F2SDRAM_SIDEBAND_FLAGOUTSET0 0x50 +#define F2SDRAM_SIDEBAND_FLAGOUTCLR0 0x54 + +static __always_inline int wait_for_bit(u32 *reg, const u32 mask, bool set, + unsigned int timeout_ms) +{ + u32 val; + int timeout = timeout_ms; + + while (1) { + val = readl(reg); + + if (!set) + val = ~val; + + if ((val & mask) == mask) + return 0; + + if (!timeout) + break; + + timeout--; + __socfpga_udelay(1000); + } + + return -ETIMEDOUT; +} + /* Assert or de-assert SoCFPGA reset manager reset. */ void socfpga_per_reset(u32 reset, int set) { @@ -57,66 +93,221 @@ void socfpga_per_reset_all(void) writel(0xffffffff, socfpga_get_rstmgr_addr() + RSTMGR_SOC64_PER1MODRST); }
-void socfpga_bridges_reset(int enable) +static __always_inline void socfpga_f2s_bridges_reset(int enable, + unsigned int mask) { -#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_ATF) - u64 arg = enable; + int ret; + u32 brg_mask; + u32 flagout_idlereq = 0; + u32 flagoutset_fdrain = 0; + u32 flagoutset_en = 0; + u32 flaginstatus_idleack = 0; + u32 flaginstatus_respempty = 0; + + if (CONFIG_IS_ENABLED(TARGET_SOCFPGA_STRATIX10)) { + /* Support fpga2soc and f2sdram */ + brg_mask = mask & (RSTMGR_BRGMODRST_FPGA2SOC_MASK | + RSTMGR_BRGMODRST_F2SDRAM0_MASK | + RSTMGR_BRGMODRST_F2SDRAM1_MASK | + RSTMGR_BRGMODRST_F2SDRAM2_MASK); + + if (brg_mask & RSTMGR_BRGMODRST_F2SDRAM0_MASK) { + flagout_idlereq |= BIT(0); + flaginstatus_idleack |= BIT(1); + flagoutset_fdrain |= BIT(2); + flagoutset_en |= BIT(1); + flaginstatus_respempty |= BIT(3); + } + + if (brg_mask & RSTMGR_BRGMODRST_F2SDRAM1_MASK) { + flagout_idlereq |= BIT(3); + flaginstatus_idleack |= BIT(5); + flagoutset_fdrain |= BIT(5); + flagoutset_en |= BIT(4); + flaginstatus_respempty |= BIT(7); + }
- int ret = invoke_smc(INTEL_SIP_SMC_HPS_SET_BRIDGES, &arg, 1, NULL, 0); - if (ret) { - printf("SMC call failed with error %d in %s.\n", ret, __func__); + if (brg_mask & RSTMGR_BRGMODRST_F2SDRAM2_MASK) { + flagout_idlereq |= BIT(6); + flaginstatus_idleack |= BIT(9); + flagoutset_fdrain |= BIT(8); + flagoutset_en |= BIT(7); + flaginstatus_respempty |= BIT(11); + } + } else { + /* Support fpga2soc only */ + brg_mask = mask & RSTMGR_BRGMODRST_FPGA2SOC_MASK; + if (brg_mask & RSTMGR_BRGMODRST_FPGA2SOC_MASK) { + flagout_idlereq |= BIT(0); + flaginstatus_idleack |= BIT(1); + flagoutset_fdrain |= BIT(2); + flagoutset_en |= BIT(1); + flaginstatus_respempty |= BIT(3); + } + } + + /* mask is not set, return here */ + if (!brg_mask) return; + + if (enable) { + clrbits_le32(socfpga_get_rstmgr_addr() + RSTMGR_SOC64_BRGMODRST, + brg_mask); + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTCLR0, + flagout_idlereq); + + /* Wait for mpfe noc idleack to 0 */ + wait_for_bit((u32 *)(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGINSTATUS0), + flaginstatus_idleack, false, TIMEOUT_300MS); + + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTCLR0, + flagoutset_fdrain); + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTSET0, flagoutset_en); + + __socfpga_udelay(1); /* wait 1us */ + } else { + if (readl((socfpga_get_rstmgr_addr() + + RSTMGR_SOC64_BRGMODRST) & brg_mask)) { + /* Bridge cannot be reset twice */ + return; + } + + setbits_le32(socfpga_get_rstmgr_addr() + RSTMGR_SOC64_HDSKEN, + RSTMGR_HDSKEN_FPGAHSEN); + setbits_le32(socfpga_get_rstmgr_addr() + RSTMGR_SOC64_HDSKREQ, + RSTMGR_HDSKREQ_FPGAHSREQ); + + /* Wait for FPGA ack the handshake request to 1 */ + wait_for_bit((u32 *)(socfpga_get_rstmgr_addr() + + RSTMGR_SOC64_HDSKACK), RSTMGR_HDSKREQ_FPGAHSREQ, + true, TIMEOUT_300MS); + + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTCLR0, flagoutset_en); + + __socfpga_udelay(1); + + /* Requests MPFE NoC to idle */ + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTSET0, flagout_idlereq); + + /* Force F2S bridge to drain */ + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTSET0, flagoutset_fdrain); + + /* Wait for respond queue empty status to 1 (resp idle) */ + ret = wait_for_bit((u32 *)(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGINSTATUS0), + flaginstatus_respempty, true, + TIMEOUT_300MS); + + /* Confirm again */ + if (!ret) + ret = wait_for_bit((u32 *) + (SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGINSTATUS0), + flaginstatus_respempty, true, + TIMEOUT_300MS); + + setbits_le32(socfpga_get_rstmgr_addr() + RSTMGR_SOC64_BRGMODRST, + brg_mask & ~RSTMGR_BRGMODRST_FPGA2SOC_MASK); + clrbits_le32(socfpga_get_rstmgr_addr() + RSTMGR_SOC64_HDSKREQ, + RSTMGR_HDSKREQ_FPGAHSREQ); + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTCLR0, + flagout_idlereq); + } +} + +static __always_inline void socfpga_s2f_bridges_reset(int enable, + unsigned int mask) +{ + unsigned int noc_mask = 0; + unsigned int brg_mask = 0; + + if (mask & RSTMGR_BRGMODRST_SOC2FPGA_MASK) { + noc_mask = SYSMGR_NOC_H2F_MSK; + brg_mask = RSTMGR_BRGMODRST_SOC2FPGA_MASK; } -#else - u32 reg; + + if (mask & RSTMGR_BRGMODRST_LWSOC2FPGA_MASK) { + noc_mask |= SYSMGR_NOC_LWH2F_MSK; + brg_mask |= RSTMGR_BRGMODRST_LWSOC2FPGA_MASK; + } + + /* s2f mask is not set, return here */ + if (!brg_mask) + return;
if (enable) { /* clear idle request to all bridges */ setbits_le32(socfpga_get_sysmgr_addr() + - SYSMGR_SOC64_NOC_IDLEREQ_CLR, ~0); + SYSMGR_SOC64_NOC_IDLEREQ_CLR, noc_mask);
- /* Release all bridges from reset state */ + /* Release SOC2FPGA bridges from reset state */ clrbits_le32(socfpga_get_rstmgr_addr() + RSTMGR_SOC64_BRGMODRST, - ~0); + brg_mask);
- /* Poll until all idleack to 0 */ - read_poll_timeout(readl, reg, !reg, 1000, 300000, - socfpga_get_sysmgr_addr() + - SYSMGR_SOC64_NOC_IDLEACK); + /* Wait for all NOC master ack to 0 */ + wait_for_bit((u32 *)(socfpga_get_sysmgr_addr() + + SYSMGR_SOC64_NOC_IDLEACK), noc_mask, false, + TIMEOUT_300MS); } else { /* set idle request to all bridges */ - writel(~0, - socfpga_get_sysmgr_addr() + - SYSMGR_SOC64_NOC_IDLEREQ_SET); + setbits_le32(socfpga_get_sysmgr_addr() + + SYSMGR_SOC64_NOC_IDLEREQ_SET, noc_mask);
/* Enable the NOC timeout */ writel(1, socfpga_get_sysmgr_addr() + SYSMGR_SOC64_NOC_TIMEOUT);
- /* Poll until all idleack to 1 */ - read_poll_timeout(readl, reg, - reg == (SYSMGR_NOC_H2F_MSK | - SYSMGR_NOC_LWH2F_MSK), - 1000, 300000, - socfpga_get_sysmgr_addr() + - SYSMGR_SOC64_NOC_IDLEACK); - - /* Poll until all idlestatus to 1 */ - read_poll_timeout(readl, reg, - reg == (SYSMGR_NOC_H2F_MSK | - SYSMGR_NOC_LWH2F_MSK), - 1000, 300000, - socfpga_get_sysmgr_addr() + - SYSMGR_SOC64_NOC_IDLESTATUS); - - /* Reset all bridges (except NOR DDR scheduler & F2S) */ + /* Wait for all NOC master ack to 1 */ + wait_for_bit((u32 *)(socfpga_get_sysmgr_addr() + + SYSMGR_SOC64_NOC_IDLEACK), noc_mask, true, + TIMEOUT_300MS); + + /* Wait for all NOC master idlestatus to 1 */ + wait_for_bit((u32 *)(socfpga_get_sysmgr_addr() + + SYSMGR_SOC64_NOC_IDLESTATUS), noc_mask, true, + TIMEOUT_300MS); + + /* Reset all SOC2FPGA bridges */ setbits_le32(socfpga_get_rstmgr_addr() + RSTMGR_SOC64_BRGMODRST, - ~(RSTMGR_BRGMODRST_DDRSCH_MASK | - RSTMGR_BRGMODRST_FPGA2SOC_MASK)); + brg_mask);
/* Disable NOC timeout */ writel(0, socfpga_get_sysmgr_addr() + SYSMGR_SOC64_NOC_TIMEOUT); } -#endif +} + +void socfpga_bridges_reset(int enable, unsigned int mask) +{ + if (!IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_SPL_ATF)) { + u64 arg[2]; + int ret; + + /* Set bit-1 to indicate has mask value in arg[1]. */ + arg[0] = (enable & BIT(0)) | BIT(1); + arg[1] = mask; + + ret = invoke_smc(INTEL_SIP_SMC_HPS_SET_BRIDGES, arg, + ARRAY_SIZE(arg), NULL, 0); + if (ret) + printf("Failed to %s the HPS bridges, error %d\n", + enable ? "enable" : "disable", ret); + } else { + socfpga_s2f_bridges_reset(enable, mask); + socfpga_f2s_bridges_reset(enable, mask); + } +} + +void __secure socfpga_bridges_reset_psci(int enable, unsigned int mask) +{ + socfpga_s2f_bridges_reset(enable, mask); + socfpga_f2s_bridges_reset(enable, mask); }
/* @@ -125,7 +316,7 @@ void socfpga_bridges_reset(int enable) int cpu_has_been_warmreset(void) { return readl(socfpga_get_rstmgr_addr() + RSTMGR_SOC64_STATUS) & - RSTMGR_L4WD_MPU_WARMRESET_MASK; + (RSTMGR_L4WD_MPU_WARMRESET_MASK); }
void print_reset_info(void) diff --git a/arch/arm/mach-socfpga/secure_reg_helper.c b/arch/arm/mach-socfpga/secure_reg_helper.c index 0d4f45f33d..23595d242a 100644 --- a/arch/arm/mach-socfpga/secure_reg_helper.c +++ b/arch/arm/mach-socfpga/secure_reg_helper.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2020 Intel Corporation <www.intel.com> + * Copyright (C) 2020-2022 Intel Corporation <www.intel.com> * */
@@ -18,9 +18,11 @@ int socfpga_secure_convert_reg_id_to_addr(u32 id, phys_addr_t *reg_addr) { switch (id) { +#if !IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5) case SOCFPGA_SECURE_REG_SYSMGR_SOC64_SDMMC: *reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SDMMC; break; +#endif case SOCFPGA_SECURE_REG_SYSMGR_SOC64_EMAC0: *reg_addr = socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC0; break; diff --git a/arch/arm/mach-socfpga/smmu_agilex5.c b/arch/arm/mach-socfpga/smmu_agilex5.c new file mode 100644 index 0000000000..05e74926aa --- /dev/null +++ b/arch/arm/mach-socfpga/smmu_agilex5.c @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Intel Corporation. All rights reserved + * + */ + +#include <common.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/arch/firewall.h> +#include <asm/arch/smmu_agilex5.h> +#include <asm/arch/system_manager.h> + +DECLARE_GLOBAL_DATA_PTR; + +static inline void setup_smmu_firewall(void) +{ + u32 i; + + /* Off the DDR secure transaction for all TBU supported peripherals */ + for (i = SYSMGR_DMA0_SID_ADDR; i < SYSMGR_TSN2_SID_ADDR; i += + SOCFPGA_NEXT_TBU_PERIPHERAL) { + /* skip this, future use register */ + if (i == SYSMGR_USB3_SID_ADDR) + continue; + + writel(SECURE_TRANS_RESET, (uintptr_t)i); + } +} + +void socfpga_init_smmu(void) +{ + setup_smmu_firewall(); +} diff --git a/arch/arm/mach-socfpga/smmu_s10.c b/arch/arm/mach-socfpga/smmu_s10.c new file mode 100644 index 0000000000..106834cc9a --- /dev/null +++ b/arch/arm/mach-socfpga/smmu_s10.c @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2023 Intel Corporation <www.intel.com> + * + */ + +#include <common.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/arch/firewall.h> +#include <asm/arch/smmu_s10.h> +#include <asm/arch/system_manager.h> + +DECLARE_GLOBAL_DATA_PTR; + +static const struct smmu_stream_id dev_stream_id[] = { + {SYSMGR_EMAC0_SID_ADDR, 0x01, EMAC_W_OFST, EMAC_R_OFST}, + {SYSMGR_EMAC1_SID_ADDR, 0x02, EMAC_W_OFST, EMAC_R_OFST}, + {SYSMGR_EMAC2_SID_ADDR, 0x03, EMAC_W_OFST, EMAC_R_OFST}, + {SYSMGR_NAND_SID_ADDR, 0x04, NAND_W_OFST, NAND_R_OFST}, + {SYSMGR_SDMMC_SID_ADDR, 0x05, SDMMC_OFST, SDMMC_OFST}, + {SYSMGR_USB0_SID_ADDR, 0x06, USB_OFST, USB_OFST}, + {SYSMGR_USB1_SID_ADDR, 0x07, USB_OFST, USB_OFST}, + {SYSMGR_DMA_SID_ADDR, 0x08, DMA_W_OFST, DMA_R_OFST}, + {SYSMGR_ETR_SID_ADDR, 0x09, ETR_W_OFST, ETR_R_OFST}, +}; + +static void set_smmu_streamid(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dev_stream_id); i++) { + u32 mask = SMMU_SET_STREAMID(0x3FF, + dev_stream_id[i].r_bit_ofst, + dev_stream_id[i].w_bit_ofst); + u32 value = SMMU_SET_STREAMID(dev_stream_id[i].sid, + dev_stream_id[i].r_bit_ofst, + dev_stream_id[i].w_bit_ofst); + + clrbits_le32(dev_stream_id[i].addr, mask); + setbits_le32(dev_stream_id[i].addr, value); + } +} + +/* + * Need to set the Secure bit (to make it non-secure) on each peripheral + * so that SMMU can access the peripheral + */ +static void set_smmu_accessible_reg(void) +{ + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC0, + BIT(27) | BIT(25)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC1, + BIT(27) | BIT(25)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_EMAC2, + BIT(27) | BIT(25)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_NANDGRP_L3MASTER, + BIT(21) | BIT(17)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_SDMMC_L3MASTER, + BIT(5)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_USB0_L3MASTER, + BIT(9)); + setbits_le32(socfpga_get_sysmgr_addr() + SYSMGR_SOC64_USB1_L3MASTER, + BIT(9)); +} + +static inline void setup_smmu_firewall(void) +{ + /* Enable nonsecure SMMU accesses */ + writel(FIREWALL_L4_DISABLE_ALL, SOCFPGA_FIREWALL_TCU); +} + +void socfpga_init_smmu(void) +{ + setup_smmu_firewall(); + set_smmu_streamid(); + set_smmu_accessible_reg(); +} + +int is_smmu_bypass(void) +{ + return readl(SOCFPGA_SMMU_ADDRESS + SMMU_SCR0) & SMMU_SCR0_CLIENTPD; +} + +int is_smmu_stream_id_enabled(u32 stream_id) +{ + int i; + u32 smrg_num; + u32 smr, s2cr, sid_mask; + u32 cb, cb_index, cb_num; + + if (is_smmu_bypass()) + return 0; + + /* Get number of Stream Mapping Register Groups */ + smrg_num = readl(SOCFPGA_SMMU_ADDRESS + SMMU_SIDR0) & + SMMU_SIDR0_NUMSMRG_MASK; + + /* Get number of Context Bank */ + cb_num = readl(SOCFPGA_SMMU_ADDRESS + SMMU_SIDR1) & + SMMU_SIDR1_NUMCB_MASK; + + for (i = 0; i < smrg_num; i++) { + smr = readl(SOCFPGA_SMMU_ADDRESS + SMMU_GR0_SMR((u64)i)); + sid_mask = (smr & SMMU_SMR_MASK) >> 16; + + /* Skip if Stream ID is invalid or not matched */ + if (!(smr & SMMU_SMR_VALID) || (smr & sid_mask) != stream_id) + continue; + + /* Get Context Bank index from valid matching Stream ID */ + s2cr = readl(SOCFPGA_SMMU_ADDRESS + SMMU_GR0_S2CR((u64)i)); + cb_index = s2cr & SMMU_S2CR_CBNDX; + + /* Skip if Context Bank is invalid or not Translation mode */ + if (cb_index >= cb_num || (s2cr & SMMU_S2CR_TYPE)) + continue; + + cb = readl(SOCFPGA_SMMU_ADDRESS + SMMU_GR0_CB((u64)cb_index, + SMMU_CB_SCTLR)); + /* Return MMU enable status for this Context Bank */ + return (cb & SMMU_CB_SCTLR_M); + } + + return 0; +} diff --git a/arch/arm/mach-socfpga/spl_agilex5.c b/arch/arm/mach-socfpga/spl_agilex5.c new file mode 100644 index 0000000000..da91bf5917 --- /dev/null +++ b/arch/arm/mach-socfpga/spl_agilex5.c @@ -0,0 +1,180 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019-2023 Intel Corporation <www.intel.com> + * + */ + +#include <init.h> +#include <log.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/u-boot.h> +#include <asm/utils.h> +#include <common.h> +#include <hang.h> +#include <image.h> +#include <spl.h> +#include <asm/arch/clock_manager.h> +#include <asm/arch/firewall.h> +#include <asm/arch/mailbox_s10.h> +#include <asm/arch/misc.h> +#include <asm/arch/reset_manager.h> +#include <asm/arch/smmu_s10.h> +#include <asm/arch/system_manager.h> +#include <wdt.h> +#include <dm/uclass.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define USE_HARDCODED_HANDOFF + +#ifdef USE_HARDCODED_HANDOFF +static const u32 hardcoded_handoff_data[402] = { +0x544f4f42, 0x01000500, 0x00000000, 0x00000000, 0x58554d50, 0x90010000, +0x00000000, 0x00000000, 0x00000000, 0x03000000, 0x04000000, 0x03000000, +0x08000000, 0x03000000, 0x0c000000, 0x03000000, 0x10000000, 0x03000000, +0x14000000, 0x03000000, 0x18000000, 0x03000000, 0x1c000000, 0x03000000, +0x20000000, 0x03000000, 0x24000000, 0x03000000, 0x28000000, 0x03000000, +0x2c000000, 0x03000000, 0x30000000, 0x03000000, 0x34000000, 0x03000000, +0x38000000, 0x03000000, 0x3c000000, 0x03000000, 0x40000000, 0x00000000, +0x44000000, 0x00000000, 0x48000000, 0x00000000, 0x4c000000, 0x00000000, +0x50000000, 0x00000000, 0x54000000, 0x00000000, 0x58000000, 0x04000000, +0x5c000000, 0x04000000, 0x60000000, 0x08000000, 0x64000000, 0x08000000, +0x68000000, 0x05000000, 0x6c000000, 0x05000000, 0x70000000, 0x08000000, +0x74000000, 0x08000000, 0x78000000, 0x04000000, 0x7c000000, 0x04000000, +0x80000000, 0x07000000, 0x84000000, 0x07000000, 0x88000000, 0x07000000, +0x8c000000, 0x07000000, 0x90000000, 0x01000000, 0x94000000, 0x01000000, +0x98000000, 0x01000000, 0x9c000000, 0x01000000, 0x00010000, 0x01000000, +0x04010000, 0x01000000, 0x08010000, 0x09000000, 0x0c010000, 0x08000000, +0x10010000, 0x08000000, 0x14010000, 0x08000000, 0x18010000, 0x05000000, +0x1c010000, 0x05000000, 0x54434f49, 0x90010000, 0x00000000, 0x00000000, +0x00000000, 0x34000000, 0x04000000, 0x14000000, 0x08000000, 0x34000000, +0x0c000000, 0x34000000, 0x10000000, 0x34000000, 0x14000000, 0x34000000, +0x18000000, 0x34000000, 0x1c000000, 0x34000000, 0x20000000, 0x34000000, +0x24000000, 0x34000000, 0x28000000, 0x34000000, 0x2c000000, 0x34000000, +0x30000000, 0x16000000, 0x34000000, 0x14000000, 0x38000000, 0x34000000, +0x3c000000, 0x34000000, 0x40000000, 0x14000000, 0x44000000, 0x14000000, +0x48000000, 0x34000000, 0x4c000000, 0x34000000, 0x50000000, 0x14000000, +0x54000000, 0x14000000, 0x58000000, 0x34000000, 0x5c000000, 0x34000000, +0x60000000, 0x35000000, 0x64000000, 0x35000000, 0x68000000, 0x16000000, +0x6c000000, 0x34000000, 0xd0000000, 0x35000000, 0xd4000000, 0x35000000, +0xd8000000, 0x3e000000, 0xdc000000, 0x3e000000, 0xe0000000, 0x34000000, +0xe4000000, 0x34000000, 0xe8000000, 0x16000000, 0xec000000, 0x34000000, +0xf0000000, 0x34000000, 0xf4000000, 0x34000000, 0xf8000000, 0x14000000, +0xfc000000, 0x34000000, 0x00010000, 0x34000000, 0x04010000, 0x34000000, +0x08010000, 0x34000000, 0x0c010000, 0x35000000, 0x10010000, 0x35000000, +0x14010000, 0x35000000, 0x18010000, 0x3e000000, 0x1c010000, 0x16000000, +0x41475046, 0xc0000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x04000000, 0x00000000, 0x08000000, 0x00000000, 0x0c000000, 0x00000000, +0x10000000, 0x00000000, 0x14000000, 0x00000000, 0x18000000, 0x00000000, +0x1c000000, 0x00000000, 0x20000000, 0x00000000, 0x28000000, 0x00000000, +0x2c000000, 0x00000000, 0x30000000, 0x00000000, 0x34000000, 0x00000000, +#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU) +0x38000000, 0x01000000, 0x3c000000, 0x00000000, 0x40000000, 0x00000000, +#else +0x38000000, 0x00000000, 0x3c000000, 0x00000000, 0x40000000, 0x00000000, +#endif +0x44000000, 0x00000000, 0x48000000, 0x00000000, 0x50000000, 0x00000000, +0x54000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x59414c44, 0x90010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, +0x04000000, 0x00000000, 0x08000000, 0x00000000, 0x0c000000, 0x00000000, +0x10000000, 0x00000000, 0x14000000, 0x00000000, 0x18000000, 0x00000000, +0x1c000000, 0x00000000, 0x20000000, 0x00000000, 0x24000000, 0x00000000, +0x28000000, 0x00000000, 0x2c000000, 0x00000000, 0x30000000, 0x00110000, +0x34000000, 0x00000000, 0x38000000, 0x00000000, 0x3c000000, 0x00000000, +0x40000000, 0x00000000, 0x44000000, 0x00000000, 0x48000000, 0x00000000, +0x4c000000, 0x00000000, 0x50000000, 0x00000000, 0x54000000, 0x00000000, +0x58000000, 0x00000000, 0x5c000000, 0x00000000, 0x60000000, 0x00000000, +0x64000000, 0x00000000, 0x68000000, 0x00000000, 0x6c000000, 0x00000000, +0x70000000, 0x00000000, 0x74000000, 0x00000000, 0x78000000, 0x00000000, +0x7c000000, 0x00000000, 0x80000000, 0x00000000, 0x84000000, 0x00000000, +0x88000000, 0x00000000, 0x8c000000, 0x00000000, 0x90000000, 0x00000000, +0x94000000, 0x00000000, 0x98000000, 0x00000000, 0x9c000000, 0x00000000, +0xa0000000, 0x00000000, 0xa4000000, 0x00000000, 0xa8000000, 0x00000000, +0xac000000, 0x00000000, 0xb0000000, 0x00000000, 0xb4000000, 0x00000000, +0xb8000000, 0x00000000, 0xbC000000, 0x00000000, 0x534b4c43, 0xA0000000, +0x00000000, 0x00000000, 0x00000000, 0x98002618, 0x03010016, 0x00000000, +0x02000008, 0x04000008, 0x03000008, 0x09000008, 0x90000000, 0x00000000, +0x01000000, 0x03010015, 0x00000000, 0x02000008, 0x03000008, 0x7d000008, +0x06000008, 0x78000000, 0x01000100, 0x09000000, 0x00000100, 0x01000000, +0x00000100, 0x00000100, 0x00000100, 0x13000000, 0x01000000, 0x00000100, +0x00000000, 0x00000000, 0x00000000, 0x40787d01, 0x40787d01, 0x00000000, +0x00000000, 0x00000000, 0x49524550, 0x14000000, 0x00000000, 0x00000000, +0x40000000, 0x4d524453, 0x14000000, 0x00000000, 0x00000000, 0x00000000 +}; +#endif + +#define HARDCODED_HANDOFF_DATA_SIZE (sizeof(hardcoded_handoff_data) / sizeof(u32)) + +void board_init_f(ulong dummy) +{ + int ret; + struct udevice *dev; + + ret = spl_early_init(); + if (ret) + hang(); + + socfpga_get_managers_addr(); + +#ifdef USE_HARDCODED_HANDOFF + /* Write hardcoded handoff value into OCRAM handoff area */ + u32 i; + + for (i = 0; i < HARDCODED_HANDOFF_DATA_SIZE; i++) + writel(hardcoded_handoff_data[i], + (u32 *)SOC64_HANDOFF_BASE + i); +#endif + + sysmgr_pinmux_init(); + + if (!(IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS) || + IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU))) { + /* Ensure watchdog is paused when debugging is happening */ + writel(SYSMGR_WDDBG_PAUSE_ALL_CPU, + socfpga_get_sysmgr_addr() + SYSMGR_SOC64_WDDBG); + } + + timer_init(); + + ret = uclass_get_device(UCLASS_CLK, 0, &dev); + if (ret) { + debug("Clock init failed: %d\n", ret); + hang(); + } + + if (!(IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS) || + IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU))) { + /* + * Enable watchdog as early as possible before initializing other + * component. Watchdog need to be enabled after clock driver because + * it will retrieve the clock frequency from clock driver. + */ + if (CONFIG_IS_ENABLED(WDT)) + initr_watchdog(); + } + + preloader_console_init(); + print_reset_info(); + cm_print_clock_quick_summary(); + + ret = uclass_get_device_by_name(UCLASS_NOP, "socfpga-secreg", &dev); + if (ret) { + printf("Firewall & secure settings init failed: %d\n", ret); + hang(); + } + +#if CONFIG_IS_ENABLED(ALTERA_SDRAM) + ret = uclass_get_device(UCLASS_RAM, 0, &dev); + if (ret) { + debug("DRAM init failed: %d\n", ret); + hang(); + } +#endif + + mbox_init(); + +#ifdef CONFIG_CADENCE_QSPI + mbox_qspi_open(); +#endif +} diff --git a/arch/arm/mach-socfpga/spl_soc64.c b/arch/arm/mach-socfpga/spl_soc64.c index ba6efc1d86..a4ac906ffd 100644 --- a/arch/arm/mach-socfpga/spl_soc64.c +++ b/arch/arm/mach-socfpga/spl_soc64.c @@ -1,25 +1,203 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2020 Intel Corporation. All rights reserved + * Copyright (C) 2020-2022 Intel Corporation. All rights reserved * */
+#include <asm/io.h> +#include <asm/u-boot.h> +#include <asm/utils.h> #include <common.h> +#include <debug_uart.h> +#include <dm.h> +#include <dm/ofnode.h> +#include <image.h> +#include <log.h> #include <spl.h> +#include <asm/arch/clock_manager.h> +#include <asm/arch/firewall.h> +#include <asm/arch/mailbox_s10.h> +#include <asm/arch/reset_manager.h> +#include <asm/arch/system_manager.h> +#include <asm/arch/smmu_s10.h> +#include <watchdog.h> +#include <dm/uclass.h>
DECLARE_GLOBAL_DATA_PTR;
u32 spl_boot_device(void) { + int ret, size; + ofnode node; + const fdt32_t *phandle_p; + u32 phandle; + struct udevice *dev; + + node = ofnode_path("/chosen"); + if (!ofnode_valid(node)) { + debug("%s: /chosen node was not found.\n", __func__); + goto fallback; + } + + phandle_p = ofnode_get_property(node, "u-boot,boot0", &size); + if (!phandle_p) { + debug("%s: u-boot,boot0 property was not found.\n", + __func__); + goto fallback; + } + + phandle = fdt32_to_cpu(*phandle_p); + + node = ofnode_get_by_phandle(phandle); + + ret = device_get_global_by_ofnode(node, &dev); + if (ret) { + debug("%s: Boot device at not found, error: %d\n", __func__, + ret); + goto fallback; + } + + debug("%s: Found boot device %s\n", __func__, dev->name); + + switch (device_get_uclass_id(dev)) { + case UCLASS_SPI_FLASH: + return BOOT_DEVICE_SPI; + case UCLASS_MTD: + return BOOT_DEVICE_NAND; + case UCLASS_MMC: + return BOOT_DEVICE_MMC1; + default: + debug("%s: Booting from device uclass '%s' is not supported\n", + __func__, dev_get_uclass_name(dev)); + } + +fallback: + /* Return default boot device */ return BOOT_DEVICE_MMC1; }
#if IS_ENABLED(CONFIG_SPL_MMC) u32 spl_boot_mode(const u32 boot_device) { - if (IS_ENABLED(CONFIG_SPL_FS_FAT) || IS_ENABLED(CONFIG_SPL_FS_EXT4)) - return MMCSD_MODE_FS; - else - return MMCSD_MODE_RAW; +#if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4) + return MMCSD_MODE_FS; +#else + return MMCSD_MODE_RAW; +#endif } #endif + +/* board specific function prior loading SSBL / U-Boot */ +void spl_perform_fixups(struct spl_image_info *spl_image) +{ + /* Setup and Initialize SMMU */ + socfpga_init_smmu(); + +#if !(IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_SIMICS) || \ +IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU)) + mbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); +#endif +} + +/* This function is to map specified node onto SPL boot devices */ +static int spl_node_to_boot_device(int node) +{ + const void *blob = gd->fdt_blob; + struct udevice *parent; + const char *prop; + + if (!uclass_get_device_by_of_offset(UCLASS_MMC, node, &parent)) + return BOOT_DEVICE_MMC1; + else if (!uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, &parent)) + return BOOT_DEVICE_SPI; + else if (!uclass_get_device_by_of_offset(UCLASS_MTD, node, &parent)) + return BOOT_DEVICE_NAND; + + prop = fdt_getprop(blob, node, "device_type", NULL); + if (prop) { + if (!strcmp(prop, "memory")) + return BOOT_DEVICE_RAM; + + printf("%s: unknown device_type %s\n", __func__, prop); + } + + return -1; +} + +static void default_spl_boot_list(u32 *spl_boot_list, int length) +{ + spl_boot_list[0] = BOOT_DEVICE_MMC1; + + if (length > 1) + spl_boot_list[1] = BOOT_DEVICE_SPI; + + if (length > 2) + spl_boot_list[2] = BOOT_DEVICE_NAND; +} + +void board_boot_order(u32 *spl_boot_list) +{ + int idx = 0; + const void *blob = gd->fdt_blob; + int chosen_node = fdt_path_offset(blob, "/chosen"); + const char *conf; + int elem; + int boot_device; + int node; + int length; + + /* expect valid initialized spl_boot_list */ + if (!spl_boot_list) + return; + + length = 1; + while (spl_boot_list[length] == spl_boot_list[length - 1]) + length++; + + debug("%s: chosen_node is %d\n", __func__, chosen_node); + if (chosen_node < 0) { + printf("%s: /chosen not found, using default\n", __func__); + default_spl_boot_list(spl_boot_list, length); + return; + } + + for (elem = 0; + (conf = fdt_stringlist_get(blob, chosen_node, + "u-boot,spl-boot-order", elem, NULL)); + elem++) { + if (idx >= length) { + printf("%s: limit %d to spl_boot_list exceeded\n", __func__, + length); + break; + } + + /* Resolve conf item as a path in device tree */ + node = fdt_path_offset(blob, conf); + if (node < 0) { + debug("%s: could not find %s in FDT\n", __func__, conf); + continue; + } + + /* Try to map spl node back onto SPL boot devices */ + boot_device = spl_node_to_boot_device(node); + if (boot_device < 0) { + debug("%s: could not map node @%x to a boot-device\n", + __func__, node); + continue; + } + + spl_boot_list[idx] = boot_device; + debug("%s: spl_boot_list[%d] = %u\n", __func__, idx, + spl_boot_list[idx]); + idx++; + } + + if (idx == 0) { + if (!conf && !elem) { + printf("%s: spl-boot-order invalid, using default\n", __func__); + default_spl_boot_list(spl_boot_list, length); + } else { + printf("%s: no valid element spl-boot-order list\n", __func__); + } + } +} diff --git a/arch/arm/mach-socfpga/u-boot-spl-soc64.lds b/arch/arm/mach-socfpga/u-boot-spl-soc64.lds new file mode 100644 index 0000000000..8beef91d17 --- /dev/null +++ b/arch/arm/mach-socfpga/u-boot-spl-soc64.lds @@ -0,0 +1,93 @@ +/* + * (C) Copyright 2018 + * Intel Corporation <www.intel.com> + * + * (C) Copyright 2013 + * David Feng fenghua@phytium.com.cn + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, garyj@denx.de + * + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * Aneesh V aneesh@ti.com + * + * SPDX-License-Identifier: GPL-2.0 + */ + +MEMORY { .sram : ORIGIN = CONFIG_SPL_TEXT_BASE, + LENGTH = CONFIG_SPL_MAX_SIZE } +MEMORY { .sdram : ORIGIN = CONFIG_SPL_BSS_START_ADDR, + LENGTH = CONFIG_SPL_BSS_MAX_SIZE } + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_start) +SECTIONS +{ + .text : { + . = ALIGN(8); + __image_copy_start = .; + CPUDIR/start.o (.text*) + *(.text*) + } >.sram + + .rodata : { + . = ALIGN(8); + *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) + } >.sram + + .data : { + . = ALIGN(8); + /* Run time .data section starting at this location */ + __data_start = .; + *(.data*) + /* Run time .data section ending at this location */ + __data_end = .; + } >.sram + + . = ALIGN(8); + /* Preserve original .data section starting at this location */ + __preserve_data_start = .; + . = __preserve_data_start + (__data_end - __data_start); + /* Preserve original .data section ending at this location */ + __preserve_data_end = .; + + . = ALIGN(8); + __u_boot_list . : { + KEEP(*(SORT(__u_boot_list*))); + } >.sram + + .image_copy_end : { + . = ALIGN(8); + *(.__image_copy_end) + } >.sram + + .end : { + . = ALIGN(8); + *(.__end) + } >.sram + + _image_binary_end = .; + + .bss_start (NOLOAD) : { + . = ALIGN(8); + KEEP(*(.__bss_start)); + } >.sdram + + .bss (NOLOAD) : { + *(.bss*) + . = ALIGN(8); + } >.sdram + + .bss_end (NOLOAD) : { + KEEP(*(.__bss_end)); + } >.sdram + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/arch/arm/mach-socfpga/wrap_handoff_soc64.c b/arch/arm/mach-socfpga/wrap_handoff_soc64.c index e7cb5ea89c..23434dbf6c 100644 --- a/arch/arm/mach-socfpga/wrap_handoff_soc64.c +++ b/arch/arm/mach-socfpga/wrap_handoff_soc64.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2020-2021 Intel Corporation <www.intel.com> + * Copyright (C) 2020-2022 Intel Corporation <www.intel.com> * */
@@ -19,7 +19,12 @@ static enum endianness check_endianness(u32 handoff) case SOC64_HANDOFF_MAGIC_FPGA: case SOC64_HANDOFF_MAGIC_DELAY: case SOC64_HANDOFF_MAGIC_CLOCK: +#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5) + case SOC64_HANDOFF_MAGIC_PERI: + case SOC64_HANDOFF_MAGIC_SDRAM: +#else case SOC64_HANDOFF_MAGIC_MISC: +#endif return BIG_ENDIAN; #if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X) case SOC64_HANDOFF_DDR_UMCTL2_MAGIC: