1 /* 2 * Copyright (c) 2020, 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_USE_SRCCLKENO2 | \ 25 SPM_FLAG_ENABLE_MD_MUMTAS | \ 26 SPM_FLAG_SRAM_SLEEP_CTRL) 27 28 #define SPM_SUSPEND_SLEEP_PCM_FLAG1 \ 29 (SPM_FLAG1_DISABLE_MD26M_CK_OFF) 30 31 #define SPM_SUSPEND_PCM_FLAG \ 32 (SPM_FLAG_DISABLE_VCORE_DVS | \ 33 SPM_FLAG_DISABLE_VCORE_DFS | \ 34 SPM_FLAG_ENABLE_TIA_WORKAROUND | \ 35 SPM_FLAG_ENABLE_MD_MUMTAS | \ 36 SPM_FLAG_SRAM_SLEEP_CTRL) 37 38 #define SPM_SUSPEND_PCM_FLAG1 \ 39 (SPM_FLAG1_DISABLE_MD26M_CK_OFF) 40 41 #define __WAKE_SRC_FOR_SUSPEND_COMMON__ \ 42 (R12_PCM_TIMER | \ 43 R12_KP_IRQ_B | \ 44 R12_APWDT_EVENT_B | \ 45 R12_APXGPT1_EVENT_B | \ 46 R12_CONN2AP_SPM_WAKEUP_B | \ 47 R12_EINT_EVENT_B | \ 48 R12_CONN_WDT_IRQ_B | \ 49 R12_CCIF0_EVENT_B | \ 50 R12_SSPM2SPM_WAKEUP_B | \ 51 R12_SCP2SPM_WAKEUP_B | \ 52 R12_ADSP2SPM_WAKEUP_B | \ 53 R12_USBX_CDSC_B | \ 54 R12_USBX_POWERDWN_B | \ 55 R12_SYS_TIMER_EVENT_B | \ 56 R12_EINT_EVENT_SECURE_B | \ 57 R12_CCIF1_EVENT_B | \ 58 R12_SYS_CIRQ_IRQ_B | \ 59 R12_MD2AP_PEER_EVENT_B | \ 60 R12_MD1_WDT_B | \ 61 R12_CLDMA_EVENT_B | \ 62 R12_REG_CPU_WAKEUP | \ 63 R12_APUSYS_WAKE_HOST_B | \ 64 R12_PCIE_BRIDGE_IRQ | \ 65 R12_PCIE_IRQ) 66 67 #if defined(CFG_MICROTRUST_TEE_SUPPORT) 68 #define WAKE_SRC_FOR_SUSPEND (__WAKE_SRC_FOR_SUSPEND_COMMON__) 69 #else 70 #define WAKE_SRC_FOR_SUSPEND \ 71 (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \ 72 R12_SEJ_EVENT_B) 73 #endif 74 75 static struct pwr_ctrl suspend_ctrl = { 76 .wake_src = WAKE_SRC_FOR_SUSPEND, 77 .pcm_flags = SPM_SUSPEND_PCM_FLAG | SPM_FLAG_DISABLE_INFRA_PDN, 78 .pcm_flags1 = SPM_SUSPEND_PCM_FLAG1, 79 80 /* Auto-gen Start */ 81 82 /* SPM_AP_STANDBY_CON */ 83 .reg_wfi_op = 0, 84 .reg_wfi_type = 0, 85 .reg_mp0_cputop_idle_mask = 0, 86 .reg_mp1_cputop_idle_mask = 0, 87 .reg_mcusys_idle_mask = 0, 88 .reg_md_apsrc_1_sel = 0, 89 .reg_md_apsrc_0_sel = 0, 90 .reg_conn_apsrc_sel = 0, 91 92 /* SPM_SRC6_MASK */ 93 .reg_dpmaif_srcclkena_mask_b = 1, 94 .reg_dpmaif_infra_req_mask_b = 1, 95 .reg_dpmaif_apsrc_req_mask_b = 1, 96 .reg_dpmaif_vrf18_req_mask_b = 1, 97 .reg_dpmaif_ddr_en_mask_b = 1, 98 99 /* SPM_SRC_REQ */ 100 .reg_spm_apsrc_req = 0, 101 .reg_spm_f26m_req = 0, 102 .reg_spm_infra_req = 0, 103 .reg_spm_vrf18_req = 0, 104 .reg_spm_ddr_en_req = 0, 105 .reg_spm_dvfs_req = 0, 106 .reg_spm_sw_mailbox_req = 0, 107 .reg_spm_sspm_mailbox_req = 0, 108 .reg_spm_adsp_mailbox_req = 0, 109 .reg_spm_scp_mailbox_req = 0, 110 111 /* SPM_SRC_MASK */ 112 .reg_md_srcclkena_0_mask_b = 1, 113 .reg_md_srcclkena2infra_req_0_mask_b = 0, 114 .reg_md_apsrc2infra_req_0_mask_b = 1, 115 .reg_md_apsrc_req_0_mask_b = 1, 116 .reg_md_vrf18_req_0_mask_b = 1, 117 .reg_md_ddr_en_0_mask_b = 1, 118 .reg_md_srcclkena_1_mask_b = 0, 119 .reg_md_srcclkena2infra_req_1_mask_b = 0, 120 .reg_md_apsrc2infra_req_1_mask_b = 0, 121 .reg_md_apsrc_req_1_mask_b = 0, 122 .reg_md_vrf18_req_1_mask_b = 0, 123 .reg_md_ddr_en_1_mask_b = 0, 124 .reg_conn_srcclkena_mask_b = 1, 125 .reg_conn_srcclkenb_mask_b = 0, 126 .reg_conn_infra_req_mask_b = 1, 127 .reg_conn_apsrc_req_mask_b = 1, 128 .reg_conn_vrf18_req_mask_b = 1, 129 .reg_conn_ddr_en_mask_b = 1, 130 .reg_conn_vfe28_mask_b = 0, 131 .reg_srcclkeni0_srcclkena_mask_b = 1, 132 .reg_srcclkeni0_infra_req_mask_b = 1, 133 .reg_srcclkeni1_srcclkena_mask_b = 0, 134 .reg_srcclkeni1_infra_req_mask_b = 0, 135 .reg_srcclkeni2_srcclkena_mask_b = 0, 136 .reg_srcclkeni2_infra_req_mask_b = 0, 137 .reg_infrasys_apsrc_req_mask_b = 0, 138 .reg_infrasys_ddr_en_mask_b = 1, 139 .reg_md32_srcclkena_mask_b = 1, 140 .reg_md32_infra_req_mask_b = 1, 141 .reg_md32_apsrc_req_mask_b = 1, 142 .reg_md32_vrf18_req_mask_b = 1, 143 .reg_md32_ddr_en_mask_b = 1, 144 145 /* SPM_SRC2_MASK */ 146 .reg_scp_srcclkena_mask_b = 1, 147 .reg_scp_infra_req_mask_b = 1, 148 .reg_scp_apsrc_req_mask_b = 1, 149 .reg_scp_vrf18_req_mask_b = 1, 150 .reg_scp_ddr_en_mask_b = 1, 151 .reg_audio_dsp_srcclkena_mask_b = 1, 152 .reg_audio_dsp_infra_req_mask_b = 1, 153 .reg_audio_dsp_apsrc_req_mask_b = 1, 154 .reg_audio_dsp_vrf18_req_mask_b = 1, 155 .reg_audio_dsp_ddr_en_mask_b = 1, 156 .reg_ufs_srcclkena_mask_b = 1, 157 .reg_ufs_infra_req_mask_b = 1, 158 .reg_ufs_apsrc_req_mask_b = 1, 159 .reg_ufs_vrf18_req_mask_b = 1, 160 .reg_ufs_ddr_en_mask_b = 1, 161 .reg_disp0_apsrc_req_mask_b = 1, 162 .reg_disp0_ddr_en_mask_b = 1, 163 .reg_disp1_apsrc_req_mask_b = 1, 164 .reg_disp1_ddr_en_mask_b = 1, 165 .reg_gce_infra_req_mask_b = 1, 166 .reg_gce_apsrc_req_mask_b = 1, 167 .reg_gce_vrf18_req_mask_b = 1, 168 .reg_gce_ddr_en_mask_b = 1, 169 .reg_apu_srcclkena_mask_b = 1, 170 .reg_apu_infra_req_mask_b = 1, 171 .reg_apu_apsrc_req_mask_b = 1, 172 .reg_apu_vrf18_req_mask_b = 1, 173 .reg_apu_ddr_en_mask_b = 1, 174 .reg_cg_check_srcclkena_mask_b = 0, 175 .reg_cg_check_apsrc_req_mask_b = 0, 176 .reg_cg_check_vrf18_req_mask_b = 0, 177 .reg_cg_check_ddr_en_mask_b = 0, 178 179 /* SPM_SRC3_MASK */ 180 .reg_dvfsrc_event_trigger_mask_b = 1, 181 .reg_sw2spm_int0_mask_b = 0, 182 .reg_sw2spm_int1_mask_b = 0, 183 .reg_sw2spm_int2_mask_b = 0, 184 .reg_sw2spm_int3_mask_b = 0, 185 .reg_sc_adsp2spm_wakeup_mask_b = 0, 186 .reg_sc_sspm2spm_wakeup_mask_b = 0, 187 .reg_sc_scp2spm_wakeup_mask_b = 0, 188 .reg_csyspwrreq_mask = 1, 189 .reg_spm_srcclkena_reserved_mask_b = 0, 190 .reg_spm_infra_req_reserved_mask_b = 0, 191 .reg_spm_apsrc_req_reserved_mask_b = 0, 192 .reg_spm_vrf18_req_reserved_mask_b = 0, 193 .reg_spm_ddr_en_reserved_mask_b = 0, 194 .reg_mcupm_srcclkena_mask_b = 1, 195 .reg_mcupm_infra_req_mask_b = 1, 196 .reg_mcupm_apsrc_req_mask_b = 1, 197 .reg_mcupm_vrf18_req_mask_b = 1, 198 .reg_mcupm_ddr_en_mask_b = 1, 199 .reg_msdc0_srcclkena_mask_b = 1, 200 .reg_msdc0_infra_req_mask_b = 1, 201 .reg_msdc0_apsrc_req_mask_b = 1, 202 .reg_msdc0_vrf18_req_mask_b = 1, 203 .reg_msdc0_ddr_en_mask_b = 1, 204 .reg_msdc1_srcclkena_mask_b = 1, 205 .reg_msdc1_infra_req_mask_b = 1, 206 .reg_msdc1_apsrc_req_mask_b = 1, 207 .reg_msdc1_vrf18_req_mask_b = 1, 208 .reg_msdc1_ddr_en_mask_b = 1, 209 210 /* SPM_SRC4_MASK */ 211 .ccif_event_mask_b = 0xFFF, 212 .reg_bak_psri_srcclkena_mask_b = 0, 213 .reg_bak_psri_infra_req_mask_b = 0, 214 .reg_bak_psri_apsrc_req_mask_b = 0, 215 .reg_bak_psri_vrf18_req_mask_b = 0, 216 .reg_bak_psri_ddr_en_mask_b = 0, 217 .reg_dramc0_md32_infra_req_mask_b = 1, 218 .reg_dramc0_md32_vrf18_req_mask_b = 0, 219 .reg_dramc1_md32_infra_req_mask_b = 1, 220 .reg_dramc1_md32_vrf18_req_mask_b = 0, 221 .reg_conn_srcclkenb2pwrap_mask_b = 0, 222 .reg_dramc0_md32_wakeup_mask = 1, 223 .reg_dramc1_md32_wakeup_mask = 1, 224 225 /* SPM_SRC5_MASK */ 226 .reg_mcusys_merge_apsrc_req_mask_b = 0x11, 227 .reg_mcusys_merge_ddr_en_mask_b = 0x11, 228 .reg_msdc2_srcclkena_mask_b = 1, 229 .reg_msdc2_infra_req_mask_b = 1, 230 .reg_msdc2_apsrc_req_mask_b = 1, 231 .reg_msdc2_vrf18_req_mask_b = 1, 232 .reg_msdc2_ddr_en_mask_b = 1, 233 .reg_pcie_srcclkena_mask_b = 1, 234 .reg_pcie_infra_req_mask_b = 1, 235 .reg_pcie_apsrc_req_mask_b = 1, 236 .reg_pcie_vrf18_req_mask_b = 1, 237 .reg_pcie_ddr_en_mask_b = 1, 238 239 /* SPM_WAKEUP_EVENT_MASK */ 240 .reg_wakeup_event_mask = 0x01382202, 241 242 /* SPM_WAKEUP_EVENT_EXT_MASK */ 243 .reg_ext_wakeup_event_mask = 0xFFFFFFFF, 244 245 /* Auto-gen End */ 246 }; 247 248 struct spm_lp_scen __spm_suspend = { 249 .pwrctrl = &suspend_ctrl, 250 }; 251 252 int mt_spm_suspend_mode_set(int mode) 253 { 254 if (mode == MT_SPM_SUSPEND_SLEEP) { 255 suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG; 256 suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1; 257 } else { 258 suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG; 259 suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1; 260 } 261 262 return 0; 263 } 264 265 int mt_spm_suspend_enter(int state_id, unsigned int ext_opand, 266 unsigned int resource_req) 267 { 268 /* If FMAudio / ADSP is active, change to sleep suspend mode */ 269 if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) { 270 mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP); 271 } 272 273 /* Notify MCUPM that device is going suspend flow */ 274 mmio_write_32(MCUPM_MBOX_OFFSET_PDN, MCUPM_POWER_DOWN); 275 276 /* Notify UART to sleep */ 277 mt_uart_save(); 278 279 return spm_conservation(state_id, ext_opand, 280 &__spm_suspend, resource_req); 281 } 282 283 void mt_spm_suspend_resume(int state_id, unsigned int ext_opand, 284 struct wake_status **status) 285 { 286 spm_conservation_finish(state_id, ext_opand, &__spm_suspend, status); 287 288 /* Notify UART to wakeup */ 289 mt_uart_restore(); 290 291 /* Notify MCUPM that device leave suspend */ 292 mmio_write_32(MCUPM_MBOX_OFFSET_PDN, 0); 293 294 /* If FMAudio / ADSP is active, change back to suspend mode */ 295 if ((ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) != 0U) { 296 mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN); 297 } 298 } 299 300 void mt_spm_suspend_init(void) 301 { 302 spm_conservation_pwrctrl_init(__spm_suspend.pwrctrl); 303 } 304