xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8196/constraints/mt_spm_rc_syspll.c (revision cf2df874cd09305ac7282fadb0fef6be597dfffb)
1 /*
2  * Copyright (c) 2025, Mediatek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <stdint.h>
7 
8 #include <common/debug.h>
9 
10 #include <constraints/mt_spm_rc_api.h>
11 #include <constraints/mt_spm_rc_internal.h>
12 #include <drivers/spm/mt_spm_resource_req.h>
13 #include <lib/pm/mtk_pm.h>
14 #include <lpm_v2/mt_lp_api.h>
15 #include <lpm_v2/mt_lp_rm.h>
16 #include <mt_plat_spm_setting.h>
17 #include <mt_spm.h>
18 #include <mt_spm_conservation.h>
19 #include <mt_spm_constraint.h>
20 #include <mt_spm_idle.h>
21 #include <mt_spm_internal.h>
22 #include <mt_spm_pmic_lp.h>
23 #include <mt_spm_reg.h>
24 #include <mt_spm_suspend.h>
25 #include <notifier/inc/mt_spm_notifier.h>
26 
27 #define CONSTRAINT_SYSPLL_ALLOW (MT_RM_CONSTRAINT_ALLOW_CPU_BUCK_OFF | \
28 				 MT_RM_CONSTRAINT_ALLOW_DRAM_S0 | \
29 				 MT_RM_CONSTRAINT_ALLOW_DRAM_S1 | \
30 				 MT_RM_CONSTRAINT_ALLOW_VCORE_LP | \
31 				 MT_RM_CONSTRAINT_ALLOW_LVTS_STATE)
32 
33 #define CONSTRAINT_SYSPLL_PCM_FLAG (SPM_FLAG_DISABLE_VCORE_DVS | \
34 				    SPM_FLAG_DISABLE_DDR_DFS | \
35 				    SPM_FLAG_DISABLE_EMI_DFS | \
36 				    SPM_FLAG_DISABLE_BUS_DFS | \
37 				    SPM_FLAG_ENABLE_AOV | \
38 				    SPM_FLAG_DISABLE_VLP_PDN | \
39 				    SPM_FLAG_SRAM_SLEEP_CTRL | \
40 				    SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
41 
42 #define CONSTRAINT_SYSPLL_PCM_FLAG1 (SPM_FLAG1_ENABLE_ALCO_TRACE)
43 
44 #define CONSTRAINT_SYSPLL_RESOURCE_REQ	(MT_SPM_26M | \
45 					 MT_SPM_VCORE | MT_SPM_INFRA)
46 
47 #define CHECK_VAL(val, sys_state) \
48 	((val) ? !!(*((uint32_t *)(val)) == (sys_state)) : 0)
49 
50 static uint32_t cmd;
51 
52 static struct constraint_status status = {
53 	.id = MT_RM_CONSTRAINT_ID_SYSPL,
54 	.is_valid = (MT_SPM_RC_VALID_SW |
55 		     MT_SPM_RC_VALID_FW |
56 		     MT_SPM_RC_VALID_NOTIFY),
57 	.enter_cnt = 0,
58 	.residency = 0,
59 };
60 
spm_syspll_conduct(int state_id,struct spm_lp_scen * spm_lp,uint32_t * resource_req)61 int spm_syspll_conduct(int state_id, struct spm_lp_scen *spm_lp,
62 		       uint32_t *resource_req)
63 {
64 	if ((spm_lp == NULL) || (resource_req == NULL))
65 		return -1;
66 
67 	struct pwr_ctrl *pwrctrl = spm_lp->pwrctrl;
68 
69 	pwrctrl->pcm_flags = CONSTRAINT_SYSPLL_PCM_FLAG;
70 	pwrctrl->pcm_flags1 = CONSTRAINT_SYSPLL_PCM_FLAG1;
71 
72 	*resource_req |= CONSTRAINT_SYSPLL_RESOURCE_REQ;
73 
74 	return 0;
75 }
76 
spm_is_valid_rc_syspll(uint32_t cpu,int state_id)77 bool spm_is_valid_rc_syspll(uint32_t cpu, int state_id)
78 {
79 	return IS_MT_RM_RC_READY(status.is_valid);
80 }
81 
spm_update_rc_syspll(int state_id,int type,const void * val)82 int spm_update_rc_syspll(int state_id, int type, const void *val)
83 {
84 	int res = MT_RM_STATUS_OK;
85 
86 	if (type == PLAT_RC_CLKBUF_STATUS) {
87 		bool is_flight = CHECK_VAL(val, FLIGHT_MODE_ON);
88 
89 		if (is_flight)
90 			spm_rc_constraint_valid_set(MT_RM_CONSTRAINT_ID_SYSPL,
91 						    MT_RM_CONSTRAINT_ID_SYSPL,
92 						    MT_SPM_RC_VALID_FLIGHTMODE,
93 						    &status);
94 		else
95 			spm_rc_constraint_valid_clr(MT_RM_CONSTRAINT_ID_SYSPL,
96 						    MT_RM_CONSTRAINT_ID_SYSPL,
97 						    MT_SPM_RC_VALID_FLIGHTMODE,
98 						    &status);
99 	} else if (type == PLAT_RC_UFS_STATUS) {
100 		uint32_t is_ufs_h8 =  CHECK_VAL(val, UFS_REF_CLK_OFF);
101 
102 		if (is_ufs_h8)
103 			spm_rc_constraint_valid_set(MT_RM_CONSTRAINT_ID_SYSPL,
104 						    MT_RM_CONSTRAINT_ID_SYSPL,
105 						    MT_SPM_RC_VALID_UFS_H8,
106 						    &status);
107 		else
108 			spm_rc_constraint_valid_clr(MT_RM_CONSTRAINT_ID_SYSPL,
109 						    MT_RM_CONSTRAINT_ID_SYSPL,
110 						    MT_SPM_RC_VALID_UFS_H8,
111 						    &status);
112 	} else if (type == PLAT_RC_STATUS) {
113 		const struct rc_common_state *st;
114 
115 		st = (const struct rc_common_state *)val;
116 
117 		if (!st)
118 			return 0;
119 		if ((st->type == CONSTRAINT_UPDATE_VALID) ||
120 		    (st->type == CONSTRAINT_RESIDNECY))
121 			spm_rc_constraint_status_set(st->id, st->type,
122 						     st->act,
123 						     MT_RM_CONSTRAINT_ID_SYSPL,
124 						     st->value,
125 						     &status);
126 		else
127 			INFO("[%s:%d] - Unknown type: 0x%x\n",
128 			     __func__, __LINE__, st->type);
129 	}
130 
131 	return res;
132 }
133 
spm_allow_rc_syspll(int state_id)134 uint32_t spm_allow_rc_syspll(int state_id)
135 {
136 	return CONSTRAINT_SYSPLL_ALLOW;
137 }
138 
spm_run_rc_syspll(uint32_t cpu,int state_id)139 int spm_run_rc_syspll(uint32_t cpu, int state_id)
140 {
141 	uint32_t ext_op = MT_SPM_EX_OP_HW_S1_DETECT |
142 			  MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
143 	uint32_t nb_type = MT_SPM_NOTIFY_IDLE_ENTER;
144 
145 	MT_SPM_RC_TAG(cpu, state_id, MT_RM_CONSTRAINT_ID_SYSPL);
146 	MT_SPM_RC_TAG_VALID(status.is_valid);
147 	MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_START);
148 
149 	cmd = CONSTRAINT_SYSPLL_ALLOW;
150 
151 	if (IS_PLAT_SUSPEND_ID(state_id)) {
152 		cmd |= MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND;
153 		ext_op |= (MT_SPM_EX_OP_CLR_26M_RECORD |
154 			   MT_SPM_EX_OP_SET_WDT);
155 	} else {
156 		if (status.is_valid & MT_SPM_RC_VALID_TRACE_TIME)
157 			ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
158 
159 		if (!IS_MT_PLAT_PWR_STATE(state_id,
160 					  MT_PLAT_PWR_STATE_SYSTEM_PLL)) {
161 			nb_type = MT_SPM_NOTIFY_IDLE_ENTER;
162 			ext_op &= ~MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
163 		}
164 	}
165 
166 #ifdef MTK_SPM_PMIC_LP_SUPPORT
167 	do_spm_low_power(SPM_LP_ENTER, cmd);
168 #endif
169 
170 	MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_NOTIFY);
171 
172 	if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
173 		mt_spm_sspm_notify_u32(nb_type, cmd);
174 
175 	MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_BEFORE);
176 
177 	if (IS_PLAT_SUSPEND_ID(state_id))
178 		mt_spm_suspend_enter(state_id, ext_op,
179 				     CONSTRAINT_SYSPLL_RESOURCE_REQ);
180 	else
181 		mt_spm_idle_generic_enter(state_id, ext_op, spm_syspll_conduct);
182 
183 	MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_AFTER);
184 	return 0;
185 }
186 
spm_reset_rc_syspll(uint32_t cpu,int state_id)187 int spm_reset_rc_syspll(uint32_t cpu, int state_id)
188 {
189 	uint32_t ext_op = MT_SPM_EX_OP_HW_S1_DETECT |
190 			  MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
191 	uint32_t nb_type = MT_SPM_NOTIFY_IDLE_LEAVE;
192 
193 	MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_START);
194 
195 	if (IS_PLAT_SUSPEND_ID(state_id)) {
196 		ext_op |= (MT_SPM_EX_OP_SET_WDT);
197 	} else {
198 		if (status.is_valid & MT_SPM_RC_VALID_TRACE_TIME)
199 			ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
200 
201 		if (spm_unlikely(status.is_valid &
202 		    MT_SPM_RC_VALID_TRACE_EVENT))
203 			ext_op |= MT_SPM_EX_OP_TRACE_LP;
204 
205 		if (!IS_MT_PLAT_PWR_STATE(state_id,
206 		    MT_PLAT_PWR_STATE_SYSTEM_PLL)) {
207 			nb_type = MT_SPM_NOTIFY_IDLE_LEAVE;
208 			ext_op &= ~MT_SPM_EX_OP_NOTIFY_INFRA_OFF;
209 		}
210 	}
211 
212 #ifdef MTK_SPM_PMIC_LP_SUPPORT
213 	do_spm_low_power(SPM_LP_RESUME, cmd);
214 #endif
215 
216 	MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_NOTIFY);
217 
218 	if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
219 		mt_spm_sspm_notify_u32(nb_type, cmd);
220 
221 	MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_RESET_SPM_BEFORE);
222 
223 	if (IS_PLAT_SUSPEND_ID(state_id))
224 		mt_spm_suspend_resume(state_id, ext_op, NULL);
225 	else {
226 		struct wake_status *waken = NULL;
227 
228 		mt_spm_idle_generic_resume(state_id, ext_op, &waken, NULL);
229 		status.enter_cnt++;
230 
231 		if (spm_unlikely(status.is_valid & MT_SPM_RC_VALID_RESIDNECY))
232 			status.residency += waken ?
233 					    waken->tr.comm.timer_out : 0;
234 	}
235 
236 	MT_SPM_RC_FP(MT_SPM_RC_FP_INIT);
237 	return 0;
238 }
239 
spm_get_status_rc_syspll(uint32_t type,void * priv)240 int spm_get_status_rc_syspll(uint32_t type, void *priv)
241 {
242 	int ret = MT_RM_STATUS_OK;
243 
244 	if (type == PLAT_RC_STATUS) {
245 		int res = 0;
246 		struct rc_common_state *st = (struct rc_common_state *)priv;
247 
248 		if (!st)
249 			return MT_RM_STATUS_BAD;
250 
251 		res = spm_rc_constraint_status_get(st->id, st->type,
252 						   st->act,
253 						   MT_RM_CONSTRAINT_ID_SYSPL,
254 						   &status,
255 						   st->value);
256 		if (!res && (st->id != MT_RM_CONSTRAINT_ID_ALL))
257 			ret = MT_RM_STATUS_STOP;
258 	}
259 	return ret;
260 }
261