diff options
26 files changed, 594 insertions, 122 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index a0b06e9ee24..9d5af7ebca4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -157,6 +157,7 @@ S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-socfpga.git F: drivers/ddr/altera/ F: arch/arm/mach-socfpga/ +F: configs/socfpga_agilex5_vab_defconfig F: drivers/sysreset/sysreset_socfpga* ARM AMLOGIC SOC SUPPORT diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d8c99d3ab19..df373d38a55 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1138,6 +1138,7 @@ config ARCH_SOCFPGA select DM_SERIAL select GPIO_EXTRA_HEADER select ENABLE_ARM_SOC_BOOT0_HOOK if TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10 + select LMB_ARCH_MEM_MAP if TARGET_SOCFPGA_SOC64 select OF_CONTROL select SPL_DM_RESET if DM_RESET select SPL_DM_SERIAL @@ -1171,8 +1172,6 @@ config ARCH_SOCFPGA imply SPL_DM_SPI_FLASH imply SPL_LIBDISK_SUPPORT imply SPL_MMC - imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION - imply SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION_TYPE imply SPL_SPI_FLASH_SUPPORT imply SPL_SPI imply L2X0_CACHE diff --git a/arch/arm/dts/socfpga_agilex5-u-boot.dtsi b/arch/arm/dts/socfpga_agilex5-u-boot.dtsi index 8d6503dd091..874e71b5ca4 100644 --- a/arch/arm/dts/socfpga_agilex5-u-boot.dtsi +++ b/arch/arm/dts/socfpga_agilex5-u-boot.dtsi @@ -208,7 +208,8 @@ intel,offset-settings = /* DMIUSMCTCR */ <0x00000300 0x00000001 0x00000003>, - <0x00000300 0x00000003 0x00000003>; + <0x00000300 0x00000003 0x00000003>, + <0x00000308 0x00000004 0x0000001F>; bootph-all; }; @@ -218,7 +219,8 @@ intel,offset-settings = /* DMIUSMCTCR */ <0x00000300 0x00000001 0x00000003>, - <0x00000300 0x00000003 0x00000003>; + <0x00000300 0x00000003 0x00000003>, + <0x00000308 0x00000004 0x0000001F>; bootph-all; }; }; @@ -673,6 +675,17 @@ bootph-all; }; +&gpio1 { + /* Configure GPIO 1 pin 3 as output pin with value 0 during GPIO probe */ + portb: gpio-controller@0{ + sdio_sel { + gpio-hog; + gpios = <3 GPIO_ACTIVE_HIGH>; + output-low; + }; + }; +}; + &i2c0 { reset-names = "i2c"; }; diff --git a/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi b/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi index d7ab58267eb..8d7dc0945ab 100644 --- a/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi +++ b/arch/arm/dts/socfpga_agilex5_socdk-u-boot.dtsi @@ -25,34 +25,44 @@ /* * Both Memory base address and size default info is retrieved from HW setting. * Reconfiguration / Overwrite these info can be done with examples below. - */ - /* + * + * When LPDDR ECC is enabled, the last 1/8 of the memory region must + * be reserved for the Inline ECC buffer. + * * Example for memory size with 2GB: * memory { * reg = <0x0 0x80000000 0x0 0x80000000>; * }; - */ - /* + * * Example for memory size with 8GB: * memory { * reg = <0x0 0x80000000 0x0 0x80000000>, * <0x8 0x80000000 0x1 0x80000000>; * }; - */ - /* + * * Example for memory size with 32GB: * memory { * reg = <0x0 0x80000000 0x0 0x80000000>, * <0x8 0x80000000 0x7 0x80000000>; * }; - */ - /* + * * Example for memory size with 512GB: * memory { * reg = <0x0 0x80000000 0x0 0x80000000>, * <0x8 0x80000000 0x7 0x80000000>, * <0x88 0x00000000 0x78 0x00000000>; * }; + * + * Example for memory size with 2GB with LPDDR Inline ECC ON: + * memory { + * reg = <0x0 0x80000000 0x0 0x70000000>; + * }; + * + * Example for memory size with 8GB with LPDDR Inline ECC ON: + * memory { + * reg = <0x0 0x80000000 0x0 0x80000000>, + * <0x8 0x80000000 0x1 0x40000000>; + * }; */ chosen { diff --git a/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi b/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi index 15306db6002..93a8e0697d6 100644 --- a/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi +++ b/arch/arm/dts/socfpga_soc64_fit-u-boot.dtsi @@ -106,8 +106,13 @@ arch = "arm64"; os = "linux"; compression = "none"; + #if IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5) + load = <0x86000000>; + entry = <0x86000000>; + #else load = <0x6000000>; entry = <0x6000000>; + #endif kernel_blob: blob-ext { filename = "Image"; }; diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile index 22d48dfae1c..c43fdee4a48 100644 --- a/arch/arm/mach-socfpga/Makefile +++ b/arch/arm/mach-socfpga/Makefile @@ -68,6 +68,8 @@ obj-y += altera-sysmgr.o obj-y += ccu_ncore3.o obj-y += system_manager_soc64.o obj-y += timer_s10.o +obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH) += secure_vab.o +obj-$(CONFIG_SOCFPGA_SECURE_VAB_AUTH) += vab.o endif ifdef CONFIG_TARGET_SOCFPGA_N5X diff --git a/arch/arm/mach-socfpga/board.c b/arch/arm/mach-socfpga/board.c index 27072e53135..8506d510413 100644 --- a/arch/arm/mach-socfpga/board.c +++ b/arch/arm/mach-socfpga/board.c @@ -195,3 +195,16 @@ void board_prep_linux(struct bootm_headers *images) } } #endif + +#if CONFIG_IS_ENABLED(LMB_ARCH_MEM_MAP) +void lmb_arch_add_memory(void) +{ + int i; + struct bd_info *bd = gd->bd; + + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + if (bd->bi_dram[i].size) + lmb_add(bd->bi_dram[i].start, bd->bi_dram[i].size); + } +} +#endif diff --git a/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h b/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h index 65721098b2b..5ac868a281b 100644 --- a/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h +++ b/arch/arm/mach-socfpga/include/mach/base_addr_soc64.h @@ -51,6 +51,7 @@ #else #define SOCFPGA_FW_MPU_DDR_SCR_ADDRESS 0xf8020100 #endif +#define SOCFPGA_F2SDRAM_MGR_ADDRESS 0xf8024000 #define SOCFPGA_SMMU_ADDRESS 0xfa000000 #define SOCFPGA_MAILBOX_ADDRESS 0xffa30000 #define SOCFPGA_UART0_ADDRESS 0xffc02000 diff --git a/arch/arm/mach-socfpga/include/mach/mailbox_s10.h b/arch/arm/mach-socfpga/include/mach/mailbox_s10.h index 45cc9912f94..2099c51b682 100644 --- a/arch/arm/mach-socfpga/include/mach/mailbox_s10.h +++ b/arch/arm/mach-socfpga/include/mach/mailbox_s10.h @@ -128,6 +128,7 @@ enum ALT_SDM_MBOX_RESP_CODE { #define MBOX_QSPI_CLOSE 51 #define MBOX_QSPI_DIRECT 59 #define MBOX_REBOOT_HPS 71 +#define MBOX_HPS_STAGE_NOTIFY 93 /* Mailbox registers */ #define MBOX_CIN 0 /* command valid offset */ @@ -385,6 +386,8 @@ enum MBOX_CFGSTAT_MINOR_ERR_CODE { #define RCF_SOFTFUNC_STATUS_SEU_ERROR BIT(3) #define RCF_PIN_STATUS_NSTATUS BIT(31) +#define HPS_EXECUTION_STATE_FSBL 0 + int mbox_send_cmd(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg, u8 urgent, u32 *resp_buf_len, u32 *resp_buf); int mbox_send_cmd_psci(u8 id, u32 cmd, u8 is_indirect, u32 len, u32 *arg, @@ -401,6 +404,7 @@ int mbox_qspi_open(void); #endif int mbox_reset_cold(void); +int mbox_hps_stage_notify(u32 execution_stage); int mbox_get_fpga_config_status(u32 cmd); int mbox_get_fpga_config_status_psci(u32 cmd); #endif /* _MAILBOX_S10_H_ */ diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager_soc64.h b/arch/arm/mach-socfpga/include/mach/reset_manager_soc64.h index 058fdd6e548..4b010be9ee8 100644 --- a/arch/arm/mach-socfpga/include/mach/reset_manager_soc64.h +++ b/arch/arm/mach-socfpga/include/mach/reset_manager_soc64.h @@ -10,9 +10,12 @@ void reset_deassert_peripherals_handoff(void); int cpu_has_been_warmreset(void); void print_reset_info(void); -void socfpga_bridges_reset(int enable); +void socfpga_bridges_reset(int enable, unsigned int mask); #define RSTMGR_SOC64_STATUS 0x00 +#define RSTMGR_SOC64_HDSKEN 0x10 +#define RSTMGR_SOC64_HDSKREQ 0x14 +#define RSTMGR_SOC64_HDSKACK 0x18 #define RSTMGR_SOC64_MPUMODRST 0x20 #define RSTMGR_SOC64_PER0MODRST 0x24 #define RSTMGR_SOC64_PER1MODRST 0x28 @@ -20,8 +23,17 @@ void socfpga_bridges_reset(int enable); #define RSTMGR_MPUMODRST_CORE0 0 #define RSTMGR_PER0MODRST_OCP_MASK 0x0020bf00 -#define RSTMGR_BRGMODRST_DDRSCH_MASK 0X00000040 -#define RSTMGR_BRGMODRST_FPGA2SOC_MASK 0x00000004 + +#define RSTMGR_BRGMODRST_SOC2FPGA_MASK BIT(0) +#define RSTMGR_BRGMODRST_LWSOC2FPGA_MASK BIT(1) +#define RSTMGR_BRGMODRST_FPGA2SOC_MASK BIT(2) +#define RSTMGR_BRGMODRST_F2SDRAM0_MASK BIT(3) +#define RSTMGR_BRGMODRST_F2SDRAM1_MASK BIT(4) +#define RSTMGR_BRGMODRST_F2SDRAM2_MASK BIT(5) +#define RSTMGR_BRGMODRST_DDRSCH_MASK BIT(6) + +#define RSTMGR_HDSKEN_FPGAHSEN BIT(2) +#define RSTMGR_HDSKREQ_FPGAHSREQ BIT(2) /* SDM, Watchdogs and MPU warm reset mask */ #define RSTMGR_STAT_SDMWARMRST 0x2 diff --git a/arch/arm/mach-socfpga/mailbox_s10.c b/arch/arm/mach-socfpga/mailbox_s10.c index b69bd3e47ec..f9c34e85711 100644 --- a/arch/arm/mach-socfpga/mailbox_s10.c +++ b/arch/arm/mach-socfpga/mailbox_s10.c @@ -6,6 +6,7 @@ #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/global_data.h> #include <asm/io.h> @@ -474,6 +475,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_soc64.c b/arch/arm/mach-socfpga/misc_soc64.c index e0b2b4237e1..4f080f4f0b3 100644 --- a/arch/arm/mach-socfpga/misc_soc64.c +++ b/arch/arm/mach-socfpga/misc_soc64.c @@ -61,7 +61,7 @@ void save_boot_params(unsigned long r0, unsigned long r1, unsigned long r2, #if defined(CONFIG_DISPLAY_CPUINFO) int print_cpuinfo(void) { - printf("CPU: Intel FPGA SoCFPGA Platform (ARMv8 64bit Cortex-%s)\n", + printf("CPU: Altera FPGA SoCFPGA Platform (ARMv8 64bit Cortex-%s)\n", IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5) ? "A55/A76" : "A53"); return 0; @@ -107,5 +107,5 @@ void do_bridge_reset(int enable, unsigned int mask) return; } - socfpga_bridges_reset(enable); + socfpga_bridges_reset(enable, mask); } diff --git a/arch/arm/mach-socfpga/mmu-arm64_s10.c b/arch/arm/mach-socfpga/mmu-arm64_s10.c index b8e40d9a788..1dc44ab4797 100644 --- a/arch/arm/mach-socfpga/mmu-arm64_s10.c +++ b/arch/arm/mach-socfpga/mmu-arm64_s10.c @@ -58,6 +58,20 @@ static struct mm_region socfpga_agilex5_mem_map[] = { .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE, }, { + /* MEM 30GB */ + .virt = 0x880000000UL, + .phys = 0x880000000UL, + .size = 0x780000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { + /* MEM 480GB */ + .virt = 0x8800000000UL, + .phys = 0x8800000000UL, + .size = 0x7800000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, { /* List terminator */ }, }; diff --git a/arch/arm/mach-socfpga/reset_manager_s10.c b/arch/arm/mach-socfpga/reset_manager_s10.c index a634c11a028..abb62a9b49f 100644 --- a/arch/arm/mach-socfpga/reset_manager_s10.c +++ b/arch/arm/mach-socfpga/reset_manager_s10.c @@ -1,21 +1,34 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2016-2018 Intel Corporation <www.intel.com> + * Copyright (C) 2025 Altera Corporation <www.altera.com> * */ +#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> +#include <wait_bit.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 + /* Assert or de-assert SoCFPGA reset manager reset. */ void socfpga_per_reset(u32 reset, int set) { @@ -56,66 +69,213 @@ void socfpga_per_reset_all(void) writel(0xffffffff, socfpga_get_rstmgr_addr() + RSTMGR_SOC64_PER1MODRST); } -void socfpga_bridges_reset(int enable) +static void socfpga_f2s_bridges_reset(int enable, unsigned int mask) { -#if !defined(CONFIG_XPL_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); - 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_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); + } + + 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_le32((u32 *)(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGINSTATUS0), + flaginstatus_idleack, false, TIMEOUT_300MS, false); + + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTCLR0, + flagoutset_fdrain); + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTSET0, flagoutset_en); + + 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_le32((u32 *)(socfpga_get_rstmgr_addr() + + RSTMGR_SOC64_HDSKACK), RSTMGR_HDSKREQ_FPGAHSREQ, + true, TIMEOUT_300MS, false); + + setbits_le32(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGOUTCLR0, flagoutset_en); + + 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_le32((u32 *)(SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGINSTATUS0), + flaginstatus_respempty, true, + TIMEOUT_300MS, false); + + /* Confirm again */ + if (!ret) + ret = wait_for_bit_le32((u32 *) + (SOCFPGA_F2SDRAM_MGR_ADDRESS + + F2SDRAM_SIDEBAND_FLAGINSTATUS0), + flaginstatus_respempty, true, + TIMEOUT_300MS, false); + + 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); } -#else - u32 reg; +} + +static 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; + } + + 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_le32((u32 *)(socfpga_get_sysmgr_addr() + + SYSMGR_SOC64_NOC_IDLEACK), noc_mask, false, + TIMEOUT_300MS, false); } 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_le32((u32 *)(socfpga_get_sysmgr_addr() + + SYSMGR_SOC64_NOC_IDLEACK), noc_mask, true, + TIMEOUT_300MS, false); + + /* Wait for all NOC master idlestatus to 1 */ + wait_for_bit_le32((u32 *)(socfpga_get_sysmgr_addr() + + SYSMGR_SOC64_NOC_IDLESTATUS), noc_mask, true, + TIMEOUT_300MS, false); + + /* 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_XPL_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, check bridges availability. Status %d.\n", + enable ? "enable" : "disable", ret); + } else { + socfpga_s2f_bridges_reset(enable, mask); + socfpga_f2s_bridges_reset(enable, mask); + } } /* diff --git a/arch/arm/mach-socfpga/spl_agilex.c b/arch/arm/mach-socfpga/spl_agilex.c index 52617a39cca..91c27a5543d 100644 --- a/arch/arm/mach-socfpga/spl_agilex.c +++ b/arch/arm/mach-socfpga/spl_agilex.c @@ -50,6 +50,10 @@ void board_init_f(ulong dummy) timer_init(); + mbox_init(); + + mbox_hps_stage_notify(HPS_EXECUTION_STATE_FSBL); + sysmgr_pinmux_init(); ret = uclass_get_device(UCLASS_CLK, 0, &dev); @@ -77,8 +81,6 @@ void board_init_f(ulong dummy) } #endif - mbox_init(); - #ifdef CONFIG_CADENCE_QSPI mbox_qspi_open(); #endif diff --git a/arch/arm/mach-socfpga/spl_agilex5.c b/arch/arm/mach-socfpga/spl_agilex5.c index 3451611082d..a9aad5350d2 100644 --- a/arch/arm/mach-socfpga/spl_agilex5.c +++ b/arch/arm/mach-socfpga/spl_agilex5.c @@ -62,6 +62,10 @@ void board_init_f(ulong dummy) timer_init(); + mbox_init(); + + mbox_hps_stage_notify(HPS_EXECUTION_STATE_FSBL); + ret = uclass_get_device(UCLASS_CLK, 0, &dev); if (ret) { debug("Clock init failed: %d\n", ret); @@ -100,8 +104,6 @@ void board_init_f(ulong dummy) } } - mbox_init(); - if (IS_ENABLED(CONFIG_CADENCE_QSPI)) mbox_qspi_open(); diff --git a/arch/arm/mach-socfpga/spl_n5x.c b/arch/arm/mach-socfpga/spl_n5x.c index 5ff137e5c6f..81283ef7162 100644 --- a/arch/arm/mach-socfpga/spl_n5x.c +++ b/arch/arm/mach-socfpga/spl_n5x.c @@ -49,6 +49,10 @@ void board_init_f(ulong dummy) timer_init(); + mbox_init(); + + mbox_hps_stage_notify(HPS_EXECUTION_STATE_FSBL); + sysmgr_pinmux_init(); preloader_console_init(); @@ -84,8 +88,6 @@ void board_init_f(ulong dummy) } #endif - mbox_init(); - #ifdef CONFIG_CADENCE_QSPI mbox_qspi_open(); #endif diff --git a/arch/arm/mach-socfpga/spl_s10.c b/arch/arm/mach-socfpga/spl_s10.c index 53852cb7443..fa83ff96adc 100644 --- a/arch/arm/mach-socfpga/spl_s10.c +++ b/arch/arm/mach-socfpga/spl_s10.c @@ -52,6 +52,10 @@ void board_init_f(ulong dummy) socfpga_per_reset(SOCFPGA_RESET(OSC1TIMER0), 0); timer_init(); + mbox_init(); + + mbox_hps_stage_notify(HPS_EXECUTION_STATE_FSBL); + sysmgr_pinmux_init(); /* configuring the HPS clocks */ @@ -84,8 +88,6 @@ void board_init_f(ulong dummy) } #endif - mbox_init(); - #ifdef CONFIG_CADENCE_QSPI mbox_qspi_open(); #endif diff --git a/configs/socfpga_agilex5_defconfig b/configs/socfpga_agilex5_defconfig index 8f327e5f2ab..4ac0a5d9b99 100644 --- a/configs/socfpga_agilex5_defconfig +++ b/configs/socfpga_agilex5_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_SOCFPGA=y CONFIG_TEXT_BASE=0x80200000 +CONFIG_SPL_GPIO=y CONFIG_NR_DRAM_BANKS=3 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80300000 @@ -31,6 +32,8 @@ CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 initrd=0x90000000 root=/dev/ram0 rw init=/sbin/init ramdisk_size=10000000 earlycon panic=-1 nosmp kvm-arm.mode=nvhe" CONFIG_BOARD_EARLY_INIT_F=y CONFIG_BLOBLIST=y +CONFIG_BLOBLIST_FIXED=y +CONFIG_BLOBLIST_ADDR=0x7e000 CONFIG_BLOBLIST_SIZE=0x1000 CONFIG_SPL_MAX_SIZE=0x40000 CONFIG_HANDOFF=y @@ -73,6 +76,8 @@ CONFIG_BOOTFILE="kernel.itb" CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_SPL_ALTERA_SDRAM=y +CONFIG_GPIO_HOG=y +CONFIG_SPL_GPIO_HOG=y CONFIG_DWAPB_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_DW=y @@ -82,6 +87,7 @@ CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y +CONFIG_PHY_MARVELL=y CONFIG_DWC_ETH_XGMAC=y CONFIG_RGMII=y CONFIG_SYS_NS16550_MEM32=y diff --git a/configs/socfpga_agilex5_vab_defconfig b/configs/socfpga_agilex5_vab_defconfig new file mode 100644 index 00000000000..a5f4b335760 --- /dev/null +++ b/configs/socfpga_agilex5_vab_defconfig @@ -0,0 +1,3 @@ +#include <configs/socfpga_agilex5_defconfig> + +CONFIG_SOCFPGA_SECURE_VAB_AUTH=y diff --git a/drivers/ddr/altera/iossm_mailbox.c b/drivers/ddr/altera/iossm_mailbox.c index db9435db657..fc09dde3f9e 100644 --- a/drivers/ddr/altera/iossm_mailbox.c +++ b/drivers/ddr/altera/iossm_mailbox.c @@ -10,6 +10,7 @@ #include <asm/arch/base_addr_soc64.h> #include <asm/io.h> #include <linux/bitfield.h> +#include <linux/sizes.h> #include "iossm_mailbox.h" #define TIMEOUT_120000MS 120000 @@ -87,6 +88,7 @@ /* offset info of ECC_ENABLE_INTF */ #define INTF_ECC_ENABLE_TYPE_MASK GENMASK(1, 0) +#define INTF_ECC_TYPE_MASK BIT(8) /* cmd opcode BIST_MEM_INIT_START, BIST performed on full memory address range */ #define BIST_FULL_MEM BIT(6) @@ -96,6 +98,7 @@ /* offset info of ECC_ERR_STATUS */ #define ECC_ERR_COUNTER_MASK GENMASK(15, 0) +#define ECC_ERR_OVERFLOW_MASK GENMASK(31, 16) /* offset info of ECC_ERR_DATA */ #define ECC_ERR_IP_TYPE_MASK GENMASK(24, 22) @@ -104,9 +107,15 @@ #define ECC_ERR_TYPE_MASK GENMASK(9, 6) #define ECC_ERR_ADDR_UPPER_MASK GENMASK(5, 0) #define ECC_ERR_ADDR_LOWER_MASK GENMASK(31, 0) +#define ECC_FULL_ADDR_UPPER_MASK GENMASK(63, 32) +#define ECC_FULL_ADDR_LOWER_MASK GENMASK(31, 0) #define MAX_ECC_ERR_INFO_COUNT 16 +#define BIST_START_ADDR_SPACE_MASK GENMASK(5, 0) +#define BIST_START_ADDR_LOW_MASK GENMASK(31, 0) +#define BIST_START_ADDR_HIGH_MASK GENMASK(37, 32) + #define IO96B_MB_REQ_SETUP(v, w, x, y, z) \ usr_req.ip_type = v; \ usr_req.ip_id = w; \ @@ -161,6 +170,24 @@ struct ecc_err_info { u32 addr_lower; }; +struct ecc_overflow_error_desc { + int bit; + const char *msg; +}; + +static const struct ecc_overflow_error_desc ecc_overflow_errors[] = { + { 0, " - Single-bit error\n" }, + { 1, " - Multiple single-bit errors\n" }, + { 2, " - Double-bit error\n" }, + { 3, " - Multiple double-bit errors\n" }, + { 8, " - Single-bit error during ECC scrubbing\n" }, + { 9, " - Write link ECC single-bit error (LPDDR5 only)\n" }, + { 10, " - Write link ECC double-bit error (LPDDR5 only)\n" }, + { 11, " - Read link ECC single-bit error (LPDDR5 only)\n" }, + { 12, " - Read link ECC double-bit error (LPDDR5 only)\n" }, + { 13, " - RMW read link ECC double-bit error (LPDDR5 only)\n" }, +}; + static int is_ddr_csr_clkgen_locked(u8 io96b_pll) { int ret = 0; @@ -512,7 +539,7 @@ int get_mem_width_info(struct io96b_info *io96b_ctrl) { int i, j, ret = 0; u32 mem_width_info; - u16 memory_size, total_memory_size = 0; + phys_size_t memory_size, total_memory_size = 0; u32 mem_total_capacity_intf_offset[MAX_MEM_INTERFACE_SUPPORTED] = { IOSSM_MEM_TOTAL_CAPACITY_INTF0_OFFSET, @@ -526,8 +553,11 @@ int get_mem_width_info(struct io96b_info *io96b_ctrl) mem_width_info = readl(io96b_ctrl->io96b[i].io96b_csr_addr + mem_total_capacity_intf_offset[j]); - memory_size = memory_size + - FIELD_GET(INTF_CAPACITY_GBITS_MASK, mem_width_info); + io96b_ctrl->io96b[i].mb_ctrl.memory_size[j] = + FIELD_GET(INTF_CAPACITY_GBITS_MASK, mem_width_info) * SZ_1G / SZ_8; + + if (io96b_ctrl->io96b[i].mb_ctrl.memory_size[j] != 0) + memory_size += io96b_ctrl->io96b[i].mb_ctrl.memory_size[j]; } if (!memory_size) { @@ -536,8 +566,6 @@ int get_mem_width_info(struct io96b_info *io96b_ctrl) goto err; } - io96b_ctrl->io96b[i].size = memory_size; - total_memory_size = total_memory_size + memory_size; } @@ -556,7 +584,7 @@ int ecc_enable_status(struct io96b_info *io96b_ctrl) { int i, j, ret = 0; u32 ecc_enable_intf; - bool ecc_stat, ecc_stat_set = false; + bool ecc_status, ecc_status_set = false, inline_ecc = false; u32 ecc_enable_intf_offset[MAX_MEM_INTERFACE_SUPPORTED] = { IOSSM_ECC_ENABLE_INTF0_OFFSET, @@ -565,6 +593,7 @@ int ecc_enable_status(struct io96b_info *io96b_ctrl) /* Initialize ECC status */ io96b_ctrl->ecc_status = false; + io96b_ctrl->inline_ecc = false; /* Get and ensure all memory interface(s) same ECC status */ for (i = 0; i < io96b_ctrl->num_instance; i++) { @@ -572,15 +601,21 @@ int ecc_enable_status(struct io96b_info *io96b_ctrl) ecc_enable_intf = readl(io96b_ctrl->io96b[i].io96b_csr_addr + ecc_enable_intf_offset[j]); - ecc_stat = (FIELD_GET(INTF_ECC_ENABLE_TYPE_MASK, ecc_enable_intf) + ecc_status = (FIELD_GET(INTF_ECC_ENABLE_TYPE_MASK, ecc_enable_intf) == 0) ? false : true; + inline_ecc = FIELD_GET(INTF_ECC_TYPE_MASK, ecc_enable_intf); + + if (!ecc_status_set) { + io96b_ctrl->ecc_status = ecc_status; + + if (io96b_ctrl->ecc_status) + io96b_ctrl->inline_ecc = inline_ecc; - if (!ecc_stat_set) { - io96b_ctrl->ecc_status = ecc_stat; - ecc_stat_set = true; + ecc_status_set = true; } - if (ecc_stat != io96b_ctrl->ecc_status) { + if (ecc_status != io96b_ctrl->ecc_status || + (io96b_ctrl->ecc_status && inline_ecc != io96b_ctrl->inline_ecc)) { printf("%s: Mismatch DDR ECC status on IO96B_%d\n", __func__, i); ret = -EINVAL; @@ -614,16 +649,28 @@ bool ecc_interrupt_status(struct io96b_info *io96b_ctrl) { int i, j; u32 ecc_err_status; - u16 ecc_err_counter; + u16 ecc_err_counter, ecc_overflow_status; bool ecc_error_flag = false; /* Get ECC double-bit error status */ for (i = 0; i < io96b_ctrl->num_instance; i++) { ecc_err_status = readl(io96b_ctrl->io96b[i].io96b_csr_addr + IOSSM_ECC_ERR_STATUS_OFFSET); + ecc_err_counter = FIELD_GET(ECC_ERR_COUNTER_MASK, ecc_err_status); - debug("%s: ECC error number detected on IO96B_%d: %d\n", - __func__, i, ecc_err_counter); + log_err("%s: ECC error number detected on IO96B_%d: %d\n", + __func__, i, ecc_err_counter); + + ecc_overflow_status = FIELD_GET(ECC_ERR_OVERFLOW_MASK, ecc_err_status); + if (ecc_overflow_status != 0) { + log_err("ECC Error Overflow Flags:\n"); + + for (int i = 0; i < ARRAY_SIZE(ecc_overflow_errors); i++) { + if (ecc_overflow_status & BIT(ecc_overflow_errors[i].bit)) { + log_err("%s", ecc_overflow_errors[i].msg); + } + } + } if (ecc_err_counter != 0) { phys_addr_t address; @@ -647,15 +694,20 @@ bool ecc_interrupt_status(struct io96b_info *io96b_ctrl) ecc_err_data); err_info.addr_lower = readl(address + sizeof(u32)); - debug("%s: ECC double-bit error detected on IO96B_%d:\n", - __func__, i); - debug("- error info address :0x%llx\n", address); - debug("- error ip type: %d\n", err_info.ip_type); - debug("- error instance id: %d\n", err_info.instance_id); - debug("- error source id: %d\n", err_info.source_id); - debug("- error type: %d\n", err_info.err_type); - debug("- error address upper: 0x%x\n", err_info.addr_upper); - debug("- error address lower: 0x%x\n", err_info.addr_lower); + log_err(" %s: DDR ECC Error Detected on IO96B_%d number:%d\n", + __func__, i, j); + log_err(" - error info address :0x%llx\n", address); + log_err(" - error ip type: %d\n", err_info.ip_type); + log_err(" - error instance id: %d\n", err_info.instance_id); + log_err(" - error source id: %d\n", err_info.source_id); + log_err(" - error type: %s\n", + is_double_bit_error(err_info.err_type) ? + "Double-bit error" : "Single-bit error"); + log_err(" - error address: 0x%016llx\n", + (u64)FIELD_PREP(ECC_FULL_ADDR_UPPER_MASK, + err_info.addr_upper) | + FIELD_PREP(ECC_FULL_ADDR_LOWER_MASK, + err_info.addr_lower)); if (is_double_bit_error(err_info.err_type)) { if (!ecc_error_flag) @@ -668,12 +720,12 @@ bool ecc_interrupt_status(struct io96b_info *io96b_ctrl) } if (ecc_error_flag) - printf("\n%s: ECC double-bit error detected!\n", __func__); + log_err("\n%s: ECC double-bit error detected!\n", __func__); return ecc_error_flag; } -int bist_mem_init_start(struct io96b_info *io96b_ctrl) +int out_of_band_bist_mem_init_start(struct io96b_info *io96b_ctrl) { struct io96b_mb_req usr_req; struct io96b_mb_resp usr_resp; @@ -746,3 +798,126 @@ int bist_mem_init_start(struct io96b_info *io96b_ctrl) err: return ret; } + +int bist_mem_init_by_addr(struct io96b_info *io96b_ctrl, int inst_id, int intf_id, + phys_addr_t base_addr, phys_size_t size) +{ + struct io96b_mb_req usr_req; + struct io96b_mb_resp usr_resp; + int n, ret = 0; + bool bist_start, bist_success; + u32 mem_exp, mem_init_status_intf, start; + phys_size_t chunk_size; + + u32 mem_init_status_offset[MAX_MEM_INTERFACE_SUPPORTED] = { + IOSSM_MEM_INIT_STATUS_INTF0_OFFSET, + IOSSM_MEM_INIT_STATUS_INTF1_OFFSET + }; + + /* Check if size is a power of 2 */ + if (size == 0 || (size & (size - 1)) != 0) { + ret = -EINVAL; + goto err; + } + + mem_exp = 0; + chunk_size = size; + + while (chunk_size >>= 1) + mem_exp++; + + /* Start memory initialization BIST on the specified address range */ + IO96B_MB_REQ_SETUP(io96b_ctrl->io96b[inst_id].mb_ctrl.ip_type[intf_id], + io96b_ctrl->io96b[inst_id].mb_ctrl.ip_id[intf_id], + CMD_TRIG_CONTROLLER_OP, BIST_MEM_INIT_START, 0); + + /* CMD_PARAM_0 bit[5:0] = mem_exp */ + /* CMD_PARAM_0 bit[6]: 0 - on the specified address range */ + usr_req.cmd_param[0] = FIELD_PREP(BIST_START_ADDR_SPACE_MASK, mem_exp); + /* Extract address fields START_ADDR[31:0] */ + usr_req.cmd_param[1] = FIELD_GET(BIST_START_ADDR_LOW_MASK, base_addr); + /* Extract address fields START_ADDR[37:32] */ + usr_req.cmd_param[2] = FIELD_GET(BIST_START_ADDR_HIGH_MASK, base_addr); + /* Initialize memory to all zeros */ + usr_req.cmd_param[3] = 0; + + bist_start = false; + bist_success = false; + + /* Send request to DDR controller */ + debug("%s:Initializing memory: Addr=0x%llx, Size=2^%u\n", __func__, + base_addr, mem_exp); + ret = io96b_mb_req(io96b_ctrl->io96b[inst_id].io96b_csr_addr, + usr_req, 0, &usr_resp); + if (ret) + goto err; + + bist_start = IOSSM_CMD_RESPONSE_DATA_SHORT(usr_resp.cmd_resp_status) + & BIT(0); + + if (!bist_start) { + printf("%s: Failed to initialize memory on IO96B_%d\n", __func__, + inst_id); + printf("%s: BIST_MEM_INIT_START Error code 0x%lx\n", __func__, + IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status)); + + ret = -EINVAL; + goto err; + } + + /* Polling for the initiated memory initialization BIST status */ + start = get_timer(0); + while (!bist_success) { + udelay(1); + + mem_init_status_intf = readl(io96b_ctrl->io96b[inst_id].io96b_csr_addr + + mem_init_status_offset[intf_id]); + + bist_success = FIELD_GET(INTF_BIST_STATUS_MASK, mem_init_status_intf); + + if (!bist_success && (get_timer(start) > TIMEOUT)) { + printf("%s: Timeout initialize memory on IO96B_%d\n", + __func__, inst_id); + printf("%s: BIST_MEM_INIT_STATUS Error code 0x%lx\n", + __func__, + IOSSM_STATUS_CMD_RESPONSE_ERROR(usr_resp.cmd_resp_status)); + + ret = -ETIMEDOUT; + goto err; + } + } + + debug("%s:DDR memory initializationat 0x%llx completed.\n", __func__, base_addr); + +err: + return ret; +} + +int inline_ecc_bist_mem_init(struct io96b_info *io96b_ctrl) +{ + int i, j, ret = 0; + + /* Memory initialization BIST performed on all memory interfaces */ + for (i = 0; i < io96b_ctrl->num_instance; i++) { + for (j = 0; j < io96b_ctrl->io96b[i].mb_ctrl.num_mem_interface; j++) { + ret = bist_mem_init_by_addr(io96b_ctrl, i, j, 0, + io96b_ctrl->io96b[i].mb_ctrl.memory_size[j]); + if (ret) { + printf("Error: Memory init failed at Instance %d, Interface %d\n", + i, j); + goto err; + } + } + } + +err: + return ret; +} + +int bist_mem_init_start(struct io96b_info *io96b_ctrl) +{ + if (io96b_ctrl->inline_ecc) + return inline_ecc_bist_mem_init(io96b_ctrl); + else + return out_of_band_bist_mem_init_start(io96b_ctrl); +} diff --git a/drivers/ddr/altera/iossm_mailbox.h b/drivers/ddr/altera/iossm_mailbox.h index 6f794781d30..02d1db28e20 100644 --- a/drivers/ddr/altera/iossm_mailbox.h +++ b/drivers/ddr/altera/iossm_mailbox.h @@ -40,11 +40,13 @@ enum iossm_mailbox_cmd_opcode { * @num_mem_interface: Number of memory interfaces instantiated * @ip_type: IP type implemented on the IO96B * @ip_instance_id: IP identifier for every IP instance implemented on the IO96B + * @memory_size[2]: Memory size for every IP instance implemented on the IO96B */ struct io96b_mb_ctrl { u32 num_mem_interface; u32 ip_type[2]; u32 ip_id[2]; + phys_size_t memory_size[2]; }; /* CMD_REQ Register Definition */ @@ -53,6 +55,9 @@ struct io96b_mb_ctrl { #define CMD_TYPE_MASK GENMASK(23, 16) #define CMD_OPCODE_MASK GENMASK(15, 0) +/* Computes the Inline ECC data region size */ +#define CALC_INLINE_ECC_HW_SIZE(size) (((size) * 7) / 8) + /* * IOSSM mailbox request * @ip_type: IP type for the specified memory interface @@ -83,13 +88,11 @@ struct io96b_mb_resp { /* * IO96B instance specific information * - * @size: Memory size * @io96b_csr_addr: IO96B instance CSR address * @cal_status: IO96B instance calibration status * @mb_ctrl: IOSSM mailbox required information */ struct io96b_instance { - u16 size; phys_addr_t io96b_csr_addr; bool cal_status; struct io96b_mb_ctrl mb_ctrl; @@ -102,6 +105,7 @@ struct io96b_instance { * @overall_cal_status: Overall calibration status for all IO96B instance(s) * @ddr_type: DDR memory type * @ecc_status: ECC enable status (false = disabled, true = enabled) + * @inline_ecc: Inline ECC or Out of Band ECC (false = Out of Band ECC, true = Inline ECC) * @overall_size: Total DDR memory size * @io96b[]: IO96B instance specific information * @ckgen_lock: IO96B GEN PLL lock (false = not locked, true = locked) @@ -115,7 +119,8 @@ struct io96b_info { bool overall_cal_status; const char *ddr_type; bool ecc_status; - u16 overall_size; + bool inline_ecc; + phys_size_t overall_size; struct io96b_instance io96b[MAX_IO96B_SUPPORTED]; bool ckgen_lock; u8 num_port; diff --git a/drivers/ddr/altera/sdram_agilex5.c b/drivers/ddr/altera/sdram_agilex5.c index 801a6bbab46..ee66c72157a 100644 --- a/drivers/ddr/altera/sdram_agilex5.c +++ b/drivers/ddr/altera/sdram_agilex5.c @@ -291,7 +291,14 @@ int sdram_mmr_init_full(struct udevice *dev) goto err; } - hw_size = (phys_size_t)io96b_ctrl->overall_size * SZ_1G / SZ_8; + ret = ecc_enable_status(io96b_ctrl); + if (ret) { + printf("DDR: Failed to get ECC enabled status\n"); + + goto err; + } + + hw_size = io96b_ctrl->overall_size; /* Get bank configuration from devicetree */ ret = fdtdec_decode_ram_size(gd->fdt_blob, NULL, 0, NULL, @@ -303,6 +310,9 @@ int sdram_mmr_init_full(struct udevice *dev) goto err; } + if (io96b_ctrl->inline_ecc) + hw_size = CALC_INLINE_ECC_HW_SIZE(hw_size); + if (gd->ram_size > hw_size) { printf("DDR: Warning: DRAM size from device tree (%lld MiB) exceeds\n", gd->ram_size >> 20); @@ -355,13 +365,6 @@ int sdram_mmr_init_full(struct udevice *dev) printf("%s: %lld MiB\n", io96b_ctrl->ddr_type, gd->ram_size >> 20); - ret = ecc_enable_status(io96b_ctrl); - if (ret) { - printf("DDR: Failed to get ECC enabled status\n"); - - goto err; - } - /* Is HPS cold or warm reset? If yes, Skip full memory initialization if ECC * enabled to preserve memory content */ diff --git a/drivers/ddr/altera/sdram_soc64.c b/drivers/ddr/altera/sdram_soc64.c index c8c9211adce..27fbe80ed41 100644 --- a/drivers/ddr/altera/sdram_soc64.c +++ b/drivers/ddr/altera/sdram_soc64.c @@ -185,35 +185,51 @@ void sdram_init_ecc_bits(struct bd_info *bd) void sdram_size_check(struct bd_info *bd) { phys_size_t total_ram_check = 0; - phys_size_t ram_check = 0; - phys_addr_t start = 0; - phys_size_t size, remaining_size; int bank; /* Sanity check ensure correct SDRAM size specified */ debug("DDR: Running SDRAM size sanity check\n"); for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + phys_size_t ram_check = 0; + phys_addr_t start = 0; + phys_size_t remaining_size; + start = bd->bi_dram[bank].start; remaining_size = bd->bi_dram[bank].size; + debug("Checking bank %d: start=0x%llx, size=0x%llx\n", + bank, start, remaining_size); + while (ram_check < bd->bi_dram[bank].size) { - size = min((phys_addr_t)SZ_1G, - (phys_addr_t)remaining_size); - - /* - * Ensure the size is power of two, this is requirement - * to run get_ram_size() / memory test - */ - if (size != 0 && ((size & (size - 1)) == 0)) { - ram_check += get_ram_size((void *) - (start + ram_check), size); - remaining_size = bd->bi_dram[bank].size - - ram_check; - } else { - puts("DDR: Memory test requires SDRAM size "); - puts("in power of two!\n"); + phys_size_t size, test_size, detected_size; + + size = min((phys_addr_t)SZ_1G, (phys_addr_t)remaining_size); + + if (size < SZ_8) { + puts("Invalid size: Memory size required to be multiple\n"); + puts("of 64-Bit word!\n"); hang(); } + + /* Adjust size to the nearest power of two to support get_ram_size() */ + test_size = SZ_8; + + while (test_size * 2 <= size) + test_size *= 2; + + debug("Testing memory at 0x%llx with size 0x%llx\n", + start + ram_check, test_size); + detected_size = get_ram_size((void *)(start + ram_check), test_size); + + if (detected_size != test_size) { + debug("Detected size 0x%llx doesn’t match the test size 0x%llx!\n", + detected_size, test_size); + puts("Memory testing failed!\n"); + hang(); + } + + ram_check += detected_size; + remaining_size = bd->bi_dram[bank].size - ram_check; } total_ram_check += ram_check; @@ -249,7 +265,7 @@ phys_size_t sdram_calculate_size(struct altera_sdram_plat *plat) DRAMADDRW_CFG_ROW_ADDR_WIDTH(dramaddrw) + DRAMADDRW_CFG_COL_ADDR_WIDTH(dramaddrw)); - size *= (2 << (hmc_ecc_readl(plat, DDRIOCTRL) & + size *= ((phys_size_t)2 << (hmc_ecc_readl(plat, DDRIOCTRL) & DDR_HMC_DDRIOCTRL_IOSIZE_MSK)); return size; diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index 76d108080d9..e57729f0ef9 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -23,6 +23,7 @@ #include <linux/bitops.h> #include <linux/io.h> #include <linux/sizes.h> +#include <linux/kconfig.h> #define BANK_INCREMENT 4 #define NR_BANKS 8 @@ -114,6 +115,8 @@ static int socfpga_reset_remove(struct udevice *dev) if (socfpga_reset_keep_enabled()) { puts("Deasserting all peripheral resets\n"); writel(0, data->modrst_base + 4); + if (IS_ENABLED(CONFIG_TARGET_SOCFPGA_ARRIA10)) + writel(0, data->modrst_base + 8); } return 0; diff --git a/include/linux/intel-smc.h b/include/linux/intel-smc.h index a54eff43add..6455335bae4 100644 --- a/include/linux/intel-smc.h +++ b/include/linux/intel-smc.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2017-2018, Intel Corporation + * Copyright (C) 2025 Altera Corporation <www.altera.com> */ #ifndef __INTEL_SMC_H @@ -482,10 +483,16 @@ INTEL_SIP_SMC_FAST_CALL_VAL(INTEL_SIP_SMC_FUNCID_FPGA_CONFIG_COMPLETED_WRITE) * Call register usage: * a0 INTEL_SIP_SMC_HPS_SET_BRIDGES * a1 Set bridges status: - * 0 - Disable - * 1 - Enable - * a2-7 not used - * + * Bit 0: 0 - Disable, 1 - Enable + * Bit 1: 1 - Has mask value in a2 + * a2 Mask value + * Bit 0: soc2fpga + * Bit 1: lwhps2fpga + * Bit 2: fpga2soc + * Bit 3: f2sdram0 (For Stratix 10 only) + * Bit 4: f2sdram1 (For Stratix 10 only) + * Bit 5: f2sdram2 (For Stratix 10 only) + * a3-7 not used * Return status * a0 INTEL_SIP_SMC_STATUS_OK */ |