From 646a9a16150066eaa3146d4e2819d589333b6454 Mon Sep 17 00:00:00 2001 From: Jit Loon Lim Date: Tue, 24 Dec 2024 10:46:44 +0800 Subject: [PATCH] fix(intel): update warm reset routine and bootscratch register usage Agilex5 platform: Boot scratch COLD6 register is meant for Customer use only. So, use Intel specific COLD3 register with [5:2]bits to determine the warm reset and SMP boot requests. Also handle the unaligned DEVICE/IO memory store and load in the assembly entrypoint startup code. Agilex, Stratix10, N5X platforms: Use only the LSB 4bits [3:0] of the boot scratch COLD6 register to detect the warm reset request. Change-Id: I4fd6e63fe0bd42ddcb4a3f81c7a7295bdc8ca65f Signed-off-by: Girisha Dengi Signed-off-by: Jit Loon Lim --- .../soc/agilex/include/socfpga_plat_def.h | 15 +++- plat/intel/soc/agilex5/bl31_plat_setup.c | 6 +- .../soc/agilex5/include/socfpga_plat_def.h | 21 ++++- plat/intel/soc/common/aarch64/plat_helpers.S | 84 ++++++++++++++++--- plat/intel/soc/common/include/platform_def.h | 6 -- plat/intel/soc/common/socfpga_psci.c | 7 +- plat/intel/soc/n5x/include/socfpga_plat_def.h | 21 +++-- .../soc/stratix10/include/socfpga_plat_def.h | 21 +++-- 8 files changed, 144 insertions(+), 37 deletions(-) diff --git a/plat/intel/soc/agilex/include/socfpga_plat_def.h b/plat/intel/soc/agilex/include/socfpga_plat_def.h index 840ffdd6e..9445798c3 100644 --- a/plat/intel/soc/agilex/include/socfpga_plat_def.h +++ b/plat/intel/soc/agilex/include/socfpga_plat_def.h @@ -127,10 +127,21 @@ #define SDMMC_WRITE_BLOCKS mmc_write_blocks /******************************************************************************* - * sysmgr.boot_scratch_cold6 & 7 (64bit) are used to indicate L2 reset + * sysmgr.boot_scratch_cold6 Bits[3:0] is used to indicate L2 reset * is done and HPS should trigger warm reset via RMR_EL3. ******************************************************************************/ -#define L2_RESET_DONE_REG 0xFFD12218 +/* + * Magic key bits: 4 bits[3:0] from boot scratch register COLD6 are used to + * indicate the below requests/status + * 0x0 : Default value on reset, not used + * 0x1 : L2/warm reset is completed + * 0x2 - 0xF : Reserved for future use + */ +#define BS_REG_MAGIC_KEYS_MASK 0x0F +#define BS_REG_MAGIC_KEYS_POS 0x00 +#define L2_RESET_DONE_STATUS (0x01 << BS_REG_MAGIC_KEYS_POS) + +#define L2_RESET_DONE_REG SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_6) /* Platform specific system counter */ #define PLAT_SYS_COUNTER_FREQ_IN_MHZ U(400) diff --git a/plat/intel/soc/agilex5/bl31_plat_setup.c b/plat/intel/soc/agilex5/bl31_plat_setup.c index c090117a0..1ad28e166 100644 --- a/plat/intel/soc/agilex5/bl31_plat_setup.c +++ b/plat/intel/soc/agilex5/bl31_plat_setup.c @@ -234,9 +234,9 @@ void bl31_plat_set_secondary_cpu_entrypoint(unsigned int cpu_id) unsigned int pchctlr_new = 0x00; uint32_t boot_core = 0x00; - /* Store magic number for SMP secondary cores boot */ - mmio_write_32(L2_RESET_DONE_REG, SMP_SEC_CORE_BOOT_REQ); - + /* Set bit for SMP secondary cores boot */ + mmio_clrsetbits_32(L2_RESET_DONE_REG, BS_REG_MAGIC_KEYS_MASK, + SMP_SEC_CORE_BOOT_REQ); boot_core = (mmio_read_32(AGX5_PWRMGR(MPU_BOOTCONFIG)) & 0xC00); /* Update the p-channel based on cpu id */ pch_cpu = 1 << cpu_id; diff --git a/plat/intel/soc/agilex5/include/socfpga_plat_def.h b/plat/intel/soc/agilex5/include/socfpga_plat_def.h index c1f3cc50a..282958a10 100644 --- a/plat/intel/soc/agilex5/include/socfpga_plat_def.h +++ b/plat/intel/soc/agilex5/include/socfpga_plat_def.h @@ -96,6 +96,21 @@ OCRAM_REGION_0_OFFSET) #define OCRAM_NON_SECURE_ENABLE 0x0 + +/* + * Magic key bits: 4 bits[5:2] from boot scratch register COLD3 are used to + * indicate the below requests/status + * 0x0 : Default value on reset, not used + * 0x1 : L2/warm reset is completed + * 0x2 : SMP secondary core boot requests + * 0x3 - 0xF : Reserved for future use + */ +#define BS_REG_MAGIC_KEYS_MASK 0x3C +#define BS_REG_MAGIC_KEYS_POS 0x02 +#define L2_RESET_DONE_STATUS (0x01 << BS_REG_MAGIC_KEYS_POS) +#define SMP_SEC_CORE_BOOT_REQ (0x02 << BS_REG_MAGIC_KEYS_POS) +#define ALIGN_CHECK_64BIT_MASK 0x07 + /******************************************************************************* * Platform memory map related constants ******************************************************************************/ @@ -157,9 +172,9 @@ #define SDMMC_WRITE_BLOCKS sdmmc_write_blocks /******************************************************************************* - * sysmgr.boot_scratch_cold6 & 7 (64bit) are used to indicate L2 reset - * is done and HPS should trigger warm reset via RMR_EL3. + * sysmgr.boot_scratch_cold3 bits[5:2] are used to indicate L2 reset + * is done, or SMP secondary cores boot request status. ******************************************************************************/ -#define L2_RESET_DONE_REG 0x10D12218 +#define L2_RESET_DONE_REG SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_3) #endif /* PLAT_SOCFPGA_DEF_H */ diff --git a/plat/intel/soc/common/aarch64/plat_helpers.S b/plat/intel/soc/common/aarch64/plat_helpers.S index b3d5665bb..74ce2799a 100644 --- a/plat/intel/soc/common/aarch64/plat_helpers.S +++ b/plat/intel/soc/common/aarch64/plat_helpers.S @@ -98,7 +98,36 @@ func plat_my_core_pos endfunc plat_my_core_pos func warm_reset_req - str xzr, [x4] +#if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 + /* Clear the markup before going for warm reset */ + bic x2, x2, #BS_REG_MAGIC_KEYS_MASK + /* Check if the address is 64 bit aligned or not */ + ldr x4, =L2_RESET_DONE_REG + tst x4, #ALIGN_CHECK_64BIT_MASK + b.ne unaligned_store + /* Device memory address is aligned, store the value directly */ + str x2, [x4] + b continue_warm_reset + + /* Unaligned store, use byte by byte method to store */ +unaligned_store: + strb w2, [x4] + lsr x2, x2, #8 + add x4, x4, #1 + strb w2, [x4] + lsr x2, x2, #8 + add x4, x4, #1 + strb w2, [x4] + lsr x2, x2, #8 + add x4, x4, #1 + strb w2, [x4] +#else + /* Clear the markup before going for warm reset */ + bic x2, x2, #BS_REG_MAGIC_KEYS_MASK + str x2, [x4] +#endif + +continue_warm_reset: bl plat_is_my_cpu_primary cbz x0, cpu_in_wfi mov_imm x1, PLAT_SEC_ENTRY @@ -116,36 +145,71 @@ endfunc warm_reset_req #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 func plat_get_my_entrypoint ldr x4, =L2_RESET_DONE_REG - ldr x5, [x4] + + /* Check if the address is 64 bit aligned or not */ + tst x4, #ALIGN_CHECK_64BIT_MASK + b.ne unaligned_load + + /* Device memory address is aligned, load the value directly */ + ldr x1, [x4] + b events_check + + /* + * It is unaligned device memory access. Read only LSB 32 bits + * byte by byte and combine them to get the 32 bit value. + */ +unaligned_load: + ldrb w1, [x4] + ldrb w2, [x4, #1] + ldrb w3, [x4, #2] + ldrb w4, [x4, #3] + orr x1, x1, x2, lsl #8 + orr x1, x1, x3, lsl #16 + orr x1, x1, x4, lsl #24 + +events_check: + /* Keep a backup of the boot scratch register contents */ + mov x2, x1 + + /* Mask and get the required bits */ + and x1, x1, #BS_REG_MAGIC_KEYS_MASK /* Check for warm reset request */ - ldr x1, =L2_RESET_DONE_STATUS + ldr x5, =L2_RESET_DONE_STATUS cmp x1, x5 b.eq warm_reset_req /* Check for SMP secondary cores boot request */ - ldr x1, =SMP_SEC_CORE_BOOT_REQ + ldr x5, =SMP_SEC_CORE_BOOT_REQ cmp x1, x5 b.eq smp_request - /* Otherwise it is cold reset */ + /* Otherwise it is a cold reset request */ mov x0, #0 ret + smp_request: /* - * Return the address 'bl31_warm_entrypoint', which is passed to - * 'psci_setup' routine as part of BL31 initialization. + * On the SMP boot request, return the address 'bl31_warm_entrypoint', + * which is passed to 'psci_setup' routine as part of BL31 + * initialization. */ - mov_imm x1, PLAT_SEC_ENTRY + ldr x1, =PLAT_SEC_ENTRY ldr x0, [x1] - /* Clear the mark up before return */ - str xzr, [x4] ret endfunc plat_get_my_entrypoint #else func plat_get_my_entrypoint ldr x4, =L2_RESET_DONE_REG ldr x5, [x4] + + /* Keep a backup of the boot scratch register contents */ + mov x2, x5 + + /* Mask and get only the required bits */ + and x5, x5, #BS_REG_MAGIC_KEYS_MASK + + /* Check for warm reset request */ ldr x1, =L2_RESET_DONE_STATUS cmp x1, x5 b.eq warm_reset_req diff --git a/plat/intel/soc/common/include/platform_def.h b/plat/intel/soc/common/include/platform_def.h index a820e4144..e2efeb16d 100644 --- a/plat/intel/soc/common/include/platform_def.h +++ b/plat/intel/soc/common/include/platform_def.h @@ -38,12 +38,6 @@ /* sysmgr.boot_scratch_cold4 & 5 used for CPU release address for SPL */ #define PLAT_CPU_RELEASE_ADDR 0xffd12210 -/* Magic word to indicate L2 reset is completed */ -#define L2_RESET_DONE_STATUS 0x1228E5E7 - -/* Magic word to differentiate for SMP secondary core boot request */ -#define SMP_SEC_CORE_BOOT_REQ 0x1228E5E8 - /* Define next boot image name and offset */ /* Get non-secure image entrypoint for BL33. Zephyr and Linux */ #ifdef PRELOADED_BL33_BASE diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c index 50d4820a0..99c7412a9 100644 --- a/plat/intel/soc/common/socfpga_psci.c +++ b/plat/intel/soc/common/socfpga_psci.c @@ -223,6 +223,10 @@ static int socfpga_system_reset2(int is_vendor, int reset_type, invalidate_cache_low_el(); #endif + /* Set warm reset request bit before issuing the command to SDM. */ + mmio_clrsetbits_32(L2_RESET_DONE_REG, BS_REG_MAGIC_KEYS_MASK, + L2_RESET_DONE_STATUS); + #if PLATFORM_MODEL == PLAT_SOCFPGA_AGILEX5 mailbox_reset_warm(reset_type); #else @@ -238,9 +242,6 @@ static int socfpga_system_reset2(int is_vendor, int reset_type, gicv2_cpuif_disable(); #endif - /* Store magic number */ - mmio_write_32(L2_RESET_DONE_REG, L2_RESET_DONE_STATUS); - /* Increase timeout */ mmio_write_32(SOCFPGA_RSTMGR(HDSKTIMEOUT), 0xffffff); diff --git a/plat/intel/soc/n5x/include/socfpga_plat_def.h b/plat/intel/soc/n5x/include/socfpga_plat_def.h index 6f0a40be3..cfc9f9dca 100644 --- a/plat/intel/soc/n5x/include/socfpga_plat_def.h +++ b/plat/intel/soc/n5x/include/socfpga_plat_def.h @@ -44,7 +44,7 @@ #define SOCFPGA_MMC_REG_BASE U(0xff808000) #define SOCFPGA_RSTMGR_REG_BASE U(0xffd11000) #define SOCFPGA_SYSMGR_REG_BASE U(0xffd12000) -#define SOCFPGA_ECC_QSPI_REG_BASE U(0xffa22000) +#define SOCFPGA_ECC_QSPI_REG_BASE U(0xffa22000) #define SOCFPGA_L4_PER_SCR_REG_BASE U(0xffd21000) #define SOCFPGA_L4_SYS_SCR_REG_BASE U(0xffd21100) @@ -91,7 +91,7 @@ /******************************************************************************* * WDT related constants ******************************************************************************/ -#define WDT_BASE (0xFFD00200) +#define WDT_BASE (0xFFD00200) /******************************************************************************* * GIC related constants @@ -102,7 +102,7 @@ #define PLAT_GICR_BASE 0 #define PLAT_SYS_COUNTER_FREQ_IN_TICKS (400000000) -#define PLAT_HZ_CONVERT_TO_MHZ (1000000) +#define PLAT_HZ_CONVERT_TO_MHZ (1000000) /******************************************************************************* * SDMMC related pointer function @@ -111,10 +111,21 @@ #define SDMMC_WRITE_BLOCKS mmc_write_blocks /******************************************************************************* - * sysmgr.boot_scratch_cold6 & 7 (64bit) are used to indicate L2 reset + * sysmgr.boot_scratch_cold6 Bits[3:0] is used to indicate L2 reset * is done and HPS should trigger warm reset via RMR_EL3. ******************************************************************************/ -#define L2_RESET_DONE_REG 0xFFD12218 +/* + * Magic key bits: 4 bits[3:0] from boot scratch register COLD6 are used to + * indicate the below requests/status + * 0x0 : Default value on reset, not used + * 0x1 : L2/warm reset is completed + * 0x2 - 0xF : Reserved for future use + */ +#define BS_REG_MAGIC_KEYS_MASK 0x0F +#define BS_REG_MAGIC_KEYS_POS 0x00 +#define L2_RESET_DONE_STATUS (0x01 << BS_REG_MAGIC_KEYS_POS) + +#define L2_RESET_DONE_REG SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_6) /* Platform specific system counter */ #define PLAT_SYS_COUNTER_FREQ_IN_MHZ U(400) diff --git a/plat/intel/soc/stratix10/include/socfpga_plat_def.h b/plat/intel/soc/stratix10/include/socfpga_plat_def.h index 90345c3b9..b6272fcb4 100644 --- a/plat/intel/soc/stratix10/include/socfpga_plat_def.h +++ b/plat/intel/soc/stratix10/include/socfpga_plat_def.h @@ -45,7 +45,7 @@ #define SOCFPGA_RSTMGR_REG_BASE 0xffd11000 #define SOCFPGA_SYSMGR_REG_BASE 0xffd12000 -#define SOCFPGA_ECC_QSPI_REG_BASE 0xffa22000 +#define SOCFPGA_ECC_QSPI_REG_BASE 0xffa22000 #define SOCFPGA_L4_PER_SCR_REG_BASE 0xffd21000 #define SOCFPGA_L4_SYS_SCR_REG_BASE 0xffd21100 @@ -91,7 +91,7 @@ /******************************************************************************* * WDT related constants ******************************************************************************/ -#define WDT_BASE (0xFFD00200) +#define WDT_BASE (0xFFD00200) /******************************************************************************* * GIC related constants @@ -102,7 +102,7 @@ #define PLAT_GICR_BASE 0 #define PLAT_SYS_COUNTER_FREQ_IN_TICKS (400000000) -#define PLAT_HZ_CONVERT_TO_MHZ (1000000) +#define PLAT_HZ_CONVERT_TO_MHZ (1000000) /******************************************************************************* * SDMMC related pointer function @@ -111,10 +111,21 @@ #define SDMMC_WRITE_BLOCKS mmc_write_blocks /******************************************************************************* - * sysmgr.boot_scratch_cold6 & 7 (64bit) are used to indicate L2 reset + * sysmgr.boot_scratch_cold6 Bits[3:0] is used to indicate L2 reset * is done and HPS should trigger warm reset via RMR_EL3. ******************************************************************************/ -#define L2_RESET_DONE_REG 0xFFD12218 +/* + * Magic key bits: 4 bits[3:0] from boot scratch register COLD6 are used to + * indicate the below requests/status + * 0x0 : Default value on reset, not used + * 0x1 : L2/warm reset is completed + * 0x2 - 0xF : Reserved for future use + */ +#define BS_REG_MAGIC_KEYS_MASK 0x0F +#define BS_REG_MAGIC_KEYS_POS 0x00 +#define L2_RESET_DONE_STATUS (0x01 << BS_REG_MAGIC_KEYS_POS) + +#define L2_RESET_DONE_REG SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_6) /* Platform specific system counter */ #define PLAT_SYS_COUNTER_FREQ_IN_MHZ U(400)