static void __iomem *console_base;
static void __iomem *suspend_ocram_base;
static void (*imx7_suspend_in_ocram_fn)(void __iomem *ocram_vbase);
+struct imx7_cpu_pm_info *pm_info;
+static bool lpsr_enabled;
/*
* suspend ocram space layout:
* ======================== high address ======================
struct imx7_pm_base iomuxc_gpr_base;
struct imx7_pm_base ccm_base;
struct imx7_pm_base gpc_base;
- struct imx7_pm_base l2_base;
+ struct imx7_pm_base snvs_base;
struct imx7_pm_base anatop_base;
+ struct imx7_pm_base lpsr_base;
u32 ttbr1; /* Store TTBR1 */
u32 ddrc_num; /* Number of DDRC which need saved/restored. */
u32 ddrc_val[MX7_MAX_DDRC_NUM][2]; /* To save offset and value */
return 0;
}
+static void imx7_pm_set_lpsr_resume_addr(unsigned long addr)
+{
+ writel_relaxed(addr, pm_info->lpsr_base.vbase);
+}
+
static int imx7_pm_enter(suspend_state_t state)
{
unsigned int console_saved_reg[10] = {0};
if (imx_gpcv2_is_mf_mix_off()) {
imx7_console_save(console_saved_reg);
memcpy(ocram_saved_in_ddr, ocram_base, ocram_size);
+ if (lpsr_enabled)
+ imx7_pm_set_lpsr_resume_addr(pm_info->resume_addr);
}
/* Zzz ... */
memcpy(ocram_base, ocram_saved_in_ddr, ocram_size);
imx7_console_restore(console_saved_reg);
}
+ /* clear LPSR resume address */
+ imx7_pm_set_lpsr_resume_addr(0);
imx_anatop_post_resume();
imx_gpcv2_post_resume();
break;
static int __init imx7_suspend_init(const struct imx7_pm_socdata *socdata)
{
struct device_node *node;
- struct imx7_cpu_pm_info *pm_info;
int i, ret = 0;
const u32 (*ddrc_offset_array)[2];
const u32 (*ddrc_phy_offset_array)[2];
*/
pm_info->ccm_base.pbase = MX7D_CCM_BASE_ADDR;
pm_info->ccm_base.vbase = (void __iomem *)
- IMX_IO_P2V(MX7D_CCM_BASE_ADDR);
+ IMX_IO_P2V(MX7D_CCM_BASE_ADDR);
pm_info->ddrc_base.pbase = MX7D_DDRC_BASE_ADDR;
pm_info->ddrc_base.vbase = (void __iomem *)
- IMX_IO_P2V(MX7D_DDRC_BASE_ADDR);
+ IMX_IO_P2V(MX7D_DDRC_BASE_ADDR);
pm_info->ddrc_phy_base.pbase = MX7D_DDRC_PHY_BASE_ADDR;
pm_info->ddrc_phy_base.vbase = (void __iomem *)
- IMX_IO_P2V(MX7D_DDRC_PHY_BASE_ADDR);
+ IMX_IO_P2V(MX7D_DDRC_PHY_BASE_ADDR);
pm_info->src_base.pbase = MX7D_SRC_BASE_ADDR;
pm_info->src_base.vbase = (void __iomem *)
- IMX_IO_P2V(MX7D_SRC_BASE_ADDR);
+ IMX_IO_P2V(MX7D_SRC_BASE_ADDR);
pm_info->iomuxc_gpr_base.pbase = MX7D_IOMUXC_GPR_BASE_ADDR;
pm_info->iomuxc_gpr_base.vbase = (void __iomem *)
- IMX_IO_P2V(MX7D_IOMUXC_GPR_BASE_ADDR);
+ IMX_IO_P2V(MX7D_IOMUXC_GPR_BASE_ADDR);
pm_info->gpc_base.pbase = MX7D_GPC_BASE_ADDR;
pm_info->gpc_base.vbase = (void __iomem *)
- IMX_IO_P2V(MX7D_GPC_BASE_ADDR);
+ IMX_IO_P2V(MX7D_GPC_BASE_ADDR);
pm_info->anatop_base.pbase = MX7D_ANATOP_BASE_ADDR;
pm_info->anatop_base.vbase = (void __iomem *)
- IMX_IO_P2V(MX7D_ANATOP_BASE_ADDR);
+ IMX_IO_P2V(MX7D_ANATOP_BASE_ADDR);
+
+ pm_info->snvs_base.pbase = MX7D_SNVS_BASE_ADDR;
+ pm_info->snvs_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_SNVS_BASE_ADDR);
+
+ pm_info->lpsr_base.pbase = MX7D_LPSR_BASE_ADDR;
+ pm_info->lpsr_base.vbase = (void __iomem *)
+ IMX_IO_P2V(MX7D_LPSR_BASE_ADDR);
pm_info->ddrc_num = socdata->ddrc_num;
ddrc_offset_array = socdata->ddrc_offset;
struct device_node *np;
struct resource res;
+ np = of_find_compatible_node(NULL, NULL, "fsl,lpm-sram");
+ if (of_get_property(np, "fsl,enable-lpsr", NULL))
+ lpsr_enabled = true;
+
+ if (lpsr_enabled)
+ pr_info("LPSR mode enabled, DSM will go into LPSR mode!\n");
+
if (imx_ddrc_get_ddr_type() == IMX_DDR_TYPE_LPDDR3
|| imx_ddrc_get_ddr_type() == IMX_DDR_TYPE_LPDDR2)
imx7_pm_common_init(&imx7d_pm_data_lpddr3);
"/soc/aips-bus@30800000/spba-bus@30800000/serial@30860000");
if (np)
console_base = of_iomap(np, 0);
+
+ /* clear LPSR resume address first */
+ imx7_pm_set_lpsr_resume_addr(0);
}
#define PM_INFO_MX7_CCM_V_OFFSET 0x40
#define PM_INFO_MX7_GPC_P_OFFSET 0x44
#define PM_INFO_MX7_GPC_V_OFFSET 0x48
-#define PM_INFO_MX7_L2_P_OFFSET 0x4c
-#define PM_INFO_MX7_L2_V_OFFSET 0x50
+#define PM_INFO_MX7_SNVS_P_OFFSET 0x4c
+#define PM_INFO_MX7_SNVS_V_OFFSET 0x50
#define PM_INFO_MX7_ANATOP_P_OFFSET 0x54
#define PM_INFO_MX7_ANATOP_V_OFFSET 0x58
-#define PM_INFO_MX7_TTBR1_V_OFFSET 0x5c
-#define PM_INFO_DDRC_REG_NUM_OFFSET 0x60
-#define PM_INFO_DDRC_REG_OFFSET 0x64
-#define PM_INFO_DDRC_VALUE_OFFSET 0x68
-#define PM_INFO_DDRC_PHY_REG_NUM_OFFSET 0x164
-#define PM_INFO_DDRC_PHY_REG_OFFSET 0x168
-#define PM_INFO_DDRC_PHY_VALUE_OFFSET 0x16c
+#define PM_INFO_MX7_LPSR_P_OFFSET 0x5c
+#define PM_INFO_MX7_LPSR_V_OFFSET 0x60
+#define PM_INFO_MX7_TTBR1_V_OFFSET 0x64
+#define PM_INFO_DDRC_REG_NUM_OFFSET 0x68
+#define PM_INFO_DDRC_REG_OFFSET 0x6c
+#define PM_INFO_DDRC_VALUE_OFFSET 0x70
+#define PM_INFO_DDRC_PHY_REG_NUM_OFFSET 0x16c
+#define PM_INFO_DDRC_PHY_REG_OFFSET 0x170
+#define PM_INFO_DDRC_PHY_VALUE_OFFSET 0x174
#define MX7_SRC_GPR1 0x74
#define MX7_SRC_GPR2 0x78
beq ddr_only_self_refresh
ddr_enter_retention
- b ddr_retention_enter_out
+ /* enter LPSR mode if resume addr is valid */
+ ldr r11, [r0, #PM_INFO_MX7_LPSR_V_OFFSET]
+ ldr r7, [r11]
+ cmp r7, #0x0
+ beq ddr_retention_enter_out
+
+ /* shut down vddsoc to enter lpsr mode */
+ ldr r11, [r0, #PM_INFO_MX7_SNVS_V_OFFSET]
+ ldr r7, [r11, #0x38]
+ orr r7, r7, #0x60
+ str r7, [r11, #0x38]
+wait_shutdown:
+ b wait_shutdown
+
ddr_only_self_refresh:
ddrc_enter_self_refresh
ddr_retention_enter_out: