aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorYe Li2023-01-31 16:42:17 +0800
committerStefano Babic2023-03-29 20:15:42 +0200
commit8b956bdddd308137b848e5ca87da0115abdb86d7 (patch)
treea23dcd24db5e381fc86d2e0671d291d1782514e0 /arch
parentaec9b5de44b0c310c1dda82ad0ad7a8bac292db0 (diff)
imx: imx8ulp: Adjust handshake to sync TRDC and XRDC completion
To fit the DBD_EN fused part, we re-design the TRDC and XRDC assignment. M33 will be the TRDC owner and needs to configure TRDC. A35 is the XRDC owner, ATF will configure XRDC. The handshake between U-boot and M33 image is used to sync TRDC and XRDC configuration completion. Once the handshake is done, A35 and M33 can access the allowed resources in others domain. The handshake is needed when M33 is booted or DBD_EN fused, because both cases will enable the TRDC. If handshake is timeout, the boot will hang. We use SIM GPR0 to pass the info from SPL to u-boot, because before the handshake, u-boot can't access SEC SIM and FSB. Signed-off-by: Ye Li <ye.li@nxp.com> Reviewed-by: Jacky Bai <ping.bai@nxp.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/include/asm/arch-imx8ulp/sys_proto.h1
-rw-r--r--arch/arm/include/asm/global_data.h3
-rw-r--r--arch/arm/mach-imx/imx8ulp/soc.c104
3 files changed, 92 insertions, 16 deletions
diff --git a/arch/arm/include/asm/arch-imx8ulp/sys_proto.h b/arch/arm/include/asm/arch-imx8ulp/sys_proto.h
index ff49c626d82..5bbae21e37c 100644
--- a/arch/arm/include/asm/arch-imx8ulp/sys_proto.h
+++ b/arch/arm/include/asm/arch-imx8ulp/sys_proto.h
@@ -14,6 +14,7 @@ int xrdc_config_pdac_openacc(u32 bridge, u32 index);
void set_lpav_qos(void);
void load_lposc_fuse(void);
bool m33_image_booted(void);
+bool is_m33_handshake_necessary(void);
int m33_image_handshake(ulong timeout_ms);
int imx8ulp_dm_post_init(void);
#endif
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index 9e746e380a2..86987838f46 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -97,6 +97,9 @@ struct arch_global_data {
u32 uid[4];
#endif
+#ifdef CONFIG_ARCH_IMX8ULP
+ bool m33_handshake_done;
+#endif
};
#include <asm-generic/global_data.h>
diff --git a/arch/arm/mach-imx/imx8ulp/soc.c b/arch/arm/mach-imx/imx8ulp/soc.c
index 0d7858a02d4..8424332f429 100644
--- a/arch/arm/mach-imx/imx8ulp/soc.c
+++ b/arch/arm/mach-imx/imx8ulp/soc.c
@@ -104,14 +104,70 @@ enum bt_mode get_boot_mode(void)
bool m33_image_booted(void)
{
- u32 gp6;
+ if (IS_ENABLED(CONFIG_SPL_BUILD)) {
+ u32 gp6 = 0;
+
+ /* DGO_GP6 */
+ gp6 = readl(SIM_SEC_BASE_ADDR + 0x28);
+ if (gp6 & BIT(5))
+ return true;
+
+ return false;
+ } else {
+ u32 gpr0 = readl(SIM1_BASE_ADDR);
+ if (gpr0 & BIT(0))
+ return true;
+
+ return false;
+ }
+}
+
+bool rdc_enabled_in_boot(void)
+{
+ if (IS_ENABLED(CONFIG_SPL_BUILD)) {
+ u32 val = 0;
+ int ret;
+ bool rdc_en = true; /* Default assume DBD_EN is set */
+
+ /* Read DBD_EN fuse */
+ ret = fuse_read(8, 1, &val);
+ if (!ret)
+ rdc_en = !!(val & 0x200); /* only A1 part uses DBD_EN, so check DBD_EN new place*/
+
+ return rdc_en;
+ } else {
+ u32 gpr0 = readl(SIM1_BASE_ADDR);
+ if (gpr0 & 0x2)
+ return true;
+
+ return false;
+ }
+}
+
+static void spl_pass_boot_info(void)
+{
+ if (IS_ENABLED(CONFIG_SPL_BUILD)) {
+ bool m33_booted = m33_image_booted();
+ bool rdc_en = rdc_enabled_in_boot();
+ u32 val = 0;
- /* DGO_GP6 */
- gp6 = readl(SIM_SEC_BASE_ADDR + 0x28);
- if (gp6 & BIT(5))
- return true;
+ if (m33_booted)
+ val |= 0x1;
- return false;
+ if (rdc_en)
+ val |= 0x2;
+
+ writel(val, SIM1_BASE_ADDR);
+ }
+}
+
+bool is_m33_handshake_necessary(void)
+{
+ /* Only need handshake in u-boot */
+ if (!IS_ENABLED(CONFIG_SPL_BUILD))
+ return (m33_image_booted() || rdc_enabled_in_boot());
+ else
+ return false;
}
int m33_image_handshake(ulong timeout_ms)
@@ -661,10 +717,6 @@ void set_lpav_qos(void)
int arch_cpu_init(void)
{
if (IS_ENABLED(CONFIG_SPL_BUILD)) {
- u32 val = 0;
- int ret;
- bool rdc_en = true; /* Default assume DBD_EN is set */
-
/* Enable System Reset Interrupt using WDOG_AD */
setbits_le32(CMC1_BASE_ADDR + 0x8C, BIT(13));
/* Clear AD_PERIPH Power switch domain out of reset interrupt flag */
@@ -681,31 +733,51 @@ int arch_cpu_init(void)
/* Disable wdog */
init_wdog();
- /* Read DBD_EN fuse */
- ret = fuse_read(8, 1, &val);
- if (!ret)
- rdc_en = !!(val & 0x4000);
-
if (get_boot_mode() == SINGLE_BOOT)
lpav_configure(false);
else
lpav_configure(true);
/* Release xrdc, then allow A35 to write SRAM2 */
- if (rdc_en)
+ if (rdc_enabled_in_boot())
release_rdc(RDC_XRDC);
xrdc_mrc_region_set_access(2, CONFIG_SPL_TEXT_BASE, 0xE00);
clock_init_early();
+
+ spl_pass_boot_info();
} else {
+ int ret;
/* reconfigure core0 reset vector to ROM */
set_core0_reset_vector(0x1000);
+
+ if (is_m33_handshake_necessary()) {
+ /* Start handshake with M33 to ensure TRDC configuration completed */
+ ret = m33_image_handshake(1000);
+ if (!ret)
+ gd->arch.m33_handshake_done = true;
+ else /* Skip and go through to panic in checkcpu as console is ready then */
+ gd->arch.m33_handshake_done = false;
+ }
}
return 0;
}
+int checkcpu(void)
+{
+ if (is_m33_handshake_necessary()) {
+ if (!gd->arch.m33_handshake_done) {
+ puts("M33 Sync: Timeout, Boot Stop!\n");
+ hang();
+ } else {
+ puts("M33 Sync: OK\n");
+ }
+ }
+ return 0;
+}
+
int imx8ulp_dm_post_init(void)
{
struct udevice *devp;