1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2017 NXP
4  *
5  * Peng Fan <peng.fan@nxp.com>
6  */
7 
8 #include <arm.h>
9 #include <arm32.h>
10 #include <console.h>
11 #include <drivers/imx_uart.h>
12 #include <io.h>
13 #include <imx.h>
14 #include <imx_pm.h>
15 #include <kernel/panic.h>
16 #include <kernel/cache_helpers.h>
17 #include <kernel/boot.h>
18 #include <kernel/misc.h>
19 #include <mm/core_mmu.h>
20 #include <mm/core_memprot.h>
21 #include <sm/sm.h>
22 #include <sm/pm.h>
23 #include <sm/psci.h>
24 #include <stdint.h>
25 
26 static int suspended_init;
27 
imx7_cpu_suspend(uint32_t power_state __unused,uintptr_t entry,uint32_t context_id __unused,struct sm_nsec_ctx * nsec)28 int imx7_cpu_suspend(uint32_t power_state __unused, uintptr_t entry,
29 		     uint32_t context_id __unused, struct sm_nsec_ctx *nsec)
30 {
31 	uint32_t suspend_ocram_base = core_mmu_get_va(TRUSTZONE_OCRAM_START +
32 						      SUSPEND_OCRAM_OFFSET,
33 						      MEM_AREA_TEE_COHERENT,
34 						      sizeof(struct
35 						      imx7_pm_info));
36 
37 	struct imx7_pm_info *p = (struct imx7_pm_info *)suspend_ocram_base;
38 	int ret;
39 
40 	if (!suspended_init) {
41 		imx7_suspend_init();
42 		suspended_init = 1;
43 	}
44 
45 	sm_save_unbanked_regs(&nsec->ub_regs);
46 
47 	ret = sm_pm_cpu_suspend((uint32_t)p, (int (*)(uint32_t))
48 				(suspend_ocram_base + sizeof(*p)));
49 	/*
50 	 * Sometimes sm_pm_cpu_suspend may not really suspended,
51 	 * we need to check it's return value to restore reg or not
52 	 */
53 	if (ret < 0) {
54 		DMSG("=== Not suspended, GPC IRQ Pending ===\n");
55 		return 0;
56 	}
57 
58 	if (!get_core_pos())
59 		plat_primary_init_early();
60 
61 	sm_restore_unbanked_regs(&nsec->ub_regs);
62 
63 	/* Set entry for back to Linux */
64 	nsec->mon_lr = (uint32_t)entry;
65 
66 	main_init_gic();
67 
68 	DMSG("=== Back from Suspended ===\n");
69 
70 	return 0;
71 }
72