1 /* 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 71 static 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 350 struct spm_lp_scen __spm_suspend = { 351 .pwrctrl = &suspend_ctrl, 352 }; 353 354 int 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 366 int 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 404 void 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 } 430