1 /* 2 * Copyright (c) 2025, Mediatek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stddef.h> 8 #include <stdio.h> 9 #include <string.h> 10 11 #include <common/debug.h> 12 #include <lib/mmio.h> 13 14 #include <drivers/spm/mt_spm_resource_req.h> 15 #include <lib/pm/mtk_pm.h> 16 #include <lpm_v2/mt_lp_api.h> 17 #include <mt_spm.h> 18 #include <mt_spm_conservation.h> 19 #include <mt_spm_idle.h> 20 #include <mt_spm_internal.h> 21 #include <mt_spm_reg.h> 22 #include <mt_spm_stats.h> 23 24 #define SPM_BYPASS_SYSPWREQ_GENERIC 1 25 26 /* Default will be the bus26m or deeper spm's low power mode*/ 27 #define __WAKE_SRC_FOR_IDLE_COMMON__ \ 28 ((R12_PCM_TIMER_B) | (R12_KP_IRQ_B) | (R12_CONN2AP_WAKEUP_B) | \ 29 (R12_EINT_EVENT_B) | (R12_CONN_WDT_IRQ_B) | (R12_SSPM2SPM_WAKEUP_B) | \ 30 (R12_SCP2SPM_WAKEUP_B) | (R12_VADSP2SPM_WAKEUP_B) | \ 31 (R12_USB0_CDSC_B) | (R12_USB0_POWERDWN_B) | (R12_SBD_INTR_B) | \ 32 (R12_UART2SPM_IRQ_B) | (R12_SYS_TIMER_EVENT_B) | \ 33 (R12_EINT_EVENT_SECURE_B) | (R12_AFE_IRQ_MCU_B) | \ 34 (R12_SYS_CIRQ_IRQ_B) | (R12_AP2AP_PEER_WAKEUP_B) | (R12_CPU_WAKEUP) | \ 35 (R12_APUSYS_WAKE_HOST_B) | (R12_PCIE_MAC_IRQ_WAKE_B) | \ 36 (R12_MSDC_WAKEUP_EVENT_B)) 37 38 #if defined(CFG_MICROTRUST_TEE_SUPPORT) 39 #define WAKE_SRC_FOR_IDLE (__WAKE_SRC_FOR_IDLE_COMMON__) 40 #else 41 #define WAKE_SRC_FOR_IDLE (__WAKE_SRC_FOR_IDLE_COMMON__ | R12_SEJ_B) 42 #endif 43 44 static struct pwr_ctrl idle_spm_pwr = { 45 .wake_src = WAKE_SRC_FOR_IDLE, 46 47 /* Auto-gen Start */ 48 49 /* SPM_SRC_REQ */ 50 .reg_spm_adsp_mailbox_req = 0, 51 .reg_spm_apsrc_req = 0, 52 .reg_spm_ddren_req = 0, 53 .reg_spm_dvfs_req = 0, 54 .reg_spm_emi_req = 0, 55 .reg_spm_f26m_req = 0, 56 .reg_spm_infra_req = 0, 57 .reg_spm_pmic_req = 0, 58 .reg_spm_scp_mailbox_req = 0, 59 .reg_spm_sspm_mailbox_req = 0, 60 .reg_spm_sw_mailbox_req = 0, 61 .reg_spm_vcore_req = 0, 62 .reg_spm_vrf18_req = 0, 63 .adsp_mailbox_state = 0, 64 .apsrc_state = 0, 65 .ddren_state = 0, 66 .dvfs_state = 0, 67 .emi_state = 0, 68 .f26m_state = 0, 69 .infra_state = 0, 70 .pmic_state = 0, 71 .scp_mailbox_state = 0, 72 .sspm_mailbox_state = 0, 73 .sw_mailbox_state = 0, 74 .vcore_state = 0, 75 .vrf18_state = 0, 76 77 /* SPM_SRC_MASK_0 */ 78 .reg_apu_apsrc_req_mask_b = 0x1, 79 .reg_apu_ddren_req_mask_b = 0x1, 80 .reg_apu_emi_req_mask_b = 0x1, 81 .reg_apu_infra_req_mask_b = 0x1, 82 .reg_apu_pmic_req_mask_b = 0x1, 83 .reg_apu_srcclkena_mask_b = 0x1, 84 .reg_apu_vrf18_req_mask_b = 0x1, 85 .reg_audio_dsp_apsrc_req_mask_b = 0x0, 86 .reg_audio_dsp_ddren_req_mask_b = 0x0, 87 .reg_audio_dsp_emi_req_mask_b = 0x0, 88 .reg_audio_dsp_infra_req_mask_b = 0x0, 89 .reg_audio_dsp_pmic_req_mask_b = 0x0, 90 .reg_audio_dsp_srcclkena_mask_b = 0x0, 91 .reg_audio_dsp_vcore_req_mask_b = 0x0, 92 .reg_audio_dsp_vrf18_req_mask_b = 0x0, 93 .reg_cam_apsrc_req_mask_b = 0x1, 94 .reg_cam_ddren_req_mask_b = 0x1, 95 .reg_cam_emi_req_mask_b = 0x1, 96 .reg_cam_infra_req_mask_b = 0x0, 97 .reg_cam_pmic_req_mask_b = 0x0, 98 .reg_cam_srcclkena_mask_b = 0x0, 99 .reg_cam_vrf18_req_mask_b = 0x0, 100 .reg_mdp_emi_req_mask_b = 0x1, 101 102 /* SPM_SRC_MASK_1 */ 103 .reg_ccif_apsrc_req_mask_b = 0x0, 104 .reg_ccif_emi_req_mask_b = 0xfff, 105 106 /* SPM_SRC_MASK_2 */ 107 .reg_ccif_infra_req_mask_b = 0x0, 108 .reg_ccif_pmic_req_mask_b = 0xfff, 109 110 /* SPM_SRC_MASK_3 */ 111 .reg_ccif_srcclkena_mask_b = 0x0, 112 .reg_ccif_vrf18_req_mask_b = 0xfff, 113 .reg_ccu_apsrc_req_mask_b = 0x0, 114 .reg_ccu_ddren_req_mask_b = 0x0, 115 .reg_ccu_emi_req_mask_b = 0x0, 116 .reg_ccu_infra_req_mask_b = 0x0, 117 .reg_ccu_pmic_req_mask_b = 0x0, 118 .reg_ccu_srcclkena_mask_b = 0x0, 119 .reg_ccu_vrf18_req_mask_b = 0x0, 120 .reg_cg_check_apsrc_req_mask_b = 0x1, 121 122 /* SPM_SRC_MASK_4 */ 123 .reg_cg_check_ddren_req_mask_b = 0x1, 124 .reg_cg_check_emi_req_mask_b = 0x1, 125 .reg_cg_check_infra_req_mask_b = 0x1, 126 .reg_cg_check_pmic_req_mask_b = 0x1, 127 .reg_cg_check_srcclkena_mask_b = 0x1, 128 .reg_cg_check_vcore_req_mask_b = 0x1, 129 .reg_cg_check_vrf18_req_mask_b = 0x1, 130 .reg_conn_apsrc_req_mask_b = 0x1, 131 .reg_conn_ddren_req_mask_b = 0x1, 132 .reg_conn_emi_req_mask_b = 0x1, 133 .reg_conn_infra_req_mask_b = 0x1, 134 .reg_conn_pmic_req_mask_b = 0x1, 135 .reg_conn_srcclkena_mask_b = 0x1, 136 .reg_conn_srcclkenb_mask_b = 0x1, 137 .reg_conn_vcore_req_mask_b = 0x1, 138 .reg_conn_vrf18_req_mask_b = 0x1, 139 .reg_cpueb_apsrc_req_mask_b = 0x1, 140 .reg_cpueb_ddren_req_mask_b = 0x1, 141 .reg_cpueb_emi_req_mask_b = 0x1, 142 .reg_cpueb_infra_req_mask_b = 0x1, 143 .reg_cpueb_pmic_req_mask_b = 0x1, 144 .reg_cpueb_srcclkena_mask_b = 0x1, 145 .reg_cpueb_vrf18_req_mask_b = 0x1, 146 .reg_disp0_apsrc_req_mask_b = 0x1, 147 .reg_disp0_ddren_req_mask_b = 0x1, 148 .reg_disp0_emi_req_mask_b = 0x1, 149 .reg_disp0_infra_req_mask_b = 0x1, 150 .reg_disp0_pmic_req_mask_b = 0x0, 151 .reg_disp0_srcclkena_mask_b = 0x0, 152 .reg_disp0_vrf18_req_mask_b = 0x1, 153 .reg_disp1_apsrc_req_mask_b = 0x0, 154 .reg_disp1_ddren_req_mask_b = 0x0, 155 156 /* SPM_SRC_MASK_5 */ 157 .reg_disp1_emi_req_mask_b = 0x0, 158 .reg_disp1_infra_req_mask_b = 0x0, 159 .reg_disp1_pmic_req_mask_b = 0x0, 160 .reg_disp1_srcclkena_mask_b = 0x0, 161 .reg_disp1_vrf18_req_mask_b = 0x0, 162 .reg_dpm_apsrc_req_mask_b = 0xf, 163 .reg_dpm_ddren_req_mask_b = 0xf, 164 .reg_dpm_emi_req_mask_b = 0xf, 165 .reg_dpm_infra_req_mask_b = 0xf, 166 .reg_dpm_pmic_req_mask_b = 0xf, 167 .reg_dpm_srcclkena_mask_b = 0xf, 168 169 /* SPM_SRC_MASK_6 */ 170 .reg_dpm_vcore_req_mask_b = 0xf, 171 .reg_dpm_vrf18_req_mask_b = 0xf, 172 .reg_dpmaif_apsrc_req_mask_b = 0x1, 173 .reg_dpmaif_ddren_req_mask_b = 0x1, 174 .reg_dpmaif_emi_req_mask_b = 0x1, 175 .reg_dpmaif_infra_req_mask_b = 0x1, 176 .reg_dpmaif_pmic_req_mask_b = 0x1, 177 .reg_dpmaif_srcclkena_mask_b = 0x1, 178 .reg_dpmaif_vrf18_req_mask_b = 0x1, 179 .reg_dvfsrc_level_req_mask_b = 0x1, 180 .reg_emisys_apsrc_req_mask_b = 0x0, 181 .reg_emisys_ddren_req_mask_b = 0x1, 182 .reg_emisys_emi_req_mask_b = 0x0, 183 .reg_gce_d_apsrc_req_mask_b = 0x1, 184 .reg_gce_d_ddren_req_mask_b = 0x1, 185 .reg_gce_d_emi_req_mask_b = 0x1, 186 .reg_gce_d_infra_req_mask_b = 0x0, 187 .reg_gce_d_pmic_req_mask_b = 0x0, 188 .reg_gce_d_srcclkena_mask_b = 0x0, 189 .reg_gce_d_vrf18_req_mask_b = 0x0, 190 .reg_gce_m_apsrc_req_mask_b = 0x1, 191 .reg_gce_m_ddren_req_mask_b = 0x1, 192 .reg_gce_m_emi_req_mask_b = 0x1, 193 .reg_gce_m_infra_req_mask_b = 0x0, 194 .reg_gce_m_pmic_req_mask_b = 0x0, 195 .reg_gce_m_srcclkena_mask_b = 0x0, 196 197 /* SPM_SRC_MASK_7 */ 198 .reg_gce_m_vrf18_req_mask_b = 0x0, 199 .reg_gpueb_apsrc_req_mask_b = 0x0, 200 .reg_gpueb_ddren_req_mask_b = 0x0, 201 .reg_gpueb_emi_req_mask_b = 0x0, 202 .reg_gpueb_infra_req_mask_b = 0x0, 203 .reg_gpueb_pmic_req_mask_b = 0x0, 204 .reg_gpueb_srcclkena_mask_b = 0x0, 205 .reg_gpueb_vrf18_req_mask_b = 0x0, 206 .reg_hwccf_apsrc_req_mask_b = 0x1, 207 .reg_hwccf_ddren_req_mask_b = 0x1, 208 .reg_hwccf_emi_req_mask_b = 0x1, 209 .reg_hwccf_infra_req_mask_b = 0x1, 210 .reg_hwccf_pmic_req_mask_b = 0x1, 211 .reg_hwccf_srcclkena_mask_b = 0x1, 212 .reg_hwccf_vcore_req_mask_b = 0x1, 213 .reg_hwccf_vrf18_req_mask_b = 0x1, 214 .reg_img_apsrc_req_mask_b = 0x1, 215 .reg_img_ddren_req_mask_b = 0x1, 216 .reg_img_emi_req_mask_b = 0x1, 217 .reg_img_infra_req_mask_b = 0x0, 218 .reg_img_pmic_req_mask_b = 0x0, 219 .reg_img_srcclkena_mask_b = 0x0, 220 .reg_img_vrf18_req_mask_b = 0x0, 221 .reg_infrasys_apsrc_req_mask_b = 0x1, 222 .reg_infrasys_ddren_req_mask_b = 0x1, 223 .reg_infrasys_emi_req_mask_b = 0x1, 224 .reg_ipic_infra_req_mask_b = 0x1, 225 .reg_ipic_vrf18_req_mask_b = 0x1, 226 .reg_mcu_apsrc_req_mask_b = 0x0, 227 .reg_mcu_ddren_req_mask_b = 0x0, 228 .reg_mcu_emi_req_mask_b = 0x0, 229 230 /* SPM_SRC_MASK_8 */ 231 .reg_mcusys_apsrc_req_mask_b = 0x7, 232 .reg_mcusys_ddren_req_mask_b = 0x7, 233 .reg_mcusys_emi_req_mask_b = 0x7, 234 .reg_mcusys_infra_req_mask_b = 0x0, 235 236 /* SPM_SRC_MASK_9 */ 237 .reg_mcusys_pmic_req_mask_b = 0x0, 238 .reg_mcusys_srcclkena_mask_b = 0x0, 239 .reg_mcusys_vrf18_req_mask_b = 0x0, 240 .reg_md_apsrc_req_mask_b = 0x0, 241 .reg_md_ddren_req_mask_b = 0x0, 242 .reg_md_emi_req_mask_b = 0x0, 243 .reg_md_infra_req_mask_b = 0x0, 244 .reg_md_pmic_req_mask_b = 0x0, 245 .reg_md_srcclkena_mask_b = 0x0, 246 .reg_md_srcclkena1_mask_b = 0x0, 247 .reg_md_vcore_req_mask_b = 0x0, 248 249 /* SPM_SRC_MASK_10 */ 250 .reg_md_vrf18_req_mask_b = 0x0, 251 .reg_mdp_apsrc_req_mask_b = 0x0, 252 .reg_mdp_ddren_req_mask_b = 0x0, 253 .reg_mm_proc_apsrc_req_mask_b = 0x0, 254 .reg_mm_proc_ddren_req_mask_b = 0x0, 255 .reg_mm_proc_emi_req_mask_b = 0x0, 256 .reg_mm_proc_infra_req_mask_b = 0x0, 257 .reg_mm_proc_pmic_req_mask_b = 0x0, 258 .reg_mm_proc_srcclkena_mask_b = 0x0, 259 .reg_mm_proc_vrf18_req_mask_b = 0x0, 260 .reg_mmsys_apsrc_req_mask_b = 0x0, 261 .reg_mmsys_ddren_req_mask_b = 0x0, 262 .reg_mmsys_vrf18_req_mask_b = 0x0, 263 .reg_pcie0_apsrc_req_mask_b = 0x0, 264 .reg_pcie0_ddren_req_mask_b = 0x0, 265 .reg_pcie0_infra_req_mask_b = 0x0, 266 .reg_pcie0_srcclkena_mask_b = 0x0, 267 .reg_pcie0_vrf18_req_mask_b = 0x0, 268 .reg_pcie1_apsrc_req_mask_b = 0x0, 269 .reg_pcie1_ddren_req_mask_b = 0x0, 270 .reg_pcie1_infra_req_mask_b = 0x0, 271 .reg_pcie1_srcclkena_mask_b = 0x0, 272 .reg_pcie1_vrf18_req_mask_b = 0x0, 273 .reg_perisys_apsrc_req_mask_b = 0x1, 274 .reg_perisys_ddren_req_mask_b = 0x1, 275 .reg_perisys_emi_req_mask_b = 0x1, 276 .reg_perisys_infra_req_mask_b = 0x1, 277 .reg_perisys_pmic_req_mask_b = 0x1, 278 .reg_perisys_srcclkena_mask_b = 0x1, 279 .reg_perisys_vcore_req_mask_b = 0x1, 280 .reg_perisys_vrf18_req_mask_b = 0x1, 281 .reg_scp_apsrc_req_mask_b = 0x1, 282 283 /* SPM_SRC_MASK_11 */ 284 .reg_scp_ddren_req_mask_b = 0x1, 285 .reg_scp_emi_req_mask_b = 0x1, 286 .reg_scp_infra_req_mask_b = 0x1, 287 .reg_scp_pmic_req_mask_b = 0x1, 288 .reg_scp_srcclkena_mask_b = 0x1, 289 .reg_scp_vcore_req_mask_b = 0x1, 290 .reg_scp_vrf18_req_mask_b = 0x1, 291 .reg_srcclkeni_infra_req_mask_b = 0x1, 292 .reg_srcclkeni_pmic_req_mask_b = 0x1, 293 .reg_srcclkeni_srcclkena_mask_b = 0x1, 294 .reg_sspm_apsrc_req_mask_b = 0x1, 295 .reg_sspm_ddren_req_mask_b = 0x1, 296 .reg_sspm_emi_req_mask_b = 0x1, 297 .reg_sspm_infra_req_mask_b = 0x1, 298 .reg_sspm_pmic_req_mask_b = 0x1, 299 .reg_sspm_srcclkena_mask_b = 0x1, 300 .reg_sspm_vrf18_req_mask_b = 0x1, 301 .reg_ssr_apsrc_req_mask_b = 0x0, 302 .reg_ssr_ddren_req_mask_b = 0x0, 303 .reg_ssr_emi_req_mask_b = 0x0, 304 .reg_ssr_infra_req_mask_b = 0x0, 305 .reg_ssr_pmic_req_mask_b = 0x0, 306 .reg_ssr_srcclkena_mask_b = 0x0, 307 .reg_ssr_vrf18_req_mask_b = 0x0, 308 .reg_ufs_apsrc_req_mask_b = 0x1, 309 .reg_ufs_ddren_req_mask_b = 0x1, 310 .reg_ufs_emi_req_mask_b = 0x1, 311 .reg_ufs_infra_req_mask_b = 0x1, 312 .reg_ufs_pmic_req_mask_b = 0x1, 313 314 /* SPM_SRC_MASK_12 */ 315 .reg_ufs_srcclkena_mask_b = 0x1, 316 .reg_ufs_vrf18_req_mask_b = 0x1, 317 .reg_vdec_apsrc_req_mask_b = 0x1, 318 .reg_vdec_ddren_req_mask_b = 0x1, 319 .reg_vdec_emi_req_mask_b = 0x1, 320 .reg_vdec_infra_req_mask_b = 0x0, 321 .reg_vdec_pmic_req_mask_b = 0x0, 322 .reg_vdec_srcclkena_mask_b = 0x0, 323 .reg_vdec_vrf18_req_mask_b = 0x0, 324 .reg_venc_apsrc_req_mask_b = 0x1, 325 .reg_venc_ddren_req_mask_b = 0x1, 326 .reg_venc_emi_req_mask_b = 0x1, 327 .reg_venc_infra_req_mask_b = 0x0, 328 .reg_venc_pmic_req_mask_b = 0x0, 329 .reg_venc_srcclkena_mask_b = 0x0, 330 .reg_venc_vrf18_req_mask_b = 0x0, 331 .reg_ipe_apsrc_req_mask_b = 0x1, 332 .reg_ipe_ddren_req_mask_b = 0x1, 333 .reg_ipe_emi_req_mask_b = 0x1, 334 .reg_ipe_infra_req_mask_b = 0x1, 335 .reg_ipe_pmic_req_mask_b = 0x1, 336 .reg_ipe_srcclkena_mask_b = 0x1, 337 .reg_ipe_vrf18_req_mask_b = 0x1, 338 .reg_ufs_vcore_req_mask_b = 0x1, 339 340 /* SPM_EVENT_CON_MISC */ 341 .reg_srcclken_fast_resp = 0, 342 .reg_csyspwrup_ack_mask = 1, 343 344 /* Auto-gen End */ 345 346 /* SPM_WAKEUP_EVENT_MASK */ 347 .reg_wakeup_event_mask = 0xC1B33012, 348 349 /* SPM_WAKEUP_EVENT_EXT_MASK */ 350 .reg_ext_wakeup_event_mask = 0xFFFFFFFF, 351 }; 352 353 static struct dbg_ctrl idle_spm_dbg = { 354 .count = 0, 355 .duration = 0, 356 .ext = NULL, 357 }; 358 359 static struct spm_lp_stat idle_lp_stat; 360 361 static struct spm_lp_scen idle_spm_lp = { 362 .pwrctrl = &idle_spm_pwr, 363 .dbgctrl = &idle_spm_dbg, 364 .lpstat = &idle_lp_stat, 365 }; 366 367 int mt_spm_idle_generic_enter(int state_id, uint32_t ext_opand, 368 spm_idle_conduct fn) 369 { 370 int ret = 0; 371 uint32_t src_req = 0; 372 struct mt_lp_publish_event event = { 373 .id = MT_LPM_PUBEVENTS_SYS_POWER_OFF, 374 .val.u32 = 0, 375 .level = 0, 376 }; 377 378 if (fn) 379 fn(state_id, &idle_spm_lp, &src_req); 380 381 ret = spm_conservation(state_id, ext_opand, &idle_spm_lp, src_req); 382 383 if (ret) { 384 NOTICE("[%s:%d] - unknown issue !!\n", __func__, __LINE__); 385 panic(); 386 } 387 388 if (ext_opand & MT_SPM_EX_OP_DEVICES_SAVE) { 389 mmio_write_32(SPM2SW_MAILBOX_0, 0x1); 390 MT_LP_SUSPEND_PUBLISH_EVENT(&event); 391 } else 392 MT_LP_PUBLISH_EVENT(&event); 393 return ret; 394 } 395 396 void mt_spm_idle_generic_resume(int state_id, uint32_t ext_opand, 397 struct wake_status **status, 398 spm_idle_conduct_restore fn) 399 { 400 struct mt_lp_publish_event event = { 401 .id = MT_LPM_PUBEVENTS_SYS_POWER_ON, 402 .val.u32 = 0, 403 }; 404 405 ext_opand |= (MT_SPM_EX_OP_TIME_CHECK | MT_SPM_EX_OP_TIME_OBS); 406 spm_conservation_finish(state_id, ext_opand, &idle_spm_lp, status); 407 408 mt_spm_update_lp_stat(&idle_lp_stat); 409 410 if (spm_unlikely(fn)) 411 fn(state_id, &idle_spm_lp, *status); 412 413 if (ext_opand & MT_SPM_EX_OP_DEVICES_SAVE) { 414 mmio_write_32(SPM2SW_MAILBOX_0, 0x0); 415 MT_LP_SUSPEND_PUBLISH_EVENT(&event); 416 } else 417 MT_LP_PUBLISH_EVENT(&event); 418 } 419 420 int mt_spm_idle_generic_get_spm_lp(struct spm_lp_scen **lp) 421 { 422 if (!lp) 423 return -1; 424 425 *lp = &idle_spm_lp; 426 return 0; 427 } 428