1 /* 2 * Copyright (c) 2025, Mediatek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <stdint.h> 8 #include <stdio.h> 9 10 #include <common/debug.h> 11 #include <drivers/delay_timer.h> 12 #include <drivers/gpio.h> 13 #include <lib/mmio.h> 14 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_v2/mt_lp_api.h> 19 #include <lpm_v2/mt_lp_rqm.h> 20 #include <mt_spm.h> 21 #include <mt_spm_conservation.h> 22 #include <mt_spm_internal.h> 23 #include <mt_spm_reg.h> 24 #include <mt_spm_stats.h> 25 #include <mt_spm_suspend.h> 26 #if defined(CONFIG_MTK_VCOREDVFS_SUPPORT) 27 #include <mt_spm_vcorefs_exp.h> 28 #endif 29 30 #define SPM_SUSPEND_SLEEP_PCM_FLAG (SPM_FLAG_DISABLE_DDR_DFS | \ 31 SPM_FLAG_DISABLE_EMI_DFS | \ 32 SPM_FLAG_DISABLE_VLP_PDN | \ 33 SPM_FLAG_DISABLE_BUS_DFS | \ 34 SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \ 35 SPM_FLAG_ENABLE_AOV | \ 36 SPM_FLAG_ENABLE_MD_MUMTAS | \ 37 SPM_FLAG_SRAM_SLEEP_CTRL) 38 39 #define SPM_SUSPEND_SLEEP_PCM_FLAG1 (SPM_FLAG1_ENABLE_ALCO_TRACE | \ 40 SPM_FLAG1_ENABLE_SUSPEND_AVS) 41 42 #define SPM_SUSPEND_PCM_FLAG (SPM_FLAG_DISABLE_VCORE_DVS | \ 43 SPM_FLAG_DISABLE_MCUPM_PDN | \ 44 SPM_FLAG_DISABLE_VLP_PDN | \ 45 SPM_FLAG_DISABLE_DDR_DFS | \ 46 SPM_FLAG_DISABLE_EMI_DFS | \ 47 SPM_FLAG_DISABLE_BUS_DFS | \ 48 SPM_FLAG_ENABLE_MD_MUMTAS | \ 49 SPM_FLAG_SRAM_SLEEP_CTRL) 50 51 #define SPM_SUSPEND_PCM_FLAG1 (SPM_FLAG1_ENABLE_ALCO_TRACE | \ 52 SPM_FLAG1_ENABLE_SUSPEND_AVS | \ 53 SPM_FLAG1_ENABLE_CSOPLU_OFF) 54 55 /* Suspend spm power control */ 56 #define __WAKE_SRC_FOR_SUSPEND_COMMON__ ( \ 57 (R12_KP_IRQ_B) | \ 58 (R12_APWDT_EVENT_B) | \ 59 (R12_CONN2AP_WAKEUP_B) | \ 60 (R12_EINT_EVENT_B) | \ 61 (R12_CONN_WDT_IRQ_B) | \ 62 (R12_CCIF0_EVENT_B) | \ 63 (R12_CCIF1_EVENT_B) | \ 64 (R12_SCP2SPM_WAKEUP_B) | \ 65 (R12_ADSP2SPM_WAKEUP_B) | \ 66 (R12_USB0_CDSC_B) | \ 67 (R12_USB0_POWERDWN_B) | \ 68 (R12_UART_EVENT_B) |\ 69 (R12_SYS_TIMER_EVENT_B) | \ 70 (R12_EINT_EVENT_SECURE_B) | \ 71 (R12_SYS_CIRQ_IRQ_B) | \ 72 (R12_MD_WDT_B) | \ 73 (R12_AP2AP_PEER_WAKEUP_B) | \ 74 (R12_CPU_WAKEUP) | \ 75 (R12_APUSYS_WAKE_HOST_B)|\ 76 (R12_PCIE_WAKE_B)) 77 78 #if defined(CFG_MICROTRUST_TEE_SUPPORT) 79 #define WAKE_SRC_FOR_SUSPEND \ 80 (__WAKE_SRC_FOR_SUSPEND_COMMON__) 81 #else 82 #define WAKE_SRC_FOR_SUSPEND \ 83 (__WAKE_SRC_FOR_SUSPEND_COMMON__ | \ 84 R12_SEJ_B) 85 #endif 86 static uint32_t gpio_bk1; 87 static uint32_t gpio_bk2; 88 static uint32_t gpio_bk3; 89 90 static struct pwr_ctrl suspend_ctrl = { 91 .wake_src = WAKE_SRC_FOR_SUSPEND, 92 93 /* SPM_SRC_REQ */ 94 .reg_spm_adsp_mailbox_req = 0, 95 .reg_spm_apsrc_req = 0, 96 .reg_spm_ddren_req = 0, 97 .reg_spm_dvfs_req = 0, 98 .reg_spm_emi_req = 0, 99 .reg_spm_f26m_req = 0, 100 .reg_spm_infra_req = 0, 101 .reg_spm_pmic_req = 0, 102 .reg_spm_scp_mailbox_req = 0, 103 .reg_spm_sspm_mailbox_req = 0, 104 .reg_spm_sw_mailbox_req = 0, 105 .reg_spm_vcore_req = 1, 106 .reg_spm_vrf18_req = 0, 107 .adsp_mailbox_state = 0, 108 .apsrc_state = 0, 109 .ddren_state = 0, 110 .dvfs_state = 0, 111 .emi_state = 0, 112 .f26m_state = 0, 113 .infra_state = 0, 114 .pmic_state = 0, 115 .scp_mailbox_state = 0, 116 .sspm_mailbox_state = 0, 117 .sw_mailbox_state = 0, 118 .vcore_state = 0, 119 .vrf18_state = 0, 120 121 /* SPM_SRC_MASK_0 */ 122 .reg_apifr_apsrc_rmb = 0, 123 .reg_apifr_ddren_rmb = 0, 124 .reg_apifr_emi_rmb = 0, 125 .reg_apifr_infra_rmb = 0, 126 .reg_apifr_pmic_rmb = 0, 127 .reg_apifr_srcclkena_mb = 0, 128 .reg_apifr_vcore_rmb = 0, 129 .reg_apifr_vrf18_rmb = 0, 130 .reg_apu_apsrc_rmb = 1, 131 .reg_apu_ddren_rmb = 0, 132 .reg_apu_emi_rmb = 1, 133 .reg_apu_infra_rmb = 1, 134 .reg_apu_pmic_rmb = 1, 135 .reg_apu_srcclkena_mb = 1, 136 .reg_apu_vcore_rmb = 1, 137 .reg_apu_vrf18_rmb = 1, 138 .reg_audio_apsrc_rmb = 1, 139 .reg_audio_ddren_rmb = 0, 140 .reg_audio_emi_rmb = 1, 141 .reg_audio_infra_rmb = 1, 142 .reg_audio_pmic_rmb = 0, 143 .reg_audio_srcclkena_mb = 1, 144 .reg_audio_vcore_rmb = 1, 145 .reg_audio_vrf18_rmb = 1, 146 147 /* SPM_SRC_MASK_1 */ 148 .reg_audio_dsp_apsrc_rmb = 1, 149 .reg_audio_dsp_ddren_rmb = 0, 150 .reg_audio_dsp_emi_rmb = 1, 151 .reg_audio_dsp_infra_rmb = 1, 152 .reg_audio_dsp_pmic_rmb = 1, 153 .reg_audio_dsp_srcclkena_mb = 1, 154 .reg_audio_dsp_vcore_rmb = 1, 155 .reg_audio_dsp_vrf18_rmb = 1, 156 .reg_cam_apsrc_rmb = 0, 157 .reg_cam_ddren_rmb = 0, 158 .reg_cam_emi_rmb = 0, 159 .reg_cam_infra_rmb = 0, 160 .reg_cam_pmic_rmb = 0, 161 .reg_cam_srcclkena_mb = 0, 162 .reg_cam_vrf18_rmb = 0, 163 .reg_ccif_apsrc_rmb = 0xfff, 164 165 /* SPM_SRC_MASK_2 */ 166 .reg_ccif_emi_rmb = 0xfff, 167 .reg_ccif_infra_rmb = 0xfff, 168 169 /* SPM_SRC_MASK_3 */ 170 .reg_ccif_pmic_rmb = 0xfff, 171 .reg_ccif_srcclkena_mb = 0xfff, 172 173 /* SPM_SRC_MASK_4 */ 174 .reg_ccif_vcore_rmb = 0xfff, 175 .reg_ccif_vrf18_rmb = 0xfff, 176 .reg_ccu_apsrc_rmb = 0, 177 .reg_ccu_ddren_rmb = 0, 178 .reg_ccu_emi_rmb = 0, 179 .reg_ccu_infra_rmb = 0, 180 .reg_ccu_pmic_rmb = 0, 181 .reg_ccu_srcclkena_mb = 0, 182 .reg_ccu_vrf18_rmb = 0, 183 .reg_cg_check_apsrc_rmb = 0, 184 185 /* SPM_SRC_MASK_5 */ 186 .reg_cg_check_ddren_rmb = 0, 187 .reg_cg_check_emi_rmb = 0, 188 .reg_cg_check_infra_rmb = 0, 189 .reg_cg_check_pmic_rmb = 0, 190 .reg_cg_check_srcclkena_mb = 0, 191 .reg_cg_check_vcore_rmb = 1, 192 .reg_cg_check_vrf18_rmb = 0, 193 .reg_cksys_apsrc_rmb = 1, 194 .reg_cksys_ddren_rmb = 0, 195 .reg_cksys_emi_rmb = 1, 196 .reg_cksys_infra_rmb = 1, 197 .reg_cksys_pmic_rmb = 1, 198 .reg_cksys_srcclkena_mb = 1, 199 .reg_cksys_vcore_rmb = 1, 200 .reg_cksys_vrf18_rmb = 1, 201 .reg_cksys_1_apsrc_rmb = 1, 202 .reg_cksys_1_ddren_rmb = 0, 203 .reg_cksys_1_emi_rmb = 1, 204 .reg_cksys_1_infra_rmb = 1, 205 .reg_cksys_1_pmic_rmb = 1, 206 .reg_cksys_1_srcclkena_mb = 1, 207 .reg_cksys_1_vcore_rmb = 1, 208 .reg_cksys_1_vrf18_rmb = 1, 209 210 /* SPM_SRC_MASK_6 */ 211 .reg_cksys_2_apsrc_rmb = 1, 212 .reg_cksys_2_ddren_rmb = 0, 213 .reg_cksys_2_emi_rmb = 1, 214 .reg_cksys_2_infra_rmb = 1, 215 .reg_cksys_2_pmic_rmb = 1, 216 .reg_cksys_2_srcclkena_mb = 1, 217 .reg_cksys_2_vcore_rmb = 1, 218 .reg_cksys_2_vrf18_rmb = 1, 219 .reg_conn_apsrc_rmb = 1, 220 .reg_conn_ddren_rmb = 0, 221 .reg_conn_emi_rmb = 1, 222 .reg_conn_infra_rmb = 1, 223 .reg_conn_pmic_rmb = 1, 224 .reg_conn_srcclkena_mb = 1, 225 .reg_conn_srcclkenb_mb = 1, 226 .reg_conn_vcore_rmb = 1, 227 .reg_conn_vrf18_rmb = 1, 228 .reg_corecfg_apsrc_rmb = 0, 229 .reg_corecfg_ddren_rmb = 0, 230 .reg_corecfg_emi_rmb = 0, 231 .reg_corecfg_infra_rmb = 0, 232 .reg_corecfg_pmic_rmb = 0, 233 .reg_corecfg_srcclkena_mb = 0, 234 .reg_corecfg_vcore_rmb = 0, 235 .reg_corecfg_vrf18_rmb = 0, 236 237 /* SPM_SRC_MASK_7 */ 238 .reg_cpueb_apsrc_rmb = 1, 239 .reg_cpueb_ddren_rmb = 0, 240 .reg_cpueb_emi_rmb = 1, 241 .reg_cpueb_infra_rmb = 1, 242 .reg_cpueb_pmic_rmb = 1, 243 .reg_cpueb_srcclkena_mb = 1, 244 .reg_cpueb_vcore_rmb = 0, 245 .reg_cpueb_vrf18_rmb = 1, 246 .reg_disp0_apsrc_rmb = 0, 247 .reg_disp0_ddren_rmb = 0, 248 .reg_disp0_emi_rmb = 0, 249 .reg_disp0_infra_rmb = 0, 250 .reg_disp0_pmic_rmb = 0, 251 .reg_disp0_srcclkena_mb = 0, 252 .reg_disp0_vrf18_rmb = 0, 253 .reg_disp1_apsrc_rmb = 0, 254 .reg_disp1_ddren_rmb = 0, 255 .reg_disp1_emi_rmb = 0, 256 .reg_disp1_infra_rmb = 0, 257 .reg_disp1_pmic_rmb = 0, 258 .reg_disp1_srcclkena_mb = 0, 259 .reg_disp1_vrf18_rmb = 0, 260 .reg_dpm_apsrc_rmb = 0xf, 261 .reg_dpm_ddren_rmb = 0xf, 262 263 /* SPM_SRC_MASK_8 */ 264 .reg_dpm_emi_rmb = 0xf, 265 .reg_dpm_infra_rmb = 0xf, 266 .reg_dpm_pmic_rmb = 0xf, 267 .reg_dpm_srcclkena_mb = 0xf, 268 .reg_dpm_vcore_rmb = 0xf, 269 .reg_dpm_vrf18_rmb = 0xf, 270 .reg_dpmaif_apsrc_rmb = 1, 271 .reg_dpmaif_ddren_rmb = 0, 272 .reg_dpmaif_emi_rmb = 1, 273 .reg_dpmaif_infra_rmb = 1, 274 .reg_dpmaif_pmic_rmb = 1, 275 .reg_dpmaif_srcclkena_mb = 1, 276 .reg_dpmaif_vcore_rmb = 1, 277 .reg_dpmaif_vrf18_rmb = 1, 278 279 /* SPM_SRC_MASK_9 */ 280 .reg_dvfsrc_level_rmb = 1, 281 .reg_emisys_apsrc_rmb = 0, 282 .reg_emisys_ddren_rmb = 0, 283 .reg_emisys_emi_rmb = 0, 284 .reg_emisys_infra_rmb = 0, 285 .reg_emisys_pmic_rmb = 0, 286 .reg_emisys_srcclkena_mb = 0, 287 .reg_emisys_vcore_rmb = 0, 288 .reg_emisys_vrf18_rmb = 0, 289 .reg_gce_apsrc_rmb = 0, 290 .reg_gce_ddren_rmb = 0, 291 .reg_gce_emi_rmb = 0, 292 .reg_gce_infra_rmb = 0, 293 .reg_gce_pmic_rmb = 0, 294 .reg_gce_srcclkena_mb = 0, 295 .reg_gce_vcore_rmb = 0, 296 .reg_gce_vrf18_rmb = 0, 297 .reg_gpueb_apsrc_rmb = 1, 298 .reg_gpueb_ddren_rmb = 0, 299 .reg_gpueb_emi_rmb = 1, 300 .reg_gpueb_infra_rmb = 1, 301 .reg_gpueb_pmic_rmb = 1, 302 .reg_gpueb_srcclkena_mb = 1, 303 .reg_gpueb_vcore_rmb = 1, 304 .reg_gpueb_vrf18_rmb = 1, 305 .reg_hwccf_apsrc_rmb = 1, 306 .reg_hwccf_ddren_rmb = 0, 307 .reg_hwccf_emi_rmb = 1, 308 .reg_hwccf_infra_rmb = 1, 309 .reg_hwccf_pmic_rmb = 1, 310 .reg_hwccf_srcclkena_mb = 1, 311 .reg_hwccf_vcore_rmb = 1, 312 313 /* SPM_SRC_MASK_10 */ 314 .reg_hwccf_vrf18_rmb = 1, 315 .reg_img_apsrc_rmb = 0, 316 .reg_img_ddren_rmb = 0, 317 .reg_img_emi_rmb = 0, 318 .reg_img_infra_rmb = 0, 319 .reg_img_pmic_rmb = 0, 320 .reg_img_srcclkena_mb = 0, 321 .reg_img_vrf18_rmb = 0, 322 .reg_infrasys_apsrc_rmb = 0, 323 .reg_infrasys_ddren_rmb = 0, 324 .reg_infrasys_emi_rmb = 0, 325 .reg_infrasys_infra_rmb = 0, 326 .reg_infrasys_pmic_rmb = 0, 327 .reg_infrasys_srcclkena_mb = 0, 328 .reg_infrasys_vcore_rmb = 0, 329 .reg_infrasys_vrf18_rmb = 0, 330 .reg_ipic_infra_rmb = 1, 331 .reg_ipic_vrf18_rmb = 1, 332 .reg_mcu_apsrc_rmb = 1, 333 .reg_mcu_ddren_rmb = 0, 334 .reg_mcu_emi_rmb = 1, 335 .reg_mcu_infra_rmb = 1, 336 .reg_mcu_pmic_rmb = 1, 337 .reg_mcu_srcclkena_mb = 1, 338 .reg_mcu_vcore_rmb = 0, 339 .reg_mcu_vrf18_rmb = 1, 340 .reg_md_apsrc_rmb = 1, 341 .reg_md_ddren_rmb = 0, 342 .reg_md_emi_rmb = 1, 343 .reg_md_infra_rmb = 1, 344 .reg_md_pmic_rmb = 1, 345 .reg_md_srcclkena_mb = 1, 346 347 /* SPM_SRC_MASK_11 */ 348 .reg_md_srcclkena1_mb = 1, 349 .reg_md_vcore_rmb = 1, 350 .reg_md_vrf18_rmb = 1, 351 .reg_mm_proc_apsrc_rmb = 1, 352 .reg_mm_proc_ddren_rmb = 0, 353 .reg_mm_proc_emi_rmb = 1, 354 .reg_mm_proc_infra_rmb = 1, 355 .reg_mm_proc_pmic_rmb = 1, 356 .reg_mm_proc_srcclkena_mb = 1, 357 .reg_mm_proc_vcore_rmb = 1, 358 .reg_mm_proc_vrf18_rmb = 1, 359 .reg_mml0_apsrc_rmb = 0, 360 .reg_mml0_ddren_rmb = 0, 361 .reg_mml0_emi_rmb = 0, 362 .reg_mml0_infra_rmb = 0, 363 .reg_mml0_pmic_rmb = 0, 364 .reg_mml0_srcclkena_mb = 0, 365 .reg_mml0_vrf18_rmb = 0, 366 .reg_mml1_apsrc_rmb = 0, 367 .reg_mml1_ddren_rmb = 0, 368 .reg_mml1_emi_rmb = 0, 369 .reg_mml1_infra_rmb = 0, 370 .reg_mml1_pmic_rmb = 0, 371 .reg_mml1_srcclkena_mb = 0, 372 .reg_mml1_vrf18_rmb = 0, 373 .reg_ovl0_apsrc_rmb = 0, 374 .reg_ovl0_ddren_rmb = 0, 375 .reg_ovl0_emi_rmb = 0, 376 .reg_ovl0_infra_rmb = 0, 377 .reg_ovl0_pmic_rmb = 0, 378 .reg_ovl0_srcclkena_mb = 0, 379 .reg_ovl0_vrf18_rmb = 0, 380 381 /* SPM_SRC_MASK_12 */ 382 .reg_ovl1_apsrc_rmb = 0, 383 .reg_ovl1_ddren_rmb = 0, 384 .reg_ovl1_emi_rmb = 0, 385 .reg_ovl1_infra_rmb = 0, 386 .reg_ovl1_pmic_rmb = 0, 387 .reg_ovl1_srcclkena_mb = 0, 388 .reg_ovl1_vrf18_rmb = 0, 389 .reg_pcie0_apsrc_rmb = 1, 390 .reg_pcie0_ddren_rmb = 0, 391 .reg_pcie0_emi_rmb = 1, 392 .reg_pcie0_infra_rmb = 1, 393 .reg_pcie0_pmic_rmb = 1, 394 .reg_pcie0_srcclkena_mb = 1, 395 .reg_pcie0_vcore_rmb = 1, 396 .reg_pcie0_vrf18_rmb = 1, 397 .reg_pcie1_apsrc_rmb = 1, 398 .reg_pcie1_ddren_rmb = 0, 399 .reg_pcie1_emi_rmb = 1, 400 .reg_pcie1_infra_rmb = 1, 401 .reg_pcie1_pmic_rmb = 1, 402 .reg_pcie1_srcclkena_mb = 1, 403 .reg_pcie1_vcore_rmb = 1, 404 .reg_pcie1_vrf18_rmb = 1, 405 .reg_perisys_apsrc_rmb = 1, 406 .reg_perisys_ddren_rmb = 0, 407 .reg_perisys_emi_rmb = 1, 408 .reg_perisys_infra_rmb = 1, 409 .reg_perisys_pmic_rmb = 1, 410 .reg_perisys_srcclkena_mb = 1, 411 .reg_perisys_vcore_rmb = 1, 412 .reg_perisys_vrf18_rmb = 1, 413 .reg_pmsr_apsrc_rmb = 1, 414 415 /* SPM_SRC_MASK_13 */ 416 .reg_pmsr_ddren_rmb = 0, 417 .reg_pmsr_emi_rmb = 1, 418 .reg_pmsr_infra_rmb = 1, 419 .reg_pmsr_pmic_rmb = 1, 420 .reg_pmsr_srcclkena_mb = 1, 421 .reg_pmsr_vcore_rmb = 1, 422 .reg_pmsr_vrf18_rmb = 1, 423 .reg_scp_apsrc_rmb = 1, 424 .reg_scp_ddren_rmb = 0, 425 .reg_scp_emi_rmb = 1, 426 .reg_scp_infra_rmb = 1, 427 .reg_scp_pmic_rmb = 1, 428 .reg_scp_srcclkena_mb = 1, 429 .reg_scp_vcore_rmb = 1, 430 .reg_scp_vrf18_rmb = 1, 431 .reg_spu_hwr_apsrc_rmb = 1, 432 .reg_spu_hwr_ddren_rmb = 0, 433 .reg_spu_hwr_emi_rmb = 1, 434 .reg_spu_hwr_infra_rmb = 1, 435 .reg_spu_hwr_pmic_rmb = 1, 436 .reg_spu_hwr_srcclkena_mb = 1, 437 .reg_spu_hwr_vcore_rmb = 1, 438 .reg_spu_hwr_vrf18_rmb = 1, 439 .reg_spu_ise_apsrc_rmb = 1, 440 .reg_spu_ise_ddren_rmb = 0, 441 .reg_spu_ise_emi_rmb = 1, 442 .reg_spu_ise_infra_rmb = 1, 443 .reg_spu_ise_pmic_rmb = 1, 444 .reg_spu_ise_srcclkena_mb = 1, 445 .reg_spu_ise_vcore_rmb = 1, 446 .reg_spu_ise_vrf18_rmb = 1, 447 448 /* SPM_SRC_MASK_14 */ 449 .reg_srcclkeni_infra_rmb = 0x3, 450 .reg_srcclkeni_pmic_rmb = 0x3, 451 .reg_srcclkeni_srcclkena_mb = 0x3, 452 .reg_srcclkeni_vcore_rmb = 0x3, 453 .reg_sspm_apsrc_rmb = 1, 454 .reg_sspm_ddren_rmb = 0, 455 .reg_sspm_emi_rmb = 1, 456 .reg_sspm_infra_rmb = 1, 457 .reg_sspm_pmic_rmb = 1, 458 .reg_sspm_srcclkena_mb = 1, 459 .reg_sspm_vrf18_rmb = 1, 460 .reg_ssrsys_apsrc_rmb = 1, 461 .reg_ssrsys_ddren_rmb = 0, 462 .reg_ssrsys_emi_rmb = 1, 463 .reg_ssrsys_infra_rmb = 1, 464 .reg_ssrsys_pmic_rmb = 1, 465 .reg_ssrsys_srcclkena_mb = 1, 466 .reg_ssrsys_vcore_rmb = 1, 467 .reg_ssrsys_vrf18_rmb = 1, 468 .reg_ssusb_apsrc_rmb = 1, 469 .reg_ssusb_ddren_rmb = 0, 470 .reg_ssusb_emi_rmb = 1, 471 .reg_ssusb_infra_rmb = 1, 472 .reg_ssusb_pmic_rmb = 1, 473 .reg_ssusb_srcclkena_mb = 1, 474 .reg_ssusb_vcore_rmb = 1, 475 .reg_ssusb_vrf18_rmb = 1, 476 .reg_uart_hub_infra_rmb = 1, 477 478 /* SPM_SRC_MASK_15 */ 479 .reg_uart_hub_pmic_rmb = 1, 480 .reg_uart_hub_srcclkena_mb = 1, 481 .reg_uart_hub_vcore_rmb = 1, 482 .reg_uart_hub_vrf18_rmb = 1, 483 .reg_ufs_apsrc_rmb = 1, 484 .reg_ufs_ddren_rmb = 0, 485 .reg_ufs_emi_rmb = 1, 486 .reg_ufs_infra_rmb = 1, 487 .reg_ufs_pmic_rmb = 1, 488 .reg_ufs_srcclkena_mb = 1, 489 .reg_ufs_vcore_rmb = 1, 490 .reg_ufs_vrf18_rmb = 1, 491 .reg_vdec_apsrc_rmb = 0, 492 .reg_vdec_ddren_rmb = 0, 493 .reg_vdec_emi_rmb = 0, 494 .reg_vdec_infra_rmb = 0, 495 .reg_vdec_pmic_rmb = 0, 496 .reg_vdec_srcclkena_mb = 0, 497 .reg_vdec_vrf18_rmb = 0, 498 .reg_venc_apsrc_rmb = 0, 499 .reg_venc_ddren_rmb = 0, 500 .reg_venc_emi_rmb = 0, 501 .reg_venc_infra_rmb = 0, 502 .reg_venc_pmic_rmb = 0, 503 .reg_venc_srcclkena_mb = 0, 504 .reg_venc_vrf18_rmb = 0, 505 .reg_vlpcfg_apsrc_rmb = 1, 506 .reg_vlpcfg_ddren_rmb = 0, 507 .reg_vlpcfg_emi_rmb = 1, 508 .reg_vlpcfg_infra_rmb = 1, 509 .reg_vlpcfg_pmic_rmb = 1, 510 .reg_vlpcfg_srcclkena_mb = 1, 511 512 /* SPM_SRC_MASK_16 */ 513 .reg_vlpcfg_vcore_rmb = 1, 514 .reg_vlpcfg_vrf18_rmb = 1, 515 .reg_vlpcfg1_apsrc_rmb = 1, 516 .reg_vlpcfg1_ddren_rmb = 0, 517 .reg_vlpcfg1_emi_rmb = 1, 518 .reg_vlpcfg1_infra_rmb = 1, 519 .reg_vlpcfg1_pmic_rmb = 0, 520 .reg_vlpcfg1_srcclkena_mb = 1, 521 .reg_vlpcfg1_vcore_rmb = 1, 522 .reg_vlpcfg1_vrf18_rmb = 1, 523 524 /* SPM_EVENT_CON_MISC */ 525 .reg_srcclken_fast_resp = 0, 526 .reg_csyspwrup_ack_mask = 1, 527 528 /* SPM_SRC_MASK_17 */ 529 .reg_spm_sw_vcore_rmb = 0x3, 530 .reg_spm_sw_pmic_rmb = 0, 531 532 /* SPM_SRC_MASK_18 */ 533 .reg_spm_sw_srcclkena_mb = 0, 534 535 /* SPM_WAKE_MASK*/ 536 .reg_wake_mask = 0x81322012, 537 538 /* SPM_WAKEUP_EVENT_EXT_MASK */ 539 .reg_ext_wake_mask = 0xFFFFFFFF, 540 541 /*SW flag setting */ 542 .pcm_flags = SPM_SUSPEND_PCM_FLAG, 543 .pcm_flags1 = SPM_SUSPEND_PCM_FLAG1, 544 }; 545 546 static struct suspend_dbg_ctrl suspend_spm_dbg_ext = { 547 .sleep_suspend_cnt = 0, 548 }; 549 550 static struct dbg_ctrl suspend_spm_dbg = { 551 .count = 0, 552 .duration = 0, 553 .ext = &suspend_spm_dbg_ext, 554 }; 555 556 static struct spm_lp_stat suspend_lp_stat; 557 558 struct spm_lp_scen __spm_suspend = { 559 .pwrctrl = &suspend_ctrl, 560 .dbgctrl = &suspend_spm_dbg, 561 .lpstat = &suspend_lp_stat, 562 }; 563 564 static uint8_t bak_spm_vcore_req; 565 566 int mt_spm_suspend_mode_set(enum mt_spm_suspend_mode mode, void *prv) 567 { 568 569 if (mode == MT_SPM_SUSPEND_SLEEP) { 570 suspend_ctrl.pcm_flags = SPM_SUSPEND_SLEEP_PCM_FLAG; 571 suspend_ctrl.pcm_flags1 = SPM_SUSPEND_SLEEP_PCM_FLAG1; 572 suspend_ctrl.reg_spm_vcore_req = 1; 573 } else { 574 suspend_ctrl.pcm_flags = SPM_SUSPEND_PCM_FLAG; 575 suspend_ctrl.pcm_flags1 = SPM_SUSPEND_PCM_FLAG1; 576 } 577 578 return 0; 579 } 580 581 static void spm_CSOPLU_ctrl_leave_suspend(void) 582 { 583 mmio_setbits_32(SPM_RSV_CSOPLU_REQ, (0x1)); 584 } 585 586 static void mt_spm_suspend_ec_pin(void) 587 { 588 gpio_bk1 = mmio_read_32(MODE_BACKUP_REG); 589 gpio_bk2 = mmio_read_32(DIR_BACKUP_REG); 590 gpio_bk3 = mmio_read_32(DOUT_BACKUP_REG); 591 592 mmio_write_32(MODE_SET, SET_GPIO_MODE); 593 gpio_set_direction(EC_SUSPEND_BK_PIN, GPIO_DIR_OUT); 594 /* GPIO111 LOW */ 595 gpio_set_value(EC_SUSPEND_BK_PIN, GPIO_LEVEL_LOW); 596 /* GPIO38 LOW */ 597 gpio_set_value(EC_SUSPEND_PIN, GPIO_LEVEL_LOW); 598 } 599 600 static void mt_spm_resume_ec_pin(void) 601 { 602 /* GPIO38 HIGH */ 603 gpio_set_value(EC_SUSPEND_PIN, GPIO_LEVEL_HIGH); 604 /* GPIO111 HIGH */ 605 gpio_set_value(EC_SUSPEND_BK_PIN, GPIO_LEVEL_HIGH); 606 udelay(10); 607 608 mmio_write_32(MODE_BACKUP_REG, gpio_bk1); 609 mmio_write_32(DIR_BACKUP_REG, gpio_bk2); 610 mmio_write_32(DOUT_BACKUP_REG, gpio_bk3); 611 } 612 613 int mt_spm_suspend_enter(int state_id, 614 uint32_t ext_opand, uint32_t resource_req) 615 { 616 int ret = 0; 617 618 bak_spm_vcore_req = suspend_ctrl.reg_spm_vcore_req; 619 620 /* if FMAudio, ADSP, USB headset is active, change to sleep mode */ 621 if (ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) 622 mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP, 623 &resource_req); 624 else 625 mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN, 626 &resource_req); 627 628 mmio_write_32(SPM2SW_MAILBOX_0, 0x1); 629 630 ext_opand |= MT_SPM_EX_OP_DEVICES_SAVE; 631 632 #if defined(CONFIG_MTK_VCOREDVFS_SUPPORT) 633 /* Notify vcoredvfs suspend enter */ 634 spm_vcorefs_plat_suspend(); 635 #endif 636 637 ret = spm_conservation(state_id, ext_opand, 638 &__spm_suspend, resource_req); 639 if (ret == 0) { 640 struct mt_lp_publish_event event = { 641 .id = MT_LPM_PUBEVENTS_SYS_POWER_OFF, 642 .val.u32 = 0, 643 .level = MT_LP_SYSPOWER_LEVEL_SUSPEND, 644 }; 645 646 MT_LP_SUSPEND_PUBLISH_EVENT(&event); 647 } 648 649 mt_spm_suspend_ec_pin(); 650 651 return ret; 652 } 653 654 void mt_spm_suspend_resume(int state_id, uint32_t ext_opand, 655 struct wake_status **status) 656 { 657 struct mt_lp_publish_event event; 658 struct wake_status *st = NULL; 659 660 ext_opand |= MT_SPM_EX_OP_DEVICES_SAVE; 661 662 mt_spm_resume_ec_pin(); 663 spm_conservation_finish(state_id, ext_opand, &__spm_suspend, &st); 664 665 spm_CSOPLU_ctrl_leave_suspend(); 666 667 mt_spm_update_lp_stat(&suspend_lp_stat); 668 #if defined(CONFIG_MTK_VCOREDVFS_SUPPORT) 669 /* Notify vcoredvfs suspend enter */ 670 spm_vcorefs_plat_resume(); 671 mmio_write_32(SPM2SW_MAILBOX_0, 0x0); 672 #endif 673 674 /***************************************** 675 * If FMAudio, ADSP, USB headset is active, 676 * change back to suspend mode and counting in resume 677 *****************************************/ 678 679 if (ext_opand & MT_SPM_EX_OP_SET_SUSPEND_MODE) { 680 mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN, NULL); 681 suspend_spm_dbg_ext.sleep_suspend_cnt += 1; 682 } 683 684 suspend_ctrl.reg_spm_vcore_req = bak_spm_vcore_req; 685 686 suspend_spm_dbg.count += 1; 687 event.id = MT_LPM_PUBEVENTS_SYS_POWER_ON; 688 event.val.u32 = 0; 689 event.level = MT_LP_SYSPOWER_LEVEL_SUSPEND; 690 691 if (st) { 692 if (st->tr.comm.r12 & R12_AP2AP_PEER_WAKEUP_B) 693 event.val.u32 = MT_LPM_WAKE_MD_WAKEUP_DPMAIF; 694 if (st->tr.comm.r12 & R12_CCIF0_EVENT_B) 695 event.val.u32 = MT_LPM_WAKE_MD_WAKEUP_CCIF0; 696 if (st->tr.comm.r12 & R12_CCIF1_EVENT_B) 697 event.val.u32 = MT_LPM_WAKE_MD_WAKEUP_CCIF1; 698 } 699 if (status) 700 *status = st; 701 MT_LP_SUSPEND_PUBLISH_EVENT(&event); 702 } 703 704 int mt_spm_suspend_get_spm_lp(struct spm_lp_scen **lp) 705 { 706 if (!lp) 707 return -1; 708 709 *lp = &__spm_suspend; 710 return 0; 711 } 712