Add the capability to detect a resume on J7200, J784s4, j722s, j721s2 SoCs.
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: Although this is called in board_init_f(), we can use global/static variables because CONFIG_SPL_EARLY_BSS is selected. Signed-off-by: Richard Genoud (TI) <[email protected]> --- arch/arm/mach-k3/common.c | 6 +++ arch/arm/mach-k3/include/mach/hardware.h | 1 + arch/arm/mach-k3/r5/lpm-common.c | 53 +++++++++++++++++++++++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index 6e382efdb3be..d934f732b330 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -713,3 +713,9 @@ int spl_start_uboot(void) return 0; } #endif + +/* if r5/lpm-common.c is compiled, this will be overridden */ +__weak bool j7xx_board_is_resuming(void) +{ + return false; +} diff --git a/arch/arm/mach-k3/include/mach/hardware.h b/arch/arm/mach-k3/include/mach/hardware.h index 2c771a1195f5..c45bd3747163 100644 --- a/arch/arm/mach-k3/include/mach/hardware.h +++ b/arch/arm/mach-k3/include/mach/hardware.h @@ -137,6 +137,7 @@ u32 get_boot_device(void); const char *get_reset_reason(void); enum k3_device_type get_device_type(void); int k3_fit_config_match_security_state(const char *name); +bool j7xx_board_is_resuming(void); #define writel_verify(val, addr) \ do { \ diff --git a/arch/arm/mach-k3/r5/lpm-common.c b/arch/arm/mach-k3/r5/lpm-common.c index 91707fd19501..5d484f6df037 100644 --- a/arch/arm/mach-k3/r5/lpm-common.c +++ b/arch/arm/mach-k3/r5/lpm-common.c @@ -7,17 +7,25 @@ */ #include <clk.h> +#include <dm/device.h> #include <dm/read.h> #include <elf.h> #include <linux/printk.h> #include <linux/soc/ti/ti_sci_protocol.h> #include <power-domain.h> +#include <power/pmic.h> #include <remoteproc.h> #include <mach/security.h> #include "../common.h" #include "../lpm-common.h" +/* Magic value in PMIC register to indicate the suspend state (SOC_OFF) */ +#define K3_LPM_MAGIC_SUSPEND 0xba + +/* PMIC register where the magic value resides */ +#define K3_LPM_SCRATCH_PAD_REG_3 0xcb + #define CONTEXT_SAVE_SZ 0x80000 #define ATF_CERT_SZ 0x80000 #define OPTEE_CERT_SZ 0x100000 @@ -32,9 +40,50 @@ struct lpm_addr_info { u32 size; }; -__weak bool j7xx_board_is_resuming(void) +enum k3_resume_state { + K3_RESUME_STATE_UNKNOWN = 0, + K3_RESUME_STATE_BOOTING, + K3_RESUME_STATE_RESUMING +}; + +bool j7xx_board_is_resuming(void) { - return false; + static enum k3_resume_state k3_resuming; + struct udevice *pmic; + int ret, magic; + + if (k3_resuming != K3_RESUME_STATE_UNKNOWN) + goto end; + + ret = uclass_get_device_by_name(UCLASS_PMIC, + "pmic@48", &pmic); + if (ret) { + printf("Getting PMIC init failed: %d\n", ret); + goto end; + } + debug("%s: PMIC is detected (%s)\n", __func__, pmic->name); + + magic = pmic_reg_read(pmic, K3_LPM_SCRATCH_PAD_REG_3); + + if (magic == K3_LPM_MAGIC_SUSPEND) { + debug("%s: board is resuming\n", __func__); + k3_resuming = K3_RESUME_STATE_RESUMING; + + /* clean magic suspend */ + ret = pmic_reg_write(pmic, K3_LPM_SCRATCH_PAD_REG_3, 0); + + if (ret) + printf("Failed to clean magic value for suspend detection in PMIC\n"); + /* + * For robustness, the DM should also clean the magic value at + * startup. + */ + } else { + debug("%s: board is booting (no resume detected)\n", __func__); + k3_resuming = K3_RESUME_STATE_BOOTING; + } +end: + return k3_resuming == K3_RESUME_STATE_RESUMING; } static const char *lpm_core_compatible; -- 2.55.0
