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 <girisha.dengi@intel.com>
Signed-off-by: Jit Loon Lim <jit.loon.lim@altera.com>
diff --git a/plat/intel/soc/agilex/include/socfpga_plat_def.h b/plat/intel/soc/agilex/include/socfpga_plat_def.h
index 840ffdd..9445798 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 c090117..1ad28e1 100644
--- a/plat/intel/soc/agilex5/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl31_plat_setup.c
@@ -234,9 +234,9 @@
 	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 c1f3cc5..282958a 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 b3d5665..74ce279 100644
--- a/plat/intel/soc/common/aarch64/plat_helpers.S
+++ b/plat/intel/soc/common/aarch64/plat_helpers.S
@@ -98,7 +98,36 @@
 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 @@
 #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 a820e41..e2efeb1 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 50d4820..99c7412 100644
--- a/plat/intel/soc/common/socfpga_psci.c
+++ b/plat/intel/soc/common/socfpga_psci.c
@@ -223,6 +223,10 @@
 	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 @@
 	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 6f0a40b..cfc9f9d 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 90345c3..b6272fc 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)