From 2f27754eb7f5321b9e4ff80870f03e35357a02a5 Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Sun, 7 Nov 2021 23:08:54 +0800 Subject: arm: socfpga: arria10: Setting image magic value to romcode initswstate reg The romcode_initswstate register need to be set with FSBL_IMAGE_IS_VALID value if the current FSBL image is found valid, otherwise BootROM will look for next subsequent valid FSBL image when warm reset is triggered. Signed-off-by: Tien Fong Chee Signed-off-by: Sin Hui Kho Reviewed-by: Tien Fong Chee --- arch/arm/mach-socfpga/include/mach/system_manager_arria10.h | 3 ++- arch/arm/mach-socfpga/spl_a10.c | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h index e4fc6d2e55..75e1fcd80f 100644 --- a/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2016-2017 Intel Corporation + * Copyright (C) 2016-2021 Intel Corporation */ #ifndef _SYSTEM_MANAGER_ARRIA10_H_ @@ -31,6 +31,7 @@ #define SYSMGR_A10_NOC_IDLEACK 0xd0 #define SYSMGR_A10_NOC_IDLESTATUS 0xd4 #define SYSMGR_A10_FPGA2SOC_CTRL 0xd8 +#define SYSMGR_A10_ROMCODE_INITSWSTATE 0x20C #define SYSMGR_SDMMC SYSMGR_A10_SDMMC diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index ecb656e4de..f6c4b5708d 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2012-2019 Altera Corporation + * Copyright (C) 2012-2021 Altera Corporation */ #include @@ -32,6 +32,7 @@ #include #define FPGA_BUFSIZ 16 * 1024 +#define FSBL_IMAGE_IS_VALID 0x49535756 DECLARE_GLOBAL_DATA_PTR; @@ -169,3 +170,10 @@ void board_init_f(ulong dummy) config_dedicated_pins(gd->fdt_blob); WATCHDOG_RESET(); } + +/* board specific function prior loading SSBL / U-Boot proper */ +void spl_board_prepare_for_boot(void) +{ + writel(FSBL_IMAGE_IS_VALID, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_INITSWSTATE); +} -- cgit v1.2.3 From 3b4ee40f20eb7bb687a4429546fd3cd3073b90d2 Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Sun, 7 Nov 2021 23:08:55 +0800 Subject: arm: socfpga: arria10: Reset MPFE NoC after program periph / combined RBF This patch triggers warm reset to recover the MPFE NoC from corruption due to high frequency transient clock output from HPS EMIF IOPLL at VCO startup after peripheral RBF is programmed. Signed-off-by: Tien Fong Chee Signed-off-by: Sin Hui Kho Reviewed-by: Tien Fong Chee --- arch/arm/mach-socfpga/include/mach/misc.h | 5 +- .../include/mach/reset_manager_arria10.h | 6 +- .../include/mach/system_manager_arria10.h | 4 + arch/arm/mach-socfpga/misc_arria10.c | 90 +++++++++++++++++++- arch/arm/mach-socfpga/spl_a10.c | 96 +++++++++++++++++++++- 5 files changed, 195 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-socfpga/include/mach/misc.h b/arch/arm/mach-socfpga/include/mach/misc.h index 649d2f6ce2..74e8e2590f 100644 --- a/arch/arm/mach-socfpga/include/mach/misc.h +++ b/arch/arm/mach-socfpga/include/mach/misc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2016-2017 Intel Corporation + * Copyright (C) 2016-2021 Intel Corporation */ #ifndef _SOCFPGA_MISC_H_ @@ -45,7 +45,10 @@ int is_fpga_config_ready(void); #endif void do_bridge_reset(int enable, unsigned int mask); +bool is_regular_boot_valid(void); +void set_regular_boot(unsigned int status); void socfpga_pl310_clear(void); void socfpga_get_managers_addr(void); +int qspi_flash_software_reset(void); #endif /* _SOCFPGA_MISC_H_ */ diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h index 19507c292d..26faa628a0 100644 --- a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2016-2017 Intel Corporation + * Copyright (C) 2016-2021 Intel Corporation */ #ifndef _RESET_MANAGER_ARRIA10_H_ @@ -22,6 +22,7 @@ int socfpga_bridges_reset(void); #define RSTMGR_A10_PER1MODRST 0x28 #define RSTMGR_A10_BRGMODRST 0x2c #define RSTMGR_A10_SYSMODRST 0x30 +#define RSTMGR_A10_SYSWARMMASK 0x50 #define RSTMGR_CTRL RSTMGR_A10_CTRL @@ -115,4 +116,7 @@ int socfpga_bridges_reset(void); #define ALT_RSTMGR_HDSKEN_FPGAHSEN_SET_MSK BIT(2) #define ALT_RSTMGR_HDSKEN_ETRSTALLEN_SET_MSK BIT(3) +#define ALT_RSTMGR_FPGAMGRWARMMASK_S2F_SET_MSK BIT(3) +#define ALT_RSTMGR_SYSWARMMASK_S2F_SET_MSK BIT(4) + #endif /* _RESET_MANAGER_ARRIA10_H_ */ diff --git a/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h index 75e1fcd80f..0afe63e647 100644 --- a/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h @@ -31,7 +31,11 @@ #define SYSMGR_A10_NOC_IDLEACK 0xd0 #define SYSMGR_A10_NOC_IDLESTATUS 0xd4 #define SYSMGR_A10_FPGA2SOC_CTRL 0xd8 +#define SYSMGR_A10_ROMCODE_CTRL 0x204 #define SYSMGR_A10_ROMCODE_INITSWSTATE 0x20C +#define SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND 0x208 +#define SYSMGR_A10_ISW_HANDOFF_BASE 0x230 +#define SYSMGR_A10_ISW_HANDOFF_7 0x1c #define SYSMGR_SDMMC SYSMGR_A10_SDMMC diff --git a/arch/arm/mach-socfpga/misc_arria10.c b/arch/arm/mach-socfpga/misc_arria10.c index bf978053ca..634e63ed42 100644 --- a/arch/arm/mach-socfpga/misc_arria10.c +++ b/arch/arm/mach-socfpga/misc_arria10.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2016-2017 Intel Corporation + * Copyright (C) 2016-2021 Intel Corporation */ #include @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q1_3 0x08 #define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q2_11 0x58 @@ -29,6 +31,12 @@ #define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q3_7 0x78 #define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q4_3 0x98 +#define REGULAR_BOOT_MAGIC 0xd15ea5e + +#define QSPI_S25FL_SOFT_RESET_COMMAND 0x00f0ff82 +#define QSPI_N25_SOFT_RESET_COMMAND 0x00000001 +#define QSPI_NO_SOFT_RESET 0x00000000 + /* * FPGA programming support for SoC FPGA Arria 10 */ @@ -122,3 +130,83 @@ void do_bridge_reset(int enable, unsigned int mask) else socfpga_bridges_reset(); } + +/* + * This function set/unset magic number "0xd15ea5e" to + * handoff register isw_handoff[7] - 0xffd0624c + * This magic number is part of boot progress tracking + * and it's required for warm reset workaround on MPFE hang issue. + */ +void set_regular_boot(unsigned int status) +{ + if (status) + writel(REGULAR_BOOT_MAGIC, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); + else + writel(0, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); +} + +/* + * This function is used to check whether + * handoff register isw_handoff[7] contains + * magic number "0xd15ea5e". + */ +bool is_regular_boot_valid(void) +{ + unsigned int status; + + status = readl(socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); + + if (status == REGULAR_BOOT_MAGIC) + return true; + else + return false; +} + +#if IS_ENABLED(CONFIG_CADENCE_QSPI) +/* This function is used to trigger software reset + * to the QSPI flash. On some boards, the QSPI flash reset may + * not be connected to the HPS warm reset. + */ +int qspi_flash_software_reset(void) +{ + struct udevice *flash; + int ret; + + /* Get the flash info */ + ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, + CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE, + &flash); + + if (ret) { + debug("Failed to initialize SPI flash at "); + debug("%u:%u (error %d)\n", CONFIG_SF_DEFAULT_BUS, + CONFIG_SF_DEFAULT_CS, ret); + return -ENODEV; + } + + if (!flash) + return -EINVAL; + + /* + * QSPI flash software reset command, for the case where + * no HPS reset connected to QSPI flash reset + */ + if (!memcmp(flash->name, "N25", SZ_1 + SZ_2)) + writel(QSPI_N25_SOFT_RESET_COMMAND, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND); + else if (!memcmp(flash->name, "S25FL", SZ_1 + SZ_4)) + writel(QSPI_S25FL_SOFT_RESET_COMMAND, + socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND); + else /* No software reset */ + writel(QSPI_NO_SOFT_RESET, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND); + + return 0; +} +#endif diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index f6c4b5708d..6450f75058 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -30,10 +30,14 @@ #include #include #include +#include #define FPGA_BUFSIZ 16 * 1024 #define FSBL_IMAGE_IS_VALID 0x49535756 +#define FSBL_IMAGE_IS_INVALID 0x0 +#define BOOTROM_CONFIGURES_IO_PINMUX 0x3 + DECLARE_GLOBAL_DATA_PTR; #define BOOTROM_SHARED_MEM_SIZE 0x800 /* 2KB */ @@ -107,6 +111,8 @@ u32 spl_mmc_boot_mode(const u32 boot_device) void spl_board_init(void) { + int ret; + ALLOC_CACHE_ALIGN_BUFFER(char, buf, FPGA_BUFSIZ); /* enable console uart printing */ @@ -117,8 +123,7 @@ void spl_board_init(void) /* If the full FPGA is already loaded, ie.from EPCQ, config fpga pins */ if (is_fpgamgr_user_mode()) { - int ret = config_pins(gd->fdt_blob, "shared"); - + ret = config_pins(gd->fdt_blob, "shared"); if (ret) return; @@ -131,8 +136,93 @@ void spl_board_init(void) } /* If the IOSSM/full FPGA is already loaded, start DDR */ - if (is_fpgamgr_early_user_mode() || is_fpgamgr_user_mode()) + if (is_fpgamgr_early_user_mode() || is_fpgamgr_user_mode()) { + if (!is_regular_boot_valid()) { + /* + * Ensure all signals in stable state before triggering + * warm reset. This value is recommended from stress + * test. + */ + mdelay(10); + +#if IS_ENABLED(CONFIG_CADENCE_QSPI) + /* + * Trigger software reset to QSPI flash. + * On some boards, the QSPI flash reset may not be + * connected to the HPS warm reset. + */ + qspi_flash_software_reset(); +#endif + + ret = readl(socfpga_get_rstmgr_addr() + + RSTMGR_A10_SYSWARMMASK); + /* + * Masking s2f & FPGA manager module reset from warm + * reset + */ + writel(ret & (~(ALT_RSTMGR_SYSWARMMASK_S2F_SET_MSK | + ALT_RSTMGR_FPGAMGRWARMMASK_S2F_SET_MSK)), + socfpga_get_rstmgr_addr() + + RSTMGR_A10_SYSWARMMASK); + + /* + * BootROM will configure both IO and pin mux after a + * warm reset + */ + ret = readl(socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_CTRL); + writel(ret | BOOTROM_CONFIGURES_IO_PINMUX, + socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_CTRL); + + /* + * Up to here, image is considered valid and should be + * set as valid before warm reset is triggered + */ + writel(FSBL_IMAGE_IS_VALID, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_INITSWSTATE); + + /* + * Set this flag to scratch register, so that a proper + * boot progress before / after warm reset can be + * tracked by FSBL + */ + set_regular_boot(true); + + WATCHDOG_RESET(); + + reset_cpu(); + } + + /* + * Reset this flag to scratch register, so that a proper + * boot progress before / after warm reset can be + * tracked by FSBL + */ + set_regular_boot(false); + + ret = readl(socfpga_get_rstmgr_addr() + + RSTMGR_A10_SYSWARMMASK); + + /* + * Unmasking s2f & FPGA manager module reset from warm + * reset + */ + writel(ret | ALT_RSTMGR_SYSWARMMASK_S2F_SET_MSK | + ALT_RSTMGR_FPGAMGRWARMMASK_S2F_SET_MSK, + socfpga_get_rstmgr_addr() + RSTMGR_A10_SYSWARMMASK); + + /* + * Up to here, MPFE hang workaround is considered done and + * should be reset as invalid until FSBL successfully loading + * SSBL, and prepare jumping to SSBL, then only setting as + * valid + */ + writel(FSBL_IMAGE_IS_INVALID, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_INITSWSTATE); + ddr_calibration_sequence(); + } if (!is_fpgamgr_user_mode()) fpgamgr_program(buf, FPGA_BUFSIZ, 0); -- cgit v1.2.3 From 4720b83d2c711062cfb55f03591b8f12c897d7cb Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Sun, 7 Nov 2021 23:08:56 +0800 Subject: arm: socfpga: arria10: Enable double peripheral RBF configuration Double peripheral RBF configuration are needed on some devices or boards to stabilize the IO configuration system. Signed-off-by: Tien Fong Chee Signed-off-by: Sin Hui Kho Reviewed-by: Tien Fong Chee --- arch/arm/mach-socfpga/include/mach/misc.h | 2 ++ arch/arm/mach-socfpga/misc_arria10.c | 36 +++++++++++++++++++++++++++++++ arch/arm/mach-socfpga/spl_a10.c | 14 ++++++++++++ drivers/fpga/socfpga_arria10.c | 3 ++- 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-socfpga/include/mach/misc.h b/arch/arm/mach-socfpga/include/mach/misc.h index 74e8e2590f..8460acb00d 100644 --- a/arch/arm/mach-socfpga/include/mach/misc.h +++ b/arch/arm/mach-socfpga/include/mach/misc.h @@ -45,7 +45,9 @@ int is_fpga_config_ready(void); #endif void do_bridge_reset(int enable, unsigned int mask); +void force_periph_program(unsigned int status); bool is_regular_boot_valid(void); +bool is_periph_program_force(void); void set_regular_boot(unsigned int status); void socfpga_pl310_clear(void); void socfpga_get_managers_addr(void); diff --git a/arch/arm/mach-socfpga/misc_arria10.c b/arch/arm/mach-socfpga/misc_arria10.c index 634e63ed42..0ed2adfd84 100644 --- a/arch/arm/mach-socfpga/misc_arria10.c +++ b/arch/arm/mach-socfpga/misc_arria10.c @@ -32,6 +32,7 @@ #define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q4_3 0x98 #define REGULAR_BOOT_MAGIC 0xd15ea5e +#define PERIPH_RBF_PROG_FORCE 0x50455249 #define QSPI_S25FL_SOFT_RESET_COMMAND 0x00f0ff82 #define QSPI_N25_SOFT_RESET_COMMAND 0x00000001 @@ -131,6 +132,41 @@ void do_bridge_reset(int enable, unsigned int mask) socfpga_bridges_reset(); } +/* + * This function set/unset flag with number "0x50455249" to + * handoff register isw_handoff[7] - 0xffd0624c + * This flag is used to force periph RBF program regardless FPGA status + * and double periph RBF config are needed on some devices or boards to + * stabilize the IO config system. + */ +void force_periph_program(unsigned int status) +{ + if (status) + writel(PERIPH_RBF_PROG_FORCE, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); + else + writel(0, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); +} + +/* + * This function is used to check whether + * handoff register isw_handoff[7] contains + * flag for forcing the periph RBF program "0x50455249". + */ +bool is_periph_program_force(void) +{ + unsigned int status; + + status = readl(socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); + + if (status == PERIPH_RBF_PROG_FORCE) + return true; + else + return false; +} + /* * This function set/unset magic number "0xd15ea5e" to * handoff register isw_handoff[7] - 0xffd0624c diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index 6450f75058..d2f454cd24 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -133,6 +133,20 @@ void spl_board_init(void) } else if (!is_fpgamgr_early_user_mode()) { /* Program IOSSM(early IO release) or full FPGA */ fpgamgr_program(buf, FPGA_BUFSIZ, 0); + + /* Skipping double program for combined RBF */ + if (!is_fpgamgr_user_mode()) { + /* + * Expect FPGA entered early user mode, so + * the flag is set to re-program IOSSM + */ + force_periph_program(true); + + /* Re-program IOSSM to stabilize IO system */ + fpgamgr_program(buf, FPGA_BUFSIZ, 0); + + force_periph_program(false); + } } /* If the IOSSM/full FPGA is already loaded, start DDR */ diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index b992e6f080..798e3a3f90 100644 --- a/drivers/fpga/socfpga_arria10.c +++ b/drivers/fpga/socfpga_arria10.c @@ -604,7 +604,8 @@ static int first_loading_rbf_to_buffer(struct udevice *dev, if (strstr(uname, "fpga-periph") && (!is_fpgamgr_early_user_mode() || - is_fpgamgr_user_mode())) { + is_fpgamgr_user_mode() || + is_periph_program_force())) { fpga_node_name = uname; printf("FPGA: Start to program "); printf("peripheral/full bitstream ...\n"); -- cgit v1.2.3