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 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 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 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 391 void mt_spm_suspend_init(void) 392 { 393 spm_conservation_pwrctrl_init(__spm_suspend.pwrctrl); 394 } 395