[PATCH 05/20] board: ti: j722s: Add resume detection

Richard Genoud (TI) richard.genoud at bootlin.com
Thu Apr 30 10:43:58 CEST 2026


Add the capability to detect a resume. This overrides the weak
function j7xx_board_is_resuming().
To detect the resume, SPL searches a magic value (0xBA) in a register
of PMIC.
This value is set by DM-Firmware during the suspend sequence.

NB: As this is called in board_init_f(), there's no BSS, so we can't
use global/static variables.

NB2: For HS-SE device, we need an extra call to ctrl_mmr_unlock(), and
we have to use I2C API instead of PMIC API for this to work.
This is because bind is called before anything comes up, in between either
bootrom or TIFS messing up, clearing pad config and pd config.

Co-developed-by: Udit Kumar <u-kumar1 at ti.com>
Signed-off-by: Udit Kumar <u-kumar1 at ti.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud at bootlin.com>
---
 arch/arm/mach-k3/j722s/j722s_init.c |  2 +-
 board/ti/j722s/evm.c                | 51 +++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-k3/j722s/j722s_init.c b/arch/arm/mach-k3/j722s/j722s_init.c
index 1180c75f551d..7b3d27c1e855 100644
--- a/arch/arm/mach-k3/j722s/j722s_init.c
+++ b/arch/arm/mach-k3/j722s/j722s_init.c
@@ -37,7 +37,7 @@ static void store_boot_info_from_rom(void)
 	       sizeof(struct rom_extended_boot_data));
 }
 
-static void ctrl_mmr_unlock(void)
+void ctrl_mmr_unlock(void)
 {
 	/* Unlock all WKUP_CTRL_MMR0 module registers */
 	mmr_unlock(WKUP_CTRL_MMR0_BASE, 0);
diff --git a/board/ti/j722s/evm.c b/board/ti/j722s/evm.c
index 1173adc072be..86aa10ffb0fd 100644
--- a/board/ti/j722s/evm.c
+++ b/board/ti/j722s/evm.c
@@ -9,12 +9,15 @@
 #include <asm/arch/hardware.h>
 #include <asm/io.h>
 #include <cpu_func.h>
+#include <dm/device.h>
 #include <dm/uclass.h>
+#include <i2c.h>
 #include <env.h>
 #include <fdt_support.h>
 #include <spl.h>
 #include <asm/arch/k3-ddr.h>
 #include "../common/fdt_ops.h"
+#include "../common/k3-lpm.h"
 
 #if IS_ENABLED(CONFIG_SPL_BUILD)
 void spl_board_init(void)
@@ -23,6 +26,54 @@ void spl_board_init(void)
 }
 #endif
 
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J722S_R5_EVM))
+
+extern void ctrl_mmr_unlock(void);
+
+/* in board_init_f(), there's no BSS, so we can't use global/static variables */
+bool j7xx_board_is_resuming(void)
+{
+	struct udevice *pmic, *i2c;
+	int err;
+
+	if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
+		goto end;
+
+	/*
+	 * On HS-SE devices, i2c access fails unless MMR registers are unlocked.
+	 * Moreover, it fails also if we use PMIC API instead of I2C API.
+	 */
+	ctrl_mmr_unlock();
+	err = uclass_get_device_by_name(UCLASS_I2C,
+					"i2c at 2b200000", &i2c);
+	if (err) {
+		printf("Getting I2C failed: %d\n", err);
+		goto end;
+	}
+	err = dm_i2c_probe(i2c, 0x48, 0, &pmic);
+	if (err) {
+		printf("Getting PMIC failed: %d\n", err);
+		goto end;
+	}
+
+	debug("%s: PMIC is detected (%s)\n", __func__, pmic->name);
+
+	if (dm_i2c_reg_read(pmic, K3_LPM_SCRATCH_PAD_REG) == K3_LPM_MAGIC_SUSPEND) {
+		debug("%s: board is resuming\n", __func__);
+		gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
+
+		/* clean magic suspend */
+		if (dm_i2c_reg_write(pmic, K3_LPM_SCRATCH_PAD_REG, 0))
+			printf("Failed to clean magic value for suspend detection in PMIC\n");
+	} else {
+		debug("%s: board is booting (no resume detected)\n", __func__);
+		gd_set_k3_resuming(K3_RESUME_STATE_BOOTING);
+	}
+end:
+	return gd_k3_resuming() == K3_RESUME_STATE_RESUMING;
+}
+#endif /* CONFIG_SPL_BUILD && CONFIG_TARGET_J722S_R5_EVM */
+
 #if defined(CONFIG_XPL_BUILD)
 void spl_perform_board_fixups(struct spl_image_info *spl_image)
 {


More information about the U-Boot mailing list