1 /* 2 * Copyright (c) 2023, MediaTek Inc. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <common/debug.h> 8 #include <drivers/spm/mt_spm_resource_req.h> 9 #include <lib/pm/mtk_pm.h> 10 #include <lpm/mt_lpm_smc.h> 11 #include <mt_spm.h> 12 #include <mt_spm_cond.h> 13 #include <mt_spm_conservation.h> 14 #include <mt_spm_constraint.h> 15 #include <mt_spm_idle.h> 16 #include <mt_spm_internal.h> 17 #include <mt_spm_notifier.h> 18 #include "mt_spm_rc_api.h" 19 #include "mt_spm_rc_internal.h" 20 #include <mt_spm_reg.h> 21 #include <mt_spm_suspend.h> 22 23 #define CONSTRAINT_CPU_BUCK_PCM_FLAG (SPM_FLAG_DISABLE_INFRA_PDN | \ 24 SPM_FLAG_DISABLE_VCORE_DVS | \ 25 SPM_FLAG_DISABLE_VCORE_DFS | \ 26 SPM_FLAG_SRAM_SLEEP_CTRL | \ 27 SPM_FLAG_DISABLE_DRAMC_MCU_SRAM_SLEEP | \ 28 SPM_FLAG_KEEP_CSYSPWRACK_HIGH) 29 30 #define CONSTRAINT_CPU_BUCK_PCM_FLAG1 (0) 31 32 #define CONSTRAINT_CPU_BUCK_RESOURCE_REQ (MT_SPM_DRAM_S1 | \ 33 MT_SPM_DRAM_S0 | \ 34 MT_SPM_SYSPLL | \ 35 MT_SPM_INFRA | \ 36 MT_SPM_26M | \ 37 MT_SPM_XO_FPM) 38 39 static unsigned int cpubuckldo_status = (MT_SPM_RC_VALID_SW | MT_SPM_RC_VALID_TRACE_TIME); 40 static unsigned int cpubuckldo_enter_cnt; 41 42 int spm_cpu_bcuk_ldo_conduct(int state_id, 43 struct spm_lp_scen *spm_lp, 44 unsigned int *resource_req) 45 { 46 unsigned int res_req = CONSTRAINT_CPU_BUCK_RESOURCE_REQ; 47 48 if ((spm_lp == NULL) || (resource_req == NULL)) { 49 return -1; 50 } 51 52 spm_lp->pwrctrl->pcm_flags = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG; 53 spm_lp->pwrctrl->pcm_flags1 = (uint32_t)CONSTRAINT_CPU_BUCK_PCM_FLAG1; 54 55 *resource_req |= res_req; 56 return 0; 57 } 58 59 bool spm_is_valid_rc_cpu_buck_ldo(unsigned int cpu, int state_id) 60 { 61 return IS_MT_RM_RC_READY(cpubuckldo_status); 62 } 63 64 static void update_rc_status(const void *val) 65 { 66 const struct rc_common_state *st = (const struct rc_common_state *)val; 67 68 if (st == NULL) { 69 return; 70 } 71 72 if ((st->type == CONSTRAINT_UPDATE_VALID) && st->value) { 73 if ((st->id == MT_RM_CONSTRAINT_ID_ALL) || 74 (st->id == MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO)) { 75 struct constraint_status *con = (struct constraint_status *)st->value; 76 77 if ((st->act & MT_LPM_SMC_ACT_CLR) > 0U) { 78 SPM_RC_BITS_CLR(cpubuckldo_status, con->is_valid); 79 } else { 80 SPM_RC_BITS_SET(cpubuckldo_status, con->is_valid); 81 } 82 } 83 } 84 } 85 86 int spm_update_rc_cpu_buck_ldo(int state_id, int type, const void *val) 87 { 88 if (type == PLAT_RC_STATUS) { 89 update_rc_status(val); 90 } 91 return MT_RM_STATUS_OK; 92 } 93 94 unsigned int spm_allow_rc_cpu_buck_ldo(int state_id) 95 { 96 return MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF; 97 } 98 99 int spm_run_rc_cpu_buck_ldo(unsigned int cpu, int state_id) 100 { 101 (void)cpu; 102 unsigned int ext_op = 0U; 103 104 #ifndef MTK_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT 105 mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_ENTER, 106 (IS_PLAT_SUSPEND_ID(state_id) ? 107 MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND : (0U))); 108 #endif 109 if (cpubuckldo_status & MT_SPM_RC_VALID_TRACE_TIME) { 110 ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN; 111 } 112 113 if (IS_PLAT_SUSPEND_ID(state_id)) { 114 mt_spm_suspend_enter(state_id, 115 (MT_SPM_EX_OP_CLR_26M_RECORD | 116 MT_SPM_EX_OP_SET_SUSPEND_MODE | 117 MT_SPM_EX_OP_SET_WDT), 118 CONSTRAINT_CPU_BUCK_RESOURCE_REQ); 119 } else { 120 mt_spm_idle_generic_enter(state_id, ext_op, spm_cpu_bcuk_ldo_conduct); 121 } 122 123 cpubuckldo_enter_cnt++; 124 125 return 0; 126 } 127 128 int spm_reset_rc_cpu_buck_ldo(unsigned int cpu, int state_id) 129 { 130 (void)cpu; 131 unsigned int ext_op = 0U; 132 133 #ifndef MTK_PLAT_SPM_SSPM_NOTIFIER_UNSUPPORT 134 mt_spm_sspm_notify_u32(MT_SPM_NOTIFY_LP_LEAVE, 0U); 135 #endif 136 if (cpubuckldo_status & MT_SPM_RC_VALID_TRACE_TIME) { 137 ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN; 138 } 139 140 if (IS_PLAT_SUSPEND_ID(state_id)) { 141 mt_spm_suspend_resume(state_id, MT_SPM_EX_OP_SET_WDT, NULL); 142 } else { 143 mt_spm_idle_generic_resume(state_id, ext_op, NULL, NULL); 144 } 145 146 return 0; 147 } 148 149 int spm_get_status_rc_cpu_buck_ldo(unsigned int type, void *priv) 150 { 151 int ret = MT_RM_STATUS_OK; 152 153 if (type != PLAT_RC_STATUS) { 154 return ret; 155 } 156 157 struct rc_common_state *st = (struct rc_common_state *)priv; 158 159 if (st == NULL) { 160 return MT_RM_STATUS_BAD; 161 } 162 163 if ((st->id == MT_RM_CONSTRAINT_ID_ALL) || 164 (st->id == MT_RM_CONSTRAINT_ID_CPU_BUCK_LDO)) { 165 struct constraint_status *dest; 166 167 dest = (struct constraint_status *)st->value; 168 do { 169 if (dest == NULL) { 170 break; 171 } 172 if (st->type == CONSTRAINT_GET_VALID) { 173 dest->is_valid = cpubuckldo_status; 174 } else if (st->type == CONSTRAINT_COND_BLOCK) { 175 dest->is_cond_block = 0; 176 } else if (st->type == CONSTRAINT_GET_ENTER_CNT) { 177 if (st->id == MT_RM_CONSTRAINT_ID_ALL) { 178 dest->enter_cnt += cpubuckldo_enter_cnt; 179 } else { 180 dest->enter_cnt = cpubuckldo_enter_cnt; 181 } 182 } else { 183 break; 184 } 185 if (st->id != MT_RM_CONSTRAINT_ID_ALL) { 186 ret = MT_RM_STATUS_STOP; 187 } 188 } while (0); 189 } 190 return ret; 191 } 192