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