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