xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8189/mt_spm_suspend.c (revision 083cfadb6a246c89e306f5a83d05cad90e3bab1f)
1 /*
2  * Copyright (c) 2025, Mediatek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <stdint.h>
8 #include <stdio.h>
9 
10 #include <common/debug.h>
11 #include <lib/mmio.h>
12 
13 #include <constraints/mt_spm_rc_internal.h>
14 #include <drivers/spm/mt_spm_resource_req.h>
15 #include <lib/pm/mtk_pm.h>
16 #include <lpm_v2/mt_lp_api.h>
17 #include <lpm_v2/mt_lp_rqm.h>
18 #include <mt_spm.h>
19 #include <mt_spm_conservation.h>
20 #include <mt_spm_internal.h>
21 #include <mt_spm_reg.h>
22 #include <mt_spm_stats.h>
23 #include <mt_spm_suspend.h>
24 #if defined(CONFIG_MTK_VCOREDVFS_SUPPORT)
25 #include <mt_spm_vcorefs_exp.h>
26 #endif
27 
28 #define SPM_SUSPEND_SLEEP_PCM_FLAG                                  \
29 	(SPM_FLAG_DISABLE_INFRA_PDN | SPM_FLAG_DISABLE_DPM_PDN |    \
30 	 SPM_FLAG_DISABLE_MCUPM_PDN | SPM_FLAG_DISABLE_VCORE_DVS |  \
31 	 SPM_FLAG_DISABLE_DDR_DFS | SPM_FLAG_DISABLE_EMI_DFS |      \
32 	 SPM_FLAG_DISABLE_BUS_DFS | SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
33 	 SPM_FLAG_SRAM_SLEEP_CTRL)
34 
35 #define SPM_SUSPEND_SLEEP_PCM_FLAG1 (SPM_FLAG1_ENABLE_VS2_VS3_VOTER)
36 
37 #define SPM_SUSPEND_PCM_FLAG                                     \
38 	(SPM_FLAG_DISABLE_VCORE_DVS | SPM_FLAG_DISABLE_DDR_DFS | \
39 	 SPM_FLAG_DISABLE_EMI_DFS | SPM_FLAG_DISABLE_BUS_DFS |   \
40 	 SPM_FLAG_SRAM_SLEEP_CTRL)
41 
42 #define SPM_SUSPEND_PCM_FLAG1 (SPM_FLAG1_ENABLE_VS2_VS3_VOTER)
43 
44 /* Suspend spm power control */
45 #define __WAKE_SRC_FOR_SUSPEND_COMMON__                                        \
46 	((R12_PCM_TIMER_B) | (R12_KP_IRQ_B) | (R12_CONN2AP_WAKEUP_B) |         \
47 	 (R12_EINT_EVENT_B) | (R12_CONN_WDT_IRQ_B) | (R12_SSPM2SPM_WAKEUP_B) | \
48 	 (R12_SCP2SPM_WAKEUP_B) | (R12_VADSP2SPM_WAKEUP_B) |                   \
49 	 (R12_USB0_CDSC_B) | (R12_USB0_POWERDWN_B) | (R12_SBD_INTR_B) |        \
50 	 (R12_UART2SPM_IRQ_B) | (R12_SYS_TIMER_EVENT_B) |                      \
51 	 (R12_EINT_EVENT_SECURE_B) | (R12_SYS_CIRQ_IRQ_B) | (R12_CPU_WAKEUP) | \
52 	 (R12_APUSYS_WAKE_HOST_B) | (R12_PCIE_MAC_IRQ_WAKE_B) |                \
53 	 (R12_MSDC_WAKEUP_EVENT_B))
54 
55 #if defined(CFG_MICROTRUST_TEE_SUPPORT)
56 #define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__)
57 #else
58 #define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__ | R12_SEJ_B)
59 #endif
60 
61 static struct pwr_ctrl suspend_ctrl = {
62 	.wake_src = WAKE_SRC_FOR_SUSPEND,
63 
64 	/* Auto-gen Start */
65 
66 	/* SPM_SRC_REQ */
67 	.reg_spm_adsp_mailbox_req = 0,
68 	.reg_spm_apsrc_req = 0,
69 	.reg_spm_ddren_req = 0,
70 	.reg_spm_dvfs_req = 0,
71 	.reg_spm_emi_req = 0,
72 	.reg_spm_f26m_req = 0,
73 	.reg_spm_infra_req = 0,
74 	.reg_spm_pmic_req = 0,
75 	.reg_spm_scp_mailbox_req = 0,
76 	.reg_spm_sspm_mailbox_req = 0,
77 	.reg_spm_sw_mailbox_req = 0,
78 	.reg_spm_vcore_req = 0,
79 	.reg_spm_vrf18_req = 0,
80 	.adsp_mailbox_state = 0,
81 	.apsrc_state = 0,
82 	.ddren_state = 0,
83 	.dvfs_state = 0,
84 	.emi_state = 0,
85 	.f26m_state = 0,
86 	.infra_state = 0,
87 	.pmic_state = 0,
88 	.scp_mailbox_state = 0,
89 	.sspm_mailbox_state = 0,
90 	.sw_mailbox_state = 0,
91 	.vcore_state = 0,
92 	.vrf18_state = 0,
93 
94 	/* SPM_SRC_MASK_0 */
95 	.reg_apu_apsrc_req_mask_b = 0x1,
96 	.reg_apu_ddren_req_mask_b = 0x1,
97 	.reg_apu_emi_req_mask_b = 0x1,
98 	.reg_apu_infra_req_mask_b = 0x1,
99 	.reg_apu_pmic_req_mask_b = 0x1,
100 	.reg_apu_srcclkena_mask_b = 0x1,
101 	.reg_apu_vrf18_req_mask_b = 0x1,
102 	.reg_audio_dsp_apsrc_req_mask_b = 0x0,
103 	.reg_audio_dsp_ddren_req_mask_b = 0x0,
104 	.reg_audio_dsp_emi_req_mask_b = 0x0,
105 	.reg_audio_dsp_infra_req_mask_b = 0x0,
106 	.reg_audio_dsp_pmic_req_mask_b = 0x0,
107 	.reg_audio_dsp_srcclkena_mask_b = 0x0,
108 	.reg_audio_dsp_vcore_req_mask_b = 0x0,
109 	.reg_audio_dsp_vrf18_req_mask_b = 0x0,
110 	.reg_cam_apsrc_req_mask_b = 0x1,
111 	.reg_cam_ddren_req_mask_b = 0x1,
112 	.reg_cam_emi_req_mask_b = 0x1,
113 	.reg_cam_infra_req_mask_b = 0x0,
114 	.reg_cam_pmic_req_mask_b = 0x0,
115 	.reg_cam_srcclkena_mask_b = 0x0,
116 	.reg_cam_vrf18_req_mask_b = 0x0,
117 	.reg_mdp_emi_req_mask_b = 0x1,
118 
119 	/* SPM_SRC_MASK_1 */
120 	.reg_ccif_apsrc_req_mask_b = 0x0,
121 	.reg_ccif_emi_req_mask_b = 0xfff,
122 
123 	/* SPM_SRC_MASK_2 */
124 	.reg_ccif_infra_req_mask_b = 0x0,
125 	.reg_ccif_pmic_req_mask_b = 0xfff,
126 
127 	/* SPM_SRC_MASK_3 */
128 	.reg_ccif_srcclkena_mask_b = 0x0,
129 	.reg_ccif_vrf18_req_mask_b = 0xfff,
130 	.reg_ccu_apsrc_req_mask_b = 0x0,
131 	.reg_ccu_ddren_req_mask_b = 0x0,
132 	.reg_ccu_emi_req_mask_b = 0x0,
133 	.reg_ccu_infra_req_mask_b = 0x0,
134 	.reg_ccu_pmic_req_mask_b = 0x0,
135 	.reg_ccu_srcclkena_mask_b = 0x0,
136 	.reg_ccu_vrf18_req_mask_b = 0x0,
137 	.reg_cg_check_apsrc_req_mask_b = 0x1,
138 
139 	/* SPM_SRC_MASK_4 */
140 	.reg_cg_check_ddren_req_mask_b = 0x1,
141 	.reg_cg_check_emi_req_mask_b = 0x1,
142 	.reg_cg_check_infra_req_mask_b = 0x1,
143 	.reg_cg_check_pmic_req_mask_b = 0x1,
144 	.reg_cg_check_srcclkena_mask_b = 0x1,
145 	.reg_cg_check_vcore_req_mask_b = 0x1,
146 	.reg_cg_check_vrf18_req_mask_b = 0x1,
147 	.reg_conn_apsrc_req_mask_b = 0x1,
148 	.reg_conn_ddren_req_mask_b = 0x1,
149 	.reg_conn_emi_req_mask_b = 0x1,
150 	.reg_conn_infra_req_mask_b = 0x1,
151 	.reg_conn_pmic_req_mask_b = 0x1,
152 	.reg_conn_srcclkena_mask_b = 0x1,
153 	.reg_conn_srcclkenb_mask_b = 0x1,
154 	.reg_conn_vcore_req_mask_b = 0x1,
155 	.reg_conn_vrf18_req_mask_b = 0x1,
156 	.reg_cpueb_apsrc_req_mask_b = 0x1,
157 	.reg_cpueb_ddren_req_mask_b = 0x1,
158 	.reg_cpueb_emi_req_mask_b = 0x1,
159 	.reg_cpueb_infra_req_mask_b = 0x1,
160 	.reg_cpueb_pmic_req_mask_b = 0x1,
161 	.reg_cpueb_srcclkena_mask_b = 0x1,
162 	.reg_cpueb_vrf18_req_mask_b = 0x1,
163 	.reg_disp0_apsrc_req_mask_b = 0x1,
164 	.reg_disp0_ddren_req_mask_b = 0x1,
165 	.reg_disp0_emi_req_mask_b = 0x1,
166 	.reg_disp0_infra_req_mask_b = 0x1,
167 	.reg_disp0_pmic_req_mask_b = 0x0,
168 	.reg_disp0_srcclkena_mask_b = 0x0,
169 	.reg_disp0_vrf18_req_mask_b = 0x1,
170 	.reg_disp1_apsrc_req_mask_b = 0x0,
171 	.reg_disp1_ddren_req_mask_b = 0x0,
172 
173 	/* SPM_SRC_MASK_5 */
174 	.reg_disp1_emi_req_mask_b = 0x0,
175 	.reg_disp1_infra_req_mask_b = 0x0,
176 	.reg_disp1_pmic_req_mask_b = 0x0,
177 	.reg_disp1_srcclkena_mask_b = 0x0,
178 	.reg_disp1_vrf18_req_mask_b = 0x0,
179 	.reg_dpm_apsrc_req_mask_b = 0xf,
180 	.reg_dpm_ddren_req_mask_b = 0xf,
181 	.reg_dpm_emi_req_mask_b = 0xf,
182 	.reg_dpm_infra_req_mask_b = 0xf,
183 	.reg_dpm_pmic_req_mask_b = 0xf,
184 	.reg_dpm_srcclkena_mask_b = 0xf,
185 
186 	/* SPM_SRC_MASK_6 */
187 	.reg_dpm_vcore_req_mask_b = 0xf,
188 	.reg_dpm_vrf18_req_mask_b = 0xf,
189 	.reg_dpmaif_apsrc_req_mask_b = 0x1,
190 	.reg_dpmaif_ddren_req_mask_b = 0x1,
191 	.reg_dpmaif_emi_req_mask_b = 0x1,
192 	.reg_dpmaif_infra_req_mask_b = 0x1,
193 	.reg_dpmaif_pmic_req_mask_b = 0x1,
194 	.reg_dpmaif_srcclkena_mask_b = 0x1,
195 	.reg_dpmaif_vrf18_req_mask_b = 0x1,
196 	.reg_dvfsrc_level_req_mask_b = 0x1,
197 	.reg_emisys_apsrc_req_mask_b = 0x0,
198 	.reg_emisys_ddren_req_mask_b = 0x1,
199 	.reg_emisys_emi_req_mask_b = 0x0,
200 	.reg_gce_d_apsrc_req_mask_b = 0x1,
201 	.reg_gce_d_ddren_req_mask_b = 0x1,
202 	.reg_gce_d_emi_req_mask_b = 0x1,
203 	.reg_gce_d_infra_req_mask_b = 0x0,
204 	.reg_gce_d_pmic_req_mask_b = 0x0,
205 	.reg_gce_d_srcclkena_mask_b = 0x0,
206 	.reg_gce_d_vrf18_req_mask_b = 0x0,
207 	.reg_gce_m_apsrc_req_mask_b = 0x1,
208 	.reg_gce_m_ddren_req_mask_b = 0x1,
209 	.reg_gce_m_emi_req_mask_b = 0x1,
210 	.reg_gce_m_infra_req_mask_b = 0x0,
211 	.reg_gce_m_pmic_req_mask_b = 0x0,
212 	.reg_gce_m_srcclkena_mask_b = 0x0,
213 
214 	/* SPM_SRC_MASK_7 */
215 	.reg_gce_m_vrf18_req_mask_b = 0x0,
216 	.reg_gpueb_apsrc_req_mask_b = 0x0,
217 	.reg_gpueb_ddren_req_mask_b = 0x0,
218 	.reg_gpueb_emi_req_mask_b = 0x0,
219 	.reg_gpueb_infra_req_mask_b = 0x0,
220 	.reg_gpueb_pmic_req_mask_b = 0x0,
221 	.reg_gpueb_srcclkena_mask_b = 0x0,
222 	.reg_gpueb_vrf18_req_mask_b = 0x0,
223 	.reg_hwccf_apsrc_req_mask_b = 0x1,
224 	.reg_hwccf_ddren_req_mask_b = 0x1,
225 	.reg_hwccf_emi_req_mask_b = 0x1,
226 	.reg_hwccf_infra_req_mask_b = 0x1,
227 	.reg_hwccf_pmic_req_mask_b = 0x1,
228 	.reg_hwccf_srcclkena_mask_b = 0x1,
229 	.reg_hwccf_vcore_req_mask_b = 0x1,
230 	.reg_hwccf_vrf18_req_mask_b = 0x1,
231 	.reg_img_apsrc_req_mask_b = 0x1,
232 	.reg_img_ddren_req_mask_b = 0x1,
233 	.reg_img_emi_req_mask_b = 0x1,
234 	.reg_img_infra_req_mask_b = 0x0,
235 	.reg_img_pmic_req_mask_b = 0x0,
236 	.reg_img_srcclkena_mask_b = 0x0,
237 	.reg_img_vrf18_req_mask_b = 0x0,
238 	.reg_infrasys_apsrc_req_mask_b = 0x1,
239 	.reg_infrasys_ddren_req_mask_b = 0x1,
240 	.reg_infrasys_emi_req_mask_b = 0x1,
241 	.reg_ipic_infra_req_mask_b = 0x1,
242 	.reg_ipic_vrf18_req_mask_b = 0x1,
243 	.reg_mcu_apsrc_req_mask_b = 0x0,
244 	.reg_mcu_ddren_req_mask_b = 0x0,
245 	.reg_mcu_emi_req_mask_b = 0x0,
246 
247 	/* SPM_SRC_MASK_8 */
248 	.reg_mcusys_apsrc_req_mask_b = 0x7,
249 	.reg_mcusys_ddren_req_mask_b = 0x7,
250 	.reg_mcusys_emi_req_mask_b = 0x7,
251 	.reg_mcusys_infra_req_mask_b = 0x0,
252 
253 	/* SPM_SRC_MASK_9 */
254 	.reg_mcusys_pmic_req_mask_b = 0x0,
255 	.reg_mcusys_srcclkena_mask_b = 0x0,
256 	.reg_mcusys_vrf18_req_mask_b = 0x0,
257 	.reg_md_apsrc_req_mask_b = 0x0,
258 	.reg_md_ddren_req_mask_b = 0x0,
259 	.reg_md_emi_req_mask_b = 0x0,
260 	.reg_md_infra_req_mask_b = 0x0,
261 	.reg_md_pmic_req_mask_b = 0x0,
262 	.reg_md_srcclkena_mask_b = 0x0,
263 	.reg_md_srcclkena1_mask_b = 0x0,
264 	.reg_md_vcore_req_mask_b = 0x0,
265 
266 	/* SPM_SRC_MASK_10 */
267 	.reg_md_vrf18_req_mask_b = 0x0,
268 	.reg_mdp_apsrc_req_mask_b = 0x0,
269 	.reg_mdp_ddren_req_mask_b = 0x0,
270 	.reg_mm_proc_apsrc_req_mask_b = 0x0,
271 	.reg_mm_proc_ddren_req_mask_b = 0x0,
272 	.reg_mm_proc_emi_req_mask_b = 0x0,
273 	.reg_mm_proc_infra_req_mask_b = 0x0,
274 	.reg_mm_proc_pmic_req_mask_b = 0x0,
275 	.reg_mm_proc_srcclkena_mask_b = 0x0,
276 	.reg_mm_proc_vrf18_req_mask_b = 0x0,
277 	.reg_mmsys_apsrc_req_mask_b = 0x0,
278 	.reg_mmsys_ddren_req_mask_b = 0x0,
279 	.reg_mmsys_vrf18_req_mask_b = 0x0,
280 	.reg_pcie0_apsrc_req_mask_b = 0x0,
281 	.reg_pcie0_ddren_req_mask_b = 0x0,
282 	.reg_pcie0_infra_req_mask_b = 0x0,
283 	.reg_pcie0_srcclkena_mask_b = 0x0,
284 	.reg_pcie0_vrf18_req_mask_b = 0x0,
285 	.reg_pcie1_apsrc_req_mask_b = 0x0,
286 	.reg_pcie1_ddren_req_mask_b = 0x0,
287 	.reg_pcie1_infra_req_mask_b = 0x0,
288 	.reg_pcie1_srcclkena_mask_b = 0x0,
289 	.reg_pcie1_vrf18_req_mask_b = 0x0,
290 	.reg_perisys_apsrc_req_mask_b = 0x1,
291 	.reg_perisys_ddren_req_mask_b = 0x1,
292 	.reg_perisys_emi_req_mask_b = 0x1,
293 	.reg_perisys_infra_req_mask_b = 0x1,
294 	.reg_perisys_pmic_req_mask_b = 0x1,
295 	.reg_perisys_srcclkena_mask_b = 0x1,
296 	.reg_perisys_vcore_req_mask_b = 0x1,
297 	.reg_perisys_vrf18_req_mask_b = 0x1,
298 	.reg_scp_apsrc_req_mask_b = 0x1,
299 
300 	/* SPM_SRC_MASK_11 */
301 	.reg_scp_ddren_req_mask_b = 0x1,
302 	.reg_scp_emi_req_mask_b = 0x1,
303 	.reg_scp_infra_req_mask_b = 0x1,
304 	.reg_scp_pmic_req_mask_b = 0x1,
305 	.reg_scp_srcclkena_mask_b = 0x1,
306 	.reg_scp_vcore_req_mask_b = 0x1,
307 	.reg_scp_vrf18_req_mask_b = 0x1,
308 	.reg_srcclkeni_infra_req_mask_b = 0x1,
309 	.reg_srcclkeni_pmic_req_mask_b = 0x1,
310 	.reg_srcclkeni_srcclkena_mask_b = 0x1,
311 	.reg_sspm_apsrc_req_mask_b = 0x1,
312 	.reg_sspm_ddren_req_mask_b = 0x1,
313 	.reg_sspm_emi_req_mask_b = 0x1,
314 	.reg_sspm_infra_req_mask_b = 0x1,
315 	.reg_sspm_pmic_req_mask_b = 0x1,
316 	.reg_sspm_srcclkena_mask_b = 0x1,
317 	.reg_sspm_vrf18_req_mask_b = 0x1,
318 	.reg_ssr_apsrc_req_mask_b = 0x0,
319 	.reg_ssr_ddren_req_mask_b = 0x0,
320 	.reg_ssr_emi_req_mask_b = 0x0,
321 	.reg_ssr_infra_req_mask_b = 0x0,
322 	.reg_ssr_pmic_req_mask_b = 0x0,
323 	.reg_ssr_srcclkena_mask_b = 0x0,
324 	.reg_ssr_vrf18_req_mask_b = 0x0,
325 	.reg_ufs_apsrc_req_mask_b = 0x1,
326 	.reg_ufs_ddren_req_mask_b = 0x1,
327 	.reg_ufs_emi_req_mask_b = 0x1,
328 	.reg_ufs_infra_req_mask_b = 0x1,
329 	.reg_ufs_pmic_req_mask_b = 0x1,
330 
331 	/* SPM_SRC_MASK_12 */
332 	.reg_ufs_srcclkena_mask_b = 0x1,
333 	.reg_ufs_vrf18_req_mask_b = 0x1,
334 	.reg_vdec_apsrc_req_mask_b = 0x1,
335 	.reg_vdec_ddren_req_mask_b = 0x1,
336 	.reg_vdec_emi_req_mask_b = 0x1,
337 	.reg_vdec_infra_req_mask_b = 0x0,
338 	.reg_vdec_pmic_req_mask_b = 0x0,
339 	.reg_vdec_srcclkena_mask_b = 0x0,
340 	.reg_vdec_vrf18_req_mask_b = 0x0,
341 	.reg_venc_apsrc_req_mask_b = 0x1,
342 	.reg_venc_ddren_req_mask_b = 0x1,
343 	.reg_venc_emi_req_mask_b = 0x1,
344 	.reg_venc_infra_req_mask_b = 0x0,
345 	.reg_venc_pmic_req_mask_b = 0x0,
346 	.reg_venc_srcclkena_mask_b = 0x0,
347 	.reg_venc_vrf18_req_mask_b = 0x0,
348 	.reg_ipe_apsrc_req_mask_b = 0x1,
349 	.reg_ipe_ddren_req_mask_b = 0x1,
350 	.reg_ipe_emi_req_mask_b = 0x1,
351 	.reg_ipe_infra_req_mask_b = 0x1,
352 	.reg_ipe_pmic_req_mask_b = 0x1,
353 	.reg_ipe_srcclkena_mask_b = 0x1,
354 	.reg_ipe_vrf18_req_mask_b = 0x1,
355 	.reg_ufs_vcore_req_mask_b = 0x1,
356 
357 	/* SPM_EVENT_CON_MISC */
358 	.reg_srcclken_fast_resp = 0,
359 	.reg_csyspwrup_ack_mask = 1,
360 
361 	/* Auto-gen End */
362 
363 	/* SPM_WAKEUP_EVENT_MASK */
364 	.reg_wakeup_event_mask = 0xC1B33012,
365 
366 	/* SPM_WAKEUP_EVENT_EXT_MASK */
367 	.reg_ext_wakeup_event_mask = 0xFFFFFFFF,
368 
369 	/*sw flag setting */
370 	.pcm_flags = SPM_SUSPEND_PCM_FLAG,
371 	.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1,
372 };
373 
374 static struct suspend_dbg_ctrl suspend_spm_dbg_ext = {
375 	.sleep_suspend_cnt = 0,
376 };
377 
378 static struct dbg_ctrl suspend_spm_dbg = {
379 	.count = 0,
380 	.duration = 0,
381 	.ext = &suspend_spm_dbg_ext,
382 };
383 
384 static struct spm_lp_stat suspend_lp_stat;
385 
386 struct spm_lp_scen __spm_suspend = {
387 	.pwrctrl = &suspend_ctrl,
388 	.dbgctrl = &suspend_spm_dbg,
389 	.lpstat = &suspend_lp_stat,
390 };
391 
392 static uint8_t bak_spm_vcore_req;
393 
394 int mt_spm_suspend_mode_set(enum mt_spm_suspend_mode mode, void *prv)
395 {
396 	if (mode == MT_SPM_SUSPEND_SLEEP) {
397 		suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG;
398 		suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1;
399 		suspend_ctrl.reg_spm_vcore_req = 1; /* disable AOC */
400 	} else {
401 		suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG;
402 		suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1;
403 	}
404 	return 0;
405 }
406 
407 int mt_spm_suspend_enter(int state_id, uint32_t ext_opand,
408 			 uint32_t resource_req)
409 {
410 	int ret = 0;
411 
412 	bak_spm_vcore_req = suspend_ctrl.reg_spm_vcore_req;
413 
414 	/* if FMAudio, ADSP, USB headset is active, change to sleep suspend mode */
415 	if (ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE)
416 		mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP, NULL);
417 
418 	mmio_write_32(SPM2SW_MAILBOX_0, 0x1);
419 
420 	ext_opand |= MT_SPM_EX_OP_DEVICES_SAVE;
421 
422 #if defined(CONFIG_MTK_VCOREDVFS_SUPPORT)
423 	/* Notify vcoredvfs suspend enter */
424 	spm_vcorefs_plat_suspend();
425 #endif
426 
427 	ret = spm_conservation(state_id, ext_opand, &__spm_suspend,
428 			       resource_req);
429 	if (ret == 0) {
430 		struct mt_lp_publish_event event = {
431 			.id = MT_LPM_PUBEVENTS_SYS_POWER_OFF,
432 			.val.u32 = 0,
433 			.level = MT_LP_SYSPOWER_LEVEL_SUSPEND,
434 		};
435 
436 		MT_LP_SUSPEND_PUBLISH_EVENT(&event);
437 	}
438 	return ret;
439 }
440 
441 void mt_spm_suspend_resume(int state_id, uint32_t ext_opand,
442 			   struct wake_status **status)
443 {
444 	struct mt_lp_publish_event event;
445 	struct wake_status *st = NULL;
446 
447 	ext_opand |= MT_SPM_EX_OP_DEVICES_SAVE;
448 
449 	spm_conservation_finish(state_id, ext_opand, &__spm_suspend, &st);
450 
451 	mt_spm_update_lp_stat(&suspend_lp_stat);
452 #if defined(CONFIG_MTK_VCOREDVFS_SUPPORT)
453 	/* Notify vcoredvfs suspend enter */
454 	spm_vcorefs_plat_resume();
455 	mmio_write_32(SPM2SW_MAILBOX_0, 0x0);
456 #endif
457 
458 	/*****************************************
459 	 * if FMAudio, ADSP, USB headset is active,
460 	 * change back to suspend mode and counting in resume
461 	 *****************************************/
462 
463 	if (ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) {
464 		mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN, NULL);
465 		suspend_spm_dbg_ext.sleep_suspend_cnt += 1;
466 	}
467 
468 	suspend_ctrl.reg_spm_vcore_req = bak_spm_vcore_req;
469 
470 	suspend_spm_dbg.count += 1;
471 	event.id = MT_LPM_PUBEVENTS_SYS_POWER_ON;
472 	event.val.u32 = 0;
473 	event.level = MT_LP_SYSPOWER_LEVEL_SUSPEND;
474 
475 	if (st) {
476 		if (st->tr.comm.r12 & R12_AP2AP_PEER_WAKEUP_B)
477 			event.val.u32 = MT_LPM_WAKE_MD_WAKEUP_DPMAIF;
478 		if (st->tr.comm.r12 & R12_CCIF0_EVENT_B)
479 			event.val.u32 = MT_LPM_WAKE_MD_WAKEUP_CCIF0;
480 		if (st->tr.comm.r12 & R12_CCIF1_EVENT_B)
481 			event.val.u32 = MT_LPM_WAKE_MD_WAKEUP_CCIF1;
482 	}
483 	if (status)
484 		*status = st;
485 	MT_LP_SUSPEND_PUBLISH_EVENT(&event);
486 }
487 
488 int mt_spm_suspend_get_spm_lp(struct spm_lp_scen **lp)
489 {
490 	if (!lp)
491 		return -1;
492 
493 	*lp = &__spm_suspend;
494 	return 0;
495 }
496