xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8189/constraints/mt_spm_rc_bus26m.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_rm.h>
16 #include <mt_plat_spm_setting.h>
17 #include <mt_spm.h>
18 #include <mt_spm_cond.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_BUS26M_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 	 MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF)
33 
34 #define CONSTRAINT_BUS26M_PCM_FLAG                                      \
35 	(SPM_FLAG_DISABLE_INFRA_PDN | SPM_FLAG_DISABLE_DPM_PDN |        \
36 	 SPM_FLAG_DISABLE_MCUPM_PDN | SPM_FLAG_ENABLE_LVTS_WORKAROUND | \
37 	 SPM_FLAG_DISABLE_VCORE_DVS | SPM_FLAG_DISABLE_DDR_DFS |        \
38 	 SPM_FLAG_DISABLE_EMI_DFS | SPM_FLAG_DISABLE_BUS_DFS |          \
39 	 SPM_FLAG_SRAM_SLEEP_CTRL | SPM_FLAG_KEEP_CSYSPWRACK_HIGH)
40 
41 #define CONSTRAINT_BUS26M_PCM_FLAG1                                     \
42 	(SPM_FLAG1_DISABLE_PERI_OFF | SPM_FLAG1_ENABLE_MCU_INFRA_PARITY)
43 
44 /*
45  * If sspm sram won't enter  sleep voltage
46  * then vcore couldn't enter low power mode
47  */
48 
49 #if defined(MTK_PLAT_SPM_SRAM_SLP_UNSUPPORT) && SPM_SRAM_SLEEP_RC_RES_RESTRICT
50 #define CONSTRAINT_BUS26M_RESOURCE_REQ (MT_SPM_26M | MT_SPM_VCORE)
51 #else
52 #define CONSTRAINT_BUS26M_RESOURCE_REQ (MT_SPM_VCORE)
53 #endif
54 static uint32_t bus26m_ext_opand;
55 static struct mt_irqremain *refer2remain_irq;
56 static uint32_t cmd;
57 
58 static struct mt_spm_cond_tables cond_bus26m = {
59 	.table_pll = (PLL_BIT_MFG | PLL_BIT_MFGSC),
60 };
61 
62 static struct mt_spm_cond_tables cond_bus26m_res = {
63 	.table_pll = 0,
64 };
65 
66 static struct constraint_status status = {
67 	.id = MT_RM_CONSTRAINT_ID_BUS26,
68 	.is_valid = (MT_SPM_RC_VALID_SW | MT_SPM_RC_VALID_FW |
69 		     MT_SPM_RC_VALID_COND_CHECK | MT_SPM_RC_VALID_COND_LATCH |
70 		     MT_SPM_RC_VALID_TRACE_TIME | MT_SPM_RC_VALID_NOTIFY),
71 	.is_cond_block = 0,
72 	.enter_cnt = 0,
73 	.all_pll_dump = 0,
74 	.cond_res = &cond_bus26m_res,
75 	.residency = 0,
76 };
77 
spm_bus26m_conduct(int state_id,struct spm_lp_scen * spm_lp,uint32_t * resource_req)78 int spm_bus26m_conduct(int state_id, struct spm_lp_scen *spm_lp,
79 		       uint32_t *resource_req)
80 {
81 	if ((spm_lp == NULL) || (resource_req == NULL))
82 		return -1;
83 
84 	struct pwr_ctrl *pwrctrl = spm_lp->pwrctrl;
85 
86 	pwrctrl->pcm_flags = CONSTRAINT_BUS26M_PCM_FLAG;
87 	pwrctrl->pcm_flags1 = CONSTRAINT_BUS26M_PCM_FLAG1;
88 
89 	*resource_req |= CONSTRAINT_BUS26M_RESOURCE_REQ;
90 	return 0;
91 }
92 
spm_is_valid_rc_bus26m(uint32_t cpu,int state_id)93 bool spm_is_valid_rc_bus26m(uint32_t cpu, int state_id)
94 {
95 	return (!(status.is_cond_block &&
96 		  (status.is_valid & MT_SPM_RC_VALID_COND_CHECK)) &&
97 		IS_MT_RM_RC_READY(status.is_valid) &&
98 		!(bus26m_ext_opand & (MT_BUS26M_EXT_LP_26M_ON_MODE)));
99 }
100 
spm_update_rc_bus26m(int state_id,int type,const void * val)101 int spm_update_rc_bus26m(int state_id, int type, const void *val)
102 {
103 	int res = MT_RM_STATUS_OK;
104 	uint32_t flag = *(uint32_t *)val;
105 
106 	if (type == PLAT_RC_UPDATE_CONDITION) {
107 		const struct mt_spm_cond_tables *tlb =
108 			(const struct mt_spm_cond_tables *)val;
109 		const struct mt_spm_cond_tables *tlb_check =
110 			(const struct mt_spm_cond_tables *)&cond_bus26m;
111 
112 		if (!tlb)
113 			return MT_RM_STATUS_BAD;
114 
115 		status.is_cond_block = mt_spm_cond_check(
116 			tlb, tlb_check,
117 			(status.is_valid & MT_SPM_RC_VALID_COND_LATCH) ?
118 				&cond_bus26m_res :
119 				NULL);
120 		status.all_pll_dump = mt_spm_dump_all_pll(
121 			tlb, tlb_check,
122 			(status.is_valid & MT_SPM_RC_VALID_COND_LATCH) ?
123 				&cond_bus26m_res :
124 				NULL);
125 
126 	} else if (type == PLAT_RC_UPDATE_REMAIN_IRQS) {
127 		refer2remain_irq = (struct mt_irqremain *)val;
128 	} else if (type == PLAT_RC_IS_FMAUDIO) {
129 		if (flag)
130 			bus26m_ext_opand |= MT_SPM_EX_OP_SET_IS_FM_AUDIO;
131 		else
132 			bus26m_ext_opand &= ~MT_SPM_EX_OP_SET_IS_FM_AUDIO;
133 	} else if (type == PLAT_RC_IS_ADSP) {
134 		if (flag)
135 			bus26m_ext_opand |= MT_SPM_EX_OP_SET_IS_ADSP;
136 		else
137 			bus26m_ext_opand &= ~MT_SPM_EX_OP_SET_IS_ADSP;
138 	} else if (type == PLAT_RC_IS_USB_HEADSET) {
139 		if (flag)
140 			bus26m_ext_opand |= MT_SPM_EX_OP_SET_IS_USB_HEADSET;
141 		else
142 			bus26m_ext_opand &= ~MT_SPM_EX_OP_SET_IS_USB_HEADSET;
143 	} else if (type == PLAT_RC_STATUS) {
144 		const struct rc_common_state *st;
145 
146 		st = (const struct rc_common_state *)val;
147 
148 		if (!st)
149 			return 0;
150 		if (st->type == CONSTRAINT_UPDATE_COND_CHECK) {
151 			struct mt_spm_cond_tables *const tlb = &cond_bus26m;
152 
153 			spm_rc_condition_modifier(st->id, st->act, st->value,
154 						  MT_RM_CONSTRAINT_ID_BUS26,
155 						  tlb);
156 		} else if ((st->type == CONSTRAINT_UPDATE_VALID) ||
157 			   (st->type == CONSTRAINT_RESIDNECY)) {
158 			spm_rc_constraint_status_set(st->id, st->type, st->act,
159 						     MT_RM_CONSTRAINT_ID_BUS26,
160 						     st->value, &status);
161 		} else {
162 			INFO("[%s:%d] - Unknown type: 0x%x\n", __func__,
163 			     __LINE__, st->type);
164 		}
165 	}
166 
167 	return res;
168 }
169 
spm_allow_rc_bus26m(int state_id)170 uint32_t spm_allow_rc_bus26m(int state_id)
171 {
172 	return CONSTRAINT_BUS26M_ALLOW;
173 }
174 
spm_run_rc_bus26m(uint32_t cpu,int state_id)175 int spm_run_rc_bus26m(uint32_t cpu, int state_id)
176 {
177 	uint32_t ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
178 	uint32_t nb_type = 0;
179 
180 	MT_SPM_RC_TAG(cpu, state_id, MT_RM_CONSTRAINT_ID_BUS26);
181 	MT_SPM_RC_TAG_VALID(status.is_valid);
182 	MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_START);
183 
184 	cmd = CONSTRAINT_BUS26M_ALLOW;
185 
186 	if (IS_PLAT_SUSPEND_ID(state_id)) {
187 		cmd |= (MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND |
188 			MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND);
189 		ext_op |= (MT_SPM_EX_OP_CLR_26M_RECORD | MT_SPM_EX_OP_SET_WDT);
190 
191 		nb_type = MT_SPM_NOTIFY_LP_ENTER;
192 	} else {
193 		if (status.is_valid & MT_SPM_RC_VALID_TRACE_TIME)
194 			ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
195 
196 		nb_type = MT_SPM_NOTIFY_IDLE_ENTER;
197 	}
198 
199 #ifdef MTK_SPM_PMIC_LP_SUPPORT
200 	if (do_spm_low_power(SPM_LP_ENTER, cmd) == PMIC_ONLV)
201 		ext_op |= MT_SPM_EX_OP_DISABLE_VCORE_LP;
202 #endif
203 
204 	MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_NOTIFY);
205 
206 	if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
207 		mt_spm_sspm_notify_u32(nb_type, cmd);
208 
209 	MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_BEFORE);
210 
211 	if (IS_PLAT_SUSPEND_ID(state_id))
212 		mt_spm_suspend_enter(state_id, ext_op,
213 				     CONSTRAINT_BUS26M_RESOURCE_REQ);
214 	else
215 		mt_spm_idle_generic_enter(state_id, ext_op, spm_bus26m_conduct);
216 
217 	MT_SPM_RC_FP(MT_SPM_RC_FP_ENTER_WAKE_SPM_AFTER);
218 	return 0;
219 }
220 
spm_reset_rc_bus26m(uint32_t cpu,int state_id)221 int spm_reset_rc_bus26m(uint32_t cpu, int state_id)
222 {
223 	struct wake_status *waken = NULL;
224 	uint32_t ext_op = MT_SPM_EX_OP_HW_S1_DETECT;
225 	uint32_t nb_type = 0;
226 
227 	MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_START);
228 
229 	if (IS_PLAT_SUSPEND_ID(state_id)) {
230 		ext_op |= MT_SPM_EX_OP_SET_WDT;
231 
232 		nb_type = MT_SPM_NOTIFY_LP_LEAVE;
233 	} else {
234 		if (status.is_valid & MT_SPM_RC_VALID_TRACE_TIME)
235 			ext_op |= MT_SPM_EX_OP_TRACE_TIMESTAMP_EN;
236 
237 		if (spm_unlikely(status.is_valid & MT_SPM_RC_VALID_TRACE_EVENT))
238 			ext_op |= MT_SPM_EX_OP_TRACE_LP;
239 
240 		nb_type = MT_SPM_NOTIFY_IDLE_LEAVE;
241 	}
242 
243 #ifdef MTK_SPM_PMIC_LP_SUPPORT
244 	do_spm_low_power(SPM_LP_RESUME, cmd);
245 #endif
246 
247 	MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_NOTIFY);
248 
249 	if (IS_MT_SPM_RC_NOTIFY_ENABLE(status.is_valid))
250 		mt_spm_sspm_notify_u32(nb_type, 0);
251 
252 	MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_RESET_SPM_BEFORE);
253 
254 	if (IS_PLAT_SUSPEND_ID(state_id)) {
255 		mt_spm_suspend_resume(state_id, ext_op, &waken);
256 		bus26m_ext_opand = 0;
257 	} else {
258 		mt_spm_idle_generic_resume(state_id, ext_op, &waken, NULL);
259 		status.enter_cnt++;
260 
261 		if (spm_unlikely(status.is_valid & MT_SPM_RC_VALID_RESIDNECY))
262 			status.residency += waken ? waken->tr.comm.timer_out :
263 						    0;
264 	}
265 
266 	MT_SPM_RC_FP(MT_SPM_RC_FP_RESUME_BACKUP_EDGE_INT);
267 	do_irqs_delivery(refer2remain_irq, waken);
268 	MT_SPM_RC_FP(MT_SPM_RC_FP_INIT);
269 	return 0;
270 }
271 
spm_get_status_rc_bus26m(uint32_t type,void * priv)272 int spm_get_status_rc_bus26m(uint32_t type, void *priv)
273 {
274 	int ret = MT_RM_STATUS_OK;
275 
276 	if (type == PLAT_RC_STATUS) {
277 		struct rc_common_state *st = (struct rc_common_state *)priv;
278 
279 		if (!st)
280 			return MT_RM_STATUS_BAD;
281 
282 		ret = spm_rc_constraint_status_get(st->id, st->type, st->act,
283 						   MT_RM_CONSTRAINT_ID_BUS26,
284 						   &status, st->value);
285 		if (!ret && (st->id != MT_RM_CONSTRAINT_ID_ALL))
286 			ret = MT_RM_STATUS_STOP;
287 	}
288 	return ret;
289 }
290