* [PATCH 01/20] configs: j784s4_evm_r5: enable TI_SCI_POWER_DOMAIN
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
@ 2026-04-30 8:43 ` Richard Genoud (TI)
2026-05-11 9:49 ` Kumar, Udit
2026-04-30 8:43 ` [PATCH 02/20] global: k3: use gd to store the resume state Richard Genoud (TI)
` (18 subsequent siblings)
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:43 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
When resuming, we need the power domain driver to enable R5 cores.
So, enable TI_SCI_POWER_DOMAIN driver in R5 configuration.
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
configs/j784s4_evm_r5_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/configs/j784s4_evm_r5_defconfig b/configs/j784s4_evm_r5_defconfig
index 25ab6f17d175..35ac2287bcc7 100644
--- a/configs/j784s4_evm_r5_defconfig
+++ b/configs/j784s4_evm_r5_defconfig
@@ -124,6 +124,7 @@ CONFIG_PINCTRL=y
CONFIG_SPL_PINCTRL=y
CONFIG_PINCTRL_SINGLE=y
CONFIG_POWER_DOMAIN=y
+CONFIG_TI_SCI_POWER_DOMAIN=y
CONFIG_TI_POWER_DOMAIN=y
CONFIG_DM_PMIC=y
CONFIG_PMIC_TPS65941=y
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 01/20] configs: j784s4_evm_r5: enable TI_SCI_POWER_DOMAIN
2026-04-30 8:43 ` [PATCH 01/20] configs: j784s4_evm_r5: enable TI_SCI_POWER_DOMAIN Richard Genoud (TI)
@ 2026-05-11 9:49 ` Kumar, Udit
0 siblings, 0 replies; 32+ messages in thread
From: Kumar, Udit @ 2026-05-11 9:49 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Jayesh Choudhary,
Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Abhash Kumar, Thomas Richard,
Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/2026 2:13 PM, Richard Genoud (TI) wrote:
> When resuming, we need the power domain driver to enable R5 cores.
> So, enable TI_SCI_POWER_DOMAIN driver in R5 configuration.
>
> Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
> ---
> configs/j784s4_evm_r5_defconfig | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/configs/j784s4_evm_r5_defconfig b/configs/j784s4_evm_r5_defconfig
> index 25ab6f17d175..35ac2287bcc7 100644
> --- a/configs/j784s4_evm_r5_defconfig
> +++ b/configs/j784s4_evm_r5_defconfig
> @@ -124,6 +124,7 @@ CONFIG_PINCTRL=y
> CONFIG_SPL_PINCTRL=y
> CONFIG_PINCTRL_SINGLE=y
> CONFIG_POWER_DOMAIN=y
> +CONFIG_TI_SCI_POWER_DOMAIN=y
> CONFIG_TI_POWER_DOMAIN=y
Wondering how this is helping, to deal with any power you have
CONFIG_TI_POWER_DOMAIN
> CONFIG_DM_PMIC=y
> CONFIG_PMIC_TPS65941=y
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 02/20] global: k3: use gd to store the resume state
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
2026-04-30 8:43 ` [PATCH 01/20] configs: j784s4_evm_r5: enable TI_SCI_POWER_DOMAIN Richard Genoud (TI)
@ 2026-04-30 8:43 ` Richard Genoud (TI)
2026-04-30 8:43 ` [PATCH 03/20] board: ti: j721e: Add resume detection for J721e/J7200 Richard Genoud (TI)
` (17 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:43 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
For J7200, J784s4, J721e, j722s, j721s2 SoCs, the everything is shutdown
at suspend but the PMIC and the DDR.
In order for U-Boot SPL to know that it is resuming from suspend and not
booting, a flag is set in a PMIC register.
So, at startup, U-Boot will read the PMIC register and deduce if the
board is resuming from suspend or not.
This state (resuming or not) is consulted at several places (in
board_init_f() and in k3_ddrss_probe().
As it takes some time to read a i2c register, it's best to cache the
information.
But, as stated by the README, in board_init_f(), the BSS is not
available, so we cannot use global/static variables, only stack
variables and global_data.
Thus, we use gd to store the resume state of the board.
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/include/asm/global_data.h | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm/include/asm/global_data.h b/arch/arm/include/asm/global_data.h
index b2ec450f9002..f343d3396c1c 100644
--- a/arch/arm/include/asm/global_data.h
+++ b/arch/arm/include/asm/global_data.h
@@ -14,6 +14,14 @@
#include <linux/types.h>
#include <asm/u-boot.h>
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_ARCH_K3))
+enum k3_resume_state {
+ K3_RESUME_STATE_UNKNOWN = 0,
+ K3_RESUME_STATE_BOOTING,
+ K3_RESUME_STATE_RESUMING
+};
+#endif
+
/* Architecture-specific global data */
struct arch_global_data {
#if defined(CONFIG_FSL_ESDHC) || defined(CONFIG_FSL_ESDHC_IMX)
@@ -108,8 +116,19 @@ struct arch_global_data {
#ifdef CONFIG_SMBIOS
ulong smbios_start; /* Start address of SMBIOS table */
#endif
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_ARCH_K3))
+ enum k3_resume_state k3_resuming;
+#endif
};
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_ARCH_K3))
+#define gd_k3_resuming() gd->arch.k3_resuming
+#define gd_set_k3_resuming(state) gd->arch.k3_resuming = (state)
+#else
+#define gd_k3_resuming() 0
+#define gd_set_k3_resuming(state)
+#endif
+
#include <asm-generic/global_data.h>
#if defined(__clang__) || defined(LTO_ENABLE)
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 03/20] board: ti: j721e: Add resume detection for J721e/J7200
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
2026-04-30 8:43 ` [PATCH 01/20] configs: j784s4_evm_r5: enable TI_SCI_POWER_DOMAIN Richard Genoud (TI)
2026-04-30 8:43 ` [PATCH 02/20] global: k3: use gd to store the resume state Richard Genoud (TI)
@ 2026-04-30 8:43 ` Richard Genoud (TI)
2026-05-11 9:53 ` Kumar, Udit
2026-04-30 8:43 ` [PATCH 04/20] board: ti: j784s4: Add resume detection Richard Genoud (TI)
` (16 subsequent siblings)
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:43 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: "Thomas Richard (TI)" <thomas.richard@bootlin.com>
Add the capability to detect a resume. This overrides the weak
function j7xx_board_is_resuming(void).
To detect the resume, SPL searches a magic value (0xBA) in a register
of PMICA.
This value is set by DM-Firmware during the suspend sequence.
Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
Co-developed-by: Gregory CLEMENT (TI) <gregory.clement@bootlin.com>
Signed-off-by: Gregory CLEMENT (TI) <gregory.clement@bootlin.com>
Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
board/ti/common/k3-lpm.h | 17 +++++++++++++++++
board/ti/j721e/evm.c | 37 +++++++++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+)
create mode 100644 board/ti/common/k3-lpm.h
diff --git a/board/ti/common/k3-lpm.h b/board/ti/common/k3-lpm.h
new file mode 100644
index 000000000000..a2141a0c25a8
--- /dev/null
+++ b/board/ti/common/k3-lpm.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2026, Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2026, Bootlin
+ */
+
+#ifndef __K3_LPM_H
+#define __K3_LPM_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 0xcb
+
+#endif /* __K3_LPM_H */
+
diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c
index 881392bd963a..67ff13828514 100644
--- a/board/ti/j721e/evm.c
+++ b/board/ti/j721e/evm.c
@@ -17,9 +17,11 @@
#include <spl.h>
#include <dm.h>
#include <asm/arch/k3-ddr.h>
+#include <power/pmic.h>
#include "../common/board_detect.h"
#include "../common/fdt_ops.h"
+#include "../common/k3-lpm.h"
#define board_is_j721e_som() (board_ti_k3_is("J721EX-PM1-SOM") || \
board_ti_k3_is("J721EX-PM2-SOM"))
@@ -469,6 +471,41 @@ err_free_gpio:
}
}
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J7200_R5_EVM))
+
+bool j7xx_board_is_resuming(void)
+{
+ struct udevice *pmica;
+ int ret;
+
+ if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
+ goto end;
+
+ ret = uclass_get_device_by_name(UCLASS_PMIC,
+ "pmic@48", &pmica);
+ if (ret) {
+ printf("Getting PMICA init failed: %d\n", ret);
+ goto end;
+ }
+ debug("%s: PMICA is detected (%s)\n", __func__, pmica->name);
+
+ if (pmic_reg_read(pmica, 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 (pmic_reg_write(pmica, K3_LPM_SCRATCH_PAD_REG, 0))
+ printf("Failed to clean magic value for suspend detection in PMICA\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_J7200_R5_EVM */
+
void spl_board_init(void)
{
struct udevice *dev;
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 03/20] board: ti: j721e: Add resume detection for J721e/J7200
2026-04-30 8:43 ` [PATCH 03/20] board: ti: j721e: Add resume detection for J721e/J7200 Richard Genoud (TI)
@ 2026-05-11 9:53 ` Kumar, Udit
0 siblings, 0 replies; 32+ messages in thread
From: Kumar, Udit @ 2026-05-11 9:53 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Simon Glass,
Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Abhash Kumar, Thomas Richard,
Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/2026 2:13 PM, Richard Genoud (TI) wrote:
> From: "Thomas Richard (TI)" <thomas.richard@bootlin.com>
>
> Add the capability to detect a resume. This overrides the weak
> function j7xx_board_is_resuming(void).
> To detect the resume, SPL searches a magic value (0xBA) in a register
> of PMICA.
> This value is set by DM-Firmware during the suspend sequence.
>
> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
> Co-developed-by: Gregory CLEMENT (TI) <gregory.clement@bootlin.com>
> Signed-off-by: Gregory CLEMENT (TI) <gregory.clement@bootlin.com>
> Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
> Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
> ---
> board/ti/common/k3-lpm.h | 17 +++++++++++++++++
> board/ti/j721e/evm.c | 37 +++++++++++++++++++++++++++++++++++++
> 2 files changed, 54 insertions(+)
> create mode 100644 board/ti/common/k3-lpm.h
>
> diff --git a/board/ti/common/k3-lpm.h b/board/ti/common/k3-lpm.h
> new file mode 100644
> index 000000000000..a2141a0c25a8
> --- /dev/null
> +++ b/board/ti/common/k3-lpm.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2026, Texas Instruments Incorporated - https://www.ti.com/
> + * Copyright (C) 2026, Bootlin
> + */
> +
> +#ifndef __K3_LPM_H
> +#define __K3_LPM_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 0xcb
> +
> +#endif /* __K3_LPM_H */
> +
> diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c
> index 881392bd963a..67ff13828514 100644
> --- a/board/ti/j721e/evm.c
> +++ b/board/ti/j721e/evm.c
> @@ -17,9 +17,11 @@
> #include <spl.h>
> #include <dm.h>
> #include <asm/arch/k3-ddr.h>
> +#include <power/pmic.h>
>
> #include "../common/board_detect.h"
> #include "../common/fdt_ops.h"
> +#include "../common/k3-lpm.h"
>
> #define board_is_j721e_som() (board_ti_k3_is("J721EX-PM1-SOM") || \
> board_ti_k3_is("J721EX-PM2-SOM"))
> @@ -469,6 +471,41 @@ err_free_gpio:
> }
> }
>
> +#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J7200_R5_EVM))
> +
> +bool j7xx_board_is_resuming(void)
> +{
> + struct udevice *pmica;
> + int ret;
> +
> + if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
> + goto end;
> +
> + ret = uclass_get_device_by_name(UCLASS_PMIC,
> + "pmic@48", &pmica);
> + if (ret) {
> + printf("Getting PMICA init failed: %d\n", ret);
> + goto end;
> + }
> + debug("%s: PMICA is detected (%s)\n", __func__, pmica->name);
> +
> + if (pmic_reg_read(pmica, K3_LPM_SCRATCH_PAD_REG) == K3_LPM_MAGIC_SUSPEND) {
> + debug("%s: board is resuming\n", __func__);
> + gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
If you failed to clear magic word then, we are not in correct state.
So doing all work with PMIC, set state to resuming
> +
> + /* clean magic suspend */
> + if (pmic_reg_write(pmica, K3_LPM_SCRATCH_PAD_REG, 0))
> + printf("Failed to clean magic value for suspend detection in PMICA\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_J7200_R5_EVM */
> +
> void spl_board_init(void)
> {
> struct udevice *dev;
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 04/20] board: ti: j784s4: Add resume detection
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (2 preceding siblings ...)
2026-04-30 8:43 ` [PATCH 03/20] board: ti: j721e: Add resume detection for J721e/J7200 Richard Genoud (TI)
@ 2026-04-30 8:43 ` Richard Genoud (TI)
2026-05-11 10:47 ` Kumar, Udit
2026-04-30 8:43 ` [PATCH 05/20] board: ti: j722s: " Richard Genoud (TI)
` (15 subsequent siblings)
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:43 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
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.
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
board/ti/j784s4/evm.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/board/ti/j784s4/evm.c b/board/ti/j784s4/evm.c
index cabb3017ee14..4a74024fe4fe 100644
--- a/board/ti/j784s4/evm.c
+++ b/board/ti/j784s4/evm.c
@@ -12,7 +12,9 @@
#include <init.h>
#include <spl.h>
#include <asm/arch/k3-ddr.h>
+#include <power/pmic.h>
#include "../common/fdt_ops.h"
+#include "../common/k3-lpm.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -61,6 +63,42 @@ int board_late_init(void)
}
#endif
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J784S4_R5_EVM))
+
+/* 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;
+ int err;
+
+ if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
+ goto end;
+
+ err = uclass_get_device_by_name(UCLASS_PMIC,
+ "pmic@48", &pmic);
+ if (err) {
+ printf("Getting PMIC init failed: %d\n", err);
+ goto end;
+ }
+ debug("%s: PMIC is detected (%s)\n", __func__, pmic->name);
+
+ if (pmic_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 (pmic_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_J784s4_R5_EVM */
+
void spl_board_init(void)
{
struct udevice *dev;
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 04/20] board: ti: j784s4: Add resume detection
2026-04-30 8:43 ` [PATCH 04/20] board: ti: j784s4: Add resume detection Richard Genoud (TI)
@ 2026-05-11 10:47 ` Kumar, Udit
0 siblings, 0 replies; 32+ messages in thread
From: Kumar, Udit @ 2026-05-11 10:47 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Apurva Nandan,
Andrew F . Davis, Vignesh Raghavendra, Bryan Brattlof,
Vaishnav Achath, Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Abhash Kumar, Thomas Richard,
Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/2026 2:13 PM, Richard Genoud (TI) wrote:
> 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.
>
> Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
> ---
> board/ti/j784s4/evm.c | 38 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/board/ti/j784s4/evm.c b/board/ti/j784s4/evm.c
> index cabb3017ee14..4a74024fe4fe 100644
> --- a/board/ti/j784s4/evm.c
> +++ b/board/ti/j784s4/evm.c
> @@ -12,7 +12,9 @@
> #include <init.h>
> #include <spl.h>
> #include <asm/arch/k3-ddr.h>
> +#include <power/pmic.h>
> #include "../common/fdt_ops.h"
> +#include "../common/k3-lpm.h"
>
> DECLARE_GLOBAL_DATA_PTR;
>
> @@ -61,6 +63,42 @@ int board_late_init(void)
> }
> #endif
>
> +#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J784S4_R5_EVM))
> +
> +/* 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;
> + int err;
> +
> + if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
> + goto end;
> +
> + err = uclass_get_device_by_name(UCLASS_PMIC,
> + "pmic@48", &pmic);
> + if (err) {
> + printf("Getting PMIC init failed: %d\n", err);
> + goto end;
> + }
> + debug("%s: PMIC is detected (%s)\n", __func__, pmic->name);
> +
> + if (pmic_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);
> +
Same comment as patch 3/20
> + /* clean magic suspend */
> + if (pmic_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_J784s4_R5_EVM */
> +
> void spl_board_init(void)
> {
> struct udevice *dev;
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 05/20] board: ti: j722s: Add resume detection
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (3 preceding siblings ...)
2026-04-30 8:43 ` [PATCH 04/20] board: ti: j784s4: Add resume detection Richard Genoud (TI)
@ 2026-04-30 8:43 ` Richard Genoud (TI)
2026-04-30 8:43 ` [PATCH 06/20] board: ti: j721s2: " Richard Genoud (TI)
` (14 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:43 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
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@ti.com>
Signed-off-by: Udit Kumar <u-kumar1@ti.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@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@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)
{
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 06/20] board: ti: j721s2: Add resume detection
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (4 preceding siblings ...)
2026-04-30 8:43 ` [PATCH 05/20] board: ti: j722s: " Richard Genoud (TI)
@ 2026-04-30 8:43 ` Richard Genoud (TI)
2026-05-11 10:48 ` Kumar, Udit
2026-04-30 8:44 ` [PATCH 07/20] ram: k3-ddrss: Add exit retention support Richard Genoud (TI)
` (13 subsequent siblings)
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:43 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: "Thomas Richard (TI)" <thomas.richard@bootlin.com>
Add the capability to detect a resume. This overrides the weak function
j7xx_board_is_resuming(void).
To detect the resume, SPL searches a magic value (0xBA) in a register of
PMICA.
This value is set by DM-Firmware during the suspend sequence.
Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
---
board/ti/j721s2/evm.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/board/ti/j721s2/evm.c b/board/ti/j721s2/evm.c
index 92d5c8498643..e18ba1a540c9 100644
--- a/board/ti/j721s2/evm.c
+++ b/board/ti/j721s2/evm.c
@@ -22,9 +22,11 @@
#include <dm/uclass-internal.h>
#include <dm/root.h>
#include <asm/arch/k3-ddr.h>
+#include <power/pmic.h>
#include "../common/board_detect.h"
#include "../common/fdt_ops.h"
+#include "../common/k3-lpm.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -304,6 +306,41 @@ int board_late_init(void)
return 0;
}
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J721S2_R5_EVM) && IS_ENABLED(CONFIG_PMIC_TPS65941))
+
+/* 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;
+ int err;
+
+ if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
+ goto end;
+
+ err = uclass_get_device_by_name(UCLASS_PMIC,
+ "pmic@48", &pmic);
+ if (err) {
+ printf("Getting PMIC init failed: %d\n", err);
+ goto end;
+ }
+ debug("%s: PMIC is detected (%s)\n", __func__, pmic->name);
+
+ if (pmic_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 (pmic_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_J721S2_R5_EVM && CONFIG_PMIC_TPS65941 */
+
void spl_board_init(void)
{
struct udevice *dev;
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 06/20] board: ti: j721s2: Add resume detection
2026-04-30 8:43 ` [PATCH 06/20] board: ti: j721s2: " Richard Genoud (TI)
@ 2026-05-11 10:48 ` Kumar, Udit
0 siblings, 0 replies; 32+ messages in thread
From: Kumar, Udit @ 2026-05-11 10:48 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Apurva Nandan,
Andrew F . Davis, Vignesh Raghavendra, Bryan Brattlof,
Vaishnav Achath, Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Abhash Kumar, Thomas Richard,
Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/2026 2:13 PM, Richard Genoud (TI) wrote:
> From: "Thomas Richard (TI)" <thomas.richard@bootlin.com>
>
> Add the capability to detect a resume. This overrides the weak function
> j7xx_board_is_resuming(void).
> To detect the resume, SPL searches a magic value (0xBA) in a register of
> PMICA.
> This value is set by DM-Firmware during the suspend sequence.
>
> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
> ---
> board/ti/j721s2/evm.c | 37 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/board/ti/j721s2/evm.c b/board/ti/j721s2/evm.c
> index 92d5c8498643..e18ba1a540c9 100644
> --- a/board/ti/j721s2/evm.c
> +++ b/board/ti/j721s2/evm.c
> @@ -22,9 +22,11 @@
> #include <dm/uclass-internal.h>
> #include <dm/root.h>
> #include <asm/arch/k3-ddr.h>
> +#include <power/pmic.h>
>
> #include "../common/board_detect.h"
> #include "../common/fdt_ops.h"
> +#include "../common/k3-lpm.h"
>
> DECLARE_GLOBAL_DATA_PTR;
>
> @@ -304,6 +306,41 @@ int board_late_init(void)
> return 0;
> }
>
> +#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J721S2_R5_EVM) && IS_ENABLED(CONFIG_PMIC_TPS65941))
> +
> +/* 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;
> + int err;
> +
> + if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
> + goto end;
> +
> + err = uclass_get_device_by_name(UCLASS_PMIC,
> + "pmic@48", &pmic);
> + if (err) {
> + printf("Getting PMIC init failed: %d\n", err);
> + goto end;
> + }
> + debug("%s: PMIC is detected (%s)\n", __func__, pmic->name);
> +
> + if (pmic_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 (pmic_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);
> + }
Could all function be combined into common_j7xx_lpm.c for all supporting
SOCs.
> +end:
> + return gd_k3_resuming() == K3_RESUME_STATE_RESUMING;
> +}
> +#endif /* CONFIG_SPL_BUILD && CONFIG_TARGET_J721S2_R5_EVM && CONFIG_PMIC_TPS65941 */
> +
> void spl_board_init(void)
> {
> struct udevice *dev;
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 07/20] ram: k3-ddrss: Add exit retention support
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (5 preceding siblings ...)
2026-04-30 8:43 ` [PATCH 06/20] board: ti: j721s2: " Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 8:44 ` [PATCH 08/20] ram: k3-ddrss: Add j722s DDR resume sequence Richard Genoud (TI)
` (12 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: "Thomas Richard (TI)" <thomas.richard@bootlin.com>
Add functions that implements retention exit sequence of DDR.
Typical DDR resume sequence is:
- exit DDR from retention
- de-assert the DDR_RET pin
- restore DDR max frequency
- exit DDR from low power
We have to separate each action in order to de-assert the DDR_RET pins
at the right time, because the DDR_RET pins are all tied together
in hardware.
Additional interleaving to be taken care and configuring of PMIC differs
device to device depending on number of PMIC.
Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/include/mach/k3-ddr.h | 16 ++
| 253 +++++++++++++++++++++++++
| 94 +++++++++
3 files changed, 363 insertions(+)
create mode 100644 drivers/ram/k3-ddrss/lpddr4_k3_reg.h
diff --git a/arch/arm/mach-k3/include/mach/k3-ddr.h b/arch/arm/mach-k3/include/mach/k3-ddr.h
index 6ac7f682fb80..5dd4025bdbb7 100644
--- a/arch/arm/mach-k3/include/mach/k3-ddr.h
+++ b/arch/arm/mach-k3/include/mach/k3-ddr.h
@@ -7,6 +7,7 @@
#define _K3_DDR_H_
#include <spl.h>
+#include <compiler.h>
/* We need 4 extra entries for:
* 1. SoC peripherals
@@ -17,10 +18,25 @@
#define K3_MEM_MAP_LEN ((CONFIG_NR_DRAM_BANKS) + 4)
#define K3_MEM_MAP_FIRST_BANK_IDX 3
+struct k3_ddrss_regs {
+ u32 ctl_141;
+ u32 phy_1305;
+ u32 ctl_88;
+ u32 pi_134;
+ u32 pi_7;
+ u32 ctl_20;
+ u32 wdqlvl_f1;
+ u32 wdqlvl_f2;
+};
+
int dram_init(void);
int dram_init_banksize(void);
void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image);
void fixup_memory_node(struct spl_image_info *spl_image);
+/* LPDDR4 power management functions */
+void k3_ddrss_lpddr4_exit_retention(struct udevice *dev, struct k3_ddrss_regs *regs);
+void k3_ddrss_lpddr4_change_freq(struct udevice *dev);
+void k3_ddrss_lpddr4_exit_low_power(struct udevice *dev, struct k3_ddrss_regs *regs);
#endif /* _K3_DDR_H_ */
--git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index 27823e91d5ef..7b2d2e0814b8 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -19,12 +19,14 @@
#include <power-domain.h>
#include <wait_bit.h>
#include <power/regulator.h>
+#include <mach/k3-ddr.h>
#include "k3-ddrss-lpm.h"
#include "lpddr4_obj_if.h"
#include "lpddr4_if.h"
#include "lpddr4_structs_if.h"
#include "lpddr4_ctl_regs.h"
+#include "lpddr4_k3_reg.h"
#define SRAM_MAX 512
@@ -441,6 +443,257 @@ static int k3_ddrss_ofdata_to_priv(struct udevice *dev)
return ret;
}
+#if defined(CONFIG_K3_J721E_DDRSS)
+
+void k3_ddrss_lpddr4_exit_retention(struct udevice *dev,
+ struct k3_ddrss_regs *regs)
+{
+ struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
+ u32 regval;
+ unsigned int pll_ctrl;
+ unsigned int val;
+
+ /*
+ * Saving registers
+ */
+ lpddr4_k3_readreg_ctl(ddrss, DENALI_CTL_141, ®s->ctl_141);
+ lpddr4_k3_readreg_phy(ddrss, DENALI_PHY_1305, ®s->phy_1305);
+ lpddr4_k3_readreg_ctl(ddrss, DENALI_CTL_88, ®s->ctl_88);
+ lpddr4_k3_readreg_pi(ddrss, DENALI_PI_134, ®s->pi_134);
+ // PI_139 cannot be restored
+ lpddr4_k3_readreg_pi(ddrss, DENALI_PI_7, ®s->pi_7);
+ lpddr4_k3_readreg_ctl(ddrss, DENALI_CTL_20, ®s->ctl_20);
+
+ /* disable auto entry / exit */
+ lpddr4_k3_clr_ctl(ddrss, DENALI_CTL_141, (0xF << 24) | (0xF << 16));
+
+ /* Configure DFI Interface, DDR retention exit occurs through PHY */
+ lpddr4_k3_readreg_phy(ddrss, LPDDR4__PHY_SET_DFI_INPUT_0__REG, ®val);
+ regval &= ~0xF0F; // Set DFI_Input_1 = 0
+ regval |= 0x01; // Set DFI Input_0 = 1
+ lpddr4_k3_writereg_phy(ddrss, LPDDR4__PHY_SET_DFI_INPUT_0__REG, regval);
+
+ /* PWRUP_SREFRESH_EXIT = 1 */
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__PWRUP_SREFRESH_EXIT__REG, 0x1);
+
+ /* PI_PWRUP_SREFRESH_EXIT = 0 */
+ lpddr4_k3_clr_pi(ddrss, LPDDR4__PI_PWRUP_SREFRESH_EXIT__REG, 0x1 << 16);
+
+ /* PI_DRAM_INIT_EN = 0 */
+ lpddr4_k3_clr_pi(ddrss, LPDDR4__PI_DRAM_INIT_EN__REG, 0x1 << 8);
+
+ /* PI_DFI_PHYMSTR_STATE_SEL_R = 1 (force memory into self-refresh) */
+ lpddr4_k3_set_pi(ddrss, LPDDR4__PI_DFI_PHYMSTR_STATE_SEL_R__REG, (1 << 24));
+
+ /* PHY_INDEP_INIT_MODE = 0 */
+ lpddr4_k3_clr_ctl(ddrss, LPDDR4__PHY_INDEP_INIT_MODE__REG, (0x1 << 16));
+
+ /* PHY_INDEP_TRAIN_MODE = 1 */
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__PHY_INDEP_TRAIN_MODE__REG, 0x1);
+
+ lpddr4_k3_readreg_pi(ddrss, LPDDR4__PI_WDQLVL_EN_F1__REG, ®s->wdqlvl_f1);
+ regs->wdqlvl_f1 &= LPDDR4__DENALI_PI_214__PI_WDQLVL_EN_F1_MASK;
+
+ lpddr4_k3_readreg_pi(ddrss, LPDDR4__PI_WDQLVL_EN_F2__REG, ®s->wdqlvl_f2);
+ regs->wdqlvl_f2 &= LPDDR4__DENALI_PI_217__PI_WDQLVL_EN_F2_MASK;
+
+ /* clear periodic WDQLVL for F0 */
+ lpddr4_k3_clr_pi(ddrss, LPDDR4__PI_WDQLVL_EN_F0__REG,
+ 0x2 << LPDDR4__DENALI_PI_212__PI_WDQLVL_EN_F0_SHIFT);
+
+ /* clear periodic WDQLVL for F1 */
+ lpddr4_k3_clr_pi(ddrss, LPDDR4__PI_WDQLVL_EN_F1__REG,
+ 0x2 << LPDDR4__DENALI_PI_214__PI_WDQLVL_EN_F1_SHIFT);
+
+ /* clear periodic WDQLVL for F2 */
+ lpddr4_k3_clr_pi(ddrss, LPDDR4__PI_WDQLVL_EN_F2__REG,
+ 0x2 << LPDDR4__DENALI_PI_217__PI_WDQLVL_EN_F2_SHIFT);
+
+#define PLL_CTRL_OFF 0x20
+#define PLL_CFG 0x00680000
+ switch (ddrss->instance) {
+ case 0:
+ pll_ctrl = PLL_CFG + 12 * 0x1000 + PLL_CTRL_OFF;
+ break;
+ case 1:
+ pll_ctrl = PLL_CFG + 26 * 0x1000 + PLL_CTRL_OFF;
+ break;
+ case 2:
+ pll_ctrl = PLL_CFG + 27 * 0x1000 + PLL_CTRL_OFF;
+ break;
+ case 3:
+ pll_ctrl = PLL_CFG + 28 * 0x1000 + PLL_CTRL_OFF;
+ break;
+ }
+
+ *(unsigned int *)pll_ctrl |= 0x80000000;
+ val = *(unsigned int *)pll_ctrl;
+ if ((val & 0x80000000) != 0x80000000)
+ val = *(unsigned int *)pll_ctrl;
+}
+
+void k3_ddrss_lpddr4_change_freq(struct udevice *dev)
+{
+ struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
+ u32 regval;
+ unsigned long tmo;
+
+ /* PI_START=1 */
+ lpddr4_k3_set_pi(ddrss, LPDDR4__PI_START__REG, 0x01);
+ /* START=1 */
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__START__REG, 0x01);
+
+ k3_lpddr4_freq_update(ddrss);
+
+ tmo = timer_get_us() + 100000;
+ do {
+ lpddr4_k3_readreg_pi(ddrss, LPDDR4__PI_INT_STATUS__REG, ®val);
+ if (timer_get_us() > tmo) {
+ printf("%s:%d timeout error\n", __func__, __LINE__);
+ hang();
+ }
+ } while ((regval & (1 << 0)) == 0x00);
+
+ tmo = timer_get_us() + 4000;
+ do {
+ lpddr4_k3_readreg_ctl(ddrss, LPDDR4__INT_STATUS_0__REG, ®val);
+ if (timer_get_us() > tmo) {
+ printf("%s:%d timeout error\n", __func__, __LINE__);
+ hang();
+ }
+ } while ((regval & (1 << 9)) == 0x00);
+
+ lpddr4_k3_readreg_pi(ddrss, LPDDR4__PI_INT_STATUS__REG, ®val);
+ debug("%s: PI interrupt status: 0x%08x\n", __func__, regval);
+
+ lpddr4_k3_readreg_ctl(ddrss, LPDDR4__INT_STATUS_0__REG, ®val);
+ debug("%s: Controller interrupt status: 0x%08x\n", __func__, regval);
+
+ debug("%s: Successfully exited Retention\n", __func__);
+}
+
+void k3_ddrss_lpddr4_exit_low_power(struct udevice *dev,
+ struct k3_ddrss_regs *regs)
+{
+ struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
+ u32 regval, fspop, fspwr;
+ unsigned long tmo;
+
+ lpddr4_k3_readreg_ctl(ddrss, LPDDR4__LP_STATE_CS0__REG, ®val);
+ debug("%s: LP State: 0x%08x\n", __func__, regval);
+
+ /* make sure that LP flag is clear before going through this process */
+ lpddr4_k3_writereg_ctl(ddrss, LPDDR4__INT_ACK_0__REG, (0x1 << 10));
+
+ lpddr4_k3_readreg_ctl(ddrss, LPDDR4__CKSRX_F1__REG, ®val);
+ regval &= ~(0x7F << 24);
+ regval |= (0x2 << 24); // set low power mode exit
+ lpddr4_k3_writereg_ctl(ddrss, LPDDR4__CKSRX_F1__REG, regval);
+
+ lpddr4_k3_readreg_ctl(ddrss, LPDDR4__LP_STATE_CS0__REG, ®val);
+ debug("%s: LP State: 0x%08x\n", __func__, regval);
+
+ /* wait until low power operation has been completed */
+ tmo = timer_get_us() + 4000;
+ do {
+ lpddr4_k3_readreg_ctl(ddrss, LPDDR4__INT_STATUS_0__REG, ®val);
+ if (timer_get_us() > tmo) {
+ printf("%s:%d timeout error\n", __func__, __LINE__);
+ hang();
+ }
+ } while ((regval & (0x1 << 10)) == 0);
+
+ lpddr4_k3_readreg_ctl(ddrss, LPDDR4__LP_STATE_CS0__REG, ®val);
+ debug("%s: LP State: 0x%08x\n", __func__, regval);
+
+ lpddr4_k3_writereg_ctl(ddrss, LPDDR4__INT_ACK_0__REG, (0x1 << 10));
+
+ /*
+ * bit 6 / 14 -- lp_state valid
+ * bits 13:8 / 5:0 0x0F SRPD Long with Mem and Controller Clk Gating
+ */
+ tmo = timer_get_us() + 4000;
+ do {
+ lpddr4_k3_readreg_ctl(ddrss, LPDDR4__LP_STATE_CS0__REG, ®val);
+ if (timer_get_us() > tmo) {
+ printf("%s:%d timeout error\n", __func__, __LINE__);
+ hang();
+ }
+ } while ((regval & 0x4F4F) != 0x4040);
+
+ lpddr4_k3_readreg_ctl(ddrss, LPDDR4__LP_STATE_CS0__REG, ®val);
+ debug("%s: LP State: 0x%08x\n", __func__, regval);
+
+ /*
+ * MR13 data within the PI is based upon CS but NOT based upon
+ * frequency set point.
+ * MR13 is the current MR13 value
+ */
+ lpddr4_k3_readreg_pi(ddrss, LPDDR4__PI_MR13_DATA_0__REG, ®val);
+ fspop = (regval & ((u32)1 << 31)) >> 31;
+ fspwr = (regval & ((u32)1 << 30)) >> 30;
+
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__FSP_OP_CURRENT__REG,
+ fspop << LPDDR4__DENALI_CTL_192__FSP_OP_CURRENT_SHIFT);
+
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__FSP_WR_CURRENT__REG,
+ fspwr << LPDDR4__DENALI_CTL_192__FSP_WR_CURRENT_SHIFT);
+
+ // do not allow CTL to update MR
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__FSP_PHY_UPDATE_MRW__REG,
+ 1 << LPDDR4__DENALI_CTL_191__FSP_PHY_UPDATE_MRW_SHIFT);
+
+ // do not allow PI to update MR
+ lpddr4_k3_clr_pi(ddrss, DENALI_PI_64, 1 << 0);
+
+ // PI_FREQ_MAP defines supported working frequencies
+ lpddr4_k3_readreg_pi(ddrss, LPDDR4__PI_FREQ_MAP__REG, ®val);
+ if (regval & (0x1 << 1)) {
+ // define FSP0 and FSP1 as trained
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__MR_FSP_DATA_VALID_F0__REG,
+ LPDDR4__DENALI_CTL_190__MR_FSP_DATA_VALID_F0_MASK);
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__MR_FSP_DATA_VALID_F1__REG,
+ LPDDR4__DENALI_CTL_190__MR_FSP_DATA_VALID_F1_MASK);
+ }
+ if (regval & (0x1 << 2)) {
+ // define FSP0 and FSP2 as trained
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__MR_FSP_DATA_VALID_F0__REG,
+ LPDDR4__DENALI_CTL_190__MR_FSP_DATA_VALID_F0_MASK);
+ lpddr4_k3_set_ctl(ddrss, LPDDR4__MR_FSP_DATA_VALID_F2__REG,
+ LPDDR4__DENALI_CTL_190__MR_FSP_DATA_VALID_F2_MASK);
+ }
+
+ /*
+ * Restore registers
+ */
+ lpddr4_k3_writereg_ctl(ddrss, DENALI_CTL_141, regs->ctl_141);
+ lpddr4_k3_writereg_phy(ddrss, DENALI_PHY_1305, regs->phy_1305);
+ lpddr4_k3_writereg_ctl(ddrss, DENALI_CTL_88, regs->ctl_88);
+ lpddr4_k3_writereg_pi(ddrss, DENALI_PI_134, regs->pi_134);
+ // PI_139 cannot be restored
+ lpddr4_k3_writereg_pi(ddrss, DENALI_PI_7, regs->pi_7);
+ lpddr4_k3_writereg_ctl(ddrss, DENALI_CTL_20, regs->ctl_20);
+
+ lpddr4_k3_readreg_ctl(ddrss, DENALI_CTL_141, ®s->ctl_141);
+ lpddr4_k3_readreg_phy(ddrss, DENALI_PHY_1305, ®s->phy_1305);
+ lpddr4_k3_readreg_ctl(ddrss, DENALI_CTL_88, ®s->ctl_88);
+ // PI_139 cannot be restored
+ lpddr4_k3_readreg_pi(ddrss, DENALI_PI_7, ®s->pi_7);
+
+ lpddr4_k3_readreg_pi(ddrss, DENALI_PI_79, ®val);
+ lpddr4_k3_writereg_pi(ddrss, DENALI_PI_80, regval);
+
+ lpddr4_k3_readreg_ctl(ddrss, DENALI_CTL_293, ®val);
+ lpddr4_k3_writereg_ctl(ddrss, DENALI_CTL_295, regval);
+
+ lpddr4_k3_readreg_ctl(ddrss, DENALI_CTL_294, ®val);
+ lpddr4_k3_writereg_ctl(ddrss, DENALI_CTL_296, regval);
+
+ lpddr4_k3_set_pi(ddrss, DENALI_PI_214, regs->wdqlvl_f1);
+ lpddr4_k3_set_pi(ddrss, DENALI_PI_217, regs->wdqlvl_f2);
+}
+#endif /* CONFIG_K3_J721E_DDRSS */
+
void k3_lpddr4_probe(struct k3_ddrss_desc *ddrss)
{
u32 status = 0U;
--git a/drivers/ram/k3-ddrss/lpddr4_k3_reg.h b/drivers/ram/k3-ddrss/lpddr4_k3_reg.h
new file mode 100644
index 000000000000..aca56200a96b
--- /dev/null
+++ b/drivers/ram/k3-ddrss/lpddr4_k3_reg.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#ifndef LPDDR4_K3_REG
+#define LPDDR4_K3_REG
+
+#define _lpddr4_k3_readreg(_shift, _fnct, _ddrss, _reg, _p) do { \
+ u16 offset = 0U; \
+ u32 result = 0U; \
+ TH_OFFSET_FROM_REG(_reg, _shift, offset); \
+ result = (_fnct)(&(_ddrss)->pd, _p, (u16 *)(&offset), 1); \
+ if (result > 0U) { \
+ printf("%s: Failed to read %s\n", __func__, xstr(_reg));\
+ hang(); \
+ } \
+} while (0)
+
+#define _lpddr4_k3_writereg(_shift, _fnct, _ddrss, _reg, _val) do { \
+ u16 offset = 0U; \
+ u32 result = 0U; \
+ u32 writeval = _val; \
+ TH_OFFSET_FROM_REG(_reg, _shift, offset); \
+ result = (_fnct)(&(_ddrss)->pd, &writeval, (u16 *)(&offset), 1);\
+ if (result > 0U) { \
+ printf("%s: Failed to write %s\n", __func__, xstr(_reg));\
+ hang(); \
+ } \
+} while (0)
+
+#define lpddr4_k3_readreg_ctl(_ddrss, _reg, _pt) \
+ _lpddr4_k3_readreg(CTL_SHIFT, \
+ (_ddrss)->driverdt->readctlconfig, \
+ _ddrss, _reg, _pt)
+
+#define lpddr4_k3_readreg_pi(_ddrss, _reg, _pt) \
+ _lpddr4_k3_readreg(PI_SHIFT, \
+ (_ddrss)->driverdt->readphyindepconfig, \
+ _ddrss, _reg, _pt)
+
+#define lpddr4_k3_readreg_phy(_ddrss, _reg, _pt) \
+ _lpddr4_k3_readreg(PHY_SHIFT, \
+ (_ddrss)->driverdt->readphyconfig, \
+ _ddrss, _reg, _pt)
+
+#define lpddr4_k3_writereg_ctl(_ddrss, _reg, _val) \
+ _lpddr4_k3_writereg(CTL_SHIFT, \
+ (_ddrss)->driverdt->writectlconfig, \
+ _ddrss, _reg, _val)
+
+#define lpddr4_k3_writereg_pi(_ddrss, _reg, _val) \
+ _lpddr4_k3_writereg(PI_SHIFT, \
+ (_ddrss)->driverdt->writephyindepconfig, \
+ _ddrss, _reg, _val)
+
+#define lpddr4_k3_writereg_phy(_ddrss, _reg, _val) \
+ _lpddr4_k3_writereg(PHY_SHIFT, \
+ (_ddrss)->driverdt->writephyconfig, \
+ _ddrss, _reg, _val)
+
+#define _lpddr4_k3_set(_type, _ddrss, _reg, _mask) do { \
+ u32 _val; \
+ lpddr4_k3_readreg_##_type(_ddrss, _reg, &_val); \
+ _val |= _mask; \
+ lpddr4_k3_writereg_##_type(_ddrss, _reg, _val); \
+} while (0)
+
+#define _lpddr4_k3_clr(_type, _ddrss, _reg, _mask) do { \
+ u32 _val; \
+ lpddr4_k3_readreg_##_type(_ddrss, _reg, &_val); \
+ _val &= ~(_mask); \
+ lpddr4_k3_writereg_##_type(_ddrss, _reg, _val); \
+} while (0)
+
+#define lpddr4_k3_set_ctl(_ddrss, _reg, _mask) \
+ _lpddr4_k3_set(ctl, _ddrss, _reg, _mask)
+
+#define lpddr4_k3_clr_ctl(_ddrss, _reg, _mask) \
+ _lpddr4_k3_clr(ctl, _ddrss, _reg, _mask)
+
+#define lpddr4_k3_set_pi(_ddrss, _reg, _mask) \
+ _lpddr4_k3_set(pi, _ddrss, _reg, _mask)
+
+#define lpddr4_k3_clr_pi(_ddrss, _reg, _mask) \
+ _lpddr4_k3_clr(pi, _ddrss, _reg, _mask)
+
+#define lpddr4_k3_set_phy(_ddrss, _reg, _mask) \
+ _lpddr4_k3_set(phy, _ddrss, _reg, _mask)
+
+#define lpddr4_k3_clr_phy(_ddrss, _reg, _mask) \
+ _lpddr4_k3_clr(phy, _ddrss, _reg, _mask)
+
+#endif /* LPDDR4_K3_REG */
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 08/20] ram: k3-ddrss: Add j722s DDR resume sequence
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (6 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 07/20] ram: k3-ddrss: Add exit retention support Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 8:44 ` [PATCH 09/20] ram: k3-ddrss: support j784s4/j721e/j721s2 DDR resume Richard Genoud (TI)
` (11 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
As the j722s and am62p resume sequence differs on the way they are
detecting that the board is resuming, we should have a specific
compatible for each one of them.
For that purpose, introduce ti,j722s-ddrss compatible.
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/dts/k3-j722s-r5-evm.dts | 4 ++++
| 12 ++++++++++++
2 files changed, 16 insertions(+)
diff --git a/arch/arm/dts/k3-j722s-r5-evm.dts b/arch/arm/dts/k3-j722s-r5-evm.dts
index e1ef5d181ed7..cc4a5910673b 100644
--- a/arch/arm/dts/k3-j722s-r5-evm.dts
+++ b/arch/arm/dts/k3-j722s-r5-evm.dts
@@ -11,6 +11,10 @@
#include "k3-am62a-ddr.dtsi"
#include "k3-j722s-r5.dtsi"
+&memorycontroller {
+ compatible = "ti,j722s-ddrss", "ti,am62a-ddrss";
+};
+
/* WKUP UART0 is used for DM firmware logs */
&wkup_uart0 {
status = "okay";
--git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index 7b2d2e0814b8..7b23123ab00d 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -1283,6 +1283,11 @@ static int k3_ddrss_get_info(struct udevice *dev, struct ram_info *info)
return 0;
}
+__weak bool j7xx_board_is_resuming(void)
+{
+ return false;
+}
+
static struct ram_ops k3_ddrss_ops = {
.get_info = k3_ddrss_get_info,
};
@@ -1301,11 +1306,18 @@ static const struct k3_ddrss_data j721s2_data = {
.flags = MULTI_DDR_SUBSYSTEM,
};
+static const struct k3_ddrss_data j722s_data = {
+ .flags = SINGLE_DDR_SUBSYSTEM,
+ .is_lpm_resume = j7xx_board_is_resuming,
+ .ddrss_deassert_retention = am62xx_ddrss_deassert_retention,
+};
+
static const struct udevice_id k3_ddrss_ids[] = {
{.compatible = "ti,am62a-ddrss", .data = (ulong)&am62xx_data, },
{.compatible = "ti,am64-ddrss", .data = (ulong)&k3_data, },
{.compatible = "ti,j721e-ddrss", .data = (ulong)&k3_data, },
{.compatible = "ti,j721s2-ddrss", .data = (ulong)&j721s2_data, },
+ {.compatible = "ti,j722s-ddrss", .data = (ulong)&j722s_data, },
{}
};
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 09/20] ram: k3-ddrss: support j784s4/j721e/j721s2 DDR resume
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (7 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 08/20] ram: k3-ddrss: Add j722s DDR resume sequence Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 8:44 ` [PATCH 10/20] firmware: ti_sci: add low power mode operations Richard Genoud (TI)
` (10 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
j78s4/j721e/j7200/J721s2 can't use the standard resume sequence.
Typical DDR resume sequence is:
- exit DDR from retention
- de-assert the DDR_RET pin
- restore DDR max frequency
- exit DDR from low power
We have to separate each action in order to de-assert the DDR_RET pins
at the right time, because the DDR_RET pins are all tied together in
hardware.
At resume, only the initialization of the DDR is done by the driver, the
rest is handled in boart_init_f().
So, introduce lpm_init_only flag to only initialize the DDR when resume
is detected for those boards.
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
| 8 ++++++++
1 file changed, 8 insertions(+)
--git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index 7b23123ab00d..5db421353e1f 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -122,6 +122,7 @@ enum intrlv_size {
struct k3_ddrss_data {
u32 flags;
+ bool lpm_init_only;
bool (*is_lpm_resume)(void);
void (*ddrss_deassert_retention)(void);
};
@@ -1157,6 +1158,9 @@ static int k3_ddrss_probe(struct udevice *dev)
k3_lpddr4_init(ddrss);
k3_lpddr4_hardware_reg_init(ddrss);
+ if (is_lpm_resume && ddrss_data->lpm_init_only)
+ return k3_ddrss_init_freq(ddrss);
+
if (is_lpm_resume)
k3_ddrss_self_refresh_exit(ddrss->ddrss_ctl_cfg);
@@ -1294,6 +1298,8 @@ static struct ram_ops k3_ddrss_ops = {
static const struct k3_ddrss_data k3_data = {
.flags = SINGLE_DDR_SUBSYSTEM,
+ .lpm_init_only = true,
+ .is_lpm_resume = j7xx_board_is_resuming,
};
static const struct k3_ddrss_data am62xx_data = {
@@ -1304,6 +1310,8 @@ static const struct k3_ddrss_data am62xx_data = {
static const struct k3_ddrss_data j721s2_data = {
.flags = MULTI_DDR_SUBSYSTEM,
+ .lpm_init_only = true,
+ .is_lpm_resume = j7xx_board_is_resuming,
};
static const struct k3_ddrss_data j722s_data = {
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 10/20] firmware: ti_sci: add low power mode operations
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (8 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 09/20] ram: k3-ddrss: support j784s4/j721e/j721s2 DDR resume Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-05-11 10:50 ` Kumar, Udit
2026-04-30 8:44 ` [PATCH 11/20] mach-k3: r5: common: add helper functions needed in LPM resume sequence Richard Genoud (TI)
` (9 subsequent siblings)
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: Prasanth Babu Mantena <p-mantena@ti.com>
From: Prasanth Babu Mantena <p-mantena@ti.com>
On TI-k3 platform, at resume, uboot SPL needs to do several tasks:
- restore TIFS minimal context from DDR
- send DDR save address to TIFS
- load TFA and its context in MSMC
- set TFA resume vector to its warm_entrypoint
- authenticate certificates and apply firewalls
All those operations are now done by TIFS with those messages:
ti_sci_cmd_min_context_restore
ti_sci_cmd_decrypt_tfa
ti_sci_cmd_core_resume
ti_sci_cmd_lpm_save_addr
ti_sci_cmd_proc_auth_apply_fwls
https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html
https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/security/PROC_BOOT.html
Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/include/mach/security.h | 1 +
arch/arm/mach-k3/security.c | 64 ++++++++
drivers/firmware/ti_sci.c | 179 +++++++++++++++++++++++
drivers/firmware/ti_sci.h | 92 ++++++++++++
include/linux/soc/ti/ti_sci_protocol.h | 8 +
5 files changed, 344 insertions(+)
diff --git a/arch/arm/mach-k3/include/mach/security.h b/arch/arm/mach-k3/include/mach/security.h
index 8502b57bd80a..d9f31e1500a1 100644
--- a/arch/arm/mach-k3/include/mach/security.h
+++ b/arch/arm/mach-k3/include/mach/security.h
@@ -9,3 +9,4 @@
#include <linux/types.h>
void ti_secure_image_post_process(void **p_image, size_t *p_size);
+void ti_secure_image_auth_apply_fwls(void **p_image, size_t *p_size);
diff --git a/arch/arm/mach-k3/security.c b/arch/arm/mach-k3/security.c
index c7017bba99ab..752912c6930a 100644
--- a/arch/arm/mach-k3/security.c
+++ b/arch/arm/mach-k3/security.c
@@ -133,3 +133,67 @@ void ti_secure_image_post_process(void **p_image, size_t *p_size)
spl_boot_device() == BOOT_DEVICE_UART))
printf("Authentication passed\n");
}
+
+void ti_secure_image_auth_apply_fwls(void **p_image, size_t *p_size)
+{
+ struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+ struct ti_sci_proc_ops *proc_ops = &ti_sci->ops.proc_ops;
+ u64 image_addr;
+ u32 image_size, backup_size;
+ int ret;
+
+ image_size = *p_size;
+ backup_size = image_size;
+ if (!image_size) {
+ debug("%s: Image size is %d\n", __func__, image_size);
+ return;
+ }
+
+ if (get_device_type() == K3_DEVICE_TYPE_GP)
+ return;
+
+ if (get_device_type() != K3_DEVICE_TYPE_HS_SE &&
+ !ti_secure_cert_detected(*p_image)) {
+ printf("Warning: Did not detect image signing certificate. "
+ "Skipping authentication to prevent boot failure. "
+ "This will fail on Security Enforcing(HS-SE) devices\n");
+ return;
+ }
+
+ /* Clean out image so it can be seen by system firmware */
+ image_addr = dma_map_single(*p_image, *p_size, DMA_BIDIRECTIONAL);
+
+ debug("Authenticating image at address 0x%016llx\n", image_addr);
+ debug("Authenticating image of size %d bytes\n", image_size);
+
+ /* Authenticate image */
+ ret = proc_ops->proc_auth_apply_fwls(ti_sci, &image_addr, &image_size);
+ if (ret) {
+ printf("Authentication failed..but assume pass!\n");
+ hang();
+ }
+
+ /* Invalidate any stale lines over data written by system firmware */
+ if (backup_size)
+ dma_unmap_single(image_addr, backup_size, DMA_BIDIRECTIONAL);
+
+ /*
+ * The image_size returned may be 0 when the authentication process has
+ * moved the image. When this happens no further processing on the
+ * image is needed or often even possible as it may have also been
+ * placed behind a firewall when moved.
+ */
+ *p_size = backup_size;
+
+ /*
+ * Output notification of successful authentication to re-assure the
+ * user that the secure code is being processed as expected. However
+ * suppress any such log output in case of building for SPL and booting
+ * via YMODEM. This is done to avoid disturbing the YMODEM serial
+ * protocol transactions.
+ */
+ if (!(IS_ENABLED(CONFIG_XPL_BUILD) &&
+ IS_ENABLED(CONFIG_SPL_YMODEM_SUPPORT) &&
+ spl_boot_device() == BOOT_DEVICE_UART))
+ printf("Certificate replay passed\n");
+}
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index c015bd3cc245..a40f2918d75f 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -2014,6 +2014,62 @@ static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle,
return ret;
}
+/**
+ * ti_sci_cmd_proc_auth_apply_fwls() - Command to authenticate certificate and
+ * apply the firewalls present in it.
+ * @handle: Pointer to TI SCI handle
+ * @image_addr: Memory address at which payload image and certificate is
+ * located in memory, this is updated if the image data is
+ * moved during authentication.
+ * @image_size: This is updated with the final size of the image after
+ * authentication.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_proc_auth_apply_fwls(const struct ti_sci_handle *handle,
+ u64 *image_addr, u32 *image_size)
+{
+ struct ti_sci_msg_req_proc_auth_boot_image req;
+ struct ti_sci_msg_resp_proc_auth_boot_image *resp;
+ struct ti_sci_info *info;
+ struct ti_sci_xfer *xfer;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+
+ xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_APPLY_FWLS,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ (u32 *)&req, sizeof(req), sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ printf("%s Error making the tisci command\n", __func__);
+ return ret;
+ }
+ req.cert_addr_low = *image_addr & TISCI_ADDR_LOW_MASK;
+ req.cert_addr_high = (*image_addr & TISCI_ADDR_HIGH_MASK) >>
+ TISCI_ADDR_HIGH_SHIFT;
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret) {
+ printf("%s Error sending the tisci command\n", __func__);
+ return ret;
+ }
+
+ resp = (struct ti_sci_msg_resp_proc_auth_boot_image *)xfer->tx_message.buf;
+
+ *image_addr = (resp->image_addr_low & TISCI_ADDR_LOW_MASK) |
+ (((u64)resp->image_addr_high <<
+ TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
+ *image_size = resp->image_size;
+
+ return ret;
+}
+
/**
* ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the
* image and then set the processor configuration flags.
@@ -2745,6 +2801,125 @@ static int ti_sci_cmd_min_context_restore(const struct ti_sci_handle *handle, u6
return ret;
}
+/**
+ * ti_sci_cmd_decrypt_tfa() - Request for decrypting TFA to specific address.
+ * @handle: pointer to TI SCI handle
+ * @unencrypted_address: Address where the unencrypted TFA will be restored to.
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_decrypt_tfa(const struct ti_sci_handle *handle,
+ u64 unencrypted_address)
+{
+ struct ti_sci_msg_decrypt_tfa_req req;
+ struct ti_sci_msg_decrypt_tfa_resp *resp;
+ struct ti_sci_info *info;
+ struct ti_sci_xfer *xfer;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+
+ xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_LPM_DECRYPT,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ (u32 *)&req, sizeof(req), sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ return ret;
+ }
+
+ req.unencrypted_address = unencrypted_address;
+
+ ret = ti_sci_do_xfer(info, xfer);
+
+ return ret;
+}
+
+/**
+ * ti_sci_cmd_core_resume() - Request for resuming TFA.
+ *
+ * The TIFS will launch the TFA from the entrypoint saved via the ENTER_SLEEP
+ * message.
+ *
+ * @handle: pointer to TI SCI handle
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_core_resume(const struct ti_sci_handle *handle)
+{
+ struct ti_sci_msg_core_resume_req req;
+ struct ti_sci_msg_core_resume_resp *resp;
+ struct ti_sci_info *info;
+ struct ti_sci_xfer *xfer;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+
+ xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_CORE_RESUME,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ (u32 *)&req, sizeof(req), sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ return ret;
+ }
+
+ ret = ti_sci_do_xfer(info, xfer);
+
+ return ret;
+}
+
+/**
+ * ti_sci_cmd_lpm_save_addr() - Message to inform TIFS about the context save address.
+ *
+ * By restoring its context, TIFS will restore its firewall.
+ *
+ * @handle: pointer to TI SCI handle
+ * @ctx_addr: address where the context will be store to and restored from
+ * @size: Size of the context save region
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_lpm_save_addr(const struct ti_sci_handle *handle,
+ u64 context_addr, u32 size)
+{
+ struct tisci_msg_lpm_save_ctx_addr_req req;
+ struct tisci_msg_lpm_save_ctx_addr_resp *resp;
+ struct ti_sci_info *info;
+ struct ti_sci_xfer *xfer;
+ int ret = 0;
+
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ if (!handle)
+ return -EINVAL;
+
+ info = handle_to_ti_sci_info(handle);
+
+ xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_LPM_SAVE_ADDR,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ (u32 *)&req, sizeof(req), sizeof(*resp));
+ if (IS_ERR(xfer)) {
+ ret = PTR_ERR(xfer);
+ return ret;
+ }
+
+ req.ctx_addr = context_addr;
+ req.size = size;
+
+ ret = ti_sci_do_xfer(info, xfer);
+
+ return ret;
+}
+
/*
* ti_sci_setup_ops() - Setup the operations structures
* @info: pointer to TISCI pointer
@@ -2813,6 +2988,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg;
pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl;
pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image;
+ pops->proc_auth_apply_fwls = ti_sci_cmd_proc_auth_apply_fwls;
pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status;
pops->proc_shutdown_no_wait = ti_sci_cmd_proc_shutdown_no_wait;
@@ -2833,6 +3009,9 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
fw_ops->query_dm_cap = ti_sci_cmd_query_dm_cap;
lpm_ops->min_context_restore = ti_sci_cmd_min_context_restore;
+ lpm_ops->decrypt_tfa = ti_sci_cmd_decrypt_tfa;
+ lpm_ops->core_resume = ti_sci_cmd_core_resume;
+ lpm_ops->lpm_save_addr = ti_sci_cmd_lpm_save_addr;
}
/**
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index 68908c6c8c46..8fb519b62dbd 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -57,6 +57,7 @@
#define TISCI_MSG_PROC_AUTH_BOOT_IMAGE 0xc120
#define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400
#define TISCI_MSG_WAIT_PROC_BOOT_STATUS 0xc401
+#define TISCI_MSG_PROC_AUTH_APPLY_FWLS 0xc402
/* Resource Management Requests */
#define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500
@@ -85,6 +86,24 @@
#define TISCI_MSG_FWL_GET 0x9001
#define TISCI_MSG_FWL_CHANGE_OWNER 0x9002
+/* LPM requests */
+#define TISCI_MSG_SYNC_RESUME (0x0302U)
+#define TISCI_MSG_CONTINUE_RESUME (0x0303U)
+#define TISCI_MSG_CORE_RESUME (0x0304U)
+#define TISCI_MSG_ABORT_ENTER_SLEEP (0x0305U)
+#define TISCI_MSG_LPM_WAKE_REASON (0x0306U)
+#define TISCI_MSG_SET_IO_ISOLATION (0x0307U)
+#define TISCI_MSG_MIN_CONTEXT_RESTORE (0x0308U)
+#define TISCI_MSG_LPM_SET_DEVICE_CONSTRAINT (0x0309U)
+#define TISCI_MSG_LPM_SET_LATENCY_CONSTRAINT (0x030AU)
+#define TISCI_MSG_LPM_GET_DEVICE_CONSTRAINT (0x030BU)
+#define TISCI_MSG_LPM_GET_LATENCY_CONSTRAINT (0x030CU)
+#define TISCI_MSG_LPM_GET_NEXT_SYS_MODE (0x030DU)
+#define TISCI_MSG_LPM_GET_NEXT_HOST_STATE (0x030EU)
+#define TISCI_MSG_LPM_ENCRYPT (0x030FU)
+#define TISCI_MSG_LPM_DECRYPT (0x0310U)
+#define TISCI_MSG_LPM_SAVE_ADDR (0x0313U)
+
/**
* struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
* @type: Type of messages: One of TI_SCI_MSG* values
@@ -1588,4 +1607,77 @@ struct ti_sci_msg_min_restore_context_req {
u32 ctx_hi;
} __packed;
+/*
+ * struct ti_sci_msg_core_resume_req - Request for TISCI_MSG_CORE_RESUME.
+ *
+ * @hdr: Generic Header
+ *
+ * This message is to be sent to start the TFA on the main core.
+ * The TIFS will launch the TFA from the entrypoint saved via the ENTER_SLEEP
+ * message.
+ */
+struct ti_sci_msg_core_resume_req {
+ struct ti_sci_msg_hdr hdr;
+} __packed;
+
+/**
+ * struct ti_sci_msg_core_resume_resp - Response for TISCI_MSG_CORE_RESUME.
+ *
+ * @hdr: Generic Header
+ */
+struct ti_sci_msg_core_resume_resp {
+ struct ti_sci_msg_hdr hdr;
+} __packed;
+
+/**
+ * struct ti_sci_msg_decrypt_tfa_req - Request for TISCI_MSG_LPM_DECRYPT.
+ *
+ * @hdr: Generic Header
+ * @unencrypted_address: Address where the TFA should be decrypted
+ * @encrypted_address: Address where the TFA lies encrypted
+ *
+ * This message is to be sent when the system is resuming from suspend, in order
+ * to restore the TFA.
+ * The TIFS will decrypt the TFA at specified location and restore it in SRAM.
+ */
+struct ti_sci_msg_decrypt_tfa_req {
+ struct ti_sci_msg_hdr hdr;
+ u64 unencrypted_address;
+} __packed;
+
+/**
+ * struct ti_sci_msg_decrypt_tfa_resp - Response for TISCI_MSG_LPM_DECRYPT.
+ *
+ * @hdr: Generic Header
+ */
+struct ti_sci_msg_decrypt_tfa_resp {
+ struct ti_sci_msg_hdr hdr;
+} __packed;
+
+/**
+ * struct tisci_msg_lpm_save_ctx_addr_req - Request for TISCI_MSG_LPM_SAVE_ADDR.
+ *
+ * @hdr: Generic Header
+ * @ctx_addr: Address where the LPM data is to be saved
+ * @size: Size of the context save memory region
+ *
+ * This message is sent to TIFS to inform it about the addresse where it
+ * will save the context to in case of system suspend and where to get the
+ * context back from when resuming the system
+ */
+struct tisci_msg_lpm_save_ctx_addr_req {
+ struct ti_sci_msg_hdr hdr;
+ u64 ctx_addr;
+ u32 size;
+} __packed;
+
+/**
+ * struct tisci_msg_lpm_save_ctx_addr_resp - Response for TISCI_MSG_SAVE_ADDR.
+ *
+ * @hdr: Generic Header
+ */
+struct tisci_msg_lpm_save_ctx_addr_resp {
+ struct ti_sci_msg_hdr hdr;
+} __packed;
+
#endif /* __TI_SCI_H */
diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
index 6b1dd801f5f8..1d0a6340e1ee 100644
--- a/include/linux/soc/ti/ti_sci_protocol.h
+++ b/include/linux/soc/ti/ti_sci_protocol.h
@@ -336,6 +336,8 @@ struct ti_sci_proc_ops {
u32 *sts_flags);
int (*proc_shutdown_no_wait)(const struct ti_sci_handle *handle,
u8 pid);
+ int (*proc_auth_apply_fwls)(const struct ti_sci_handle *handle,
+ u64 *image_addr, u32 *image_size);
};
#define TI_SCI_RING_MODE_RING (0)
@@ -635,9 +637,15 @@ struct ti_sci_fwl_ops {
/**
* struct ti_sci_lpm_ops - Low Power Mode operations
* @min_context_restore: Request restoring context from DDR.
+ * @decrypt_tfa: Request for decrypting TFA at specific address.
+ * @core_resume: Request for resuming TFA once decrypted.
+ * @lpm_save_addr: Send DDR Save address to TIFS
*/
struct ti_sci_lpm_ops {
int (*min_context_restore)(const struct ti_sci_handle *handle, u64 ctx_addr);
+ int (*decrypt_tfa)(const struct ti_sci_handle *handle, u64 unencrypted_address);
+ int (*core_resume)(const struct ti_sci_handle *handle);
+ int (*lpm_save_addr)(const struct ti_sci_handle *handle, u64 context_addr, u32 size);
};
/**
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 10/20] firmware: ti_sci: add low power mode operations
2026-04-30 8:44 ` [PATCH 10/20] firmware: ti_sci: add low power mode operations Richard Genoud (TI)
@ 2026-05-11 10:50 ` Kumar, Udit
0 siblings, 0 replies; 32+ messages in thread
From: Kumar, Udit @ 2026-05-11 10:50 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Apurva Nandan,
Andrew F . Davis, Vignesh Raghavendra, Bryan Brattlof,
Vaishnav Achath, Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Abhash Kumar, Thomas Richard,
Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/2026 2:14 PM, Richard Genoud (TI) wrote:
> From: Prasanth Babu Mantena <p-mantena@ti.com>
>
> From: Prasanth Babu Mantena <p-mantena@ti.com>
Drop duplication above
>
> On TI-k3 platform, at resume, uboot SPL needs to do several tasks:
> - restore TIFS minimal context from DDR
> - send DDR save address to TIFS
> - load TFA and its context in MSMC
> - set TFA resume vector to its warm_entrypoint
> - authenticate certificates and apply firewalls
>
> All those operations are now done by TIFS with those messages:
> ti_sci_cmd_min_context_restore
> ti_sci_cmd_decrypt_tfa
> ti_sci_cmd_core_resume
> ti_sci_cmd_lpm_save_addr
> ti_sci_cmd_proc_auth_apply_fwls
>
> https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html
> https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/security/PROC_BOOT.html
>
> Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
> Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
> Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
> ---
> arch/arm/mach-k3/include/mach/security.h | 1 +
> arch/arm/mach-k3/security.c | 64 ++++++++
> drivers/firmware/ti_sci.c | 179 +++++++++++++++++++++++
> drivers/firmware/ti_sci.h | 92 ++++++++++++
> include/linux/soc/ti/ti_sci_protocol.h | 8 +
> 5 files changed, 344 insertions(+)
>
> diff --git a/arch/arm/mach-k3/include/mach/security.h b/arch/arm/mach-k3/include/mach/security.h
> index 8502b57bd80a..d9f31e1500a1 100644
> --- a/arch/arm/mach-k3/include/mach/security.h
> +++ b/arch/arm/mach-k3/include/mach/security.h
> @@ -9,3 +9,4 @@
> #include <linux/types.h>
>
> void ti_secure_image_post_process(void **p_image, size_t *p_size);
> +void ti_secure_image_auth_apply_fwls(void **p_image, size_t *p_size);
> diff --git a/arch/arm/mach-k3/security.c b/arch/arm/mach-k3/security.c
> index c7017bba99ab..752912c6930a 100644
> --- a/arch/arm/mach-k3/security.c
> +++ b/arch/arm/mach-k3/security.c
> @@ -133,3 +133,67 @@ void ti_secure_image_post_process(void **p_image, size_t *p_size)
> spl_boot_device() == BOOT_DEVICE_UART))
> printf("Authentication passed\n");
> }
> +
> +void ti_secure_image_auth_apply_fwls(void **p_image, size_t *p_size)
> +{
> + struct ti_sci_handle *ti_sci = get_ti_sci_handle();
> + struct ti_sci_proc_ops *proc_ops = &ti_sci->ops.proc_ops;
> + u64 image_addr;
> + u32 image_size, backup_size;
> + int ret;
> +
> + image_size = *p_size;
> + backup_size = image_size;
> + if (!image_size) {
> + debug("%s: Image size is %d\n", __func__, image_size);
> + return;
> + }
> +
> + if (get_device_type() == K3_DEVICE_TYPE_GP)
> + return;
> +
> + if (get_device_type() != K3_DEVICE_TYPE_HS_SE &&
> + !ti_secure_cert_detected(*p_image)) {
> + printf("Warning: Did not detect image signing certificate. "
> + "Skipping authentication to prevent boot failure. "
> + "This will fail on Security Enforcing(HS-SE) devices\n");
> + return;
> + }
> +
> + /* Clean out image so it can be seen by system firmware */
> + image_addr = dma_map_single(*p_image, *p_size, DMA_BIDIRECTIONAL);
> +
> + debug("Authenticating image at address 0x%016llx\n", image_addr);
> + debug("Authenticating image of size %d bytes\n", image_size);
> +
> + /* Authenticate image */
> + ret = proc_ops->proc_auth_apply_fwls(ti_sci, &image_addr, &image_size);
> + if (ret) {
> + printf("Authentication failed..but assume pass!\n");
> + hang();
> + }
> +
> + /* Invalidate any stale lines over data written by system firmware */
> + if (backup_size)
> + dma_unmap_single(image_addr, backup_size, DMA_BIDIRECTIONAL);
> +
> + /*
> + * The image_size returned may be 0 when the authentication process has
> + * moved the image. When this happens no further processing on the
> + * image is needed or often even possible as it may have also been
> + * placed behind a firewall when moved.
> + */
> + *p_size = backup_size;
> +
> + /*
> + * Output notification of successful authentication to re-assure the
> + * user that the secure code is being processed as expected. However
> + * suppress any such log output in case of building for SPL and booting
> + * via YMODEM. This is done to avoid disturbing the YMODEM serial
> + * protocol transactions.
> + */
> + if (!(IS_ENABLED(CONFIG_XPL_BUILD) &&
> + IS_ENABLED(CONFIG_SPL_YMODEM_SUPPORT) &&
> + spl_boot_device() == BOOT_DEVICE_UART))
> + printf("Certificate replay passed\n");
> +}
> diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
> index c015bd3cc245..a40f2918d75f 100644
> --- a/drivers/firmware/ti_sci.c
> +++ b/drivers/firmware/ti_sci.c
> @@ -2014,6 +2014,62 @@ static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle,
> return ret;
> }
>
> +/**
> + * ti_sci_cmd_proc_auth_apply_fwls() - Command to authenticate certificate and
> + * apply the firewalls present in it.
> + * @handle: Pointer to TI SCI handle
> + * @image_addr: Memory address at which payload image and certificate is
> + * located in memory, this is updated if the image data is
> + * moved during authentication.
> + * @image_size: This is updated with the final size of the image after
> + * authentication.
> + *
> + * Return: 0 if all went well, else returns appropriate error value.
> + */
> +static int ti_sci_cmd_proc_auth_apply_fwls(const struct ti_sci_handle *handle,
> + u64 *image_addr, u32 *image_size)
> +{
> + struct ti_sci_msg_req_proc_auth_boot_image req;
> + struct ti_sci_msg_resp_proc_auth_boot_image *resp;
> + struct ti_sci_info *info;
> + struct ti_sci_xfer *xfer;
> + int ret = 0;
> +
> + if (IS_ERR(handle))
> + return PTR_ERR(handle);
> + if (!handle)
> + return -EINVAL;
> +
> + info = handle_to_ti_sci_info(handle);
> +
> + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_APPLY_FWLS,
> + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
> + (u32 *)&req, sizeof(req), sizeof(*resp));
> + if (IS_ERR(xfer)) {
> + ret = PTR_ERR(xfer);
> + printf("%s Error making the tisci command\n", __func__);
> + return ret;
> + }
> + req.cert_addr_low = *image_addr & TISCI_ADDR_LOW_MASK;
> + req.cert_addr_high = (*image_addr & TISCI_ADDR_HIGH_MASK) >>
> + TISCI_ADDR_HIGH_SHIFT;
> +
> + ret = ti_sci_do_xfer(info, xfer);
> + if (ret) {
> + printf("%s Error sending the tisci command\n", __func__);
> + return ret;
> + }
> +
> + resp = (struct ti_sci_msg_resp_proc_auth_boot_image *)xfer->tx_message.buf;
> +
> + *image_addr = (resp->image_addr_low & TISCI_ADDR_LOW_MASK) |
> + (((u64)resp->image_addr_high <<
> + TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
> + *image_size = resp->image_size;
> +
> + return ret;
> +}
> +
> /**
> * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the
> * image and then set the processor configuration flags.
> @@ -2745,6 +2801,125 @@ static int ti_sci_cmd_min_context_restore(const struct ti_sci_handle *handle, u6
> return ret;
> }
>
> +/**
> + * ti_sci_cmd_decrypt_tfa() - Request for decrypting TFA to specific address.
> + * @handle: pointer to TI SCI handle
> + * @unencrypted_address: Address where the unencrypted TFA will be restored to.
> + *
> + * Return: 0 if all went well, else returns appropriate error value.
> + */
> +static int ti_sci_cmd_decrypt_tfa(const struct ti_sci_handle *handle,
> + u64 unencrypted_address)
> +{
> + struct ti_sci_msg_decrypt_tfa_req req;
> + struct ti_sci_msg_decrypt_tfa_resp *resp;
> + struct ti_sci_info *info;
> + struct ti_sci_xfer *xfer;
> + int ret = 0;
> +
> + if (IS_ERR(handle))
> + return PTR_ERR(handle);
> + if (!handle)
> + return -EINVAL;
> +
> + info = handle_to_ti_sci_info(handle);
> +
> + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_LPM_DECRYPT,
> + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
> + (u32 *)&req, sizeof(req), sizeof(*resp));
> + if (IS_ERR(xfer)) {
> + ret = PTR_ERR(xfer);
> + return ret;
> + }
> +
> + req.unencrypted_address = unencrypted_address;
> +
> + ret = ti_sci_do_xfer(info, xfer);
> +
> + return ret;
> +}
> +
> +/**
> + * ti_sci_cmd_core_resume() - Request for resuming TFA.
> + *
> + * The TIFS will launch the TFA from the entrypoint saved via the ENTER_SLEEP
> + * message.
> + *
> + * @handle: pointer to TI SCI handle
> + *
> + * Return: 0 if all went well, else returns appropriate error value.
> + */
> +static int ti_sci_cmd_core_resume(const struct ti_sci_handle *handle)
> +{
> + struct ti_sci_msg_core_resume_req req;
> + struct ti_sci_msg_core_resume_resp *resp;
> + struct ti_sci_info *info;
> + struct ti_sci_xfer *xfer;
> + int ret = 0;
> +
> + if (IS_ERR(handle))
> + return PTR_ERR(handle);
> + if (!handle)
> + return -EINVAL;
> +
> + info = handle_to_ti_sci_info(handle);
> +
> + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_CORE_RESUME,
> + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
> + (u32 *)&req, sizeof(req), sizeof(*resp));
> + if (IS_ERR(xfer)) {
> + ret = PTR_ERR(xfer);
> + return ret;
> + }
> +
> + ret = ti_sci_do_xfer(info, xfer);
> +
> + return ret;
> +}
> +
> +/**
> + * ti_sci_cmd_lpm_save_addr() - Message to inform TIFS about the context save address.
> + *
> + * By restoring its context, TIFS will restore its firewall.
> + *
> + * @handle: pointer to TI SCI handle
> + * @ctx_addr: address where the context will be store to and restored from
> + * @size: Size of the context save region
> + *
> + * Return: 0 if all went well, else returns appropriate error value.
> + */
> +static int ti_sci_cmd_lpm_save_addr(const struct ti_sci_handle *handle,
> + u64 context_addr, u32 size)
> +{
> + struct tisci_msg_lpm_save_ctx_addr_req req;
> + struct tisci_msg_lpm_save_ctx_addr_resp *resp;
> + struct ti_sci_info *info;
> + struct ti_sci_xfer *xfer;
> + int ret = 0;
> +
> + if (IS_ERR(handle))
> + return PTR_ERR(handle);
> + if (!handle)
> + return -EINVAL;
> +
> + info = handle_to_ti_sci_info(handle);
> +
> + xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_LPM_SAVE_ADDR,
> + TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
> + (u32 *)&req, sizeof(req), sizeof(*resp));
> + if (IS_ERR(xfer)) {
> + ret = PTR_ERR(xfer);
> + return ret;
> + }
> +
> + req.ctx_addr = context_addr;
> + req.size = size;
> +
> + ret = ti_sci_do_xfer(info, xfer);
> +
> + return ret;
> +}
> +
> /*
> * ti_sci_setup_ops() - Setup the operations structures
> * @info: pointer to TISCI pointer
> @@ -2813,6 +2988,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
> pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg;
> pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl;
> pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image;
> + pops->proc_auth_apply_fwls = ti_sci_cmd_proc_auth_apply_fwls;
> pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status;
> pops->proc_shutdown_no_wait = ti_sci_cmd_proc_shutdown_no_wait;
>
> @@ -2833,6 +3009,9 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
> fw_ops->query_dm_cap = ti_sci_cmd_query_dm_cap;
>
> lpm_ops->min_context_restore = ti_sci_cmd_min_context_restore;
> + lpm_ops->decrypt_tfa = ti_sci_cmd_decrypt_tfa;
> + lpm_ops->core_resume = ti_sci_cmd_core_resume;
> + lpm_ops->lpm_save_addr = ti_sci_cmd_lpm_save_addr;
> }
>
> /**
> diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
> index 68908c6c8c46..8fb519b62dbd 100644
> --- a/drivers/firmware/ti_sci.h
> +++ b/drivers/firmware/ti_sci.h
> @@ -57,6 +57,7 @@
> #define TISCI_MSG_PROC_AUTH_BOOT_IMAGE 0xc120
> #define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400
> #define TISCI_MSG_WAIT_PROC_BOOT_STATUS 0xc401
> +#define TISCI_MSG_PROC_AUTH_APPLY_FWLS 0xc402
>
> /* Resource Management Requests */
> #define TI_SCI_MSG_GET_RESOURCE_RANGE 0x1500
> @@ -85,6 +86,24 @@
> #define TISCI_MSG_FWL_GET 0x9001
> #define TISCI_MSG_FWL_CHANGE_OWNER 0x9002
>
> +/* LPM requests */
> +#define TISCI_MSG_SYNC_RESUME (0x0302U)
> +#define TISCI_MSG_CONTINUE_RESUME (0x0303U)
> +#define TISCI_MSG_CORE_RESUME (0x0304U)
> +#define TISCI_MSG_ABORT_ENTER_SLEEP (0x0305U)
> +#define TISCI_MSG_LPM_WAKE_REASON (0x0306U)
> +#define TISCI_MSG_SET_IO_ISOLATION (0x0307U)
> +#define TISCI_MSG_MIN_CONTEXT_RESTORE (0x0308U)
> +#define TISCI_MSG_LPM_SET_DEVICE_CONSTRAINT (0x0309U)
> +#define TISCI_MSG_LPM_SET_LATENCY_CONSTRAINT (0x030AU)
> +#define TISCI_MSG_LPM_GET_DEVICE_CONSTRAINT (0x030BU)
> +#define TISCI_MSG_LPM_GET_LATENCY_CONSTRAINT (0x030CU)
> +#define TISCI_MSG_LPM_GET_NEXT_SYS_MODE (0x030DU)
> +#define TISCI_MSG_LPM_GET_NEXT_HOST_STATE (0x030EU)
> +#define TISCI_MSG_LPM_ENCRYPT (0x030FU)
> +#define TISCI_MSG_LPM_DECRYPT (0x0310U)
> +#define TISCI_MSG_LPM_SAVE_ADDR (0x0313U)
> +
> /**
> * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses
> * @type: Type of messages: One of TI_SCI_MSG* values
> @@ -1588,4 +1607,77 @@ struct ti_sci_msg_min_restore_context_req {
> u32 ctx_hi;
> } __packed;
>
> +/*
> + * struct ti_sci_msg_core_resume_req - Request for TISCI_MSG_CORE_RESUME.
> + *
> + * @hdr: Generic Header
> + *
> + * This message is to be sent to start the TFA on the main core.
> + * The TIFS will launch the TFA from the entrypoint saved via the ENTER_SLEEP
> + * message.
> + */
> +struct ti_sci_msg_core_resume_req {
> + struct ti_sci_msg_hdr hdr;
> +} __packed;
> +
> +/**
> + * struct ti_sci_msg_core_resume_resp - Response for TISCI_MSG_CORE_RESUME.
> + *
> + * @hdr: Generic Header
> + */
> +struct ti_sci_msg_core_resume_resp {
> + struct ti_sci_msg_hdr hdr;
> +} __packed;
> +
> +/**
> + * struct ti_sci_msg_decrypt_tfa_req - Request for TISCI_MSG_LPM_DECRYPT.
> + *
> + * @hdr: Generic Header
> + * @unencrypted_address: Address where the TFA should be decrypted
> + * @encrypted_address: Address where the TFA lies encrypted
> + *
> + * This message is to be sent when the system is resuming from suspend, in order
> + * to restore the TFA.
> + * The TIFS will decrypt the TFA at specified location and restore it in SRAM.
> + */
> +struct ti_sci_msg_decrypt_tfa_req {
> + struct ti_sci_msg_hdr hdr;
> + u64 unencrypted_address;
> +} __packed;
> +
> +/**
> + * struct ti_sci_msg_decrypt_tfa_resp - Response for TISCI_MSG_LPM_DECRYPT.
> + *
> + * @hdr: Generic Header
> + */
> +struct ti_sci_msg_decrypt_tfa_resp {
> + struct ti_sci_msg_hdr hdr;
> +} __packed;
> +
> +/**
> + * struct tisci_msg_lpm_save_ctx_addr_req - Request for TISCI_MSG_LPM_SAVE_ADDR.
> + *
> + * @hdr: Generic Header
> + * @ctx_addr: Address where the LPM data is to be saved
> + * @size: Size of the context save memory region
> + *
> + * This message is sent to TIFS to inform it about the addresse where it
> + * will save the context to in case of system suspend and where to get the
> + * context back from when resuming the system
> + */
> +struct tisci_msg_lpm_save_ctx_addr_req {
> + struct ti_sci_msg_hdr hdr;
> + u64 ctx_addr;
> + u32 size;
> +} __packed;
> +
> +/**
> + * struct tisci_msg_lpm_save_ctx_addr_resp - Response for TISCI_MSG_SAVE_ADDR.
> + *
> + * @hdr: Generic Header
> + */
> +struct tisci_msg_lpm_save_ctx_addr_resp {
> + struct ti_sci_msg_hdr hdr;
> +} __packed;
> +
> #endif /* __TI_SCI_H */
> diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
> index 6b1dd801f5f8..1d0a6340e1ee 100644
> --- a/include/linux/soc/ti/ti_sci_protocol.h
> +++ b/include/linux/soc/ti/ti_sci_protocol.h
> @@ -336,6 +336,8 @@ struct ti_sci_proc_ops {
> u32 *sts_flags);
> int (*proc_shutdown_no_wait)(const struct ti_sci_handle *handle,
> u8 pid);
> + int (*proc_auth_apply_fwls)(const struct ti_sci_handle *handle,
> + u64 *image_addr, u32 *image_size);
> };
>
> #define TI_SCI_RING_MODE_RING (0)
> @@ -635,9 +637,15 @@ struct ti_sci_fwl_ops {
> /**
> * struct ti_sci_lpm_ops - Low Power Mode operations
> * @min_context_restore: Request restoring context from DDR.
> + * @decrypt_tfa: Request for decrypting TFA at specific address.
> + * @core_resume: Request for resuming TFA once decrypted.
> + * @lpm_save_addr: Send DDR Save address to TIFS
> */
> struct ti_sci_lpm_ops {
> int (*min_context_restore)(const struct ti_sci_handle *handle, u64 ctx_addr);
> + int (*decrypt_tfa)(const struct ti_sci_handle *handle, u64 unencrypted_address);
> + int (*core_resume)(const struct ti_sci_handle *handle);
> + int (*lpm_save_addr)(const struct ti_sci_handle *handle, u64 context_addr, u32 size);
> };
>
> /**
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 11/20] mach-k3: r5: common: add helper functions needed in LPM resume sequence
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (9 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 10/20] firmware: ti_sci: add low power mode operations Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-05-11 10:52 ` Kumar, Udit
2026-04-30 8:44 ` [PATCH 12/20] arm: mach-k3: j721e: Enable LPM resume flow for J7200/J721e SOC Richard Genoud (TI)
` (8 subsequent siblings)
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: Prasanth Babu Mantena <p-mantena@ti.com>
Add helper functions that are used by respective SoCs in LPM resume flow.
- lpm_process() is called at boot time to:
- retrieve the LPM memory region from DTS
- save ATF/OPTEE certificates information and DM code in this memory
region
- Forward the LPM address to TIFS via TISCI_MSG_LPM_SAVE_ADDR
TIFS will use this address to save TFA context and its own minimal
context just before suspend.
- do_resume() is called at resume, just after bringing the DDR out of
retention to:
- retrieve the LPM memory region from DTS
- authenticate certificates from LPM memory region and apply firewalls
- ask TIFS to restore TFA and its own minimal context
- start TFA on remote proc
- load and jump to DM
https://software-dl.ti.com/tisci/esd/latest/2_tisci_msgs/pm/lpm.html#lpm-msg-lpm-save-addr
Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/common.h | 16 +++
arch/arm/mach-k3/lpm-common.h | 15 ++
arch/arm/mach-k3/r5/Kconfig | 4 +
arch/arm/mach-k3/r5/Makefile | 1 +
arch/arm/mach-k3/r5/common.c | 17 +--
arch/arm/mach-k3/r5/lpm-common.c | 228 +++++++++++++++++++++++++++++++
6 files changed, 269 insertions(+), 12 deletions(-)
create mode 100644 arch/arm/mach-k3/lpm-common.h
create mode 100644 arch/arm/mach-k3/r5/lpm-common.c
diff --git a/arch/arm/mach-k3/common.h b/arch/arm/mach-k3/common.h
index e970076d08ec..50e670f845e3 100644
--- a/arch/arm/mach-k3/common.h
+++ b/arch/arm/mach-k3/common.h
@@ -8,6 +8,7 @@
#include <asm/armv7_mpu.h>
#include <asm/hardware.h>
+#include <image.h>
#include <mach/security.h>
/* keep ram_top in the 32-bit address space */
@@ -16,6 +17,21 @@
#define K3_FIREWALL_BACKGROUND_BIT (8)
#define K3_SPEED_GRADE_UNKNOWN '\0'
+#if IS_ENABLED(CONFIG_SYS_K3_SPL_ATF)
+enum {
+ IMAGE_ID_ATF,
+ IMAGE_ID_OPTEE,
+ IMAGE_ID_SPL,
+ IMAGE_ID_DM_FW,
+ IMAGE_ID_TIFSSTUB_HS,
+ IMAGE_ID_TIFSSTUB_FS,
+ IMAGE_ID_TIFSSTUB_GP,
+ IMAGE_AMT,
+};
+
+extern struct image_info fit_image_info[IMAGE_AMT];
+#endif
+
struct fwl_data {
const char *name;
u16 fwl_id;
diff --git a/arch/arm/mach-k3/lpm-common.h b/arch/arm/mach-k3/lpm-common.h
new file mode 100644
index 000000000000..2b360e6f03f3
--- /dev/null
+++ b/arch/arm/mach-k3/lpm-common.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * K3: LPM Architecture common definitions
+ *
+ * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2026 Bootlin
+ */
+
+#ifndef _LPM_COMMON_H_
+#define _LPM_COMMON_H_
+
+void __noreturn do_resume(void);
+void lpm_process(void);
+
+#endif
diff --git a/arch/arm/mach-k3/r5/Kconfig b/arch/arm/mach-k3/r5/Kconfig
index 12335880e106..7a9c005a6d7c 100644
--- a/arch/arm/mach-k3/r5/Kconfig
+++ b/arch/arm/mach-k3/r5/Kconfig
@@ -1,6 +1,10 @@
config K3_LOAD_SYSFW
bool
+config K3_LPM
+ bool
+ default y if SOC_K3_J721E || SOC_K3_J7200 || SOC_K3_J784S4 || SOC_K3_J722S || SOC_K3_J721S2
+
config K3_OPP_LOW
depends on ARCH_K3 && K3_AVS0
bool "Enable OPP_LOW on supported TI K3 SoCs"
diff --git a/arch/arm/mach-k3/r5/Makefile b/arch/arm/mach-k3/r5/Makefile
index 074e3b61a262..ccededbc0d60 100644
--- a/arch/arm/mach-k3/r5/Makefile
+++ b/arch/arm/mach-k3/r5/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SOC_K3_J722S) += j722s/
obj-$(CONFIG_SOC_K3_J784S4) += j784s4/
obj-y += common.o
+obj-$(CONFIG_K3_LPM) += lpm-common.o
obj-y += lowlevel_init.o
obj-y += r5_mpu.o
diff --git a/arch/arm/mach-k3/r5/common.c b/arch/arm/mach-k3/r5/common.c
index 03638366046b..a80e903de85a 100644
--- a/arch/arm/mach-k3/r5/common.c
+++ b/arch/arm/mach-k3/r5/common.c
@@ -18,19 +18,9 @@
#include <elf.h>
#include "../common.h"
+#include "../lpm-common.h"
#if IS_ENABLED(CONFIG_SYS_K3_SPL_ATF)
-enum {
- IMAGE_ID_ATF,
- IMAGE_ID_OPTEE,
- IMAGE_ID_SPL,
- IMAGE_ID_DM_FW,
- IMAGE_ID_TIFSSTUB_HS,
- IMAGE_ID_TIFSSTUB_FS,
- IMAGE_ID_TIFSSTUB_GP,
- IMAGE_AMT,
-};
-
#if CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS)
static const char *image_os_match[IMAGE_AMT] = {
"arm-trusted-firmware",
@@ -43,7 +33,7 @@ static const char *image_os_match[IMAGE_AMT] = {
};
#endif
-static struct image_info fit_image_info[IMAGE_AMT];
+struct image_info fit_image_info[IMAGE_AMT];
void init_env(void)
{
@@ -170,6 +160,9 @@ void __noreturn jump_to_image(struct spl_image_info *spl_image)
if (ret)
panic("%s: ATF failed to load on rproc (%d)\n", __func__, ret);
+ if (IS_ENABLED(CONFIG_K3_LPM))
+ lpm_process();
+
#if CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS)
/* Authenticate ATF */
void *image_addr = (void *)fit_image_info[IMAGE_ID_ATF].image_start;
diff --git a/arch/arm/mach-k3/r5/lpm-common.c b/arch/arm/mach-k3/r5/lpm-common.c
new file mode 100644
index 000000000000..c39d85a43fd2
--- /dev/null
+++ b/arch/arm/mach-k3/r5/lpm-common.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * K3: R5 Common LPM Architecture initialization
+ *
+ * Copyright (C) 2023-2026 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2026 Bootlin
+ */
+
+#include <clk.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 <remoteproc.h>
+#include <mach/security.h>
+
+#include "../common.h"
+#include "../lpm-common.h"
+
+#define FW_IMAGE_SIZE 0x80000
+
+struct lpm_addr_info {
+ u32 *context_save_addr;
+ u32 *atf_cert_addr;
+ u32 *optee_cert_addr;
+ u32 *dm_save_addr;
+ u32 size;
+};
+
+struct lpm_addr_info mem_addr_lpm;
+
+__weak bool j7xx_board_is_resuming(void)
+{
+ return false;
+}
+
+static int extract_lpm_region(void)
+{
+ ofnode node;
+ fdt_addr_t lpm_reg_addr;
+ fdt_size_t lpm_reg_size;
+
+ node = ofnode_path("/reserved-memory/lpm-memory");
+ if (!ofnode_valid(node)) {
+ printf("lpm will not be functional\n");
+ return -ENODEV;
+ }
+
+ lpm_reg_addr = ofnode_get_addr(node);
+ if (lpm_reg_addr == FDT_ADDR_T_NONE) {
+ printf("Can't find a valid reserved node!\n");
+ return -ENODEV;
+ }
+
+ lpm_reg_size = ofnode_get_size(node);
+ if (lpm_reg_size == FDT_ADDR_T_NONE) {
+ printf("Can't find a valid reserved node!\n");
+ return -ENODEV;
+ }
+
+ mem_addr_lpm.context_save_addr = (u32 *)lpm_reg_addr;
+ mem_addr_lpm.atf_cert_addr = mem_addr_lpm.context_save_addr + FW_IMAGE_SIZE;
+ mem_addr_lpm.optee_cert_addr = mem_addr_lpm.atf_cert_addr + FW_IMAGE_SIZE;
+ mem_addr_lpm.dm_save_addr = mem_addr_lpm.optee_cert_addr + (2 * FW_IMAGE_SIZE);
+ mem_addr_lpm.size = lpm_reg_size;
+
+ return 0;
+}
+
+static int save_certificate(void)
+{
+ int ret;
+
+ if (!fit_image_info[IMAGE_ID_ATF].image_start ||
+ !fit_image_info[IMAGE_ID_OPTEE].image_start ||
+ !fit_image_info[IMAGE_ID_DM_FW].image_start) {
+ pr_err("Invalid images to save\n");
+ return -EINVAL;
+ }
+
+ ret = extract_lpm_region();
+ if (ret) {
+ pr_err("Cannot find valid LPM address range..\n");
+ return -ENOMEM;
+ }
+
+ memcpy(mem_addr_lpm.atf_cert_addr,
+ (void *)fit_image_info[IMAGE_ID_ATF].image_start,
+ fit_image_info[IMAGE_ID_ATF].image_len);
+
+ memcpy(mem_addr_lpm.optee_cert_addr,
+ (void *)fit_image_info[IMAGE_ID_OPTEE].image_start,
+ fit_image_info[IMAGE_ID_OPTEE].image_len);
+
+ memcpy(mem_addr_lpm.dm_save_addr,
+ (void *)fit_image_info[IMAGE_ID_DM_FW].image_start,
+ fit_image_info[IMAGE_ID_DM_FW].image_len);
+
+ return 0;
+}
+
+void lpm_process(void)
+{
+ int ret = 0;
+ unsigned long save_addr;
+ struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+
+ ret = save_certificate();
+ if (ret)
+ return;
+ save_addr = (unsigned long)mem_addr_lpm.context_save_addr;
+ ret = ti_sci->ops.lpm_ops.lpm_save_addr(ti_sci, save_addr,
+ mem_addr_lpm.size);
+ if (ret)
+ pr_err("TIFS lpm save addr fail\n");
+}
+
+static u32 resume_to_dm_f(void)
+{
+ struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+ u32 loadaddr = 0, save_addr = 0;
+ int ret = 0;
+
+ loadaddr = (u32)mem_addr_lpm.dm_save_addr;
+ if (!valid_elf_image(loadaddr))
+ panic("%s: DM-Firmware image is not valid, it cannot be loaded\n",
+ __func__);
+
+ loadaddr = load_elf_image_phdr(loadaddr);
+ save_addr = (uintptr_t)mem_addr_lpm.context_save_addr;
+ ret = ti_sci->ops.lpm_ops.lpm_save_addr(ti_sci, save_addr, mem_addr_lpm.size);
+ if (ret)
+ panic("TIFS lpm save addr fail : %x\n", ret);
+
+ /*
+ * TIFS minimal context restore
+ * This restores also the firewall
+ */
+ ret = ti_sci->ops.lpm_ops.min_context_restore(ti_sci, 0);
+ if (ret)
+ panic("TIFS restore_context failed (%d)\n", ret);
+
+ /*
+ * Restore TFA in msmc memory
+ */
+ ret = ti_sci->ops.lpm_ops.decrypt_tfa(ti_sci,
+ CONFIG_K3_ATF_LOAD_ADDR);
+ if (ret)
+ panic("%s: TIFS failed to decrytp TFA : %x\n", __func__, ret);
+
+ /* restore TFA resume vectore address in main core */
+ ret = ti_sci->ops.lpm_ops.core_resume(ti_sci);
+ if (ret)
+ panic("ATF failed to resume (%d)\n", ret);
+
+ return loadaddr;
+}
+
+static void resume_rproc_f(void)
+{
+ struct power_domain rproc_pwrdmn;
+ unsigned long gtc_rate;
+ struct udevice *dev;
+ struct clk gtc_clk;
+ void *gtc_base;
+ int ret;
+
+ ret = uclass_get_device_by_seq(UCLASS_REMOTEPROC, 1, &dev);
+ if (ret)
+ panic("Unknown remote processor 1 (%d)\n", ret);
+
+ ret = power_domain_get_by_index(dev, &rproc_pwrdmn, 1);
+ if (ret)
+ panic("power_domain_get_rproc() failed: %d\n", ret);
+
+ ret = clk_get_by_index(dev, 0, >c_clk);
+ if (ret)
+ panic("clk_get failed: %d\n", ret);
+
+ gtc_base = dev_read_addr_ptr(dev);
+ if (!gtc_base)
+ panic("Get GTC address failed\n");
+
+ gtc_rate = clk_get_rate(>c_clk);
+
+#define GTC_CNTCR_REG 0x0
+#define GTC_CNTFID0_REG 0x20
+#define GTC_CNTR_EN 0x3
+ /* TFA expect the Global Timebase Counter to be set-up */
+ writel((u32)gtc_rate, gtc_base + GTC_CNTFID0_REG);
+ writel(GTC_CNTR_EN, gtc_base + GTC_CNTCR_REG);
+
+ ret = power_domain_on(&rproc_pwrdmn);
+ if (ret)
+ panic("power_domain_on failed: %d\n", ret);
+}
+
+typedef void __noreturn (*image_entry_noargs_t)(void);
+
+void __noreturn do_resume(void)
+{
+ image_entry_noargs_t image_entry;
+ u32 loadaddr, size_int = FW_IMAGE_SIZE;
+ void *image_addr;
+ int ret;
+
+ ret = extract_lpm_region();
+ if (ret)
+ panic("Cannot find valid LPM address range..LPM resume failed\n");
+
+ image_addr = mem_addr_lpm.atf_cert_addr;
+ ret = rproc_load(1, (ulong)image_addr, 0x200);
+ if (ret)
+ panic("rproc failed to be initialized (%d)\n", ret);
+
+ ti_secure_image_auth_apply_fwls(&image_addr, &size_int);
+
+ image_addr = mem_addr_lpm.optee_cert_addr;
+ ti_secure_image_auth_apply_fwls(&image_addr, &size_int);
+
+ loadaddr = resume_to_dm_f();
+ printf("Starting ATF on ARM64 core...\n\n");
+ resume_rproc_f();
+
+ image_entry = (image_entry_noargs_t)loadaddr;
+ image_entry();
+}
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 11/20] mach-k3: r5: common: add helper functions needed in LPM resume sequence
2026-04-30 8:44 ` [PATCH 11/20] mach-k3: r5: common: add helper functions needed in LPM resume sequence Richard Genoud (TI)
@ 2026-05-11 10:52 ` Kumar, Udit
0 siblings, 0 replies; 32+ messages in thread
From: Kumar, Udit @ 2026-05-11 10:52 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Apurva Nandan,
Andrew F . Davis, Vignesh Raghavendra, Bryan Brattlof,
Vaishnav Achath, Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Abhash Kumar, Thomas Richard,
Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/2026 2:14 PM, Richard Genoud (TI) wrote:
> +
[..]if (ret)
> + return;
> + save_addr = (unsigned long)mem_addr_lpm.context_save_addr;
> + ret = ti_sci->ops.lpm_ops.lpm_save_addr(ti_sci, save_addr,
> + mem_addr_lpm.size);
> + if (ret)
> + pr_err("TIFS lpm save addr fail\n");
please check firmware capability instead of sending it w/o any check
[..]
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 12/20] arm: mach-k3: j721e: Enable LPM resume flow for J7200/J721e SOC
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (10 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 11/20] mach-k3: r5: common: add helper functions needed in LPM resume sequence Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 8:44 ` [PATCH 13/20] arm: mach-k3: j784s4: Enable LPM resume flow for J784s4/J742s2 SOCs Richard Genoud (TI)
` (7 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: "Thomas Richard (TI)" <thomas.richard@bootlin.com>
Add support for resuming from suspend in board_init_f.
The resume state of the SOC is identified and lpm resume
sequence is followed accordingly.
First, add the board specific part of the exit retention sequence for
k3-ddrss following the DDR resume sequence:
- exit DDR from retention
- de-assert the DDR_RET pin
- restore DDR max frequency
- exit DDR from low power
Then:
- Extract context address from devicetree and send to TIFS.
- Power on the rproc cluster.
- Replay the certificates attached to saved images of ATF and OPTEE.
- Resume sequence for context restore and rproc resume.
- Image entry to DM firmware.
(All those steps are done in do_resume())
The context address area is firewalled by TIFS to protect it from
other hosts.
Co-developed-by: Gregory CLEMENT (TI) <gregory.clement@bootlin.com>
Signed-off-by: Gregory CLEMENT (TI) <gregory.clement@bootlin.com>
Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
Co-developed-by: Prasanth Babu Mantena <p-mantena@ti.com>
Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/j721e/j721e_init.c | 64 +++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/arch/arm/mach-k3/j721e/j721e_init.c b/arch/arm/mach-k3/j721e/j721e_init.c
index f9af0288cf66..a1f87e653299 100644
--- a/arch/arm/mach-k3/j721e/j721e_init.c
+++ b/arch/arm/mach-k3/j721e/j721e_init.c
@@ -20,9 +20,12 @@
#include <mmc.h>
#include <remoteproc.h>
#include <k3-avs.h>
+#include <power/pmic.h>
+#include <mach/k3-ddr.h>
#include "../sysfw-loader.h"
#include "../common.h"
+#include "../lpm-common.h"
/* NAVSS North Bridge (NB) registers */
#define NAVSS0_NBSS_NB0_CFG_MMRS 0x03802000
@@ -294,10 +297,55 @@ void do_dt_magic(void)
}
#endif
+#define GPIO_OUT_1 0x3D
+#define DDR_RET_VAL BIT(1)
+#define DDR_RET_CLK BIT(2)
+#define PMIC_NSLEEP_REG 0x86
+
+static void __maybe_unused k3_deassert_DDR_RET(void)
+{
+ struct udevice *pmica;
+ struct udevice *pmicb;
+ int regval;
+ int ret;
+
+ ret = uclass_get_device_by_name(UCLASS_PMIC,
+ "pmic@48", &pmica);
+ if (ret) {
+ printf("Getting PMICA init failed: %d\n", ret);
+ return;
+ }
+
+ ret = uclass_get_device_by_name(UCLASS_PMIC,
+ "pmic@4c", &pmicb);
+ if (ret) {
+ printf("Getting PMICB init failed: %d\n", ret);
+ return;
+ }
+ /* Set DDR_RET Signal Low on PMIC B */
+ regval = pmic_reg_read(pmicb, GPIO_OUT_1) & ~DDR_RET_VAL;
+
+ pmic_reg_write(pmicb, GPIO_OUT_1, regval);
+
+ /* Now toggle the CLK of the latch for DDR ret */
+ pmic_reg_write(pmicb, GPIO_OUT_1, regval | DDR_RET_CLK);
+ pmic_reg_write(pmicb, GPIO_OUT_1, regval & ~(DDR_RET_CLK));
+ pmic_reg_write(pmicb, GPIO_OUT_1, regval | DDR_RET_CLK);
+ pmic_reg_write(pmicb, GPIO_OUT_1, regval & ~(DDR_RET_CLK));
+
+ pmic_reg_write(pmica, PMIC_NSLEEP_REG, 0x3);
+}
+
+__weak bool j7xx_board_is_resuming(void)
+{
+ return false;
+}
+
void board_init_f(ulong dummy)
{
int ret;
#if defined(CONFIG_K3_J721E_DDRSS) || defined(CONFIG_K3_LOAD_SYSFW)
+ struct k3_ddrss_regs regs;
struct udevice *dev;
#endif
/*
@@ -410,6 +458,22 @@ void board_init_f(ulong dummy)
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret)
panic("DRAM init failed: %d\n", ret);
+
+ if (j7xx_board_is_resuming()) {
+ /*
+ * The DDR resume sequence is:
+ * - exit DDR from retention
+ * - de-assert the DDR_RET pin
+ * - restore DDR max frequency
+ * - exit DDR from low power
+ */
+ k3_ddrss_lpddr4_exit_retention(dev, ®s);
+ k3_deassert_DDR_RET();
+ k3_ddrss_lpddr4_change_freq(dev);
+ k3_ddrss_lpddr4_exit_low_power(dev, ®s);
+
+ do_resume();
+ }
#endif
spl_enable_cache();
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 13/20] arm: mach-k3: j784s4: Enable LPM resume flow for J784s4/J742s2 SOCs
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (11 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 12/20] arm: mach-k3: j721e: Enable LPM resume flow for J7200/J721e SOC Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 8:44 ` [PATCH 14/20] arm: mach-k3: j722s: Enable LPM resume flow Richard Genoud (TI)
` (6 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
Add support for resuming from suspend in board_init_f.
The resume state of the SOC is identified and lpm resume
sequence is followed accordingly.
First, add the board specific part of the exit retention sequence for
k3-ddrss following the DDR resume sequence:
- exit DDR from retention
- de-assert the DDR_RET pin
- restore DDR max frequency
- exit DDR from low power
The self-refresh exit sequence is performed in a loop for each DDR
controller. (J784S4 has 4 DDR controllers and J742S2 has only 2)
Select the number of ddr controllers on the basis of
CONFIG_TARGET_J742S2_R5_EVM build flag.
Then:
- Extract context address from devicetree and send to TIFS.
- Power on the rproc cluster.
- Replay the certificates attached to saved images of ATF and OPTEE.
- Resume sequence for context restore and rproc resume.
- Image entry to DM firmware.
(All those steps are done in do_resume())
The context address area is firewalled by TIFS to protect it from
other hosts.
Co-developed-by: Gregory CLEMENT (TI) <gregory.clement@bootlin.com>
Signed-off-by: Gregory CLEMENT (TI) <gregory.clement@bootlin.com>
Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
Co-developed-by: Prasanth Babu Mantena <p-mantena@ti.com>
Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
Co-developed-by: Abhash Kumar Jha <a-kumar2@ti.com>
Signed-off-by: Abhash Kumar Jha <a-kumar2@ti.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/j784s4/j784s4_init.c | 70 ++++++++++++++++++++++++++-
board/ti/j784s4/evm.c | 3 +-
2 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-k3/j784s4/j784s4_init.c b/arch/arm/mach-k3/j784s4/j784s4_init.c
index 53f152ccd9c6..5646d41a59f4 100644
--- a/arch/arm/mach-k3/j784s4/j784s4_init.c
+++ b/arch/arm/mach-k3/j784s4/j784s4_init.c
@@ -18,11 +18,18 @@
#include <mmc.h>
#include <remoteproc.h>
#include <k3_bist.h>
+#include <power/pmic.h>
+#include <mach/k3-ddr.h>
#include "../sysfw-loader.h"
#include "../common.h"
+#include "../lpm-common.h"
-#define J784S4_MAX_DDR_CONTROLLERS 4
+#if IS_ENABLED(CONFIG_TARGET_J742S2_R5_EVM)
+#define MAX_DDR_CONTROLLERS 2
+#else
+#define MAX_DDR_CONTROLLERS 4
+#endif
#define CTRL_MMR_CFG0_AUDIO_REFCLK1_CTRL 0x001082e4
#define AUDIO_REFCLK1_DEFAULT 0x1c
@@ -264,26 +271,85 @@ void k3_spl_init(void)
k3_dm_print_ver();
}
+#define DDR_RET_VAL BIT(5)
+#define GPIO_OUT_1 0x3D
+#define PMIC_NSLEEP_REG 0x86
+
+static void k3_deassert_DDR_RET(void)
+{
+ struct udevice *pmic;
+ int regval;
+ int err;
+
+ err = uclass_get_device_by_name(UCLASS_PMIC,
+ "pmic@48", &pmic);
+ if (err) {
+ printf("Getting PMIC init failed: %d\n", err);
+ return;
+ }
+
+ /* Set DDR_RET Signal Low on PMIC B */
+ regval = pmic_reg_read(pmic, GPIO_OUT_1) & ~DDR_RET_VAL;
+
+ pmic_reg_write(pmic, GPIO_OUT_1, regval);
+ pmic_reg_write(pmic, PMIC_NSLEEP_REG, 0x3);
+}
+
+__weak bool j7xx_board_is_resuming(void)
+{
+ return false;
+}
+
void k3_mem_init(void)
{
struct udevice *dev;
int ret, ctrl = 0;
if (IS_ENABLED(CONFIG_K3_J721E_DDRSS)) {
+ struct udevice *devs[MAX_DDR_CONTROLLERS];
+ struct k3_ddrss_regs regs[MAX_DDR_CONTROLLERS];
+
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret)
panic("DRAM 0 init failed: %d\n", ret);
+
+ devs[0] = dev;
ctrl++;
- while (ctrl < J784S4_MAX_DDR_CONTROLLERS) {
+ while (ctrl < MAX_DDR_CONTROLLERS) {
ret = uclass_next_device_err(&dev);
if (ret == -ENODEV)
break;
if (ret)
panic("DRAM %d init failed: %d\n", ctrl, ret);
+ devs[ctrl] = dev;
ctrl++;
}
+
+ if (j7xx_board_is_resuming()) {
+ /* exit DDRs from retention */
+ for (ctrl = 0; ctrl < MAX_DDR_CONTROLLERS; ctrl++) {
+ k3_ddrss_lpddr4_exit_retention(devs[ctrl],
+ ®s[ctrl]);
+ }
+
+ /* de-assert DDR_RET pin */
+ k3_deassert_DDR_RET();
+
+ /* restore DDR max frequency */
+ for (ctrl = 0; ctrl < MAX_DDR_CONTROLLERS; ctrl++)
+ k3_ddrss_lpddr4_change_freq(devs[ctrl]);
+
+ /* exit DDR from low power */
+ for (ctrl = 0; ctrl < MAX_DDR_CONTROLLERS; ctrl++) {
+ k3_ddrss_lpddr4_exit_low_power(devs[ctrl],
+ ®s[ctrl]);
+ }
+ printf("Initialized %d DRAM controllers\n", ctrl);
+
+ do_resume();
+ }
printf("Initialized %d DRAM controllers\n", ctrl);
}
diff --git a/board/ti/j784s4/evm.c b/board/ti/j784s4/evm.c
index 4a74024fe4fe..57c2f7018323 100644
--- a/board/ti/j784s4/evm.c
+++ b/board/ti/j784s4/evm.c
@@ -63,7 +63,8 @@ int board_late_init(void)
}
#endif
-#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J784S4_R5_EVM))
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && (IS_ENABLED(CONFIG_TARGET_J784S4_R5_EVM) || \
+ IS_ENABLED(CONFIG_TARGET_J742S2_R5_EVM)))
/* in board_init_f(), there's no BSS, so we can't use global/static variables */
bool j7xx_board_is_resuming(void)
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 14/20] arm: mach-k3: j722s: Enable LPM resume flow
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (12 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 13/20] arm: mach-k3: j784s4: Enable LPM resume flow for J784s4/J742s2 SOCs Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 8:44 ` [PATCH 15/20] arm: mach-k3: j721s2: " Richard Genoud (TI)
` (5 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
Add support for resuming from suspend in board_init_f for J722S.
The resume state of the SOC is identified and lpm resume
sequence is followed accordingly:
- Extract context address from devicetree and send to TIFS.
- Power on the rproc cluster.
- Replay the certificates attached to saved images of ATF and OPTEE.
- Resume sequence for context restore and rproc resume.
- Image entry to DM firmware.
The context address area is firewalled by TIFS to protect it from
other hosts.
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/j722s/j722s_init.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/mach-k3/j722s/j722s_init.c b/arch/arm/mach-k3/j722s/j722s_init.c
index 7b3d27c1e855..e687bcb354c9 100644
--- a/arch/arm/mach-k3/j722s/j722s_init.c
+++ b/arch/arm/mach-k3/j722s/j722s_init.c
@@ -14,6 +14,7 @@
#include "../sysfw-loader.h"
#include "../common.h"
+#include "../lpm-common.h"
struct fwl_data cbass_main_fwls[] = {
{ "FSS_DAT_REG3", 7, 8 },
@@ -156,6 +157,11 @@ static void k3_spl_init(void)
k3_dm_print_ver();
}
+__weak bool j7xx_board_is_resuming(void)
+{
+ return false;
+}
+
static void k3_mem_init(void)
{
struct udevice *dev;
@@ -186,6 +192,9 @@ void board_init_f(ulong dummy)
k3_spl_init();
k3_mem_init();
+ if (j7xx_board_is_resuming())
+ do_resume(); /* no return */
+
setup_qos();
if (IS_ENABLED(CONFIG_ESM_K3)) {
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 15/20] arm: mach-k3: j721s2: Enable LPM resume flow
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (13 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 14/20] arm: mach-k3: j722s: Enable LPM resume flow Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 8:44 ` [PATCH 16/20] arm: mach-k3: Update pm-boardcfg for all k3 platforms Richard Genoud (TI)
` (4 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: "Thomas Richard (TI)" <thomas.richard@bootlin.com>
Add the board specific part of the exit retention sequence for k3-ddrss:
- exit DDR from retention
- de-assert the DDR_RET pin
- restore DDR max frequency
- exit DDR from low power
Then generic resume path is run.
Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
---
arch/arm/mach-k3/j721s2/j721s2_init.c | 73 +++++++++++++++++++++++++--
1 file changed, 69 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-k3/j721s2/j721s2_init.c b/arch/arm/mach-k3/j721s2/j721s2_init.c
index b5453d8895d4..0dcdc817e5a5 100644
--- a/arch/arm/mach-k3/j721s2/j721s2_init.c
+++ b/arch/arm/mach-k3/j721s2/j721s2_init.c
@@ -16,12 +16,17 @@
#include <dm/uclass-internal.h>
#include <dm/pinctrl.h>
#include <dm/root.h>
+#include <mach/k3-ddr.h>
#include <mmc.h>
+#include <power/pmic.h>
#include <remoteproc.h>
#include "../sysfw-loader.h"
+#include "../lpm-common.h"
#include "../common.h"
+#define MAX_DDR_CONTROLLERS 2
+
/* NAVSS North Bridge (NB) */
#define NAVSS0_NBSS_NB0_CFG_MMRS 0x03702000
#define NAVSS0_NBSS_NB1_CFG_MMRS 0x03703000
@@ -250,12 +255,42 @@ bool check_rom_loaded_sysfw(void)
return is_rom_loaded_sysfw(&bootdata);
}
+#define GPIO_OUT_1 0x3D
+#define DDR_RET_VAL BIT(3)
+#define PMIC_NSLEEP_REG 0x86
+
+static void k3_deassert_ddr_ret(void)
+{
+ struct udevice *pmic;
+ int regval;
+ int err;
+
+ err = uclass_get_device_by_name(UCLASS_PMIC,
+ "pmic@4c", &pmic);
+ if (err) {
+ printf("Getting PMIC@4c init failed: %d\n", err);
+ return;
+ }
+ /* Set DDR_RET Signal Low on PMIC B */
+ regval = pmic_reg_read(pmic, GPIO_OUT_1) & ~DDR_RET_VAL;
+ regval &= ~(1 << (4 - 1));
+ pmic_reg_write(pmic, GPIO_OUT_1, regval);
+}
+
+__weak bool j7xx_board_is_resuming(void)
+{
+ return false;
+}
+
void k3_mem_init(void)
{
struct udevice *dev;
- int ret;
+ int ret, ctrl = 0;
if (IS_ENABLED(CONFIG_K3_J721E_DDRSS)) {
+ struct udevice *devs[MAX_DDR_CONTROLLERS];
+ struct k3_ddrss_regs regs[MAX_DDR_CONTROLLERS];
+
ret = uclass_get_device_by_name(UCLASS_MISC, "msmc", &dev);
if (ret)
panic("Probe of msmc failed: %d\n", ret);
@@ -263,10 +298,40 @@ void k3_mem_init(void)
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret)
panic("DRAM 0 init failed: %d\n", ret);
+ devs[0] = dev;
+ ctrl++;
- ret = uclass_next_device_err(&dev);
- if (ret && ret != -ENODEV)
- panic("DRAM 1 init failed: %d\n", ret);
+ while (ctrl < MAX_DDR_CONTROLLERS) {
+ ret = uclass_next_device_err(&dev);
+ if (ret == -ENODEV)
+ break;
+
+ if (ret)
+ panic("DRAM %d init failed: %d\n", ctrl, ret);
+ devs[ctrl] = dev;
+ ctrl++;
+ }
+
+ if (j7xx_board_is_resuming()) {
+ /* exit DDRs from retention */
+ for (ctrl = 0; ctrl < MAX_DDR_CONTROLLERS; ctrl++)
+ k3_ddrss_lpddr4_exit_retention(devs[ctrl],
+ ®s[ctrl]);
+
+ /* de-assert DDR_RET pin */
+ k3_deassert_ddr_ret();
+
+ /* restore DDR max frequency */
+ for (ctrl = 0; ctrl < MAX_DDR_CONTROLLERS; ctrl++)
+ k3_ddrss_lpddr4_change_freq(devs[ctrl]);
+
+ /* exit DDR from low power */
+ for (ctrl = 0; ctrl < MAX_DDR_CONTROLLERS; ctrl++)
+ k3_ddrss_lpddr4_exit_low_power(devs[ctrl],
+ ®s[ctrl]);
+
+ do_resume();
+ }
}
spl_enable_cache();
}
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 16/20] arm: mach-k3: Update pm-boardcfg for all k3 platforms
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (14 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 15/20] arm: mach-k3: j721s2: " Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-05-11 10:54 ` Kumar, Udit
2026-04-30 8:44 ` [PATCH 17/20] board: evm: Enable de-isolation of IOs at resume for j7200 and j784s4 Richard Genoud (TI)
` (3 subsequent siblings)
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: Abhash Kumar Jha <a-kumar2@ti.com>
Update the pm-cfg and schema to a new version. The new pm-boardcfg has the
following substructures
- lpm_cfg : Low Power Mode configuration
- pll_cfg : PLL configuration
- dev_cfg : Device Power configuration
- rsvd_pmic_cfg : Reserved PMIC configuration
- rsvd_cfg : Reserved cofiguration containing the size for the flexible
array appended at the end of pm-boardcfg
The ABI revision for pm-cfg is also changed from 0:1 to 1:1
Modify the pm-cfg for am62ax, am62dx, am62px, am62x, am64x, am65x,
j721s2, j722s to change the hierarchy from "pm-cfg -> rev" to
"pm-cfg -> pm-boardcfg -> rev".
This change only adds a new 'pm-boardcfg' property as a parent of the
'rev' property, this does not affect the generated pm-cfg binary.
Add u64 type in schema and update the boardcfg script to deal with u64
types.
Signed-off-by: Abhash Kumar Jha <a-kumar2@ti.com>
---
arch/arm/mach-k3/schema.yaml | 195 +++++++++++++++++++-----
board/phytec/phycore_am62ax/pm-cfg.yaml | 7 +-
board/ti/am62ax/pm-cfg.yaml | 7 +-
board/ti/am62px/pm-cfg.yaml | 7 +-
board/ti/am62x/pm-cfg.yaml | 7 +-
board/ti/am64x/pm-cfg.yaml | 5 +-
board/ti/am65x/pm-cfg.yaml | 7 +-
board/ti/j7200/pm-cfg.yaml | 92 ++++++++++-
board/ti/j721e/pm-cfg.yaml | 92 ++++++++++-
board/ti/j721s2/pm-cfg.yaml | 94 +++++++++++-
board/ti/j722s/pm-cfg.yaml | 7 +-
board/ti/j784s4/pm-cfg.yaml | 94 +++++++++++-
tools/binman/etype/ti_board_config.py | 4 +-
13 files changed, 552 insertions(+), 66 deletions(-)
diff --git a/arch/arm/mach-k3/schema.yaml b/arch/arm/mach-k3/schema.yaml
index 8c4691f24ed6..dbd11b6c864d 100644
--- a/arch/arm/mach-k3/schema.yaml
+++ b/arch/arm/mach-k3/schema.yaml
@@ -19,21 +19,15 @@ definitions:
type: integer
minimum: 0
maximum: 0xffffffff
+ u64:
+ type: integer
+ minimum: 0
+ maximum: 0xffffffffffffffff
type: object
properties:
- pm-cfg:
- type: object
- properties:
- rev:
- type: object
- properties:
- boardcfg_abi_maj:
- $ref: "#/definitions/u8"
- boardcfg_abi_min:
- $ref: "#/definitions/u8"
board-cfg:
type: object
properties:
@@ -283,6 +277,138 @@ properties:
items:
$ref: "#/definitions/u8"
+ pm-cfg:
+ type: object
+ properties:
+ pm_boardcfg:
+ type: object
+ properties:
+ rev:
+ type: object
+ properties:
+ boardcfg_abi_maj:
+ $ref: "#/definitions/u8"
+ boardcfg_abi_min:
+ $ref: "#/definitions/u8"
+
+ lpm_cfg:
+ type: object
+ properties:
+ subhdr:
+ type: object
+ properties:
+ magic:
+ $ref: "#/definitions/u16"
+ size:
+ $ref: "#/definitions/u16"
+ suspend_initiator:
+ $ref: "#/definitions/u8"
+ lpm_mode:
+ $ref: "#/definitions/u8"
+ lpm_rsvd1:
+ $ref: "#/definitions/u16"
+ lpm_rsvd2:
+ $ref: "#/definitions/u32"
+
+ pll_cfg:
+ type: object
+ properties:
+ subhdr:
+ type: object
+ properties:
+ magic:
+ $ref: "#/definitions/u16"
+ size:
+ $ref: "#/definitions/u16"
+ pll_cfg_entries:
+ type: array
+ minItems: 0
+ maxItems: 5
+ items:
+ type: object
+ properties:
+ dev_id:
+ $ref: "#/definitions/u32"
+ clk_id:
+ $ref: "#/definitions/u32"
+ pll_freq:
+ $ref: "#/definitions/u64"
+ dev_cfg:
+ type: object
+ properties:
+ subhdr:
+ type: object
+ properties:
+ magic:
+ $ref: "#/definitions/u16"
+ size:
+ $ref: "#/definitions/u16"
+ dev_cfg_entries:
+ type: array
+ minItems: 0
+ maxItems: 5
+ items:
+ type: object
+ properties:
+ dev_id:
+ $ref: "#/definitions/u32"
+ state:
+ $ref: "#/definitions/u32"
+ flag:
+ $ref: "#/definitions/u32"
+ rsvd_pmic_cfg:
+ type: object
+ properties:
+ subhdr:
+ type: object
+ properties:
+ magic:
+ $ref: "#/definitions/u16"
+ size:
+ $ref: "#/definitions/u16"
+ pmic_rsvd1:
+ $ref: "#/definitions/u32"
+ pmic_rsvd2:
+ $ref: "#/definitions/u32"
+ pmic_rsvd3:
+ $ref: "#/definitions/u32"
+ rsvd_cfg:
+ type: object
+ properties:
+ subhdr:
+ type: object
+ properties:
+ magic:
+ $ref: "#/definitions/u16"
+ size:
+ $ref: "#/definitions/u16"
+ rsvd1:
+ $ref: "#/definitions/u32"
+ rsvd2:
+ $ref: "#/definitions/u32"
+ rsvd3:
+ $ref: "#/definitions/u32"
+ reserved_entry_size:
+ $ref: "#/definitions/u16"
+
+ reserved_entries:
+ type: array
+ minItems: 0
+ maxItems: 2
+ items:
+ type: object
+ properties:
+ reserved1:
+ $ref: "#/definitions/u16"
+ reserved2:
+ $ref: "#/definitions/u16"
+ reserved3:
+ $ref: "#/definitions/u16"
+ reserved4:
+ $ref: "#/definitions/u8"
+ reserved5:
+ $ref: "#/definitions/u8"
+
rm-cfg:
type: object
properties:
@@ -296,36 +422,35 @@ properties:
$ref: "#/definitions/u8"
boardcfg_abi_min:
$ref: "#/definitions/u8"
-
host_cfg:
- type: object
- properties:
- subhdr:
- type: object
- properties:
- magic:
- $ref: "#/definitions/u16"
- size:
- $ref: "#/definitions/u16"
- host_cfg_entries:
- type: array
- minItems: 0
- maxItems: 32
- items:
+ type: object
+ properties:
+ subhdr:
type: object
properties:
- host_id:
- $ref: "#/definitions/u8"
- allowed_atype:
- $ref: "#/definitions/u8"
- allowed_qos:
+ magic:
$ref: "#/definitions/u16"
- allowed_orderid:
- $ref: "#/definitions/u32"
- allowed_priority:
+ size:
$ref: "#/definitions/u16"
- allowed_sched_priority:
- $ref: "#/definitions/u8"
+ host_cfg_entries:
+ type: array
+ minItems: 0
+ maxItems: 32
+ items:
+ type: object
+ properties:
+ host_id:
+ $ref: "#/definitions/u8"
+ allowed_atype:
+ $ref: "#/definitions/u8"
+ allowed_qos:
+ $ref: "#/definitions/u16"
+ allowed_orderid:
+ $ref: "#/definitions/u32"
+ allowed_priority:
+ $ref: "#/definitions/u16"
+ allowed_sched_priority:
+ $ref: "#/definitions/u8"
resasg:
type: object
properties:
diff --git a/board/phytec/phycore_am62ax/pm-cfg.yaml b/board/phytec/phycore_am62ax/pm-cfg.yaml
index 4031af2f4d3a..2eebba0d986f 100644
--- a/board/phytec/phycore_am62ax/pm-cfg.yaml
+++ b/board/phytec/phycore_am62ax/pm-cfg.yaml
@@ -7,6 +7,7 @@
---
pm-cfg:
- rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ pm_boardcfg:
+ rev:
+ boardcfg_abi_maj: 0x0
+ boardcfg_abi_min: 0x1
diff --git a/board/ti/am62ax/pm-cfg.yaml b/board/ti/am62ax/pm-cfg.yaml
index 4031af2f4d3a..2eebba0d986f 100644
--- a/board/ti/am62ax/pm-cfg.yaml
+++ b/board/ti/am62ax/pm-cfg.yaml
@@ -7,6 +7,7 @@
---
pm-cfg:
- rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ pm_boardcfg:
+ rev:
+ boardcfg_abi_maj: 0x0
+ boardcfg_abi_min: 0x1
diff --git a/board/ti/am62px/pm-cfg.yaml b/board/ti/am62px/pm-cfg.yaml
index 3ff27ce702c2..15a0cc6e8588 100644
--- a/board/ti/am62px/pm-cfg.yaml
+++ b/board/ti/am62px/pm-cfg.yaml
@@ -7,6 +7,7 @@
#
---
pm-cfg:
- rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ pm_boardcfg:
+ rev:
+ boardcfg_abi_maj: 0x0
+ boardcfg_abi_min: 0x1
diff --git a/board/ti/am62x/pm-cfg.yaml b/board/ti/am62x/pm-cfg.yaml
index 9853a25eb85c..75cdeb8098fc 100644
--- a/board/ti/am62x/pm-cfg.yaml
+++ b/board/ti/am62x/pm-cfg.yaml
@@ -7,6 +7,7 @@
---
pm-cfg:
- rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ pm_boardcfg:
+ rev:
+ boardcfg_abi_maj: 0x0
+ boardcfg_abi_min: 0x1
diff --git a/board/ti/am64x/pm-cfg.yaml b/board/ti/am64x/pm-cfg.yaml
index 7afb29621088..e9866d0ea24d 100644
--- a/board/ti/am64x/pm-cfg.yaml
+++ b/board/ti/am64x/pm-cfg.yaml
@@ -7,6 +7,7 @@
---
pm-cfg:
+ pm_boardcfg:
rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ boardcfg_abi_maj: 0x0
+ boardcfg_abi_min: 0x1
diff --git a/board/ti/am65x/pm-cfg.yaml b/board/ti/am65x/pm-cfg.yaml
index ee0d1c67a718..50df1310a38d 100644
--- a/board/ti/am65x/pm-cfg.yaml
+++ b/board/ti/am65x/pm-cfg.yaml
@@ -7,6 +7,7 @@
---
pm-cfg:
- rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ pm_boardcfg:
+ rev:
+ boardcfg_abi_maj: 0x0
+ boardcfg_abi_min: 0x1
diff --git a/board/ti/j7200/pm-cfg.yaml b/board/ti/j7200/pm-cfg.yaml
index 85cd2c9dbcaf..b38958bea888 100644
--- a/board/ti/j7200/pm-cfg.yaml
+++ b/board/ti/j7200/pm-cfg.yaml
@@ -7,6 +7,94 @@
---
pm-cfg:
+ pm_boardcfg:
rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ boardcfg_abi_maj: 0x1
+ boardcfg_abi_min: 0x1
+ lpm_cfg:
+ subhdr:
+ magic: 0x4C41
+ size: 0x0C
+ suspend_initiator: 0xA
+ lpm_mode: 0x5
+ lpm_rsvd1: 0x0
+ lpm_rsvd2: 0x0
+ pll_cfg:
+ subhdr:
+ magic: 0xC31E
+ size: 0x54
+ pll_cfg_entries:
+ - # 1
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 2
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 3
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 4
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 5
+ dev_id: 0x6
+ clk_id: 0x7
+ pll_freq: 0x8
+ dev_cfg:
+ subhdr:
+ magic: 0x74B1
+ size: 0x40
+ dev_cfg_entries:
+ - # 1
+ dev_id: 0xB
+ state: 0xD
+ flag: 0xE
+ - # 2
+ dev_id: 0xCC
+ state: 0xA
+ flag: 0xA
+ - # 3
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xA
+ - # 4
+ dev_id: 0xCC
+ state: 0xA
+ flag: 0xA
+ - # 5
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xCC
+ rsvd_pmic_cfg:
+ subhdr:
+ magic: 0x8A1D
+ size: 0x10
+ pmic_rsvd1: 0xA
+ pmic_rsvd2: 0xA
+ pmic_rsvd3: 0xDD
+ rsvd_cfg:
+ subhdr:
+ magic: 0x3CFA
+ size: 0x12
+ rsvd1: 0x0
+ rsvd2: 0x0
+ rsvd3: 0x0
+ reserved_entry_size: 0x10
+
+ reserved_entries:
+ -
+ reserved1: 4
+ reserved2: 93
+ reserved3: 77
+ reserved4: 26
+ reserved5: 0
+ -
+ reserved1: 4
+ reserved2: 93
+ reserved3: 77
+ reserved4: 26
+ reserved5: 0
diff --git a/board/ti/j721e/pm-cfg.yaml b/board/ti/j721e/pm-cfg.yaml
index 7ae52b3358e2..0d6b14de817a 100644
--- a/board/ti/j721e/pm-cfg.yaml
+++ b/board/ti/j721e/pm-cfg.yaml
@@ -7,6 +7,94 @@
---
pm-cfg:
+ pm_boardcfg:
rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ boardcfg_abi_maj: 0x1
+ boardcfg_abi_min: 0x1
+ lpm_cfg:
+ subhdr:
+ magic: 0x4C41
+ size: 0x0C
+ suspend_initiator: 0xA
+ lpm_mode: 0x5
+ lpm_rsvd1: 0x0
+ lpm_rsvd2: 0x0
+ pll_cfg:
+ subhdr:
+ magic: 0xC31E
+ size: 0x54
+ pll_cfg_entries:
+ - # 1
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 2
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 3
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 4
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 5
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ dev_cfg:
+ subhdr:
+ magic: 0x74B1
+ size: 0x40
+ dev_cfg_entries:
+ - # 1
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xA
+ - # 2
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xA
+ - # 3
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xA
+ - # 4
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xA
+ - # 5
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xA
+ rsvd_pmic_cfg:
+ subhdr:
+ magic: 0x8A1D
+ size: 0x10
+ pmic_rsvd1: 0xA
+ pmic_rsvd2: 0xA
+ pmic_rsvd3: 0xA
+ rsvd_cfg:
+ subhdr:
+ magic: 0x3CFA
+ size: 0x12
+ rsvd1: 0x0
+ rsvd2: 0x0
+ rsvd3: 0x0
+ reserved_entry_size: 0x10
+
+ reserved_entries:
+ -
+ reserved1: 4
+ reserved2: 93
+ reserved3: 7744
+ reserved4: 26
+ reserved5: 0
+ -
+ reserved1: 4
+ reserved2: 93
+ reserved3: 7744
+ reserved4: 26
+ reserved5: 0
diff --git a/board/ti/j721s2/pm-cfg.yaml b/board/ti/j721s2/pm-cfg.yaml
index e6496512b6b7..ce0435165c9e 100644
--- a/board/ti/j721s2/pm-cfg.yaml
+++ b/board/ti/j721s2/pm-cfg.yaml
@@ -7,6 +7,94 @@
---
pm-cfg:
- rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ pm_boardcfg:
+ rev:
+ boardcfg_abi_maj: 0x1
+ boardcfg_abi_min: 0x1
+ lpm_cfg:
+ subhdr:
+ magic: 0x4C41
+ size: 0x0C
+ suspend_initiator: 0xA
+ lpm_mode: 0x5
+ lpm_rsvd1: 0x0
+ lpm_rsvd2: 0x0
+ pll_cfg:
+ subhdr:
+ magic: 0xC31E
+ size: 0x54
+ pll_cfg_entries:
+ - # 1
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 2
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 3
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 4
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 5
+ dev_id: 0x6
+ clk_id: 0x7
+ pll_freq: 0x8
+ dev_cfg:
+ subhdr:
+ magic: 0x74B1
+ size: 0x40
+ dev_cfg_entries:
+ - # 1
+ dev_id: 0xB
+ state: 0xD
+ flag: 0xE
+ - # 2
+ dev_id: 0xCC
+ state: 0xA
+ flag: 0xA
+ - # 3
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xA
+ - # 4
+ dev_id: 0xCC
+ state: 0xA
+ flag: 0xA
+ - # 5
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xCC
+ rsvd_pmic_cfg:
+ subhdr:
+ magic: 0x8A1D
+ size: 0x10
+ pmic_rsvd1: 0xA
+ pmic_rsvd2: 0xA
+ pmic_rsvd3: 0xDD
+ rsvd_cfg:
+ subhdr:
+ magic: 0x3CFA
+ size: 0x12
+ rsvd1: 0x0
+ rsvd2: 0x0
+ rsvd3: 0x0
+ reserved_entry_size: 0x10
+
+ reserved_entries:
+ -
+ reserved1: 4
+ reserved2: 93
+ reserved3: 77
+ reserved4: 26
+ reserved5: 0
+ -
+ reserved1: 4
+ reserved2: 93
+ reserved3: 77
+ reserved4: 26
+ reserved5: 0
diff --git a/board/ti/j722s/pm-cfg.yaml b/board/ti/j722s/pm-cfg.yaml
index 46b3ad201091..ab1c8e06f10e 100644
--- a/board/ti/j722s/pm-cfg.yaml
+++ b/board/ti/j722s/pm-cfg.yaml
@@ -7,6 +7,7 @@
---
pm-cfg:
- rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ pm_boardcfg:
+ rev:
+ boardcfg_abi_maj: 0x0
+ boardcfg_abi_min: 0x1
diff --git a/board/ti/j784s4/pm-cfg.yaml b/board/ti/j784s4/pm-cfg.yaml
index a36b86098998..cbe166808df9 100644
--- a/board/ti/j784s4/pm-cfg.yaml
+++ b/board/ti/j784s4/pm-cfg.yaml
@@ -8,6 +8,94 @@
---
pm-cfg:
- rev:
- boardcfg_abi_maj: 0x0
- boardcfg_abi_min: 0x1
+ pm_boardcfg:
+ rev:
+ boardcfg_abi_maj: 0x1
+ boardcfg_abi_min: 0x1
+ lpm_cfg:
+ subhdr:
+ magic: 0x4C41
+ size: 0x0C
+ suspend_initiator: 0xA
+ lpm_mode: 0x5
+ lpm_rsvd1: 0x0
+ lpm_rsvd2: 0x0
+ pll_cfg:
+ subhdr:
+ magic: 0xC31E
+ size: 0x54
+ pll_cfg_entries:
+ - # 1
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 2
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 3
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 4
+ dev_id: 0xA
+ clk_id: 0xA
+ pll_freq: 0xA
+ - # 5
+ dev_id: 0x6
+ clk_id: 0x7
+ pll_freq: 0x8
+ dev_cfg:
+ subhdr:
+ magic: 0x74B1
+ size: 0x40
+ dev_cfg_entries:
+ - # 1
+ dev_id: 0xB
+ state: 0xD
+ flag: 0xE
+ - # 2
+ dev_id: 0xCC
+ state: 0xA
+ flag: 0xA
+ - # 3
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xA
+ - # 4
+ dev_id: 0xCC
+ state: 0xA
+ flag: 0xA
+ - # 5
+ dev_id: 0xA
+ state: 0xA
+ flag: 0xCC
+ rsvd_pmic_cfg:
+ subhdr:
+ magic: 0x8A1D
+ size: 0x10
+ pmic_rsvd1: 0xA
+ pmic_rsvd2: 0xA
+ pmic_rsvd3: 0xDD
+ rsvd_cfg:
+ subhdr:
+ magic: 0x3CFA
+ size: 0x12
+ rsvd1: 0x0
+ rsvd2: 0x0
+ rsvd3: 0x0
+ reserved_entry_size: 0x10
+
+ reserved_entries:
+ -
+ reserved1: 4
+ reserved2: 93
+ reserved3: 77
+ reserved4: 26
+ reserved5: 0
+ -
+ reserved1: 4
+ reserved2: 93
+ reserved3: 77
+ reserved4: 26
+ reserved5: 0
diff --git a/tools/binman/etype/ti_board_config.py b/tools/binman/etype/ti_board_config.py
index 7c6773ac7bcd..b0cd055bf53e 100644
--- a/tools/binman/etype/ti_board_config.py
+++ b/tools/binman/etype/ti_board_config.py
@@ -124,8 +124,10 @@ class Entry_ti_board_config(Entry_section):
size = 1
elif (data_type == '#/definitions/u16'):
size = 2
- else:
+ elif (data_type == '#/definitions/u32'):
size = 4
+ else:
+ size = 8
br = None
if type(val) == int:
br = val.to_bytes(size, byteorder='little')
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 16/20] arm: mach-k3: Update pm-boardcfg for all k3 platforms
2026-04-30 8:44 ` [PATCH 16/20] arm: mach-k3: Update pm-boardcfg for all k3 platforms Richard Genoud (TI)
@ 2026-05-11 10:54 ` Kumar, Udit
0 siblings, 0 replies; 32+ messages in thread
From: Kumar, Udit @ 2026-05-11 10:54 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Apurva Nandan,
Andrew F . Davis, Vignesh Raghavendra, Bryan Brattlof,
Vaishnav Achath, Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Abhash Kumar, Thomas Richard,
Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/2026 2:14 PM, Richard Genoud (TI) wrote:
> From: Abhash Kumar Jha <a-kumar2@ti.com>
>
> Update the pm-cfg and schema to a new version. The new pm-boardcfg has the
> following substructures
>
> - lpm_cfg : Low Power Mode configuration
> - pll_cfg : PLL configuration
> - dev_cfg : Device Power configuration
> - rsvd_pmic_cfg : Reserved PMIC configuration
> - rsvd_cfg : Reserved cofiguration containing the size for the flexible
> array appended at the end of pm-boardcfg
>
> The ABI revision for pm-cfg is also changed from 0:1 to 1:1
>
> Modify the pm-cfg for am62ax, am62dx, am62px, am62x, am64x, am65x,
> j721s2, j722s to change the hierarchy from "pm-cfg -> rev" to
> "pm-cfg -> pm-boardcfg -> rev".
>
> This change only adds a new 'pm-boardcfg' property as a parent of the
> 'rev' property, this does not affect the generated pm-cfg binary.
>
> Add u64 type in schema and update the boardcfg script to deal with u64
> types.
>
> Signed-off-by: Abhash Kumar Jha <a-kumar2@ti.com>
> ---
> arch/arm/mach-k3/schema.yaml | 195 +++++++++++++++++++-----
> board/phytec/phycore_am62ax/pm-cfg.yaml | 7 +-
> board/ti/am62ax/pm-cfg.yaml | 7 +-
> board/ti/am62px/pm-cfg.yaml | 7 +-
> board/ti/am62x/pm-cfg.yaml | 7 +-
> board/ti/am64x/pm-cfg.yaml | 5 +-
> board/ti/am65x/pm-cfg.yaml | 7 +-
> board/ti/j7200/pm-cfg.yaml | 92 ++++++++++-
> board/ti/j721e/pm-cfg.yaml | 92 ++++++++++-
> board/ti/j721s2/pm-cfg.yaml | 94 +++++++++++-
> board/ti/j722s/pm-cfg.yaml | 7 +-
> board/ti/j784s4/pm-cfg.yaml | 94 +++++++++++-
> tools/binman/etype/ti_board_config.py | 4 +-
> 13 files changed, 552 insertions(+), 66 deletions(-)
Please include all K3 platform, otherwise build will fail like beagleboard
>
> diff --git a/arch/arm/mach-k3/schema.yaml b/arch/arm/mach-k3/schema.yaml
> index 8c4691f24ed6..dbd11b6c864d 100644
> --- a/arch/arm/mach-k3/schema.yaml
> +++ b/arch/arm/mach-k3/schema.yaml
> @@ -19,21 +19,15 @@ definitions:
> type: integer
> minimum: 0
> maximum: 0xffffffff
> + u64:
> + type: integer
> + minimum: 0
> + maximum: 0xffffffffffffffff
>
>
>
> type: object
> properties:
> - pm-cfg:
> - type: object
> - properties:
> - rev:
> - type: object
> - properties:
> - boardcfg_abi_maj:
> - $ref: "#/definitions/u8"
> - boardcfg_abi_min:
> - $ref: "#/definitions/u8"
> board-cfg:
> type: object
> properties:
> @@ -283,6 +277,138 @@ properties:
> items:
> $ref: "#/definitions/u8"
>
> + pm-cfg:
> + type: object
> + properties:
> + pm_boardcfg:
> + type: object
> + properties:
> + rev:
> + type: object
> + properties:
> + boardcfg_abi_maj:
> + $ref: "#/definitions/u8"
> + boardcfg_abi_min:
> + $ref: "#/definitions/u8"
> +
> + lpm_cfg:
> + type: object
> + properties:
> + subhdr:
> + type: object
> + properties:
> + magic:
> + $ref: "#/definitions/u16"
> + size:
> + $ref: "#/definitions/u16"
> + suspend_initiator:
> + $ref: "#/definitions/u8"
> + lpm_mode:
> + $ref: "#/definitions/u8"
> + lpm_rsvd1:
> + $ref: "#/definitions/u16"
> + lpm_rsvd2:
> + $ref: "#/definitions/u32"
> +
> + pll_cfg:
> + type: object
> + properties:
> + subhdr:
> + type: object
> + properties:
> + magic:
> + $ref: "#/definitions/u16"
> + size:
> + $ref: "#/definitions/u16"
> + pll_cfg_entries:
> + type: array
> + minItems: 0
> + maxItems: 5
> + items:
> + type: object
> + properties:
> + dev_id:
> + $ref: "#/definitions/u32"
> + clk_id:
> + $ref: "#/definitions/u32"
> + pll_freq:
> + $ref: "#/definitions/u64"
> + dev_cfg:
> + type: object
> + properties:
> + subhdr:
> + type: object
> + properties:
> + magic:
> + $ref: "#/definitions/u16"
> + size:
> + $ref: "#/definitions/u16"
> + dev_cfg_entries:
> + type: array
> + minItems: 0
> + maxItems: 5
> + items:
> + type: object
> + properties:
> + dev_id:
> + $ref: "#/definitions/u32"
> + state:
> + $ref: "#/definitions/u32"
> + flag:
> + $ref: "#/definitions/u32"
> + rsvd_pmic_cfg:
> + type: object
> + properties:
> + subhdr:
> + type: object
> + properties:
> + magic:
> + $ref: "#/definitions/u16"
> + size:
> + $ref: "#/definitions/u16"
> + pmic_rsvd1:
> + $ref: "#/definitions/u32"
> + pmic_rsvd2:
> + $ref: "#/definitions/u32"
> + pmic_rsvd3:
> + $ref: "#/definitions/u32"
> + rsvd_cfg:
> + type: object
> + properties:
> + subhdr:
> + type: object
> + properties:
> + magic:
> + $ref: "#/definitions/u16"
> + size:
> + $ref: "#/definitions/u16"
> + rsvd1:
> + $ref: "#/definitions/u32"
> + rsvd2:
> + $ref: "#/definitions/u32"
> + rsvd3:
> + $ref: "#/definitions/u32"
> + reserved_entry_size:
> + $ref: "#/definitions/u16"
> +
> + reserved_entries:
> + type: array
> + minItems: 0
> + maxItems: 2
> + items:
> + type: object
> + properties:
> + reserved1:
> + $ref: "#/definitions/u16"
> + reserved2:
> + $ref: "#/definitions/u16"
> + reserved3:
> + $ref: "#/definitions/u16"
> + reserved4:
> + $ref: "#/definitions/u8"
> + reserved5:
> + $ref: "#/definitions/u8"
> +
> rm-cfg:
> type: object
> properties:
> @@ -296,36 +422,35 @@ properties:
> $ref: "#/definitions/u8"
> boardcfg_abi_min:
> $ref: "#/definitions/u8"
> -
> host_cfg:
> - type: object
> - properties:
> - subhdr:
> - type: object
> - properties:
> - magic:
> - $ref: "#/definitions/u16"
> - size:
> - $ref: "#/definitions/u16"
> - host_cfg_entries:
> - type: array
> - minItems: 0
> - maxItems: 32
> - items:
> + type: object
> + properties:
> + subhdr:
> type: object
> properties:
> - host_id:
> - $ref: "#/definitions/u8"
> - allowed_atype:
> - $ref: "#/definitions/u8"
> - allowed_qos:
> + magic:
> $ref: "#/definitions/u16"
> - allowed_orderid:
> - $ref: "#/definitions/u32"
> - allowed_priority:
> + size:
> $ref: "#/definitions/u16"
> - allowed_sched_priority:
> - $ref: "#/definitions/u8"
> + host_cfg_entries:
> + type: array
> + minItems: 0
> + maxItems: 32
> + items:
> + type: object
> + properties:
> + host_id:
> + $ref: "#/definitions/u8"
> + allowed_atype:
> + $ref: "#/definitions/u8"
> + allowed_qos:
> + $ref: "#/definitions/u16"
> + allowed_orderid:
> + $ref: "#/definitions/u32"
> + allowed_priority:
> + $ref: "#/definitions/u16"
> + allowed_sched_priority:
> + $ref: "#/definitions/u8"
> resasg:
> type: object
> properties:
> diff --git a/board/phytec/phycore_am62ax/pm-cfg.yaml b/board/phytec/phycore_am62ax/pm-cfg.yaml
> index 4031af2f4d3a..2eebba0d986f 100644
> --- a/board/phytec/phycore_am62ax/pm-cfg.yaml
> +++ b/board/phytec/phycore_am62ax/pm-cfg.yaml
> @@ -7,6 +7,7 @@
> ---
>
> pm-cfg:
> - rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + pm_boardcfg:
> + rev:
> + boardcfg_abi_maj: 0x0
> + boardcfg_abi_min: 0x1
> diff --git a/board/ti/am62ax/pm-cfg.yaml b/board/ti/am62ax/pm-cfg.yaml
> index 4031af2f4d3a..2eebba0d986f 100644
> --- a/board/ti/am62ax/pm-cfg.yaml
> +++ b/board/ti/am62ax/pm-cfg.yaml
> @@ -7,6 +7,7 @@
> ---
>
> pm-cfg:
> - rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + pm_boardcfg:
> + rev:
> + boardcfg_abi_maj: 0x0
> + boardcfg_abi_min: 0x1
> diff --git a/board/ti/am62px/pm-cfg.yaml b/board/ti/am62px/pm-cfg.yaml
> index 3ff27ce702c2..15a0cc6e8588 100644
> --- a/board/ti/am62px/pm-cfg.yaml
> +++ b/board/ti/am62px/pm-cfg.yaml
> @@ -7,6 +7,7 @@
> #
> ---
> pm-cfg:
> - rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + pm_boardcfg:
> + rev:
> + boardcfg_abi_maj: 0x0
> + boardcfg_abi_min: 0x1
> diff --git a/board/ti/am62x/pm-cfg.yaml b/board/ti/am62x/pm-cfg.yaml
> index 9853a25eb85c..75cdeb8098fc 100644
> --- a/board/ti/am62x/pm-cfg.yaml
> +++ b/board/ti/am62x/pm-cfg.yaml
> @@ -7,6 +7,7 @@
> ---
>
> pm-cfg:
> - rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + pm_boardcfg:
> + rev:
> + boardcfg_abi_maj: 0x0
> + boardcfg_abi_min: 0x1
> diff --git a/board/ti/am64x/pm-cfg.yaml b/board/ti/am64x/pm-cfg.yaml
> index 7afb29621088..e9866d0ea24d 100644
> --- a/board/ti/am64x/pm-cfg.yaml
> +++ b/board/ti/am64x/pm-cfg.yaml
> @@ -7,6 +7,7 @@
> ---
>
> pm-cfg:
> + pm_boardcfg:
> rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + boardcfg_abi_maj: 0x0
> + boardcfg_abi_min: 0x1
> diff --git a/board/ti/am65x/pm-cfg.yaml b/board/ti/am65x/pm-cfg.yaml
> index ee0d1c67a718..50df1310a38d 100644
> --- a/board/ti/am65x/pm-cfg.yaml
> +++ b/board/ti/am65x/pm-cfg.yaml
> @@ -7,6 +7,7 @@
> ---
>
> pm-cfg:
> - rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + pm_boardcfg:
> + rev:
> + boardcfg_abi_maj: 0x0
> + boardcfg_abi_min: 0x1
> diff --git a/board/ti/j7200/pm-cfg.yaml b/board/ti/j7200/pm-cfg.yaml
> index 85cd2c9dbcaf..b38958bea888 100644
> --- a/board/ti/j7200/pm-cfg.yaml
> +++ b/board/ti/j7200/pm-cfg.yaml
> @@ -7,6 +7,94 @@
> ---
>
> pm-cfg:
> + pm_boardcfg:
> rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + boardcfg_abi_maj: 0x1
> + boardcfg_abi_min: 0x1
> + lpm_cfg:
> + subhdr:
> + magic: 0x4C41
> + size: 0x0C
> + suspend_initiator: 0xA
> + lpm_mode: 0x5
> + lpm_rsvd1: 0x0
> + lpm_rsvd2: 0x0
> + pll_cfg:
> + subhdr:
> + magic: 0xC31E
> + size: 0x54
> + pll_cfg_entries:
> + - # 1
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 2
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 3
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 4
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 5
> + dev_id: 0x6
> + clk_id: 0x7
> + pll_freq: 0x8
> + dev_cfg:
> + subhdr:
> + magic: 0x74B1
> + size: 0x40
> + dev_cfg_entries:
> + - # 1
> + dev_id: 0xB
> + state: 0xD
> + flag: 0xE
> + - # 2
> + dev_id: 0xCC
> + state: 0xA
> + flag: 0xA
> + - # 3
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xA
> + - # 4
> + dev_id: 0xCC
> + state: 0xA
> + flag: 0xA
> + - # 5
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xCC
> + rsvd_pmic_cfg:
> + subhdr:
> + magic: 0x8A1D
> + size: 0x10
> + pmic_rsvd1: 0xA
> + pmic_rsvd2: 0xA
> + pmic_rsvd3: 0xDD
> + rsvd_cfg:
> + subhdr:
> + magic: 0x3CFA
> + size: 0x12
> + rsvd1: 0x0
> + rsvd2: 0x0
> + rsvd3: 0x0
> + reserved_entry_size: 0x10
> +
> + reserved_entries:
> + -
> + reserved1: 4
> + reserved2: 93
> + reserved3: 77
> + reserved4: 26
> + reserved5: 0
> + -
> + reserved1: 4
> + reserved2: 93
> + reserved3: 77
> + reserved4: 26
> + reserved5: 0
> diff --git a/board/ti/j721e/pm-cfg.yaml b/board/ti/j721e/pm-cfg.yaml
> index 7ae52b3358e2..0d6b14de817a 100644
> --- a/board/ti/j721e/pm-cfg.yaml
> +++ b/board/ti/j721e/pm-cfg.yaml
> @@ -7,6 +7,94 @@
> ---
>
> pm-cfg:
> + pm_boardcfg:
> rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + boardcfg_abi_maj: 0x1
> + boardcfg_abi_min: 0x1
> + lpm_cfg:
> + subhdr:
> + magic: 0x4C41
> + size: 0x0C
> + suspend_initiator: 0xA
> + lpm_mode: 0x5
> + lpm_rsvd1: 0x0
> + lpm_rsvd2: 0x0
> + pll_cfg:
> + subhdr:
> + magic: 0xC31E
> + size: 0x54
> + pll_cfg_entries:
> + - # 1
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 2
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 3
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 4
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 5
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + dev_cfg:
> + subhdr:
> + magic: 0x74B1
> + size: 0x40
> + dev_cfg_entries:
> + - # 1
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xA
> + - # 2
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xA
> + - # 3
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xA
> + - # 4
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xA
> + - # 5
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xA
> + rsvd_pmic_cfg:
> + subhdr:
> + magic: 0x8A1D
> + size: 0x10
> + pmic_rsvd1: 0xA
> + pmic_rsvd2: 0xA
> + pmic_rsvd3: 0xA
> + rsvd_cfg:
> + subhdr:
> + magic: 0x3CFA
> + size: 0x12
> + rsvd1: 0x0
> + rsvd2: 0x0
> + rsvd3: 0x0
> + reserved_entry_size: 0x10
> +
> + reserved_entries:
> + -
> + reserved1: 4
> + reserved2: 93
> + reserved3: 7744
> + reserved4: 26
> + reserved5: 0
> + -
> + reserved1: 4
> + reserved2: 93
> + reserved3: 7744
> + reserved4: 26
> + reserved5: 0
> diff --git a/board/ti/j721s2/pm-cfg.yaml b/board/ti/j721s2/pm-cfg.yaml
> index e6496512b6b7..ce0435165c9e 100644
> --- a/board/ti/j721s2/pm-cfg.yaml
> +++ b/board/ti/j721s2/pm-cfg.yaml
> @@ -7,6 +7,94 @@
> ---
>
> pm-cfg:
> - rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + pm_boardcfg:
> + rev:
> + boardcfg_abi_maj: 0x1
> + boardcfg_abi_min: 0x1
> + lpm_cfg:
> + subhdr:
> + magic: 0x4C41
> + size: 0x0C
> + suspend_initiator: 0xA
> + lpm_mode: 0x5
> + lpm_rsvd1: 0x0
> + lpm_rsvd2: 0x0
> + pll_cfg:
> + subhdr:
> + magic: 0xC31E
> + size: 0x54
> + pll_cfg_entries:
> + - # 1
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 2
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 3
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 4
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 5
> + dev_id: 0x6
> + clk_id: 0x7
> + pll_freq: 0x8
> + dev_cfg:
> + subhdr:
> + magic: 0x74B1
> + size: 0x40
> + dev_cfg_entries:
> + - # 1
> + dev_id: 0xB
> + state: 0xD
> + flag: 0xE
> + - # 2
> + dev_id: 0xCC
> + state: 0xA
> + flag: 0xA
> + - # 3
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xA
> + - # 4
> + dev_id: 0xCC
> + state: 0xA
> + flag: 0xA
> + - # 5
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xCC
> + rsvd_pmic_cfg:
> + subhdr:
> + magic: 0x8A1D
> + size: 0x10
> + pmic_rsvd1: 0xA
> + pmic_rsvd2: 0xA
> + pmic_rsvd3: 0xDD
> + rsvd_cfg:
> + subhdr:
> + magic: 0x3CFA
> + size: 0x12
> + rsvd1: 0x0
> + rsvd2: 0x0
> + rsvd3: 0x0
> + reserved_entry_size: 0x10
> +
> + reserved_entries:
> + -
> + reserved1: 4
> + reserved2: 93
> + reserved3: 77
> + reserved4: 26
> + reserved5: 0
> + -
> + reserved1: 4
> + reserved2: 93
> + reserved3: 77
> + reserved4: 26
> + reserved5: 0
> diff --git a/board/ti/j722s/pm-cfg.yaml b/board/ti/j722s/pm-cfg.yaml
> index 46b3ad201091..ab1c8e06f10e 100644
> --- a/board/ti/j722s/pm-cfg.yaml
> +++ b/board/ti/j722s/pm-cfg.yaml
> @@ -7,6 +7,7 @@
> ---
>
> pm-cfg:
> - rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + pm_boardcfg:
> + rev:
> + boardcfg_abi_maj: 0x0
> + boardcfg_abi_min: 0x1
> diff --git a/board/ti/j784s4/pm-cfg.yaml b/board/ti/j784s4/pm-cfg.yaml
> index a36b86098998..cbe166808df9 100644
> --- a/board/ti/j784s4/pm-cfg.yaml
> +++ b/board/ti/j784s4/pm-cfg.yaml
> @@ -8,6 +8,94 @@
> ---
>
> pm-cfg:
> - rev:
> - boardcfg_abi_maj: 0x0
> - boardcfg_abi_min: 0x1
> + pm_boardcfg:
> + rev:
> + boardcfg_abi_maj: 0x1
> + boardcfg_abi_min: 0x1
> + lpm_cfg:
> + subhdr:
> + magic: 0x4C41
> + size: 0x0C
> + suspend_initiator: 0xA
> + lpm_mode: 0x5
> + lpm_rsvd1: 0x0
> + lpm_rsvd2: 0x0
> + pll_cfg:
> + subhdr:
> + magic: 0xC31E
> + size: 0x54
> + pll_cfg_entries:
> + - # 1
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 2
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 3
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 4
> + dev_id: 0xA
> + clk_id: 0xA
> + pll_freq: 0xA
> + - # 5
> + dev_id: 0x6
> + clk_id: 0x7
> + pll_freq: 0x8
> + dev_cfg:
> + subhdr:
> + magic: 0x74B1
> + size: 0x40
> + dev_cfg_entries:
> + - # 1
> + dev_id: 0xB
> + state: 0xD
> + flag: 0xE
> + - # 2
> + dev_id: 0xCC
> + state: 0xA
> + flag: 0xA
> + - # 3
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xA
> + - # 4
> + dev_id: 0xCC
> + state: 0xA
> + flag: 0xA
> + - # 5
> + dev_id: 0xA
> + state: 0xA
> + flag: 0xCC
> + rsvd_pmic_cfg:
> + subhdr:
> + magic: 0x8A1D
> + size: 0x10
> + pmic_rsvd1: 0xA
> + pmic_rsvd2: 0xA
> + pmic_rsvd3: 0xDD
> + rsvd_cfg:
> + subhdr:
> + magic: 0x3CFA
> + size: 0x12
> + rsvd1: 0x0
> + rsvd2: 0x0
> + rsvd3: 0x0
> + reserved_entry_size: 0x10
> +
> + reserved_entries:
> + -
> + reserved1: 4
> + reserved2: 93
> + reserved3: 77
> + reserved4: 26
> + reserved5: 0
> + -
> + reserved1: 4
> + reserved2: 93
> + reserved3: 77
> + reserved4: 26
> + reserved5: 0
> diff --git a/tools/binman/etype/ti_board_config.py b/tools/binman/etype/ti_board_config.py
> index 7c6773ac7bcd..b0cd055bf53e 100644
> --- a/tools/binman/etype/ti_board_config.py
> +++ b/tools/binman/etype/ti_board_config.py
> @@ -124,8 +124,10 @@ class Entry_ti_board_config(Entry_section):
> size = 1
> elif (data_type == '#/definitions/u16'):
> size = 2
> - else:
> + elif (data_type == '#/definitions/u32'):
> size = 4
> + else:
> + size = 8
> br = None
> if type(val) == int:
> br = val.to_bytes(size, byteorder='little')
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 17/20] board: evm: Enable de-isolation of IOs at resume for j7200 and j784s4
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (15 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 16/20] arm: mach-k3: Update pm-boardcfg for all k3 platforms Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 8:44 ` [PATCH 18/20] board: ti: evm: Store wakeup reason on scratchpad memory Richard Genoud (TI)
` (2 subsequent siblings)
19 siblings, 0 replies; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: Abhash Kumar Jha <a-kumar2@ti.com>
When resuming from IO_ONLY_PLUS_DDR low power mode, the IOs are
isolated. Remove that isolation in resume sequence.
On j7200, The canuart IOs are isolated whereas on j784s4, the
mcu_general IOs are isolated.
Signed-off-by: Abhash Kumar Jha <a-kumar2@ti.com>
---
.../arm/mach-k3/include/mach/j721e_hardware.h | 11 +++++++
.../mach-k3/include/mach/j784s4_hardware.h | 10 +++++++
board/ti/j721e/evm.c | 29 ++++++++++++++++++
board/ti/j784s4/evm.c | 30 +++++++++++++++++++
4 files changed, 80 insertions(+)
diff --git a/arch/arm/mach-k3/include/mach/j721e_hardware.h b/arch/arm/mach-k3/include/mach/j721e_hardware.h
index 5bef309af0a4..587dd10eb1ea 100644
--- a/arch/arm/mach-k3/include/mach/j721e_hardware.h
+++ b/arch/arm/mach-k3/include/mach/j721e_hardware.h
@@ -15,6 +15,17 @@
#define MCU_CTRL_MMR0_BASE 0x40f00000
#define CTRL_MMR0_BASE 0x00100000
+#define PMCTRL_IO_1 (DMSC_PWRCTRL_BASE + 0x88)
+#define DMSC_PWRCTRL_BASE 0x44130000
+#define CANUART_WAKE_CTRL 0x18300
+#define CANUART_WAKE_STAT0 0x18308
+#define CANUART_WAKE_STAT1 0x1830C
+
+#define IO_ISO_MAGIC_VAL 0x55555554
+#define IO_ISO_STATUS BIT(25)
+#define CANUART_WAKE_STAT1_CANUART_IO_MODE BIT(0)
+#define DEISOLATION_TIMEOUT_MS 10
+
#define CTRLMMR_MAIN_DEVSTAT (CTRL_MMR0_BASE + 0x30)
#define MAIN_DEVSTAT_BOOT_MODE_B_MASK BIT(0)
#define MAIN_DEVSTAT_BOOT_MODE_B_SHIFT 0
diff --git a/arch/arm/mach-k3/include/mach/j784s4_hardware.h b/arch/arm/mach-k3/include/mach/j784s4_hardware.h
index 29a894baed34..dd51473419dd 100644
--- a/arch/arm/mach-k3/include/mach/j784s4_hardware.h
+++ b/arch/arm/mach-k3/include/mach/j784s4_hardware.h
@@ -15,6 +15,16 @@
#define MCU_CTRL_MMR0_BASE 0x40f00000
#define CTRL_MMR0_BASE 0x00100000
+#define PMCTRL_IO_0 0x14084
+#define MCU_GEN_WAKE_CTRL 0x18310
+#define MCU_GEN_WAKE_STAT0 0x18318
+#define MCU_GEN_WAKE_STAT1 0x1831C
+
+#define IO_ISO_MAGIC_VAL 0x55555554
+#define IO_ISO_STATUS BIT(25)
+#define MCU_GEN_WAKE_STAT1_MCU_GEN_IO_MODE BIT(0)
+#define DEISOLATION_TIMEOUT_MS 10
+
#define CTRLMMR_MAIN_DEVSTAT (CTRL_MMR0_BASE + 0x30)
#define MAIN_DEVSTAT_BOOT_MODE_B_MASK BIT(0)
#define MAIN_DEVSTAT_BOOT_MODE_B_SHIFT 0
diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c
index 67ff13828514..41eea1bdea95 100644
--- a/board/ti/j721e/evm.c
+++ b/board/ti/j721e/evm.c
@@ -18,6 +18,7 @@
#include <dm.h>
#include <asm/arch/k3-ddr.h>
#include <power/pmic.h>
+#include <wait_bit.h>
#include "../common/board_detect.h"
#include "../common/fdt_ops.h"
@@ -473,14 +474,42 @@ err_free_gpio:
#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J7200_R5_EVM))
+static void clear_isolation(void)
+{
+ int ret;
+ const void *wait_reg = (const void *)(WKUP_CTRL_MMR0_BASE + CANUART_WAKE_STAT1);
+
+ /* un-set the magic word for canuart IOs */
+ writel(IO_ISO_MAGIC_VAL, WKUP_CTRL_MMR0_BASE + CANUART_WAKE_CTRL);
+ writel((IO_ISO_MAGIC_VAL + 0x1), WKUP_CTRL_MMR0_BASE + CANUART_WAKE_CTRL);
+ writel(IO_ISO_MAGIC_VAL, WKUP_CTRL_MMR0_BASE + CANUART_WAKE_CTRL);
+
+ /* wait for CANUART_IO_MODE bit to be cleared */
+ ret = wait_for_bit_32(wait_reg,
+ CANUART_WAKE_STAT1_CANUART_IO_MODE,
+ false,
+ DEISOLATION_TIMEOUT_MS,
+ false);
+ if (ret < 0)
+ pr_err("Deisolation timeout");
+}
+
bool j7xx_board_is_resuming(void)
{
struct udevice *pmica;
+ u32 pmctrl_val = readl(PMCTRL_IO_1);
int ret;
if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
goto end;
+ if ((pmctrl_val & IO_ISO_STATUS) == IO_ISO_STATUS) {
+ clear_isolation();
+ gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
+ debug("Resuming from IO_DDR mode\n");
+ goto end;
+ }
+
ret = uclass_get_device_by_name(UCLASS_PMIC,
"pmic@48", &pmica);
if (ret) {
diff --git a/board/ti/j784s4/evm.c b/board/ti/j784s4/evm.c
index 57c2f7018323..eef56556a33c 100644
--- a/board/ti/j784s4/evm.c
+++ b/board/ti/j784s4/evm.c
@@ -13,8 +13,10 @@
#include <spl.h>
#include <asm/arch/k3-ddr.h>
#include <power/pmic.h>
+#include <wait_bit.h>
#include "../common/fdt_ops.h"
#include "../common/k3-lpm.h"
+#include "../common.h"
DECLARE_GLOBAL_DATA_PTR;
@@ -66,15 +68,43 @@ int board_late_init(void)
#if (IS_ENABLED(CONFIG_SPL_BUILD) && (IS_ENABLED(CONFIG_TARGET_J784S4_R5_EVM) || \
IS_ENABLED(CONFIG_TARGET_J742S2_R5_EVM)))
+static void clear_isolation(void)
+{
+ int ret;
+ const void *wait_reg = (const void *)(WKUP_CTRL_MMR0_BASE + MCU_GEN_WAKE_STAT1);
+
+ /* un-set the magic word for MCU_GENERAL IOs */
+ writel(IO_ISO_MAGIC_VAL, WKUP_CTRL_MMR0_BASE + MCU_GEN_WAKE_CTRL);
+ writel((IO_ISO_MAGIC_VAL + 0x1), WKUP_CTRL_MMR0_BASE + MCU_GEN_WAKE_CTRL);
+ writel(IO_ISO_MAGIC_VAL, WKUP_CTRL_MMR0_BASE + MCU_GEN_WAKE_CTRL);
+
+ /* wait for MCU_GEN_IO_MODE bit to be cleared */
+ ret = wait_for_bit_32(wait_reg,
+ MCU_GEN_WAKE_STAT1_MCU_GEN_IO_MODE,
+ false,
+ DEISOLATION_TIMEOUT_MS,
+ false);
+ if (ret < 0)
+ pr_err("Deisolation timeout");
+}
+
/* 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;
+ u32 pmctrl_val = readl(WKUP_CTRL_MMR0_BASE + PMCTRL_IO_0);
int err;
if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
goto end;
+ if ((pmctrl_val & IO_ISO_STATUS) == IO_ISO_STATUS) {
+ clear_isolation();
+ gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
+ debug("board is resuming from IO_DDR mode\n");
+ goto end;
+ }
+
err = uclass_get_device_by_name(UCLASS_PMIC,
"pmic@48", &pmic);
if (err) {
^ permalink raw reply related [flat|nested] 32+ messages in thread* [PATCH 18/20] board: ti: evm: Store wakeup reason on scratchpad memory
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (16 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 17/20] board: evm: Enable de-isolation of IOs at resume for j7200 and j784s4 Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 17:32 ` Andrew Davis
2026-04-30 8:44 ` [PATCH 19/20] arm: dts: k3-j7200: Remove background firewall on DDR Richard Genoud (TI)
2026-04-30 8:44 ` [PATCH 20/20] arm: dts: k3-j7200: Extend firewall for ATF region to TIFS Richard Genoud (TI)
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: Abhash Kumar Jha <a-kumar2@ti.com>
While resuming from suspend, the wakeup reason need to be stored
and this will be used by the Linux kernel once its up.
Use the 32 bytes of MCU_PSRAM0_RAM area (addr = 0x40280000) to
store the wakeup reason.
Read the value as soon as it starts and store it internally.
Signed-off-by: Abhash Kumar Jha <a-kumar2@ti.com>
---
arch/arm/mach-k3/include/mach/j721e_hardware.h | 1 +
arch/arm/mach-k3/include/mach/j784s4_hardware.h | 1 +
board/ti/common/k3-lpm.h | 5 +++++
board/ti/j721e/evm.c | 9 +++++++++
board/ti/j784s4/evm.c | 9 +++++++++
5 files changed, 25 insertions(+)
diff --git a/arch/arm/mach-k3/include/mach/j721e_hardware.h b/arch/arm/mach-k3/include/mach/j721e_hardware.h
index 587dd10eb1ea..d58e2b3e1bb2 100644
--- a/arch/arm/mach-k3/include/mach/j721e_hardware.h
+++ b/arch/arm/mach-k3/include/mach/j721e_hardware.h
@@ -47,6 +47,7 @@
/* MCU SCRATCHPAD usage */
#define TI_SRAM_SCRATCH_BOARD_EEPROM_START CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE
+#define TI_SRAM_SCRATCH_LPM_START 0x40280000
#if defined(CONFIG_SYS_K3_SPL_ATF) && !defined(__ASSEMBLY__)
diff --git a/arch/arm/mach-k3/include/mach/j784s4_hardware.h b/arch/arm/mach-k3/include/mach/j784s4_hardware.h
index dd51473419dd..2fc81902f879 100644
--- a/arch/arm/mach-k3/include/mach/j784s4_hardware.h
+++ b/arch/arm/mach-k3/include/mach/j784s4_hardware.h
@@ -46,6 +46,7 @@
/* MCU SCRATCHPAD usage */
#define TI_SRAM_SCRATCH_BOARD_EEPROM_START CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE
+#define TI_SRAM_SCRATCH_LPM_START 0x40280000
#if defined(CONFIG_SYS_K3_SPL_ATF) && !defined(__ASSEMBLY__)
diff --git a/board/ti/common/k3-lpm.h b/board/ti/common/k3-lpm.h
index a2141a0c25a8..dfd8f8486f08 100644
--- a/board/ti/common/k3-lpm.h
+++ b/board/ti/common/k3-lpm.h
@@ -13,5 +13,10 @@
/* PMIC register where the magic value resides */
#define K3_LPM_SCRATCH_PAD_REG 0xcb
+struct lpm_scratch_space {
+ u16 wake_src;
+ u16 reserved;
+} __packed;
+
#endif /* __K3_LPM_H */
diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c
index 41eea1bdea95..a9f469fea1f7 100644
--- a/board/ti/j721e/evm.c
+++ b/board/ti/j721e/evm.c
@@ -474,6 +474,9 @@ err_free_gpio:
#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J7200_R5_EVM))
+#define LPM_WAKE_SOURCE_PMIC_GPIO 0x91
+#define LPM_WAKE_SOURCE_MAIN_IO 0x80
+
static void clear_isolation(void)
{
int ret;
@@ -498,12 +501,15 @@ bool j7xx_board_is_resuming(void)
{
struct udevice *pmica;
u32 pmctrl_val = readl(PMCTRL_IO_1);
+ struct lpm_scratch_space *lpm_scratch;
int ret;
if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
goto end;
+ lpm_scratch = (struct lpm_scratch_space *)TI_SRAM_SCRATCH_LPM_START;
if ((pmctrl_val & IO_ISO_STATUS) == IO_ISO_STATUS) {
+ lpm_scratch->wake_src = LPM_WAKE_SOURCE_MAIN_IO;
clear_isolation();
gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
debug("Resuming from IO_DDR mode\n");
@@ -520,6 +526,7 @@ bool j7xx_board_is_resuming(void)
if (pmic_reg_read(pmica, K3_LPM_SCRATCH_PAD_REG) == K3_LPM_MAGIC_SUSPEND) {
debug("%s: board is resuming\n", __func__);
+ lpm_scratch->wake_src = LPM_WAKE_SOURCE_PMIC_GPIO;
gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
/* clean magic suspend */
@@ -527,6 +534,8 @@ bool j7xx_board_is_resuming(void)
printf("Failed to clean magic value for suspend detection in PMICA\n");
} else {
debug("%s: board is booting (no resume detected)\n", __func__);
+ lpm_scratch->wake_src = 0;
+ lpm_scratch->reserved = 0;
gd_set_k3_resuming(K3_RESUME_STATE_BOOTING);
}
end:
diff --git a/board/ti/j784s4/evm.c b/board/ti/j784s4/evm.c
index eef56556a33c..b94ec7f3653b 100644
--- a/board/ti/j784s4/evm.c
+++ b/board/ti/j784s4/evm.c
@@ -68,6 +68,9 @@ int board_late_init(void)
#if (IS_ENABLED(CONFIG_SPL_BUILD) && (IS_ENABLED(CONFIG_TARGET_J784S4_R5_EVM) || \
IS_ENABLED(CONFIG_TARGET_J742S2_R5_EVM)))
+#define LPM_WAKE_SOURCE_PMIC_GPIO 0x91
+#define LPM_WAKE_SOURCE_MCU_IO 0x81
+
static void clear_isolation(void)
{
int ret;
@@ -93,12 +96,15 @@ bool j7xx_board_is_resuming(void)
{
struct udevice *pmic;
u32 pmctrl_val = readl(WKUP_CTRL_MMR0_BASE + PMCTRL_IO_0);
+ struct lpm_scratch_space *lpm_scratch;
int err;
if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
goto end;
+ lpm_scratch = (struct lpm_scratch_space *)TI_SRAM_SCRATCH_LPM_START;
if ((pmctrl_val & IO_ISO_STATUS) == IO_ISO_STATUS) {
+ lpm_scratch->wake_src = LPM_WAKE_SOURCE_MCU_IO;
clear_isolation();
gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
debug("board is resuming from IO_DDR mode\n");
@@ -115,6 +121,7 @@ bool j7xx_board_is_resuming(void)
if (pmic_reg_read(pmic, K3_LPM_SCRATCH_PAD_REG) == K3_LPM_MAGIC_SUSPEND) {
debug("%s: board is resuming\n", __func__);
+ lpm_scratch->wake_src = LPM_WAKE_SOURCE_PMIC_GPIO;
gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
/* clean magic suspend */
@@ -122,6 +129,8 @@ bool j7xx_board_is_resuming(void)
printf("Failed to clean magic value for suspend detection in PMIC\n");
} else {
debug("%s: board is booting (no resume detected)\n", __func__);
+ lpm_scratch->wake_src = 0;
+ lpm_scratch->reserved = 0;
gd_set_k3_resuming(K3_RESUME_STATE_BOOTING);
}
end:
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 18/20] board: ti: evm: Store wakeup reason on scratchpad memory
2026-04-30 8:44 ` [PATCH 18/20] board: ti: evm: Store wakeup reason on scratchpad memory Richard Genoud (TI)
@ 2026-04-30 17:32 ` Andrew Davis
0 siblings, 0 replies; 32+ messages in thread
From: Andrew Davis @ 2026-04-30 17:32 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Apurva Nandan,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/26 3:44 AM, Richard Genoud (TI) wrote:
> From: Abhash Kumar Jha <a-kumar2@ti.com>
>
> While resuming from suspend, the wakeup reason need to be stored
> and this will be used by the Linux kernel once its up.
>
> Use the 32 bytes of MCU_PSRAM0_RAM area (addr = 0x40280000) to
> store the wakeup reason.
>
> Read the value as soon as it starts and store it internally.
>
> Signed-off-by: Abhash Kumar Jha <a-kumar2@ti.com>
> ---
> arch/arm/mach-k3/include/mach/j721e_hardware.h | 1 +
> arch/arm/mach-k3/include/mach/j784s4_hardware.h | 1 +
> board/ti/common/k3-lpm.h | 5 +++++
> board/ti/j721e/evm.c | 9 +++++++++
> board/ti/j784s4/evm.c | 9 +++++++++
> 5 files changed, 25 insertions(+)
>
> diff --git a/arch/arm/mach-k3/include/mach/j721e_hardware.h b/arch/arm/mach-k3/include/mach/j721e_hardware.h
> index 587dd10eb1ea..d58e2b3e1bb2 100644
> --- a/arch/arm/mach-k3/include/mach/j721e_hardware.h
> +++ b/arch/arm/mach-k3/include/mach/j721e_hardware.h
> @@ -47,6 +47,7 @@
>
> /* MCU SCRATCHPAD usage */
> #define TI_SRAM_SCRATCH_BOARD_EEPROM_START CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE
> +#define TI_SRAM_SCRATCH_LPM_START 0x40280000
Should this be a Kconfig option?
Andrew
>
> #if defined(CONFIG_SYS_K3_SPL_ATF) && !defined(__ASSEMBLY__)
>
> diff --git a/arch/arm/mach-k3/include/mach/j784s4_hardware.h b/arch/arm/mach-k3/include/mach/j784s4_hardware.h
> index dd51473419dd..2fc81902f879 100644
> --- a/arch/arm/mach-k3/include/mach/j784s4_hardware.h
> +++ b/arch/arm/mach-k3/include/mach/j784s4_hardware.h
> @@ -46,6 +46,7 @@
>
> /* MCU SCRATCHPAD usage */
> #define TI_SRAM_SCRATCH_BOARD_EEPROM_START CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE
> +#define TI_SRAM_SCRATCH_LPM_START 0x40280000
>
> #if defined(CONFIG_SYS_K3_SPL_ATF) && !defined(__ASSEMBLY__)
>
> diff --git a/board/ti/common/k3-lpm.h b/board/ti/common/k3-lpm.h
> index a2141a0c25a8..dfd8f8486f08 100644
> --- a/board/ti/common/k3-lpm.h
> +++ b/board/ti/common/k3-lpm.h
> @@ -13,5 +13,10 @@
> /* PMIC register where the magic value resides */
> #define K3_LPM_SCRATCH_PAD_REG 0xcb
>
> +struct lpm_scratch_space {
> + u16 wake_src;
> + u16 reserved;
> +} __packed;
> +
> #endif /* __K3_LPM_H */
>
> diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c
> index 41eea1bdea95..a9f469fea1f7 100644
> --- a/board/ti/j721e/evm.c
> +++ b/board/ti/j721e/evm.c
> @@ -474,6 +474,9 @@ err_free_gpio:
>
> #if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J7200_R5_EVM))
>
> +#define LPM_WAKE_SOURCE_PMIC_GPIO 0x91
> +#define LPM_WAKE_SOURCE_MAIN_IO 0x80
> +
> static void clear_isolation(void)
> {
> int ret;
> @@ -498,12 +501,15 @@ bool j7xx_board_is_resuming(void)
> {
> struct udevice *pmica;
> u32 pmctrl_val = readl(PMCTRL_IO_1);
> + struct lpm_scratch_space *lpm_scratch;
> int ret;
>
> if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
> goto end;
>
> + lpm_scratch = (struct lpm_scratch_space *)TI_SRAM_SCRATCH_LPM_START;
> if ((pmctrl_val & IO_ISO_STATUS) == IO_ISO_STATUS) {
> + lpm_scratch->wake_src = LPM_WAKE_SOURCE_MAIN_IO;
> clear_isolation();
> gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
> debug("Resuming from IO_DDR mode\n");
> @@ -520,6 +526,7 @@ bool j7xx_board_is_resuming(void)
>
> if (pmic_reg_read(pmica, K3_LPM_SCRATCH_PAD_REG) == K3_LPM_MAGIC_SUSPEND) {
> debug("%s: board is resuming\n", __func__);
> + lpm_scratch->wake_src = LPM_WAKE_SOURCE_PMIC_GPIO;
> gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
>
> /* clean magic suspend */
> @@ -527,6 +534,8 @@ bool j7xx_board_is_resuming(void)
> printf("Failed to clean magic value for suspend detection in PMICA\n");
> } else {
> debug("%s: board is booting (no resume detected)\n", __func__);
> + lpm_scratch->wake_src = 0;
> + lpm_scratch->reserved = 0;
> gd_set_k3_resuming(K3_RESUME_STATE_BOOTING);
> }
> end:
> diff --git a/board/ti/j784s4/evm.c b/board/ti/j784s4/evm.c
> index eef56556a33c..b94ec7f3653b 100644
> --- a/board/ti/j784s4/evm.c
> +++ b/board/ti/j784s4/evm.c
> @@ -68,6 +68,9 @@ int board_late_init(void)
> #if (IS_ENABLED(CONFIG_SPL_BUILD) && (IS_ENABLED(CONFIG_TARGET_J784S4_R5_EVM) || \
> IS_ENABLED(CONFIG_TARGET_J742S2_R5_EVM)))
>
> +#define LPM_WAKE_SOURCE_PMIC_GPIO 0x91
> +#define LPM_WAKE_SOURCE_MCU_IO 0x81
> +
> static void clear_isolation(void)
> {
> int ret;
> @@ -93,12 +96,15 @@ bool j7xx_board_is_resuming(void)
> {
> struct udevice *pmic;
> u32 pmctrl_val = readl(WKUP_CTRL_MMR0_BASE + PMCTRL_IO_0);
> + struct lpm_scratch_space *lpm_scratch;
> int err;
>
> if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
> goto end;
>
> + lpm_scratch = (struct lpm_scratch_space *)TI_SRAM_SCRATCH_LPM_START;
> if ((pmctrl_val & IO_ISO_STATUS) == IO_ISO_STATUS) {
> + lpm_scratch->wake_src = LPM_WAKE_SOURCE_MCU_IO;
> clear_isolation();
> gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
> debug("board is resuming from IO_DDR mode\n");
> @@ -115,6 +121,7 @@ bool j7xx_board_is_resuming(void)
>
> if (pmic_reg_read(pmic, K3_LPM_SCRATCH_PAD_REG) == K3_LPM_MAGIC_SUSPEND) {
> debug("%s: board is resuming\n", __func__);
> + lpm_scratch->wake_src = LPM_WAKE_SOURCE_PMIC_GPIO;
> gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
>
> /* clean magic suspend */
> @@ -122,6 +129,8 @@ bool j7xx_board_is_resuming(void)
> printf("Failed to clean magic value for suspend detection in PMIC\n");
> } else {
> debug("%s: board is booting (no resume detected)\n", __func__);
> + lpm_scratch->wake_src = 0;
> + lpm_scratch->reserved = 0;
> gd_set_k3_resuming(K3_RESUME_STATE_BOOTING);
> }
> end:
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 19/20] arm: dts: k3-j7200: Remove background firewall on DDR
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (17 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 18/20] board: ti: evm: Store wakeup reason on scratchpad memory Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 17:30 ` Andrew Davis
2026-04-30 8:44 ` [PATCH 20/20] arm: dts: k3-j7200: Extend firewall for ATF region to TIFS Richard Genoud (TI)
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: Prasanth Babu Mantena <p-mantena@ti.com>
With updated TIFS version tag v11.02.06, the background firewall
for DDR firewalls are applied by the TIFS. This removes the
dependency of applying firewalls through binman.
Remove background firewall on the whole DDR, as this
background firewall is applied by the TIFS init for j7200
and j784s4. Modify for j7200 only, as there are no firewalls applied
for j784s4 from SPL.
Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
---
arch/arm/dts/k3-j7200-binman.dtsi | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/arch/arm/dts/k3-j7200-binman.dtsi b/arch/arm/dts/k3-j7200-binman.dtsi
index b4e0ce8bfcf2..c2b86339d593 100644
--- a/arch/arm/dts/k3-j7200-binman.dtsi
+++ b/arch/arm/dts/k3-j7200-binman.dtsi
@@ -294,13 +294,6 @@
region = <2>;
};
- firewall-4762-0 {
- /* nb_slv2__mem0 Background Firewall - 0 */
- insert-template = <&firewall_bg_3>;
- id = <4762>;
- region = <0>;
- };
-
firewall-4762-1 {
/* nb_slv2__mem0 Foreground Firewall */
insert-template = <&firewall_armv8_optee_fg>;
@@ -308,13 +301,6 @@
region = <1>;
};
- firewall-4763-0 {
- /* nb_slv3__mem0 Background Firewall - 0 */
- insert-template = <&firewall_bg_3>;
- id = <4763>;
- region = <0>;
- };
-
firewall-4763-1 {
/* nb_slv3__mem0 Foreground Firewall */
insert-template = <&firewall_armv8_optee_fg>;
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 19/20] arm: dts: k3-j7200: Remove background firewall on DDR
2026-04-30 8:44 ` [PATCH 19/20] arm: dts: k3-j7200: Remove background firewall on DDR Richard Genoud (TI)
@ 2026-04-30 17:30 ` Andrew Davis
2026-05-11 10:56 ` Kumar, Udit
0 siblings, 1 reply; 32+ messages in thread
From: Andrew Davis @ 2026-04-30 17:30 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Apurva Nandan,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/26 3:44 AM, Richard Genoud (TI) wrote:
> From: Prasanth Babu Mantena <p-mantena@ti.com>
>
> With updated TIFS version tag v11.02.06, the background firewall
> for DDR firewalls are applied by the TIFS. This removes the
> dependency of applying firewalls through binman.
>
Does this then create a dependency on using a TIFS firmware
equal or newer than v11.02.06 when using a new U-Boot?
Andrew
> Remove background firewall on the whole DDR, as this
> background firewall is applied by the TIFS init for j7200
> and j784s4. Modify for j7200 only, as there are no firewalls applied
> for j784s4 from SPL.
>
> Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
> ---
> arch/arm/dts/k3-j7200-binman.dtsi | 14 --------------
> 1 file changed, 14 deletions(-)
>
> diff --git a/arch/arm/dts/k3-j7200-binman.dtsi b/arch/arm/dts/k3-j7200-binman.dtsi
> index b4e0ce8bfcf2..c2b86339d593 100644
> --- a/arch/arm/dts/k3-j7200-binman.dtsi
> +++ b/arch/arm/dts/k3-j7200-binman.dtsi
> @@ -294,13 +294,6 @@
> region = <2>;
> };
>
> - firewall-4762-0 {
> - /* nb_slv2__mem0 Background Firewall - 0 */
> - insert-template = <&firewall_bg_3>;
> - id = <4762>;
> - region = <0>;
> - };
> -
> firewall-4762-1 {
> /* nb_slv2__mem0 Foreground Firewall */
> insert-template = <&firewall_armv8_optee_fg>;
> @@ -308,13 +301,6 @@
> region = <1>;
> };
>
> - firewall-4763-0 {
> - /* nb_slv3__mem0 Background Firewall - 0 */
> - insert-template = <&firewall_bg_3>;
> - id = <4763>;
> - region = <0>;
> - };
> -
> firewall-4763-1 {
> /* nb_slv3__mem0 Foreground Firewall */
> insert-template = <&firewall_armv8_optee_fg>;
^ permalink raw reply [flat|nested] 32+ messages in thread* Re: [PATCH 19/20] arm: dts: k3-j7200: Remove background firewall on DDR
2026-04-30 17:30 ` Andrew Davis
@ 2026-05-11 10:56 ` Kumar, Udit
0 siblings, 0 replies; 32+ messages in thread
From: Kumar, Udit @ 2026-05-11 10:56 UTC (permalink / raw)
To: Andrew Davis, Richard Genoud (TI), Tom Rini, Manorit Chawdhry,
Apurva Nandan, Vignesh Raghavendra, Bryan Brattlof,
Vaishnav Achath, Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Abhash Kumar, Thomas Richard,
Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/2026 11:00 PM, Andrew Davis wrote:
> On 4/30/26 3:44 AM, Richard Genoud (TI) wrote:
>> From: Prasanth Babu Mantena <p-mantena@ti.com>
>>
>> With updated TIFS version tag v11.02.06, the background firewall
>> for DDR firewalls are applied by the TIFS. This removes the
>> dependency of applying firewalls through binman.
>>
>
> Does this then create a dependency on using a TIFS firmware
> equal or newer than v11.02.06 when using a new U-Boot?
>
> Andrew
>
I am not sure, how this will behave but we have to keep backward and
forward compatibility
>> Remove background firewall on the whole DDR, as this
>> background firewall is applied by the TIFS init for j7200
>> and j784s4. Modify for j7200 only, as there are no firewalls applied
>> for j784s4 from SPL.
>>
>> Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
>> ---
>> arch/arm/dts/k3-j7200-binman.dtsi | 14 --------------
>> 1 file changed, 14 deletions(-)
>>
>> diff --git a/arch/arm/dts/k3-j7200-binman.dtsi b/arch/arm/dts/k3-
>> j7200-binman.dtsi
>> index b4e0ce8bfcf2..c2b86339d593 100644
>> --- a/arch/arm/dts/k3-j7200-binman.dtsi
>> +++ b/arch/arm/dts/k3-j7200-binman.dtsi
>> @@ -294,13 +294,6 @@
>> region = <2>;
>> };
>> - firewall-4762-0 {
>> - /* nb_slv2__mem0 Background Firewall - 0 */
>> - insert-template = <&firewall_bg_3>;
>> - id = <4762>;
>> - region = <0>;
>> - };
>> -
>> firewall-4762-1 {
>> /* nb_slv2__mem0 Foreground Firewall */
>> insert-template =
>> <&firewall_armv8_optee_fg>;
>> @@ -308,13 +301,6 @@
>> region = <1>;
>> };
>> - firewall-4763-0 {
>> - /* nb_slv3__mem0 Background Firewall - 0 */
>> - insert-template = <&firewall_bg_3>;
>> - id = <4763>;
>> - region = <0>;
>> - };
>> -
>> firewall-4763-1 {
>> /* nb_slv3__mem0 Foreground Firewall */
>> insert-template =
>> <&firewall_armv8_optee_fg>;
>
^ permalink raw reply [flat|nested] 32+ messages in thread
* [PATCH 20/20] arm: dts: k3-j7200: Extend firewall for ATF region to TIFS
2026-04-30 8:43 [PATCH 00/20] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (18 preceding siblings ...)
2026-04-30 8:44 ` [PATCH 19/20] arm: dts: k3-j7200: Remove background firewall on DDR Richard Genoud (TI)
@ 2026-04-30 8:44 ` Richard Genoud (TI)
2026-04-30 17:28 ` Andrew Davis
19 siblings, 1 reply; 32+ messages in thread
From: Richard Genoud (TI) @ 2026-04-30 8:44 UTC (permalink / raw)
To: Tom Rini, Manorit Chawdhry, Apurva Nandan, Andrew F . Davis,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, Richard Genoud,
u-boot
From: Prasanth Babu Mantena <p-mantena@ti.com>
Extend the access to SRAM region of ATF to TIFS as well. This is
needed for TIFS for encryption and decryption of ATF as a part of
low power mode sequence. TIFS encrypts the ATF while entering into
low power mode and decrypts it back while resuming back.
So, giving permissions for TIFS to access this region.
Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
---
arch/arm/dts/k3-binman.dtsi | 18 ++++++++++++++++--
arch/arm/dts/k3-j7200-binman.dtsi | 4 ++--
arch/arm/dts/k3-security.h | 1 +
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/arch/arm/dts/k3-binman.dtsi b/arch/arm/dts/k3-binman.dtsi
index 0fd93f9536a2..4ffd8ec9e1c1 100644
--- a/arch/arm/dts/k3-binman.dtsi
+++ b/arch/arm/dts/k3-binman.dtsi
@@ -479,7 +479,21 @@
start_address = <0x0 CONFIG_K3_ATF_LOAD_ADDR>;
end_address = <0x0 (CONFIG_K3_ATF_LOAD_ADDR + 0x1ffff)>;
};
- firewall_armv8_optee_fg: template-8 {
+ firewall_armv8_atf_tifs_fg: template-8 {
+ control = <(FWCTRL_EN | FWCTRL_LOCK |
+ FWCTRL_CACHE)>;
+ permissions = <((FWPRIVID_ARMV8 << FWPRIVID_SHIFT) |
+ FWPERM_SECURE_PRIV_RWCD |
+ FWPERM_SECURE_USER_RWCD)>,
+ <((FWPRIVID_TIFS << FWPRIVID_SHIFT) |
+ FWPERM_SECURE_PRIV_RWCD |
+ FWPERM_SECURE_USER_RWCD |
+ FWPERM_NON_SECURE_PRIV_RWCD |
+ FWPERM_NON_SECURE_USER_RWCD)>;
+ start_address = <0x0 0x70000000>;
+ end_address = <0x0 0x7001ffff>;
+ };
+ firewall_armv8_optee_fg: template-9 {
control = <(FWCTRL_EN | FWCTRL_LOCK |
FWCTRL_CACHE)>;
permissions = <((FWPRIVID_ARMV8 << FWPRIVID_SHIFT) |
@@ -489,7 +503,7 @@
end_address = <0x0 (CONFIG_K3_OPTEE_LOAD_ADDR + 0x17fffff)>;
};
- ti_falcon_template: template-9 {
+ ti_falcon_template: template-10 {
filename = "tifalcon.bin";
pad-byte = <0xff>;
diff --git a/arch/arm/dts/k3-j7200-binman.dtsi b/arch/arm/dts/k3-j7200-binman.dtsi
index c2b86339d593..68ce4aa0ff12 100644
--- a/arch/arm/dts/k3-j7200-binman.dtsi
+++ b/arch/arm/dts/k3-j7200-binman.dtsi
@@ -259,7 +259,7 @@
firewall-4760-1 {
/* nb_slv0__mem0 Foreground Firewall */
- insert-template = <&firewall_armv8_atf_fg>;
+ insert-template = <&firewall_armv8_atf_tifs_fg>;
id = <4760>;
region = <1>;
};
@@ -272,7 +272,7 @@
firewall-4761-1 {
/* nb_slv1__mem0 Foreground Firewall */
- insert-template = <&firewall_armv8_atf_fg>;
+ insert-template = <&firewall_armv8_atf_tifs_fg>;
id = <4761>;
region = <1>;
};
diff --git a/arch/arm/dts/k3-security.h b/arch/arm/dts/k3-security.h
index 33609caa8fb5..3e066bca6ad7 100644
--- a/arch/arm/dts/k3-security.h
+++ b/arch/arm/dts/k3-security.h
@@ -7,6 +7,7 @@
#define DTS_ARM64_TI_K3_FIREWALL_H
#define FWPRIVID_ALL 0xc3
+#define FWPRIVID_TIFS 0xca
#define FWPRIVID_ARMV8 1
#define FWPRIVID_SHIFT 16
^ permalink raw reply related [flat|nested] 32+ messages in thread* Re: [PATCH 20/20] arm: dts: k3-j7200: Extend firewall for ATF region to TIFS
2026-04-30 8:44 ` [PATCH 20/20] arm: dts: k3-j7200: Extend firewall for ATF region to TIFS Richard Genoud (TI)
@ 2026-04-30 17:28 ` Andrew Davis
0 siblings, 0 replies; 32+ messages in thread
From: Andrew Davis @ 2026-04-30 17:28 UTC (permalink / raw)
To: Richard Genoud (TI), Tom Rini, Manorit Chawdhry, Apurva Nandan,
Vignesh Raghavendra, Bryan Brattlof, Vaishnav Achath,
Jayesh Choudhary, Simon Glass, Alper Nebi Yasak
Cc: Markus Schneider-Pargmann, Udit Kumar, Abhash Kumar,
Thomas Richard, Gregory CLEMENT, Thomas Petazzoni, u-boot
On 4/30/26 3:44 AM, Richard Genoud (TI) wrote:
> From: Prasanth Babu Mantena <p-mantena@ti.com>
>
> Extend the access to SRAM region of ATF to TIFS as well. This is
> needed for TIFS for encryption and decryption of ATF as a part of
> low power mode sequence. TIFS encrypts the ATF while entering into
> low power mode and decrypts it back while resuming back.
> So, giving permissions for TIFS to access this region.
>
> Signed-off-by: Prasanth Babu Mantena <p-mantena@ti.com>
> ---
> arch/arm/dts/k3-binman.dtsi | 18 ++++++++++++++++--
> arch/arm/dts/k3-j7200-binman.dtsi | 4 ++--
> arch/arm/dts/k3-security.h | 1 +
> 3 files changed, 19 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/dts/k3-binman.dtsi b/arch/arm/dts/k3-binman.dtsi
> index 0fd93f9536a2..4ffd8ec9e1c1 100644
> --- a/arch/arm/dts/k3-binman.dtsi
> +++ b/arch/arm/dts/k3-binman.dtsi
> @@ -479,7 +479,21 @@
> start_address = <0x0 CONFIG_K3_ATF_LOAD_ADDR>;
> end_address = <0x0 (CONFIG_K3_ATF_LOAD_ADDR + 0x1ffff)>;
> };
> - firewall_armv8_optee_fg: template-8 {
> + firewall_armv8_atf_tifs_fg: template-8 {
> + control = <(FWCTRL_EN | FWCTRL_LOCK |
> + FWCTRL_CACHE)>;
> + permissions = <((FWPRIVID_ARMV8 << FWPRIVID_SHIFT) |
> + FWPERM_SECURE_PRIV_RWCD |
> + FWPERM_SECURE_USER_RWCD)>,
> + <((FWPRIVID_TIFS << FWPRIVID_SHIFT) |
> + FWPERM_SECURE_PRIV_RWCD |
> + FWPERM_SECURE_USER_RWCD |
> + FWPERM_NON_SECURE_PRIV_RWCD |
> + FWPERM_NON_SECURE_USER_RWCD)>;
> + start_address = <0x0 0x70000000>;
Should this be using CONFIG_K3_ATF_LOAD_ADDR like the other templates?
Might be easier to just update the existing `firewall_armv8_atf_fg`
template to also always allow TIFS. TIFS is the security root and
if it really wanted to it could just update firewalls to let itself
in, not like anything is really protected from TIFS to begin with.
(if we are not locking the firewalls that is)
Andrew
> + end_address = <0x0 0x7001ffff>;
> + };
> + firewall_armv8_optee_fg: template-9 {
> control = <(FWCTRL_EN | FWCTRL_LOCK |
> FWCTRL_CACHE)>;
> permissions = <((FWPRIVID_ARMV8 << FWPRIVID_SHIFT) |
> @@ -489,7 +503,7 @@
> end_address = <0x0 (CONFIG_K3_OPTEE_LOAD_ADDR + 0x17fffff)>;
> };
>
> - ti_falcon_template: template-9 {
> + ti_falcon_template: template-10 {
> filename = "tifalcon.bin";
> pad-byte = <0xff>;
>
> diff --git a/arch/arm/dts/k3-j7200-binman.dtsi b/arch/arm/dts/k3-j7200-binman.dtsi
> index c2b86339d593..68ce4aa0ff12 100644
> --- a/arch/arm/dts/k3-j7200-binman.dtsi
> +++ b/arch/arm/dts/k3-j7200-binman.dtsi
> @@ -259,7 +259,7 @@
>
> firewall-4760-1 {
> /* nb_slv0__mem0 Foreground Firewall */
> - insert-template = <&firewall_armv8_atf_fg>;
> + insert-template = <&firewall_armv8_atf_tifs_fg>;
> id = <4760>;
> region = <1>;
> };
> @@ -272,7 +272,7 @@
>
> firewall-4761-1 {
> /* nb_slv1__mem0 Foreground Firewall */
> - insert-template = <&firewall_armv8_atf_fg>;
> + insert-template = <&firewall_armv8_atf_tifs_fg>;
> id = <4761>;
> region = <1>;
> };
> diff --git a/arch/arm/dts/k3-security.h b/arch/arm/dts/k3-security.h
> index 33609caa8fb5..3e066bca6ad7 100644
> --- a/arch/arm/dts/k3-security.h
> +++ b/arch/arm/dts/k3-security.h
> @@ -7,6 +7,7 @@
> #define DTS_ARM64_TI_K3_FIREWALL_H
>
> #define FWPRIVID_ALL 0xc3
> +#define FWPRIVID_TIFS 0xca
> #define FWPRIVID_ARMV8 1
> #define FWPRIVID_SHIFT 16
>
^ permalink raw reply [flat|nested] 32+ messages in thread