1 /* 2 * Copyright (c) 2022, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <common/debug.h> 9 #include <mt_lp_rm.h> 10 #include <mt_spm.h> 11 #include <mt_spm_cond.h> 12 #include <mt_spm_conservation.h> 13 #include <mt_spm_constraint.h> 14 #include <mt_spm_idle.h> 15 #include <mt_spm_internal.h> 16 #include <mt_spm_notifier.h> 17 #include <mt_spm_rc_internal.h> 18 #include <mt_spm_reg.h> 19 #include <mt_spm_resource_req.h> 20 #include <mt_spm_suspend.h> 21 #include <plat_mtk_lpm.h> 22 #include <plat_pm.h> 23 24 #define CONSTRAINT_SYSPLL_ALLOW \ 25 (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \ 26 MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \ 27 MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \ 28 MT_RM_CONSTRAINT_ALLOW_VCORE_LP) 29 30 #if (MTK_SPM_EXTENSION_PMIC_CONTROL == 6362) 31 #define SPM_FLAG_EXTRA_PMIC_CONTROL (SPM_FLAG_ENABLE_6362_CTRL) 32 #else 33 #define SPM_FLAG_EXTRA_PMIC_CONTROL (SPM_FLAG_ENABLE_6315_CTRL) 34 #endif 35 36 #define CONSTRAINT_SYSPLL_PCM_FLAG \ 37 (SPM_FLAG_DISABLE_INFRA_PDN | \ 38 SPM_FLAG_DISABLE_VCORE_DVS | \ 39 SPM_FLAG_DISABLE_VCORE_DFS | \ 40 SPM_FLAG_USE_SRCCLKENO2 | \ 41 SPM_FLAG_SRAM_SLEEP_CTRL | \ 42 SPM_FLAG_KEEP_CSYSPWRACK_HIGH | \ 43 SPM_FLAG_USE_SRCCLKENO2) 44 45 #define CONSTRAINT_SYSPLL_PCM_FLAG1 (0U) 46 #define CONSTRAINT_SYSPLL_RESOURCE_REQ (MT_SPM_26M) 47 48 static struct mt_spm_cond_tables cond_syspll = { 49 .name = "syspll", 50 .table_cg = { 51 0x0385E03C, /* MTCMOS1 */ 52 0x003F0100, /* INFRA0 */ 53 0x08040802, /* INFRA1 */ 54 0x06015641, /* INFRA2 */ 55 0x00000000, /* INFRA3 */ 56 0x00000000, /* INFRA4 */ 57 0x00000000, /* INFRA5 */ 58 0x03720820, /* MMSYS0 */ 59 0x00000000, /* MMSYS1 */ 60 0x00000000, /* MMSYS2 */ 61 0x00015151, /* MMSYS3 */ 62 }, 63 .table_pll = 0U, 64 }; 65 66 static struct mt_spm_cond_tables cond_syspll_res = { 67 .table_cg = {0U}, 68 .table_pll = 0U, 69 }; 70 71 static struct constraint_status status = { 72 .id = MT_RM_CONSTRAINT_ID_SYSPLL, 73 .valid = (MT_SPM_RC_VALID_SW | 74 MT_SPM_RC_VALID_COND_LATCH | 75 MT_SPM_RC_VALID_XSOC_BBLPM), 76 .cond_block = 0U, 77 .enter_cnt = 0U, 78 .cond_res = &cond_syspll_res, 79 }; 80 81 static void spm_syspll_conduct(struct spm_lp_scen *spm_lp, 82 unsigned int *resource_req) 83 { 84 spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG; 85 spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_SYSPLL_PCM_FLAG1; 86 87 *resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ; 88 } 89 90 bool spm_is_valid_rc_syspll(unsigned int cpu, int state_id) 91 { 92 (void)cpu; 93 (void)state_id; 94 95 return ((status.cond_block == 0U) && IS_MT_RM_RC_READY(status.valid)); 96 } 97 98 int spm_update_rc_syspll(int state_id, int type, const void *val) 99 { 100 const struct mt_spm_cond_tables *tlb; 101 const struct mt_spm_cond_tables *tlb_check; 102 int res = MT_RM_STATUS_OK; 103 104 if (val == NULL) { 105 res = MT_RM_STATUS_BAD; 106 } else { 107 if (type == PLAT_RC_UPDATE_CONDITION) { 108 tlb = (const struct mt_spm_cond_tables *)val; 109 tlb_check = (const struct mt_spm_cond_tables *)&cond_syspll; 110 111 status.cond_block = 112 mt_spm_cond_check(state_id, tlb, tlb_check, 113 ((status.valid & 114 MT_SPM_RC_VALID_COND_LATCH) != 0U) ? 115 (&cond_syspll_res) : (NULL)); 116 } else { 117 res = MT_RM_STATUS_BAD; 118 } 119 } 120 121 return res; 122 } 123 124 unsigned int spm_allow_rc_syspll(int state_id) 125 { 126 (void)state_id; 127 128 return CONSTRAINT_SYSPLL_ALLOW; 129 } 130 131 int spm_run_rc_syspll(unsigned int cpu, int state_id) 132 { 133 unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; 134 unsigned int allows = CONSTRAINT_SYSPLL_ALLOW; 135 136 (void)cpu; 137 138 if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { 139 #ifdef MT_SPM_USING_SRCLKEN_RC 140 ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; 141 #else 142 allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; 143 #endif 144 } 145 146 #ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT 147 mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, allows | (IS_PLAT_SUSPEND_ID(state_id) ? 148 (MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) : (0U))); 149 #else 150 (void)allows; 151 #endif 152 if (IS_PLAT_SUSPEND_ID(state_id)) { 153 mt_spm_suspend_enter(state_id, 154 (MT_SPM_EX_OP_SET_WDT | 155 MT_SPM_EX_OP_HW_S1_DETECT | 156 MT_SPM_EX_OP_SET_SUSPEND_MODE), 157 CONSTRAINT_SYSPLL_RESOURCE_REQ); 158 } else { 159 mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct); 160 } 161 162 return 0; 163 } 164 165 int spm_reset_rc_syspll(unsigned int cpu, int state_id) 166 { 167 unsigned int ext_op = MT_SPM_EX_OP_HW_S1_DETECT; 168 unsigned int allows = CONSTRAINT_SYSPLL_ALLOW; 169 170 (void)cpu; 171 172 if (IS_MT_SPM_RC_BBLPM_MODE(status.valid)) { 173 #ifdef MT_SPM_USING_SRCLKEN_RC 174 ext_op |= MT_SPM_EX_OP_SRCLKEN_RC_BBLPM; 175 #else 176 allows |= MT_RM_CONSTRAINT_ALLOW_BBLPM; 177 #endif 178 } 179 180 #ifndef ATF_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT 181 mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, allows); 182 #else 183 (void)allows; 184 #endif 185 if (IS_PLAT_SUSPEND_ID(state_id)) { 186 mt_spm_suspend_resume(state_id, 187 (MT_SPM_EX_OP_SET_SUSPEND_MODE | 188 MT_SPM_EX_OP_SET_WDT | 189 MT_SPM_EX_OP_HW_S1_DETECT), 190 NULL); 191 } else { 192 mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL); 193 status.enter_cnt++; 194 } 195 196 return 0; 197 } 198