* [PATCH v5 01/21] ram: k3-ddrss: Add support for DDR in self-refresh
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 02/21] firmware: ti_sci: Add TI_SCI_MSG_MIN_CONTEXT_RESTORE Richard Genoud (TI)
` (19 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, Udit Kumar,
Abhash Kumar, Thomas Richard, Gregory CLEMENT, Thomas Petazzoni,
Richard Genoud, u-boot
From: "Markus Schneider-Pargmann (TI)" <msp@baylibre.com>
In IO+DDR the DDR is kept in self-refresh while the SoC cores are
powered off completely. During boot the normal initialization routine of
DDR is slightly different to exit self-refresh and keep the DDR contents.
Signed-off-by: Markus Schneider-Pargmann (TI) <msp@baylibre.com>
---
| 1 +
| 181 ++++++++++++++++++++++++++++
| 20 +++
| 26 +++-
4 files changed, 227 insertions(+), 1 deletion(-)
create mode 100644 drivers/ram/k3-ddrss/k3-ddrss-lpm.c
create mode 100644 drivers/ram/k3-ddrss/k3-ddrss-lpm.h
--git a/drivers/ram/k3-ddrss/Makefile b/drivers/ram/k3-ddrss/Makefile
index bb7dc05e3d99..a125675a2931 100644
--- a/drivers/ram/k3-ddrss/Makefile
+++ b/drivers/ram/k3-ddrss/Makefile
@@ -4,6 +4,7 @@
#
obj-$(CONFIG_K3_DDRSS) += k3-ddrss.o
+obj-$(CONFIG_K3_DDRSS) += k3-ddrss-lpm.o
obj-$(CONFIG_K3_DDRSS) += lpddr4_obj_if.o
obj-$(CONFIG_K3_DDRSS) += lpddr4.o
ccflags-$(CONFIG_K3_DDRSS) += -I$(srctree)/drivers/ram/k3-ddrss/
--git a/drivers/ram/k3-ddrss/k3-ddrss-lpm.c b/drivers/ram/k3-ddrss/k3-ddrss-lpm.c
new file mode 100644
index 000000000000..20181d0a876d
--- /dev/null
+++ b/drivers/ram/k3-ddrss/k3-ddrss-lpm.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * K3 DDRSS LPM specific functions
+ *
+ * Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2025 BayLibre, SAS
+ */
+
+#include <asm/io.h>
+#include <linux/compiler_types.h>
+#include <linux/types.h>
+#include <time.h>
+#include <vsprintf.h>
+#include <wait_bit.h>
+
+#include "k3-ddrss-lpm.h"
+
+#define AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL 0x430080d0
+#define AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD BIT(31)
+#define AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RETENTION_MASK GENMASK(3, 0)
+
+#define AM62XX_WKUP_CTRL_MMR_CANUART_WAKE_STAT1 0x4301830c
+#define AM62XX_WKUP_CTRL_MMR_CANUART_WAKE_STAT1_CANUART_IO_MODE BIT(0)
+
+#define AM62XX_WKUP_CTRL_MMR_CANUART_WAKE_OFF_MODE_STAT 0x43018318
+#define AM62XX_WKUP_CTRL_MMR_CANUART_WAKE_OFF_MODE_STAT_MW 0x555555
+
+#define K3_DDRSS_CFG_DENALI_CTL_20 0x0050
+#define K3_DDRSS_CFG_DENALI_CTL_20_PHY_INDEP_TRAIN_MODE BIT(24)
+#define K3_DDRSS_CFG_DENALI_CTL_21 0x0054
+#define K3_DDRSS_CFG_DENALI_CTL_21_PHY_INDEP_INIT_MODE BIT(8)
+#define K3_DDRSS_CFG_DENALI_CTL_106 0x01a8
+#define K3_DDRSS_CFG_DENALI_CTL_106_PWRUP_SREFRESH_EXIT BIT(16)
+#define K3_DDRSS_CFG_DENALI_CTL_160 0x0280
+#define K3_DDRSS_CFG_DENALI_CTL_160_LP_CMD_MASK GENMASK(14, 8)
+#define K3_DDRSS_CFG_DENALI_CTL_160_LP_CMD_ENTRY BIT(9)
+#define K3_DDRSS_CFG_DENALI_CTL_169 0x02a4
+#define K3_DDRSS_CFG_DENALI_CTL_169_LP_AUTO_EXIT_EN_MASK GENMASK(27, 24)
+#define K3_DDRSS_CFG_DENALI_CTL_169_LP_AUTO_ENTRY_EN_MASK GENMASK(19, 16)
+#define K3_DDRSS_CFG_DENALI_CTL_169_LP_STATE_MASK GENMASK(14, 8)
+#define K3_DDRSS_CFG_DENALI_CTL_169_LP_STATE_SHIFT 8
+#define K3_DDRSS_CFG_DENALI_CTL_345 0x0564
+#define K3_DDRSS_CFG_DENALI_CTL_345_INT_STATUS_LOWPOWER_SHIFT 16
+#define K3_DDRSS_CFG_DENALI_CTL_353 0x0584
+#define K3_DDRSS_CFG_DENALI_CTL_353_INT_ACK_LOWPOWER_SHIFT 16
+#define K3_DDRSS_CFG_DENALI_PI_6 0x2018
+#define K3_DDRSS_CFG_DENALI_PI_6_PI_DFI_PHYMSTR_STATE_SEL_R BIT(8)
+#define K3_DDRSS_CFG_DENALI_PI_146 0x2248
+#define K3_DDRSS_CFG_DENALI_PI_150 0x2258
+#define K3_DDRSS_CFG_DENALI_PI_150_PI_DRAM_INIT_EN BIT(8)
+#define K3_DDRSS_CFG_DENALI_PHY_1820 0x5C70
+#define K3_DDRSS_CFG_DENALI_PHY_1820_SET_DFI_INPUT_2_SHIFT 16
+
+#define AM62XX_WKUP_CTRL_DDRSS_RETENTION_TIMEOUT_MS 5000
+#define K3_DDRSS_LPM_TIMEOUT_MS 5000
+
+static void k3_ddrss_reg_update_bits(void __iomem *addr, u32 offset, u32 mask, u32 set)
+{
+ u32 val = readl(addr + offset);
+
+ val &= ~mask;
+ val |= set;
+ writel(val, addr + offset);
+}
+
+void k3_ddrss_self_refresh_exit(void __iomem *ddrss_ctl_cfg)
+{
+ k3_ddrss_reg_update_bits(ddrss_ctl_cfg,
+ K3_DDRSS_CFG_DENALI_CTL_169,
+ K3_DDRSS_CFG_DENALI_CTL_169_LP_AUTO_EXIT_EN_MASK |
+ K3_DDRSS_CFG_DENALI_CTL_169_LP_AUTO_ENTRY_EN_MASK,
+ 0x0);
+ k3_ddrss_reg_update_bits(ddrss_ctl_cfg,
+ K3_DDRSS_CFG_DENALI_PHY_1820,
+ 0,
+ BIT(2) << K3_DDRSS_CFG_DENALI_PHY_1820_SET_DFI_INPUT_2_SHIFT);
+ k3_ddrss_reg_update_bits(ddrss_ctl_cfg,
+ K3_DDRSS_CFG_DENALI_CTL_106,
+ 0,
+ K3_DDRSS_CFG_DENALI_CTL_106_PWRUP_SREFRESH_EXIT);
+ writel(0, ddrss_ctl_cfg + K3_DDRSS_CFG_DENALI_PI_146);
+ k3_ddrss_reg_update_bits(ddrss_ctl_cfg,
+ K3_DDRSS_CFG_DENALI_PI_150,
+ K3_DDRSS_CFG_DENALI_PI_150_PI_DRAM_INIT_EN,
+ 0x0);
+ k3_ddrss_reg_update_bits(ddrss_ctl_cfg,
+ K3_DDRSS_CFG_DENALI_PI_6,
+ 0,
+ K3_DDRSS_CFG_DENALI_PI_6_PI_DFI_PHYMSTR_STATE_SEL_R);
+ k3_ddrss_reg_update_bits(ddrss_ctl_cfg,
+ K3_DDRSS_CFG_DENALI_CTL_21,
+ K3_DDRSS_CFG_DENALI_CTL_21_PHY_INDEP_INIT_MODE,
+ 0);
+ k3_ddrss_reg_update_bits(ddrss_ctl_cfg,
+ K3_DDRSS_CFG_DENALI_CTL_20,
+ 0,
+ K3_DDRSS_CFG_DENALI_CTL_20_PHY_INDEP_TRAIN_MODE);
+}
+
+void k3_ddrss_lpm_resume(void __iomem *ddrss_ctl_cfg)
+{
+ int ret;
+ unsigned long timeout_start;
+
+ k3_ddrss_reg_update_bits(ddrss_ctl_cfg,
+ K3_DDRSS_CFG_DENALI_CTL_160,
+ K3_DDRSS_CFG_DENALI_CTL_160_LP_CMD_MASK,
+ K3_DDRSS_CFG_DENALI_CTL_160_LP_CMD_ENTRY);
+ ret = wait_for_bit_32(ddrss_ctl_cfg + K3_DDRSS_CFG_DENALI_CTL_345,
+ (1 << K3_DDRSS_CFG_DENALI_CTL_345_INT_STATUS_LOWPOWER_SHIFT),
+ true, 5000, false);
+ if (ret)
+ panic("Failed waiting for low power command %d\n", ret);
+
+ k3_ddrss_reg_update_bits(ddrss_ctl_cfg,
+ K3_DDRSS_CFG_DENALI_CTL_353,
+ 0,
+ 1 << K3_DDRSS_CFG_DENALI_CTL_353_INT_ACK_LOWPOWER_SHIFT);
+
+ timeout_start = get_timer(0);
+ while (1) {
+ if (get_timer(timeout_start) > K3_DDRSS_LPM_TIMEOUT_MS)
+ panic("Failed waiting for low power state\n");
+
+ if ((readl(ddrss_ctl_cfg + K3_DDRSS_CFG_DENALI_CTL_169) &
+ K3_DDRSS_CFG_DENALI_CTL_169_LP_STATE_MASK) ==
+ 0x40 << K3_DDRSS_CFG_DENALI_CTL_169_LP_STATE_SHIFT)
+ break;
+ }
+}
+
+void am62xx_ddrss_deassert_retention(void)
+{
+ int ret;
+
+ k3_ddrss_reg_update_bits((void *)AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL,
+ 0x0,
+ AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD |
+ AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RETENTION_MASK,
+ 0);
+ k3_ddrss_reg_update_bits((void *)AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL,
+ 0x0,
+ AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD,
+ AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD);
+
+ ret = wait_for_bit_32((void *)AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL,
+ AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD,
+ true, AM62XX_WKUP_CTRL_DDRSS_RETENTION_TIMEOUT_MS, false);
+ if (ret)
+ panic("Failed waiting for latching of retention %d\n", ret);
+
+ k3_ddrss_reg_update_bits((void *)AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL,
+ 0x0,
+ AM62XX_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD,
+ 0);
+}
+
+static bool am62xx_wkup_conf_canuart_wakeup_active(void)
+{
+ u32 active;
+
+ active = readl((void *)AM62XX_WKUP_CTRL_MMR_CANUART_WAKE_STAT1);
+
+ return !!(active & AM62XX_WKUP_CTRL_MMR_CANUART_WAKE_STAT1_CANUART_IO_MODE);
+}
+
+static bool am62xx_wkup_conf_canuart_magic_word_set(void)
+{
+ u32 magic_word;
+
+ magic_word = readl((void *)AM62XX_WKUP_CTRL_MMR_CANUART_WAKE_OFF_MODE_STAT);
+
+ return magic_word == AM62XX_WKUP_CTRL_MMR_CANUART_WAKE_OFF_MODE_STAT_MW;
+}
+
+bool am62xx_wkup_conf_boot_is_resume(void)
+{
+ return IS_ENABLED(CONFIG_K3_IODDR) &&
+ am62xx_wkup_conf_canuart_wakeup_active() &&
+ am62xx_wkup_conf_canuart_magic_word_set();
+}
--git a/drivers/ram/k3-ddrss/k3-ddrss-lpm.h b/drivers/ram/k3-ddrss/k3-ddrss-lpm.h
new file mode 100644
index 000000000000..742d224327e4
--- /dev/null
+++ b/drivers/ram/k3-ddrss/k3-ddrss-lpm.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * K3 DDRSS LPM specific functions
+ *
+ * Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2025 BayLibre, SAS
+ */
+
+#ifndef _K3_DDRSS_LPM_H_
+#define _K3_DDRSS_LPM_H_
+
+#include <linux/compiler_types.h>
+#include <linux/types.h>
+
+void k3_ddrss_self_refresh_exit(void __iomem *ddrss_ctl_cfg);
+void k3_ddrss_lpm_resume(void __iomem *ddrss_ctl_cfg);
+void am62xx_ddrss_deassert_retention(void);
+bool am62xx_wkup_conf_boot_is_resume(void);
+
+#endif /* _K3_DDRSS_LPM_H_ */
--git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c
index c406998b20aa..54e191df8de9 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -20,6 +20,7 @@
#include <wait_bit.h>
#include <power/regulator.h>
+#include "k3-ddrss-lpm.h"
#include "lpddr4_obj_if.h"
#include "lpddr4_if.h"
#include "lpddr4_structs_if.h"
@@ -119,6 +120,8 @@ enum intrlv_size {
struct k3_ddrss_data {
u32 flags;
+ bool (*is_lpm_resume)(void);
+ void (*ddrss_deassert_retention)(void);
};
enum ecc_enable {
@@ -866,6 +869,7 @@ static void k3_ddrss_lpddr4_ecc_init(struct k3_ddrss_desc *ddrss)
static int k3_ddrss_probe(struct udevice *dev)
{
+ struct k3_ddrss_data *ddrss_data = (struct k3_ddrss_data *)dev_get_driver_data(dev);
u64 end, bank0, bank1, bank0_size;
int ret;
struct k3_ddrss_desc *ddrss = dev_get_priv(dev);
@@ -873,6 +877,7 @@ static int k3_ddrss_probe(struct udevice *dev)
__maybe_unused u32 inst;
__maybe_unused struct k3_ddrss_ecc_region *range = ddrss->ecc_ranges;
__maybe_unused struct k3_msmc *msmc_parent = NULL;
+ bool is_lpm_resume;
debug("%s(dev=%p)\n", __func__, dev);
@@ -880,6 +885,10 @@ static int k3_ddrss_probe(struct udevice *dev)
if (ret)
return ret;
+ is_lpm_resume = ddrss_data->is_lpm_resume && ddrss_data->is_lpm_resume();
+ if (is_lpm_resume)
+ dev_info(dev, "Detected IO+DDR resume\n");
+
ddrss->dev = dev;
ret = k3_ddrss_power_on(ddrss);
if (ret)
@@ -895,12 +904,21 @@ static int k3_ddrss_probe(struct udevice *dev)
k3_lpddr4_init(ddrss);
k3_lpddr4_hardware_reg_init(ddrss);
+ if (is_lpm_resume)
+ k3_ddrss_self_refresh_exit(ddrss->ddrss_ctl_cfg);
+
ret = k3_ddrss_init_freq(ddrss);
if (ret)
return ret;
+ if (is_lpm_resume && ddrss_data->ddrss_deassert_retention)
+ ddrss_data->ddrss_deassert_retention();
+
k3_lpddr4_start(ddrss);
+ if (is_lpm_resume)
+ k3_ddrss_lpm_resume(ddrss->ddrss_ctl_cfg);
+
if (IS_ENABLED(CONFIG_K3_INLINE_ECC)) {
if (!ddrss->ddrss_ss_cfg) {
printf("%s: ss_cfg is required if ecc is enabled but not provided.",
@@ -1019,12 +1037,18 @@ static const struct k3_ddrss_data k3_data = {
.flags = SINGLE_DDR_SUBSYSTEM,
};
+static const struct k3_ddrss_data am62xx_data = {
+ .flags = SINGLE_DDR_SUBSYSTEM,
+ .is_lpm_resume = am62xx_wkup_conf_boot_is_resume,
+ .ddrss_deassert_retention = am62xx_ddrss_deassert_retention,
+};
+
static const struct k3_ddrss_data j721s2_data = {
.flags = MULTI_DDR_SUBSYSTEM,
};
static const struct udevice_id k3_ddrss_ids[] = {
- {.compatible = "ti,am62a-ddrss", .data = (ulong)&k3_data, },
+ {.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, },
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v5 02/21] firmware: ti_sci: Add TI_SCI_MSG_MIN_CONTEXT_RESTORE
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 01/21] ram: k3-ddrss: Add support for DDR in self-refresh Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 03/21] firmware: ti_sci: add low power mode operations Richard Genoud (TI)
` (18 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, Udit Kumar,
Abhash Kumar, Thomas Richard, Gregory CLEMENT, Thomas Petazzoni,
Richard Genoud, u-boot
From: "Markus Schneider-Pargmann (TI)" <msp@baylibre.com>
This patch adds code to be able to call TI_SCI_MSG_MIN_CONTEXT_RESTORE.
The context needs to be restored after booting SPL when resuming from
IO+DDR.
Signed-off-by: Markus Schneider-Pargmann (TI) <msp@baylibre.com>
---
drivers/firmware/ti_sci.c | 38 ++++++++++++++++++++++++++
drivers/firmware/ti_sci.h | 16 +++++++++++
include/linux/soc/ti/ti_sci_protocol.h | 9 ++++++
3 files changed, 63 insertions(+)
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 0f5e180e9e94..c015bd3cc245 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -2710,6 +2710,41 @@ static int ti_sci_cmd_change_fwl_owner(const struct ti_sci_handle *handle,
return ret;
}
+static int ti_sci_cmd_min_context_restore(const struct ti_sci_handle *handle, u64 ctx_addr)
+{
+ struct ti_sci_msg_min_restore_context_req req;
+ struct ti_sci_msg_hdr *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, TI_SCI_MSG_MIN_CONTEXT_RESTORE,
+ 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_lo = (u32)(ctx_addr & 0xffffffff);
+ req.ctx_hi = (u32)(ctx_addr >> 32);
+
+ ret = ti_sci_do_xfer(info, xfer);
+ if (ret) {
+ dev_err(info->dev, "Failed restoring context %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
/*
* ti_sci_setup_ops() - Setup the operations structures
* @info: pointer to TISCI pointer
@@ -2728,6 +2763,7 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops;
struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops;
struct ti_sci_fwl_ops *fwl_ops = &ops->fwl_ops;
+ struct ti_sci_lpm_ops *lpm_ops = &ops->lpm_ops;
bops->board_config = ti_sci_cmd_set_board_config;
bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
@@ -2795,6 +2831,8 @@ static void ti_sci_setup_ops(struct ti_sci_info *info)
fw_ops->get_dm_version = ti_sci_cmd_get_dm_version;
fw_ops->query_dm_cap = ti_sci_cmd_query_dm_cap;
+
+ lpm_ops->min_context_restore = ti_sci_cmd_min_context_restore;
}
/**
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index ce50bf6800eb..68908c6c8c46 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -45,6 +45,9 @@
#define TI_SCI_MSG_QUERY_CLOCK_FREQ 0x010d
#define TI_SCI_MSG_GET_CLOCK_FREQ 0x010e
+/* Low Power Mode Requests */
+#define TI_SCI_MSG_MIN_CONTEXT_RESTORE 0x0308
+
/* Processor Control Messages */
#define TISCI_MSG_PROC_REQUEST 0xc000
#define TISCI_MSG_PROC_RELEASE 0xc001
@@ -1572,4 +1575,17 @@ struct ti_sci_msg_fwl_change_owner_info_resp {
u16 owner_permission_bits;
} __packed;
+/**
+ * struct ti_sci_msg_min_restore_context_req - Request to restore context from DDR
+ *
+ * @hdr: Generic Header
+ * @ctx_lo Low 32-bits of physical pointer to address to use for context restore.
+ * @ctx_hi High 32-bits of physical pointer to address to use for context restore.
+ */
+struct ti_sci_msg_min_restore_context_req {
+ struct ti_sci_msg_hdr hdr;
+ u32 ctx_lo;
+ u32 ctx_hi;
+} __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 52696763ecf6..6b1dd801f5f8 100644
--- a/include/linux/soc/ti/ti_sci_protocol.h
+++ b/include/linux/soc/ti/ti_sci_protocol.h
@@ -632,6 +632,14 @@ struct ti_sci_fwl_ops {
int (*change_fwl_owner)(const struct ti_sci_handle *handle, struct ti_sci_msg_fwl_owner *owner);
};
+/**
+ * struct ti_sci_lpm_ops - Low Power Mode operations
+ * @min_context_restore: Request restoring context from DDR.
+ */
+struct ti_sci_lpm_ops {
+ int (*min_context_restore)(const struct ti_sci_handle *handle, u64 ctx_addr);
+};
+
/**
* struct ti_sci_ops - Function support for TI SCI
* @board_ops: Miscellaneous operations
@@ -654,6 +662,7 @@ struct ti_sci_ops {
struct ti_sci_rm_psil_ops rm_psil_ops;
struct ti_sci_rm_udmap_ops rm_udmap_ops;
struct ti_sci_fwl_ops fwl_ops;
+ struct ti_sci_lpm_ops lpm_ops;
};
/**
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v5 03/21] firmware: ti_sci: add low power mode operations
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 01/21] ram: k3-ddrss: Add support for DDR in self-refresh Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 02/21] firmware: ti_sci: Add TI_SCI_MSG_MIN_CONTEXT_RESTORE Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 04/21] mach-k3: r5: common: add helper functions needed in LPM resume sequence Richard Genoud (TI)
` (17 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, Udit Kumar,
Abhash Kumar, Thomas Richard, Gregory CLEMENT, Thomas Petazzoni,
Richard Genoud, u-boot
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 | 62 ++++++++
drivers/firmware/ti_sci.c | 181 +++++++++++++++++++++++
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..fa90fed7c427 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 image_size);
diff --git a/arch/arm/mach-k3/security.c b/arch/arm/mach-k3/security.c
index c7017bba99ab..2df922a2fa27 100644
--- a/arch/arm/mach-k3/security.c
+++ b/arch/arm/mach-k3/security.c
@@ -133,3 +133,65 @@ 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 image_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 backup_size;
+ int ret;
+
+ if (!image_size) {
+ debug("%s: Image size is null\n", __func__);
+ 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, image_size, DMA_BIDIRECTIONAL);
+
+ debug("Authenticating image at address 0x%016llx\n", image_addr);
+ debug("Authenticating image of size %zu bytes\n", image_size);
+
+ /*
+ * Authenticate image
+ * The size argument is modified by proc_auth_apply_fwls and 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.
+ * And moreover it expects a u32*. So, use the backup_size.
+ */
+ backup_size = image_size;
+ ret = proc_ops->proc_auth_apply_fwls(ti_sci, &image_addr, &backup_size);
+ if (ret) {
+ printf("Authentication failed..but assume pass!\n");
+ hang();
+ }
+
+ /* Invalidate any stale lines over data written by system firmware */
+ dma_unmap_single(image_addr, image_size, DMA_BIDIRECTIONAL);
+
+ /*
+ * 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..050f4d61562a 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -2014,6 +2014,64 @@ 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);
+ dev_err(info->dev, "%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) {
+ dev_err(info->dev, "%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 +2803,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
+ * @context_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 +2990,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 +3011,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..d6ae08144d46 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 address 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] 22+ messages in thread* [PATCH v5 04/21] mach-k3: r5: common: add helper functions needed in LPM resume sequence
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (2 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 03/21] firmware: ti_sci: add low power mode operations Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 05/21] global: k3: use gd to store the resume state Richard Genoud (TI)
` (16 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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
- k3_set_lpm_core_bus_node_path() and k3_set_lpm_core_compatible() are
used to locate the lpm memory region in the DTB
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 | 17 ++
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 | 268 +++++++++++++++++++++++++++++++
6 files changed, 311 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 37ff98d89924..c97ccc8e0619 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..83e0fdcca6ca
--- /dev/null
+++ b/arch/arm/mach-k3/lpm-common.h
@@ -0,0 +1,17 @@
+/* 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);
+void k3_set_lpm_core_bus_node_path(const char *node_path);
+void k3_set_lpm_core_compatible(const char *compatible);
+
+#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 13736ca5dbc0..572e4848bb5e 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..9b91081e4f0f
--- /dev/null
+++ b/arch/arm/mach-k3/r5/lpm-common.c
@@ -0,0 +1,268 @@
+// 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 {
+ unsigned long context_save_addr;
+ unsigned long atf_cert_addr;
+ unsigned long optee_cert_addr;
+ unsigned long dm_save_addr;
+ u32 size;
+};
+
+__weak bool j7xx_board_is_resuming(void)
+{
+ return false;
+}
+
+static const char *lpm_core_compatible;
+static const char *lpm_core_bus_node_path;
+
+void k3_set_lpm_core_bus_node_path(const char *node_path)
+{
+ lpm_core_bus_node_path = node_path;
+}
+
+void k3_set_lpm_core_compatible(const char *compatible)
+{
+ lpm_core_compatible = compatible;
+}
+
+static int extract_lpm_region(struct lpm_addr_info *mem_addr_lpm)
+{
+ struct ofnode_phandle_args memregion_phandle;
+ fdt_addr_t lpm_reg_addr;
+ fdt_size_t lpm_reg_size;
+ ofnode memregion;
+ ofnode bus_node;
+ int ret, idx;
+
+ if (!lpm_core_compatible) {
+ printf("LPM compatible core string not set\n");
+ return -EINVAL;
+ }
+ if (!lpm_core_bus_node_path) {
+ printf("LPM core bus path not set\n");
+ return -EINVAL;
+ }
+
+ bus_node = ofnode_path(lpm_core_bus_node_path);
+ if (!ofnode_valid(bus_node)) {
+ printf("Failed to find wkup bus\n");
+ return -EINVAL;
+ }
+
+ memregion = ofnode_by_compatible(bus_node, lpm_core_compatible);
+ if (!ofnode_valid(memregion)) {
+ printf("Failed to find r5f devicetree node %s\n",
+ lpm_core_compatible);
+ return -EINVAL;
+ }
+
+ idx = ofnode_stringlist_search(memregion, "memory-region-names",
+ "lpm-metadata");
+ if (idx < 0)
+ return idx;
+
+ ret = ofnode_parse_phandle_with_args(memregion, "memory-region", NULL,
+ 0, idx, &memregion_phandle);
+
+ if (ret) {
+ printf("Failed to parse phandle for lpm memory region\n");
+ return ret;
+ }
+
+ lpm_reg_addr = ofnode_get_addr(memregion_phandle.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(memregion_phandle.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 = 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(struct lpm_addr_info *mem_addr_lpm)
+{
+ 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(mem_addr_lpm);
+ if (ret) {
+ pr_err("Cannot find valid LPM address range..\n");
+ return -ENOMEM;
+ }
+
+ memcpy((void *)mem_addr_lpm->atf_cert_addr,
+ (void *)fit_image_info[IMAGE_ID_ATF].image_start,
+ fit_image_info[IMAGE_ID_ATF].image_len);
+
+ memcpy((void *)mem_addr_lpm->optee_cert_addr,
+ (void *)fit_image_info[IMAGE_ID_OPTEE].image_start,
+ fit_image_info[IMAGE_ID_OPTEE].image_len);
+
+ memcpy((void *)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;
+ struct lpm_addr_info mem_addr_lpm;
+ struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+
+ ret = save_certificate(&mem_addr_lpm);
+ if (ret)
+ return;
+ /*
+ * As there is no function to check TIFS capabilities, we can't really
+ * know if the call failed because it's not supported by TIFS or for
+ * another reason.
+ */
+ ret = ti_sci->ops.lpm_ops.lpm_save_addr(ti_sci,
+ mem_addr_lpm.context_save_addr,
+ mem_addr_lpm.size);
+ if (ret)
+ pr_err("TIFS lpm save addr fails (message not supported?)\n");
+}
+
+static unsigned long resume_to_dm_f(const struct lpm_addr_info *mem_addr_lpm)
+{
+ struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+ unsigned long loadaddr;
+ int ret = 0;
+
+ loadaddr = 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);
+ ret = ti_sci->ops.lpm_ops.lpm_save_addr(ti_sci,
+ mem_addr_lpm->context_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 vector 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;
+ struct udevice *dev;
+ 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 = 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)
+{
+ struct lpm_addr_info mem_addr_lpm;
+ image_entry_noargs_t image_entry;
+ size_t sz = FW_IMAGE_SIZE;
+ unsigned long loadaddr;
+ void *image_addr;
+ int ret;
+
+ ret = extract_lpm_region(&mem_addr_lpm);
+ if (ret)
+ panic("Cannot find valid LPM address range... LPM resume failed\n");
+
+ /*
+ * Disclamer:
+ * ---------
+ * There's a potential attack vector here, because OPTEE could be
+ * modified before being reloaded.
+ *
+ * Also, if the certificate replay is skipped, then TFA can be
+ * read from MSMC.
+ */
+ ret = rproc_load(1, mem_addr_lpm.atf_cert_addr, 0x200);
+ if (ret)
+ panic("rproc failed to be initialized (%d)\n", ret);
+
+ image_addr = (void *)mem_addr_lpm.atf_cert_addr;
+ ti_secure_image_auth_apply_fwls(&image_addr, sz);
+
+ image_addr = (void *)mem_addr_lpm.optee_cert_addr;
+ ti_secure_image_auth_apply_fwls(&image_addr, sz);
+
+ loadaddr = resume_to_dm_f(&mem_addr_lpm);
+ 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] 22+ messages in thread* [PATCH v5 05/21] global: k3: use gd to store the resume state
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (3 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 04/21] mach-k3: r5: common: add helper functions needed in LPM resume sequence Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 06/21] mach-k3: r5: common: introduce j7xx_board_is_resuming() Richard Genoud (TI)
` (15 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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.
Reviewed-by: Simon Glass <sjg@chromium.org>
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..a146206fdff9 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_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] 22+ messages in thread* [PATCH v5 06/21] mach-k3: r5: common: introduce j7xx_board_is_resuming()
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (4 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 05/21] global: k3: use gd to store the resume state Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 07/21] mach-k3: r5: common: introduce k3_deassert_ddr_ret() Richard Genoud (TI)
` (14 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, Udit Kumar,
Abhash Kumar, Thomas Richard, Gregory CLEMENT, Thomas Petazzoni,
Richard Genoud, u-boot
Add the capability to detect a resume on J7200, J784s4, J721e, j722s,
j721s2 SoCs.
To detect the resume, SPL searches a magic value (0xBA) in a register
of PMIC.
This value is set by DM-Firmware during the suspend sequence.
NB: As this is called in board_init_f(), there's no BSS, so we can't
use global/static variables.
NB2: For j722s HS-* devices, 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.
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/common.c | 6 ++
arch/arm/mach-k3/include/mach/hardware.h | 1 +
arch/arm/mach-k3/r5/lpm-common.c | 78 +++++++++++++++++++++++-
3 files changed, 83 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index 6e382efdb3be..d934f732b330 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -713,3 +713,9 @@ int spl_start_uboot(void)
return 0;
}
#endif
+
+/* if r5/lpm-common.c is compiled, this will be overridden */
+__weak bool j7xx_board_is_resuming(void)
+{
+ return false;
+}
diff --git a/arch/arm/mach-k3/include/mach/hardware.h b/arch/arm/mach-k3/include/mach/hardware.h
index 2c771a1195f5..c45bd3747163 100644
--- a/arch/arm/mach-k3/include/mach/hardware.h
+++ b/arch/arm/mach-k3/include/mach/hardware.h
@@ -137,6 +137,7 @@ u32 get_boot_device(void);
const char *get_reset_reason(void);
enum k3_device_type get_device_type(void);
int k3_fit_config_match_security_state(const char *name);
+bool j7xx_board_is_resuming(void);
#define writel_verify(val, addr) \
do { \
diff --git a/arch/arm/mach-k3/r5/lpm-common.c b/arch/arm/mach-k3/r5/lpm-common.c
index 9b91081e4f0f..c1a8c8e940de 100644
--- a/arch/arm/mach-k3/r5/lpm-common.c
+++ b/arch/arm/mach-k3/r5/lpm-common.c
@@ -6,18 +6,28 @@
* Copyright (C) 2026 Bootlin
*/
+#include <asm/global_data.h>
#include <clk.h>
+#include <dm/device.h>
#include <dm/read.h>
#include <elf.h>
+#include <i2c.h>
#include <linux/printk.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#include <power-domain.h>
+#include <power/pmic.h>
#include <remoteproc.h>
#include <mach/security.h>
#include "../common.h"
#include "../lpm-common.h"
+/* Magic value in PMIC register to indicate the suspend state (SOC_OFF) */
+#define K3_LPM_MAGIC_SUSPEND 0xba
+
+/* PMIC register where the magic value resides */
+#define K3_LPM_SCRATCH_PAD_REG_3 0xcb
+
#define FW_IMAGE_SIZE 0x80000
struct lpm_addr_info {
@@ -28,9 +38,73 @@ struct lpm_addr_info {
u32 size;
};
-__weak bool j7xx_board_is_resuming(void)
+/* This is used by J722s */
+__weak 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)
{
- return false;
+ struct udevice *pmic, *i2c;
+ int ret, magic;
+
+ if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
+ goto end;
+
+ if (IS_ENABLED(CONFIG_SOC_K3_J722S)) {
+ /*
+ * On J722S 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();
+ ret = uclass_get_device_by_name(UCLASS_I2C,
+ "i2c@2b200000", &i2c);
+ if (ret) {
+ printf("Getting I2C failed: %d\n", ret);
+ goto end;
+ }
+ ret = dm_i2c_probe(i2c, 0x48, 0, &pmic);
+ if (ret) {
+ printf("Getting PMIC failed: %d\n", ret);
+ goto end;
+ }
+ } else {
+ ret = uclass_get_device_by_name(UCLASS_PMIC,
+ "pmic@48", &pmic);
+ if (ret) {
+ printf("Getting PMIC init failed: %d\n", ret);
+ goto end;
+ }
+ }
+ debug("%s: PMIC is detected (%s)\n", __func__, pmic->name);
+
+ if (IS_ENABLED(CONFIG_SOC_K3_J722S))
+ magic = dm_i2c_reg_read(pmic, K3_LPM_SCRATCH_PAD_REG_3);
+ else
+ magic = pmic_reg_read(pmic, K3_LPM_SCRATCH_PAD_REG_3);
+
+ if (magic == K3_LPM_MAGIC_SUSPEND) {
+ debug("%s: board is resuming\n", __func__);
+ gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
+
+ /* clean magic suspend */
+ if (IS_ENABLED(CONFIG_SOC_K3_J722S))
+ ret = dm_i2c_reg_write(pmic, K3_LPM_SCRATCH_PAD_REG_3, 0);
+ else
+ ret = pmic_reg_write(pmic, K3_LPM_SCRATCH_PAD_REG_3, 0);
+
+ if (ret)
+ printf("Failed to clean magic value for suspend detection in PMIC\n");
+ /*
+ * For robustness, the DM should also clean the magic value at
+ * startup.
+ */
+ } else {
+ debug("%s: board is booting (no resume detected)\n", __func__);
+ gd_set_k3_resuming(K3_RESUME_STATE_BOOTING);
+ }
+end:
+ return gd_k3_resuming() == K3_RESUME_STATE_RESUMING;
}
static const char *lpm_core_compatible;
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v5 07/21] mach-k3: r5: common: introduce k3_deassert_ddr_ret()
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (5 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 06/21] mach-k3: r5: common: introduce j7xx_board_is_resuming() Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 08/21] board: mach-k3: r5: common: enable GTC after core_resume Richard Genoud (TI)
` (13 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, Udit Kumar,
Abhash Kumar, Thomas Richard, Gregory CLEMENT, Thomas Petazzoni,
Richard Genoud, u-boot
Deasserting DDR retention pin is quite similar from J7200, J784s4,
J721e, and j721s2 SoCs.
Instead of duplicating almost the same code, add it in lpm-common.c.
NB: On J7200, there's a latch, so the clock needs to be toggled.
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/lpm-common.h | 2 ++
arch/arm/mach-k3/r5/lpm-common.c | 27 +++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/arch/arm/mach-k3/lpm-common.h b/arch/arm/mach-k3/lpm-common.h
index 83e0fdcca6ca..7dbe72ce129e 100644
--- a/arch/arm/mach-k3/lpm-common.h
+++ b/arch/arm/mach-k3/lpm-common.h
@@ -11,6 +11,8 @@
void __noreturn do_resume(void);
void lpm_process(void);
+void k3_deassert_ddr_ret(const char *pmic_name, unsigned int ddr_ret_val,
+ unsigned int ddr_ret_clk, bool toggle);
void k3_set_lpm_core_bus_node_path(const char *node_path);
void k3_set_lpm_core_compatible(const char *compatible);
diff --git a/arch/arm/mach-k3/r5/lpm-common.c b/arch/arm/mach-k3/r5/lpm-common.c
index c1a8c8e940de..ab39ea0cd67d 100644
--- a/arch/arm/mach-k3/r5/lpm-common.c
+++ b/arch/arm/mach-k3/r5/lpm-common.c
@@ -41,6 +41,33 @@ struct lpm_addr_info {
/* This is used by J722s */
__weak void ctrl_mmr_unlock(void) { }
+#define GPIO_OUT_1 0x3D
+void k3_deassert_ddr_ret(const char *pmic_name, unsigned int ddr_ret_val,
+ unsigned int ddr_ret_clk, bool toggle)
+{
+ struct udevice *pmic;
+ int regval;
+ int err;
+
+ err = uclass_get_device_by_name(UCLASS_PMIC, pmic_name, &pmic);
+ if (err) {
+ printf("Getting %s init failed: %d\n", pmic_name, err);
+ return;
+ }
+
+ /* Set DDR_RET Signal Low on PMIC */
+ regval = pmic_reg_read(pmic, GPIO_OUT_1) & ~ddr_ret_val;
+ pmic_reg_write(pmic, GPIO_OUT_1, regval);
+
+ if (toggle) {
+ /* Now toggle the CLK of the latch for DDR retention */
+ pmic_reg_write(pmic, GPIO_OUT_1, regval | ddr_ret_clk);
+ pmic_reg_write(pmic, GPIO_OUT_1, regval & ~ddr_ret_clk);
+ pmic_reg_write(pmic, GPIO_OUT_1, regval | ddr_ret_clk);
+ pmic_reg_write(pmic, GPIO_OUT_1, regval & ~ddr_ret_clk);
+ }
+}
+
/* 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] 22+ messages in thread* [PATCH v5 08/21] board: mach-k3: r5: common: enable GTC after core_resume
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (6 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 07/21] mach-k3: r5: common: introduce k3_deassert_ddr_ret() Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 09/21] board: evm: Enable de-isolation of IOs at resume for j7200 and j784s4 Richard Genoud (TI)
` (12 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, Udit Kumar,
Abhash Kumar, Thomas Richard, Gregory CLEMENT, Thomas Petazzoni,
Richard Genoud, u-boot
From: Abhash Kumar Jha <a-kumar2@ti.com>
The GTC counter values are restored in the resume sequence by TIFS as
part of the core_resume API. Enable GTC counter after it is restored.
Also add a check to make sure that rproc_load only enables the GTC counter
in the case of a cold boot.
Signed-off-by: Abhash Kumar Jha <a-kumar2@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/r5/lpm-common.c | 11 +++++++++++
drivers/remoteproc/ti_k3_arm64_rproc.c | 10 ++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-k3/r5/lpm-common.c b/arch/arm/mach-k3/r5/lpm-common.c
index ab39ea0cd67d..4f515b51fd40 100644
--- a/arch/arm/mach-k3/r5/lpm-common.c
+++ b/arch/arm/mach-k3/r5/lpm-common.c
@@ -311,6 +311,7 @@ static void resume_rproc_f(void)
{
struct power_domain rproc_pwrdmn;
struct udevice *dev;
+ void *gtc_base;
int ret;
ret = uclass_get_device_by_seq(UCLASS_REMOTEPROC, 1, &dev);
@@ -321,6 +322,16 @@ static void resume_rproc_f(void)
if (ret)
panic("power_domain_get_rproc() failed: %d\n", ret);
+ gtc_base = dev_read_addr_ptr(dev);
+ if (!gtc_base)
+ panic("Get GTC address failed\n");
+
+#define GTC_CNTCR_REG 0x0
+#define GTC_CNTR_EN 0x3
+
+ /* GTC counter values have been restored by TIFS, so enable the counter */
+ 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);
diff --git a/drivers/remoteproc/ti_k3_arm64_rproc.c b/drivers/remoteproc/ti_k3_arm64_rproc.c
index 403c6bed2e8c..9b8a6b7dc53a 100644
--- a/drivers/remoteproc/ti_k3_arm64_rproc.c
+++ b/drivers/remoteproc/ti_k3_arm64_rproc.c
@@ -17,6 +17,7 @@
#include <dm/device_compat.h>
#include <linux/err.h>
#include <linux/soc/ti/ti_sci_protocol.h>
+#include <mach/hardware.h>
#include "ti_sci_proc.h"
#define INVALID_ID 0xff
@@ -78,8 +79,13 @@ static int k3_arm64_load(struct udevice *dev, ulong addr, ulong size)
/* Store the clock frequency down for GTC users to pick up */
writel((u32)gtc_rate, rproc->gtc_base + GTC_CNTFID0_REG);
- /* Enable the timer before starting remote core */
- writel(GTC_CNTR_EN, rproc->gtc_base + GTC_CNTCR_REG);
+ if (!j7xx_board_is_resuming()) {
+ /*
+ * In case of a fresh boot, enable the timer before
+ * starting the remote core.
+ */
+ writel(GTC_CNTR_EN, rproc->gtc_base + GTC_CNTCR_REG);
+ }
/*
* Setting the right clock frequency would have taken care by
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v5 09/21] board: evm: Enable de-isolation of IOs at resume for j7200 and j784s4
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (7 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 08/21] board: mach-k3: r5: common: enable GTC after core_resume Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 10/21] board: mach-k3: r5: common: Store wakeup reason on scratchpad memory Richard Genoud (TI)
` (11 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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>
Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
.../arm/mach-k3/include/mach/j721e_hardware.h | 11 ++++++++
.../mach-k3/include/mach/j784s4_hardware.h | 10 ++++++++
arch/arm/mach-k3/r5/lpm-common.c | 15 +++++++++++
board/ti/j721e/evm.c | 25 +++++++++++++++++++
board/ti/j784s4/evm.c | 24 ++++++++++++++++++
5 files changed, 85 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..e6e437af4ec0 100644
--- a/arch/arm/mach-k3/include/mach/j721e_hardware.h
+++ b/arch/arm/mach-k3/include/mach/j721e_hardware.h
@@ -14,6 +14,17 @@
#define WKUP_CTRL_MMR0_BASE 0x43000000
#define MCU_CTRL_MMR0_BASE 0x40f00000
#define CTRL_MMR0_BASE 0x00100000
+#define DMSC_PWRCTRL_BASE 0x44130000
+
+#define PMCTRL_IO_1 (DMSC_PWRCTRL_BASE + 0x88)
+#define PMCTRL_IO_LPM PMCTRL_IO_1
+#define CANUART_WAKE_CTRL 0x18300
+#define CANUART_WAKE_STAT0 0x18308
+#define CANUART_WAKE_STAT1 0x1830C
+
+#define IO_ISO_MAGIC_VAL 0x55555554
+#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)
diff --git a/arch/arm/mach-k3/include/mach/j784s4_hardware.h b/arch/arm/mach-k3/include/mach/j784s4_hardware.h
index 29a894baed34..033ae153d674 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 (WKUP_CTRL_MMR0_BASE + 0x14084)
+#define PMCTRL_IO_LPM PMCTRL_IO_0
+#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 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/arch/arm/mach-k3/r5/lpm-common.c b/arch/arm/mach-k3/r5/lpm-common.c
index 4f515b51fd40..559e1b5f681a 100644
--- a/arch/arm/mach-k3/r5/lpm-common.c
+++ b/arch/arm/mach-k3/r5/lpm-common.c
@@ -6,6 +6,7 @@
* Copyright (C) 2026 Bootlin
*/
+#include <asm/arch/hardware.h>
#include <asm/global_data.h>
#include <clk.h>
#include <dm/device.h>
@@ -28,6 +29,7 @@
/* PMIC register where the magic value resides */
#define K3_LPM_SCRATCH_PAD_REG_3 0xcb
+#define IO_ISO_STATUS BIT(25)
#define FW_IMAGE_SIZE 0x80000
struct lpm_addr_info {
@@ -38,6 +40,8 @@ struct lpm_addr_info {
u32 size;
};
+__weak void clear_isolation(void) { }
+
/* This is used by J722s */
__weak void ctrl_mmr_unlock(void) { }
@@ -72,11 +76,22 @@ void k3_deassert_ddr_ret(const char *pmic_name, unsigned int ddr_ret_val,
bool j7xx_board_is_resuming(void)
{
struct udevice *pmic, *i2c;
+ u32 pmctrl_val = 0;
int ret, magic;
if (gd_k3_resuming() != K3_RESUME_STATE_UNKNOWN)
goto end;
+#ifdef PMCTRL_IO_LPM
+ pmctrl_val = readl(PMCTRL_IO_LPM);
+#endif
+ 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;
+ }
+
if (IS_ENABLED(CONFIG_SOC_K3_J722S)) {
/*
* On J722S devices, i2c access fails unless MMR
diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c
index 881392bd963a..2fba16fda323 100644
--- a/board/ti/j721e/evm.c
+++ b/board/ti/j721e/evm.c
@@ -17,6 +17,7 @@
#include <spl.h>
#include <dm.h>
#include <asm/arch/k3-ddr.h>
+#include <wait_bit.h>
#include "../common/board_detect.h"
#include "../common/fdt_ops.h"
@@ -469,6 +470,30 @@ err_free_gpio:
}
}
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J7200_R5_EVM))
+
+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");
+}
+
+#endif /* CONFIG_SPL_BUILD && CONFIG_TARGET_J7200_R5_EVM */
+
void spl_board_init(void)
{
struct udevice *dev;
diff --git a/board/ti/j784s4/evm.c b/board/ti/j784s4/evm.c
index 8a4d40a5a959..179a26d570fd 100644
--- a/board/ti/j784s4/evm.c
+++ b/board/ti/j784s4/evm.c
@@ -11,7 +11,9 @@
#include <efi_loader.h>
#include <init.h>
#include <spl.h>
+#include <asm/arch/hardware.h>
#include <asm/arch/k3-ddr.h>
+#include <wait_bit.h>
#include "../common/fdt_ops.h"
struct efi_fw_image fw_images[] = {
@@ -59,6 +61,28 @@ int board_late_init(void)
}
#endif
+#if (IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_TARGET_J784S4_R5_EVM))
+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");
+}
+#endif /* CONFIG_SPL_BUILD && CONFIG_TARGET_J784s4_R5_EVM */
+
void spl_board_init(void)
{
struct udevice *dev;
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v5 10/21] board: mach-k3: r5: common: Store wakeup reason on scratchpad memory
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (8 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 09/21] board: evm: Enable de-isolation of IOs at resume for j7200 and j784s4 Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 11/21] board: mach-k3: r5: common: Set PMIC NSLEEP triggers bits at resume Richard Genoud (TI)
` (10 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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>
Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/Kconfig | 10 ++++++++++
arch/arm/mach-k3/r5/lpm-common.c | 24 ++++++++++++++++++++++++
2 files changed, 34 insertions(+)
diff --git a/arch/arm/mach-k3/Kconfig b/arch/arm/mach-k3/Kconfig
index a32ed3a9683f..bbb62fa617fc 100644
--- a/arch/arm/mach-k3/Kconfig
+++ b/arch/arm/mach-k3/Kconfig
@@ -101,6 +101,16 @@ config SYS_K3_BOOT_CORE_ID
int
default 16
+config SYS_K3_SCRATCH_LPM_ADDR
+ hex
+ default 0x40280000 if SOC_K3_J721E || SOC_K3_J7200 || SOC_K3_J784S4
+ default 0x0
+ help
+ Address where the wake-up reason is stored at resume (32 bits).
+ It will be read by the Linux kernel once its up.
+ On J7200/J784s4 the MCU_PSRAM0_RAM is used by default.
+ Set it to 0 if unused.
+
config K3_EARLY_CONS
bool "Activate to allow for an early console during SPL"
depends on SPL
diff --git a/arch/arm/mach-k3/r5/lpm-common.c b/arch/arm/mach-k3/r5/lpm-common.c
index 559e1b5f681a..0e5feae6d12d 100644
--- a/arch/arm/mach-k3/r5/lpm-common.c
+++ b/arch/arm/mach-k3/r5/lpm-common.c
@@ -29,6 +29,11 @@
/* PMIC register where the magic value resides */
#define K3_LPM_SCRATCH_PAD_REG_3 0xcb
+/* Wake-up source IDs */
+#define K3_LPM_WAKE_SOURCE_MAIN_IO 0x80
+#define K3_LPM_WAKE_SOURCE_MCU_IO 0x81
+#define K3_LPM_WAKE_SOURCE_PMIC_GPIO 0xB0
+
#define IO_ISO_STATUS BIT(25)
#define FW_IMAGE_SIZE 0x80000
@@ -40,6 +45,11 @@ struct lpm_addr_info {
u32 size;
};
+struct lpm_scratch_space {
+ u16 wake_src;
+ u16 reserved;
+} __packed;
+
__weak void clear_isolation(void) { }
/* This is used by J722s */
@@ -75,6 +85,7 @@ void k3_deassert_ddr_ret(const char *pmic_name, unsigned int ddr_ret_val,
/* in board_init_f(), there's no BSS, so we can't use global/static variables */
bool j7xx_board_is_resuming(void)
{
+ struct lpm_scratch_space *lpm_scratch;
struct udevice *pmic, *i2c;
u32 pmctrl_val = 0;
int ret, magic;
@@ -85,7 +96,18 @@ bool j7xx_board_is_resuming(void)
#ifdef PMCTRL_IO_LPM
pmctrl_val = readl(PMCTRL_IO_LPM);
#endif
+ lpm_scratch = (struct lpm_scratch_space *)CONFIG_SYS_K3_SCRATCH_LPM_ADDR;
+ if (lpm_scratch) {
+ lpm_scratch->wake_src = 0;
+ lpm_scratch->reserved = 0;
+ }
if ((pmctrl_val & IO_ISO_STATUS) == IO_ISO_STATUS) {
+ if (lpm_scratch) {
+ if (IS_ENABLED(CONFIG_SOC_K3_J784S4))
+ lpm_scratch->wake_src = K3_LPM_WAKE_SOURCE_MCU_IO;
+ else
+ lpm_scratch->wake_src = K3_LPM_WAKE_SOURCE_MAIN_IO;
+ }
clear_isolation();
gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
debug("board is resuming from IO_DDR mode\n");
@@ -127,6 +149,8 @@ bool j7xx_board_is_resuming(void)
if (magic == K3_LPM_MAGIC_SUSPEND) {
debug("%s: board is resuming\n", __func__);
+ if (lpm_scratch)
+ lpm_scratch->wake_src = K3_LPM_WAKE_SOURCE_PMIC_GPIO;
gd_set_k3_resuming(K3_RESUME_STATE_RESUMING);
/* clean magic suspend */
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v5 11/21] board: mach-k3: r5: common: Set PMIC NSLEEP triggers bits at resume
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (9 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 10/21] board: mach-k3: r5: common: Store wakeup reason on scratchpad memory Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 12/21] ram: k3-ddrss: Add exit retention support Richard Genoud (TI)
` (9 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, Udit Kumar,
Abhash Kumar, Thomas Richard, Gregory CLEMENT, Thomas Petazzoni,
Richard Genoud, u-boot
If we are resuming NSLEEP triggers bits of PMIC-A and PMIC-B shall be set
to prevent transition to S2R state while clearing interrupts.
For example PMIC RTC Linux driver accesses to interrupt registers, in this
case if NSLEEP triggers bits are not set it triggers a S2R transition.
Suggested-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/r5/lpm-common.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/arch/arm/mach-k3/r5/lpm-common.c b/arch/arm/mach-k3/r5/lpm-common.c
index 0e5feae6d12d..4b67b9417c29 100644
--- a/arch/arm/mach-k3/r5/lpm-common.c
+++ b/arch/arm/mach-k3/r5/lpm-common.c
@@ -29,6 +29,9 @@
/* PMIC register where the magic value resides */
#define K3_LPM_SCRATCH_PAD_REG_3 0xcb
+/* PMIC NSLEEP register */
+#define K3_LPM_NSLEEP_TRIGGER_REG 0x86
+
/* Wake-up source IDs */
#define K3_LPM_WAKE_SOURCE_MAIN_IO 0x80
#define K3_LPM_WAKE_SOURCE_MCU_IO 0x81
@@ -161,6 +164,30 @@ bool j7xx_board_is_resuming(void)
if (ret)
printf("Failed to clean magic value for suspend detection in PMIC\n");
+
+ /*
+ * Ensure that NSLEEP triggers bits are set to prevent a
+ * suspend/resume transition when accessing PMIC interrupt
+ * registers.
+ */
+ if (IS_ENABLED(CONFIG_SOC_K3_J722S)) {
+ ret = dm_i2c_reg_write(pmic, K3_LPM_NSLEEP_TRIGGER_REG, 0x3);
+ } else {
+ struct udevice *pmic_b;
+
+ /* Some boards may have more than one pmic */
+ ret = uclass_get_device_by_name(UCLASS_PMIC, "pmic@4c", &pmic_b);
+ if (ret == 0) {
+ ret = pmic_reg_write(pmic_b, K3_LPM_NSLEEP_TRIGGER_REG, 0x03);
+ if (ret)
+ printf("Failed to set NSLEEP triggers bits on PMIC-B\n");
+ }
+
+ ret = pmic_reg_write(pmic, K3_LPM_NSLEEP_TRIGGER_REG, 0x3);
+ }
+ if (ret)
+ printf("Failed to set PMIC NSLEEP triggers. Spurious suspend/resume may happen.\n");
+
/*
* For robustness, the DM should also clean the magic value at
* startup.
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v5 12/21] ram: k3-ddrss: Add exit retention support
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (10 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 11/21] board: mach-k3: r5: common: Set PMIC NSLEEP triggers bits at resume Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 13/21] ram: k3-ddrss: Add j722s DDR resume sequence Richard Genoud (TI)
` (8 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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 54e191df8de9..d8ec8356b286 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] 22+ messages in thread* [PATCH v5 13/21] ram: k3-ddrss: Add j722s DDR resume sequence
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (11 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 12/21] ram: k3-ddrss: Add exit retention support Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 14/21] ram: k3-ddrss: support j784s4/j721e/j721s2 DDR resume Richard Genoud (TI)
` (7 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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 ++++
| 8 ++++++++
2 files changed, 12 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 d8ec8356b286..3af360f191df 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -19,6 +19,7 @@
#include <power-domain.h>
#include <wait_bit.h>
#include <power/regulator.h>
+#include <mach/hardware.h>
#include <mach/k3-ddr.h>
#include "k3-ddrss-lpm.h"
@@ -1300,11 +1301,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] 22+ messages in thread* [PATCH v5 14/21] ram: k3-ddrss: support j784s4/j721e/j721s2 DDR resume
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (12 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 13/21] ram: k3-ddrss: Add j722s DDR resume sequence Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 15/21] arm: mach-k3: j721e: Enable LPM resume flow for J7200/J721e SOC Richard Genoud (TI)
` (6 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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 3af360f191df..60f54a72adea 100644
--- a/drivers/ram/k3-ddrss/k3-ddrss.c
+++ b/drivers/ram/k3-ddrss/k3-ddrss.c
@@ -123,6 +123,7 @@ enum intrlv_size {
struct k3_ddrss_data {
u32 flags;
+ bool lpm_init_only;
bool (*is_lpm_resume)(void);
void (*ddrss_deassert_retention)(void);
};
@@ -1158,6 +1159,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);
@@ -1289,6 +1293,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 = {
@@ -1299,6 +1305,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] 22+ messages in thread* [PATCH v5 15/21] arm: mach-k3: j721e: Enable LPM resume flow for J7200/J721e SOC
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (13 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 14/21] ram: k3-ddrss: support j784s4/j721e/j721s2 DDR resume Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 16/21] arm: mach-k3: j784s4: Enable LPM resume flow for J784s4/J742s2 SOCs Richard Genoud (TI)
` (5 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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 | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/arm/mach-k3/j721e/j721e_init.c b/arch/arm/mach-k3/j721e/j721e_init.c
index f9af0288cf66..fce6702be687 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
@@ -46,6 +49,10 @@
#define DEV_A72SS0_CORE0_ID 4
#define DEV_A72SS0_CORE0_MSMC_CLK_ID 1
+/* DDR retention bits */
+#define DDR_RET_VAL BIT(1)
+#define DDR_RET_CLK BIT(2)
+
#ifdef CONFIG_K3_LOAD_SYSFW
struct fwl_data cbass_hc_cfg0_fwls[] = {
#if defined(CONFIG_SOC_K3_J721E)
@@ -298,6 +305,7 @@ 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 +418,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("pmic@4c", DDR_RET_VAL, DDR_RET_CLK, true);
+ 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] 22+ messages in thread* [PATCH v5 16/21] arm: mach-k3: j784s4: Enable LPM resume flow for J784s4/J742s2 SOCs
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (14 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 15/21] arm: mach-k3: j721e: Enable LPM resume flow for J7200/J721e SOC Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 17/21] arm: mach-k3: j722s: Enable LPM resume flow Richard Genoud (TI)
` (4 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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 | 44 +++++++++++++++++++++++++--
board/ti/j784s4/evm.c | 3 +-
2 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-k3/j784s4/j784s4_init.c b/arch/arm/mach-k3/j784s4/j784s4_init.c
index 507b7ab685ad..d49249fa233a 100644
--- a/arch/arm/mach-k3/j784s4/j784s4_init.c
+++ b/arch/arm/mach-k3/j784s4/j784s4_init.c
@@ -18,11 +18,21 @@
#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
+
+/* DDR retention bits */
+#define DDR_RET_VAL BIT(5)
#define CTRL_MMR_CFG0_AUDIO_REFCLK1_CTRL 0x001082e4
#define AUDIO_REFCLK1_DEFAULT 0x1c
@@ -279,20 +289,50 @@ void k3_mem_init(void)
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("pmic@48", DDR_RET_VAL, 0, false);
+
+ /* 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 179a26d570fd..3b345528be5f 100644
--- a/board/ti/j784s4/evm.c
+++ b/board/ti/j784s4/evm.c
@@ -61,7 +61,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)))
void clear_isolation(void)
{
int ret;
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH v5 17/21] arm: mach-k3: j722s: Enable LPM resume flow
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (15 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 16/21] arm: mach-k3: j784s4: Enable LPM resume flow for J784s4/J742s2 SOCs Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 18/21] arm: mach-k3: j721s2: " Richard Genoud (TI)
` (3 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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 | 6 +++++-
1 file changed, 5 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..e98c9d93ac53 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 },
@@ -37,7 +38,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);
@@ -186,6 +187,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] 22+ messages in thread* [PATCH v5 18/21] arm: mach-k3: j721s2: Enable LPM resume flow
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (16 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 17/21] arm: mach-k3: j722s: Enable LPM resume flow Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 19/21] arm: mach-k3: Update pm-boardcfg for all k3 platforms Richard Genoud (TI)
` (2 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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 | 49 ++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-k3/j721s2/j721s2_init.c b/arch/arm/mach-k3/j721s2/j721s2_init.c
index 780d853423f8..e35b00ff2dbb 100644
--- a/arch/arm/mach-k3/j721s2/j721s2_init.c
+++ b/arch/arm/mach-k3/j721s2/j721s2_init.c
@@ -16,12 +16,20 @@
#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
+
+/* DDR retention bits */
+#define DDR_RET_VAL BIT(3)
+
/* NAVSS North Bridge (NB) */
#define NAVSS0_NBSS_NB0_CFG_MMRS 0x03702000
#define NAVSS0_NBSS_NB1_CFG_MMRS 0x03703000
@@ -262,9 +270,12 @@ bool check_rom_loaded_sysfw(void)
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);
@@ -272,10 +283,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("pmic@4c", DDR_RET_VAL, 0, false);
+
+ /* 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] 22+ messages in thread* [PATCH v5 19/21] arm: mach-k3: Update pm-boardcfg for all k3 platforms
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (17 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 18/21] arm: mach-k3: j721s2: " Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 20/21] arm: dts: k3-j7200: Remove background firewall on DDR Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 21/21] arm: dts: k3-j7200: Extend firewall for ATF region to TIFS Richard Genoud (TI)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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 configuration 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>
Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/mach-k3/schema.yaml | 146 ++++++++++++++++++++++--
board/beagle/beagleboneai64/pm-cfg.yaml | 5 +-
board/beagle/beagleplay/pm-cfg.yaml | 7 +-
board/beagle/beagley-ai/pm-cfg.yaml | 7 +-
board/phytec/phycore_am62ax/pm-cfg.yaml | 7 +-
board/phytec/phycore_am62x/pm-cfg.yaml | 7 +-
board/phytec/phycore_am64x/pm-cfg.yaml | 5 +-
board/phytec/phycore_am68x/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 | 94 ++++++++++++++-
board/ti/j784s4/pm-cfg.yaml | 94 ++++++++++++++-
board/toradex/aquila-am69/pm-cfg.yaml | 7 +-
board/toradex/verdin-am62/pm-cfg.yaml | 7 +-
board/toradex/verdin-am62p/pm-cfg.yaml | 7 +-
tools/binman/etype/ti_board_config.py | 4 +-
22 files changed, 649 insertions(+), 66 deletions(-)
diff --git a/arch/arm/mach-k3/schema.yaml b/arch/arm/mach-k3/schema.yaml
index 8c4691f24ed6..f9d169526061 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:
diff --git a/board/beagle/beagleboneai64/pm-cfg.yaml b/board/beagle/beagleboneai64/pm-cfg.yaml
index 7ae52b3358e2..5533a609ba4b 100644
--- a/board/beagle/beagleboneai64/pm-cfg.yaml
+++ b/board/beagle/beagleboneai64/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/beagle/beagleplay/pm-cfg.yaml b/board/beagle/beagleplay/pm-cfg.yaml
index 9853a25eb85c..75cdeb8098fc 100644
--- a/board/beagle/beagleplay/pm-cfg.yaml
+++ b/board/beagle/beagleplay/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/beagle/beagley-ai/pm-cfg.yaml b/board/beagle/beagley-ai/pm-cfg.yaml
index 46b3ad201091..ab1c8e06f10e 100644
--- a/board/beagle/beagley-ai/pm-cfg.yaml
+++ b/board/beagle/beagley-ai/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/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/phytec/phycore_am62x/pm-cfg.yaml b/board/phytec/phycore_am62x/pm-cfg.yaml
index 9853a25eb85c..75cdeb8098fc 100644
--- a/board/phytec/phycore_am62x/pm-cfg.yaml
+++ b/board/phytec/phycore_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/phytec/phycore_am64x/pm-cfg.yaml b/board/phytec/phycore_am64x/pm-cfg.yaml
index 7afb29621088..e9866d0ea24d 100644
--- a/board/phytec/phycore_am64x/pm-cfg.yaml
+++ b/board/phytec/phycore_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/phytec/phycore_am68x/pm-cfg.yaml b/board/phytec/phycore_am68x/pm-cfg.yaml
index e6496512b6b7..5d8071a2d5cb 100644
--- a/board/phytec/phycore_am68x/pm-cfg.yaml
+++ b/board/phytec/phycore_am68x/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..1ffe2f475c9e 100644
--- a/board/ti/j722s/pm-cfg.yaml
+++ b/board/ti/j722s/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/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/board/toradex/aquila-am69/pm-cfg.yaml b/board/toradex/aquila-am69/pm-cfg.yaml
index 8583da3d55ad..1da3197c1f6a 100644
--- a/board/toradex/aquila-am69/pm-cfg.yaml
+++ b/board/toradex/aquila-am69/pm-cfg.yaml
@@ -8,6 +8,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/toradex/verdin-am62/pm-cfg.yaml b/board/toradex/verdin-am62/pm-cfg.yaml
index 9853a25eb85c..75cdeb8098fc 100644
--- a/board/toradex/verdin-am62/pm-cfg.yaml
+++ b/board/toradex/verdin-am62/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/toradex/verdin-am62p/pm-cfg.yaml b/board/toradex/verdin-am62p/pm-cfg.yaml
index 3ff27ce702c2..15a0cc6e8588 100644
--- a/board/toradex/verdin-am62p/pm-cfg.yaml
+++ b/board/toradex/verdin-am62p/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/tools/binman/etype/ti_board_config.py b/tools/binman/etype/ti_board_config.py
index 3f2135f8f33b..7d1330ef3aab 100644
--- a/tools/binman/etype/ti_board_config.py
+++ b/tools/binman/etype/ti_board_config.py
@@ -126,8 +126,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] 22+ messages in thread* [PATCH v5 20/21] arm: dts: k3-j7200: Remove background firewall on DDR
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (18 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 19/21] arm: mach-k3: Update pm-boardcfg for all k3 platforms Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
2026-08-28 13:57 ` [PATCH v5 21/21] arm: dts: k3-j7200: Extend firewall for ATF region to TIFS Richard Genoud (TI)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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] 22+ messages in thread* [PATCH v5 21/21] arm: dts: k3-j7200: Extend firewall for ATF region to TIFS
2026-08-28 13:57 [PATCH v5 00/21] Introduce resume for J7xx SoCs Richard Genoud (TI)
` (19 preceding siblings ...)
2026-08-28 13:57 ` [PATCH v5 20/21] arm: dts: k3-j7200: Remove background firewall on DDR Richard Genoud (TI)
@ 2026-08-28 13:57 ` Richard Genoud (TI)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Genoud (TI) @ 2026-08-28 13:57 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, Kendall Willis, 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>
Co-developed-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
Signed-off-by: Richard Genoud (TI) <richard.genoud@bootlin.com>
---
arch/arm/dts/k3-binman.dtsi | 7 ++++++-
arch/arm/dts/k3-security.h | 1 +
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/k3-binman.dtsi b/arch/arm/dts/k3-binman.dtsi
index ad127663d03b..1cf417ed7dcd 100644
--- a/arch/arm/dts/k3-binman.dtsi
+++ b/arch/arm/dts/k3-binman.dtsi
@@ -475,7 +475,12 @@
FWCTRL_CACHE)>;
permissions = <((FWPRIVID_ARMV8 << FWPRIVID_SHIFT) |
FWPERM_SECURE_PRIV_RWCD |
- FWPERM_SECURE_USER_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 CONFIG_K3_ATF_LOAD_ADDR>;
end_address = <0x0 (CONFIG_K3_ATF_LOAD_ADDR + CONFIG_K3_ATF_RESERVED_SIZE - 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] 22+ messages in thread