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