blob: 18047e6f262fcd0fd117459adeaa8d9a4daf0340 [file] [log] [blame]
developer451d49d2022-11-16 21:52:21 +08001/*
2 * Copyright (c) 2023, MediaTek Inc. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <common/debug.h>
8#ifndef MTK_PLAT_SPM_UART_UNSUPPORT
9#include <drivers/uart.h>
10#endif
11#include <lib/mmio.h>
12#ifndef MTK_PLAT_CIRQ_UNSUPPORT
13#include <mtk_cirq.h>
14#endif
15#include <constraints/mt_spm_rc_internal.h>
16#include <drivers/spm/mt_spm_resource_req.h>
17#include <lib/pm/mtk_pm.h>
18#include <lpm/mt_lp_api.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_suspend.h>
24#include <pcm_def.h>
25
26#define SPM_SUSPEND_SLEEP_PCM_FLAG \
27 (SPM_FLAG_DISABLE_INFRA_PDN | \
28 SPM_FLAG_DISABLE_VCORE_DVS | \
29 SPM_FLAG_DISABLE_VCORE_DFS | \
30 SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \
31 SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \
32 SPM_FLAG_SRAM_SLEEP_CTRL)
33
34#define SPM_SUSPEND_SLEEP_PCM_FLAG1 (SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH)
35
36#define SPM_SUSPEND_PCM_FLAG \
37 (SPM_FLAG_DISABLE_VCORE_DVS | \
38 SPM_FLAG_DISABLE_VCORE_DFS | \
39 SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \
40 SPM_FLAG_SRAM_SLEEP_CTRL)
41
42#define SPM_SUSPEND_PCM_FLAG1 (SPM_FLAG1_DISABLE_PWRAP_CLK_SWITCH)
43
44/* Suspend spm power control */
45#define __WAKE_SRC_FOR_SUSPEND_COMMON__ ( \
46 (R12_PCM_TIMER) | \
47 (R12_KP_IRQ_B) | \
48 (R12_APWDT_EVENT_B) | \
49 (R12_MSDC_WAKEUP_B) | \
50 (R12_EINT_EVENT_B) | \
51 (R12_SBD_INTR_WAKEUP_B) | \
52 (R12_SSPM2SPM_WAKEUP_B) | \
53 (R12_SCP2SPM_WAKEUP_B) | \
54 (R12_ADSP2SPM_WAKEUP_B) | \
55 (R12_USBX_CDSC_B) | \
56 (R12_USBX_POWERDWN_B) | \
57 (R12_SYS_TIMER_EVENT_B) | \
58 (R12_EINT_EVENT_SECURE_B) | \
59 (R12_ECE_INT_HDMI_B) | \
60 (R12_SYS_CIRQ_IRQ_B) | \
61 (R12_PCIE_WAKEUPEVENT_B) | \
62 (R12_SPM_CPU_WAKEUPEVENT_B) | \
63 (R12_APUSYS_WAKE_HOST_B))
64
65#if defined(CFG_MICROTRUST_TEE_SUPPORT)
66#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__)
67#else
68#define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__ | R12_SEJ_EVENT_B)
69#endif
70
71static struct pwr_ctrl suspend_ctrl = {
72 .wake_src = WAKE_SRC_FOR_SUSPEND,
73
74 /* SPM_AP_STANDBY_CON */
75 /* [0] */
76 .reg_wfi_op = 0,
77 /* [1] */
78 .reg_wfi_type = 0,
79 /* [2] */
80 .reg_mp0_cputop_idle_mask = 0,
81 /* [3] */
82 .reg_mp1_cputop_idle_mask = 0,
83 /* [4] */
84 .reg_mcusys_idle_mask = 0,
85 /* [25] */
86 .reg_md_apsrc_1_sel = 0,
87 /* [26] */
88 .reg_md_apsrc_0_sel = 0,
89 /* [29] */
90 .reg_conn_apsrc_sel = 0,
91
92 /* SPM_SRC_REQ */
93 /* [0] */
94 .reg_spm_apsrc_req = 0,
95 /* [1] */
96 .reg_spm_f26m_req = 0,
97 /* [3] */
98 .reg_spm_infra_req = 0,
99 /* [4] */
100 .reg_spm_vrf18_req = 0,
101 /* [7] */
102 .reg_spm_ddr_en_req = 0,
103 /* [8] */
104 .reg_spm_dvfs_req = 0,
105 /* [9] */
106 .reg_spm_sw_mailbox_req = 0,
107 /* [10] */
108 .reg_spm_sspm_mailbox_req = 0,
109 /* [11] */
110 .reg_spm_adsp_mailbox_req = 0,
111 /* [12] */
112 .reg_spm_scp_mailbox_req = 0,
113
114 /* SPM_SRC_MASK */
115 /* [0] */
116 .reg_sspm_srcclkena_0_mask_b = 1,
117 /* [1] */
118 .reg_sspm_infra_req_0_mask_b = 1,
119 /* [2] */
120 .reg_sspm_apsrc_req_0_mask_b = 0,
121 /* [3] */
122 .reg_sspm_vrf18_req_0_mask_b = 0,
123 /* [4] */
124 .reg_sspm_ddr_en_0_mask_b = 0,
125 /* [5] */
126 .reg_scp_srcclkena_mask_b = 1,
127 /* [6] */
128 .reg_scp_infra_req_mask_b = 1,
129 /* [7] */
130 .reg_scp_apsrc_req_mask_b = 1,
131 /* [8] */
132 .reg_scp_vrf18_req_mask_b = 1,
133 /* [9] */
134 .reg_scp_ddr_en_mask_b = 1,
135 /* [10] */
136 .reg_audio_dsp_srcclkena_mask_b = 1,
137 /* [11] */
138 .reg_audio_dsp_infra_req_mask_b = 1,
139 /* [12] */
140 .reg_audio_dsp_apsrc_req_mask_b = 1,
141 /* [13] */
142 .reg_audio_dsp_vrf18_req_mask_b = 1,
143 /* [14] */
144 .reg_audio_dsp_ddr_en_mask_b = 1,
145 /* [15] */
146 .reg_apu_srcclkena_mask_b = 1,
147 /* [16] */
148 .reg_apu_infra_req_mask_b = 1,
149 /* [17] */
150 .reg_apu_apsrc_req_mask_b = 0,
151 /* [18] */
152 .reg_apu_vrf18_req_mask_b = 1,
153 /* [19] */
154 .reg_apu_ddr_en_mask_b = 1,
155 /* [20] */
156 .reg_cpueb_srcclkena_mask_b = 1,
157 /* [21] */
158 .reg_cpueb_infra_req_mask_b = 1,
159 /* [22] */
160 .reg_cpueb_apsrc_req_mask_b = 1,
161 /* [23] */
162 .reg_cpueb_vrf18_req_mask_b = 1,
163 /* [24] */
164 .reg_cpueb_ddr_en_mask_b = 1,
165 /* [25] */
166 .reg_bak_psri_srcclkena_mask_b = 0,
167 /* [26] */
168 .reg_bak_psri_infra_req_mask_b = 0,
169 /* [27] */
170 .reg_bak_psri_apsrc_req_mask_b = 0,
171 /* [28] */
172 .reg_bak_psri_vrf18_req_mask_b = 0,
173 /* [29] */
174 .reg_bak_psri_ddr_en_mask_b = 0,
175 /* [30] */
176 .reg_cam_ddren_req_mask_b = 0,
177 /* [31] */
178 .reg_img_ddren_req_mask_b = 0,
179
180 /* SPM_SRC2_MASK */
181 /* [0] */
182 .reg_msdc0_srcclkena_mask_b = 1,
183 /* [1] */
184 .reg_msdc0_infra_req_mask_b = 1,
185 /* [2] */
186 .reg_msdc0_apsrc_req_mask_b = 1,
187 /* [3] */
188 .reg_msdc0_vrf18_req_mask_b = 1,
189 /* [4] */
190 .reg_msdc0_ddr_en_mask_b = 1,
191 /* [5] */
192 .reg_msdc1_srcclkena_mask_b = 1,
193 /* [6] */
194 .reg_msdc1_infra_req_mask_b = 1,
195 /* [7] */
196 .reg_msdc1_apsrc_req_mask_b = 1,
197 /* [8] */
198 .reg_msdc1_vrf18_req_mask_b = 1,
199 /* [9] */
200 .reg_msdc1_ddr_en_mask_b = 1,
201 /* [10] */
202 .reg_msdc2_srcclkena_mask_b = 1,
203 /* [11] */
204 .reg_msdc2_infra_req_mask_b = 1,
205 /* [12] */
206 .reg_msdc2_apsrc_req_mask_b = 1,
207 /* [13] */
208 .reg_msdc2_vrf18_req_mask_b = 1,
209 /* [14] */
210 .reg_msdc2_ddr_en_mask_b = 1,
211 /* [15] */
212 .reg_ufs_srcclkena_mask_b = 1,
213 /* [16] */
214 .reg_ufs_infra_req_mask_b = 1,
215 /* [17] */
216 .reg_ufs_apsrc_req_mask_b = 1,
217 /* [18] */
218 .reg_ufs_vrf18_req_mask_b = 1,
219 /* [19] */
220 .reg_ufs_ddr_en_mask_b = 1,
221 /* [20] */
222 .reg_usb_srcclkena_mask_b = 1,
223 /* [21] */
224 .reg_usb_infra_req_mask_b = 1,
225 /* [22] */
226 .reg_usb_apsrc_req_mask_b = 1,
227 /* [23] */
228 .reg_usb_vrf18_req_mask_b = 1,
229 /* [24] */
230 .reg_usb_ddr_en_mask_b = 1,
231 /* [25] */
232 .reg_pextp_p0_srcclkena_mask_b = 1,
233 /* [26] */
234 .reg_pextp_p0_infra_req_mask_b = 1,
235 /* [27] */
236 .reg_pextp_p0_apsrc_req_mask_b = 1,
237 /* [28] */
238 .reg_pextp_p0_vrf18_req_mask_b = 1,
239 /* [29] */
240 .reg_pextp_p0_ddr_en_mask_b = 1,
241
242 /* SPM_SRC3_MASK */
243 /* [0] */
244 .reg_pextp_p1_srcclkena_mask_b = 1,
245 /* [1] */
246 .reg_pextp_p1_infra_req_mask_b = 1,
247 /* [2] */
248 .reg_pextp_p1_apsrc_req_mask_b = 1,
249 /* [3] */
250 .reg_pextp_p1_vrf18_req_mask_b = 1,
251 /* [4] */
252 .reg_pextp_p1_ddr_en_mask_b = 1,
253 /* [5] */
254 .reg_gce0_infra_req_mask_b = 1,
255 /* [6] */
256 .reg_gce0_apsrc_req_mask_b = 1,
257 /* [7] */
258 .reg_gce0_vrf18_req_mask_b = 1,
259 /* [8] */
260 .reg_gce0_ddr_en_mask_b = 1,
261 /* [9] */
262 .reg_gce1_infra_req_mask_b = 1,
263 /* [10] */
264 .reg_gce1_apsrc_req_mask_b = 1,
265 /* [11] */
266 .reg_gce1_vrf18_req_mask_b = 1,
267 /* [12] */
268 .reg_gce1_ddr_en_mask_b = 1,
269 /* [13] */
270 .reg_spm_srcclkena_reserved_mask_b = 1,
271 /* [14] */
272 .reg_spm_infra_req_reserved_mask_b = 1,
273 /* [15] */
274 .reg_spm_apsrc_req_reserved_mask_b = 1,
275 /* [16] */
276 .reg_spm_vrf18_req_reserved_mask_b = 1,
277 /* [17] */
278 .reg_spm_ddr_en_reserved_mask_b = 1,
279 /* [18] */
280 .reg_disp0_apsrc_req_mask_b = 1,
281 /* [19] */
282 .reg_disp0_ddr_en_mask_b = 1,
283 /* [20] */
284 .reg_disp1_apsrc_req_mask_b = 1,
285 /* [21] */
286 .reg_disp1_ddr_en_mask_b = 1,
287 /* [22] */
288 .reg_disp2_apsrc_req_mask_b = 1,
289 /* [23] */
290 .reg_disp2_ddr_en_mask_b = 1,
291 /* [24] */
292 .reg_disp3_apsrc_req_mask_b = 1,
293 /* [25] */
294 .reg_disp3_ddr_en_mask_b = 1,
295 /* [26] */
296 .reg_infrasys_apsrc_req_mask_b = 0,
297 /* [27] */
298 .reg_infrasys_ddr_en_mask_b = 1,
299
300 /* [28] */
301 .reg_cg_check_srcclkena_mask_b = 1,
302 /* [29] */
303 .reg_cg_check_apsrc_req_mask_b = 1,
304 /* [30] */
305 .reg_cg_check_vrf18_req_mask_b = 1,
306 /* [31] */
307 .reg_cg_check_ddr_en_mask_b = 1,
308
309 /* SPM_SRC4_MASK */
310 /* [8:0] */
311 .reg_mcusys_merge_apsrc_req_mask_b = 0,
312 /* [17:9] */
313 .reg_mcusys_merge_ddr_en_mask_b = 0,
314 /* [19:18] */
315 .reg_dramc_md32_infra_req_mask_b = 3,
316 /* [21:20] */
317 .reg_dramc_md32_vrf18_req_mask_b = 3,
318 /* [23:22] */
319 .reg_dramc_md32_ddr_en_mask_b = 0,
320 /* [24] */
321 .reg_dvfsrc_event_trigger_mask_b = 1,
322
323 /* SPM_WAKEUP_EVENT_MASK2 */
324 /* [3:0] */
325 .reg_sc_sw2spm_wakeup_mask_b = 0,
326 /* [4] */
327 .reg_sc_adsp2spm_wakeup_mask_b = 0,
328 /* [8:5] */
329 .reg_sc_sspm2spm_wakeup_mask_b = 0,
330 /* [9] */
331 .reg_sc_scp2spm_wakeup_mask_b = 0,
332 /* [10] */
333 .reg_csyspwrup_ack_mask = 0,
334 /* [11] */
335 .reg_csyspwrup_req_mask = 1,
336
337 /* SPM_WAKEUP_EVENT_MASK */
338 /* [31:0] */
339 .reg_wakeup_event_mask = 0xC1382213,
340
341 /* SPM_WAKEUP_EVENT_EXT_MASK */
342 /* [31:0] */
343 .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
344
345 /*sw flag setting */
346 .pcm_flags = SPM_SUSPEND_PCM_FLAG,
347 .pcm_flags1 = SPM_SUSPEND_PCM_FLAG1,
348};
349
350struct spm_lp_scen __spm_suspend = {
351 .pwrctrl = &suspend_ctrl,
352};
353
354int mt_spm_suspend_mode_set(int mode, void *prv)
355{
356 if (mode == MT_SPM_SUSPEND_SLEEP) {
357 suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG;
358 suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1;
359 } else {
360 suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG;
361 suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1;
362 }
363 return 0;
364}
365
366int mt_spm_suspend_enter(int state_id, unsigned int ext_opand, unsigned int reosuce_req)
367{
368 int ret = 0;
369
370 /* if FMAudio, ADSP is active, change to sleep suspend mode */
371 if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) {
372 mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP, NULL);
373 }
374
375 if ((ext_opand & MT_SPM_EX_OP_PERI_ON) != 0U) {
376 suspend_ctrl.pcm_flags |= SPM_FLAG_PERI_ON_IN_SUSPEND;
377 } else {
378 suspend_ctrl.pcm_flags &= ~SPM_FLAG_PERI_ON_IN_SUSPEND;
379 }
380
381 if ((ext_opand & MT_SPM_EX_OP_INFRA_ON) != 0U) {
382 suspend_ctrl.pcm_flags |= SPM_FLAG_DISABLE_INFRA_PDN;
383 } else {
384 suspend_ctrl.pcm_flags &= ~SPM_FLAG_DISABLE_INFRA_PDN;
385 }
386
387#ifndef MTK_PLAT_SPM_UART_UNSUPPORT
388 /* Notify UART to sleep */
389 mtk_uart_save();
390#endif
391
392 ret = spm_conservation(state_id, ext_opand, &__spm_suspend, reosuce_req);
393 if (ret == 0) {
394 struct mt_lp_publish_event event = {
395 .id = MT_LPM_PUBEVENTS_SYS_POWER_OFF,
396 .val.u32 = 0U,
397 };
398
399 MT_LP_SUSPEND_PUBLISH_EVENT(&event);
400 }
401 return ret;
402}
403
404void mt_spm_suspend_resume(int state_id, unsigned int ext_opand, struct wake_status **status)
405{
406 struct mt_lp_publish_event event = {
407 .id = MT_LPM_PUBEVENTS_SYS_POWER_ON,
408 .val.u32 = 0U,
409 };
410
411 struct wake_status *st = NULL;
412
413 spm_conservation_finish(state_id, ext_opand, &__spm_suspend, &st);
414
415#ifndef MTK_PLAT_SPM_UART_UNSUPPORT
416 /* Notify UART to wakeup */
417 mtk_uart_restore();
418#endif
419
420 /* If FMAudio, ADSP is active, change back to suspend mode and counting in resume */
421 if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) {
422 mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN, NULL);
423 }
424
425 if (status != NULL) {
426 *status = st;
427 }
428 MT_LP_SUSPEND_PUBLISH_EVENT(&event);
429}