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>
This commit is contained in:
Ye Li 2023-01-31 16:42:17 +08:00 committed by Stefano Babic
parent aec9b5de44
commit 8b956bdddd
4 changed files with 93 additions and 23 deletions

View file

@ -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

View file

@ -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>

View file

@ -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;
/* DGO_GP6 */
gp6 = readl(SIM_SEC_BASE_ADDR + 0x28);
if (gp6 & BIT(5))
return true;
return false;
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;
if (m33_booted)
val |= 0x1;
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;

View file

@ -101,18 +101,12 @@ void mipi_dsi_panel_backlight(void)
int board_init(void)
{
int sync = -ENODEV;
if (IS_ENABLED(CONFIG_FEC_MXC))
setup_fec();
if (m33_image_booted()) {
sync = m33_image_handshake(1000);
printf("M33 Sync: %s\n", sync ? "Timeout" : "OK");
}
/* When sync with M33 is failed, use local driver to set for video */
if (sync != 0 && IS_ENABLED(CONFIG_VIDEO)) {
if (!is_m33_handshake_necessary() && IS_ENABLED(CONFIG_VIDEO)) {
mipi_dsi_mux_panel();
mipi_dsi_panel_backlight();
}