xref: /rk3399_ARM-atf/plat/mediatek/include/lib/pm/mtk_pm.h (revision 10ecd58093a34e95e2dfad65b1180610f29397cc)
1 /*
2  * Copyright (c) 2025, Mediatek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef MTK_PM_H
8 #define MTK_PM_H
9 #include <lib/psci/psci.h>
10 
11 #if MTK_PUBEVENT_ENABLE
12 #include <vendor_pubsub_events.h>
13 #endif
14 
15 #define MTK_CPUPM_E_OK				0
16 #define MTK_CPUPM_E_UNKNOWN			-1
17 #define MTK_CPUPM_E_ERR				-2
18 #define MTK_CPUPM_E_FAIL			-3
19 #define MTK_CPUPM_E_NOT_SUPPORT			-4
20 
21 #define MTK_CPUPM_FN_PWR_LOCK_AQUIRE		BIT(0)
22 #define MTK_CPUPM_FN_INIT			BIT(1)
23 #define MTK_CPUPM_FN_PWR_STATE_VALID		BIT(2)
24 #define MTK_CPUPM_FN_PWR_ON_CORE_PREPARE	BIT(3)
25 #define MTK_CPUPM_FN_SUSPEND_CORE		BIT(4)
26 #define MTK_CPUPM_FN_RESUME_CORE		BIT(5)
27 #define MTK_CPUPM_FN_SUSPEND_CLUSTER		BIT(6)
28 #define MTK_CPUPM_FN_RESUME_CLUSTER		BIT(7)
29 #define MTK_CPUPM_FN_SUSPEND_MCUSYS		BIT(8)
30 #define MTK_CPUPM_FN_RESUME_MCUSYS		BIT(9)
31 #define MTK_CPUPM_FN_CPUPM_GET_PWR_STATE	BIT(10)
32 #define MTK_CPUPM_FN_SMP_INIT			BIT(11)
33 #define MTK_CPUPM_FN_SMP_CORE_ON		BIT(12)
34 #define MTK_CPUPM_FN_SMP_CORE_OFF		BIT(13)
35 #define MTK_CPUPM_FN_PWR_DOMAIN_POWER_DOWN_WFI	BIT(14)
36 
37 enum mtk_cpupm_pstate {
38 	MTK_CPUPM_CORE_ON,
39 	MTK_CPUPM_CORE_OFF,
40 	MTK_CPUPM_CORE_SUSPEND,
41 	MTK_CPUPM_CORE_RESUME,
42 	MTK_CPUPM_CLUSTER_SUSPEND,
43 	MTK_CPUPM_CLUSTER_RESUME,
44 	MTK_CPUPM_MCUSYS_SUSPEND,
45 	MTK_CPUPM_MCUSYS_RESUME,
46 };
47 
48 enum mtk_cpu_pm_mode {
49 	MTK_CPU_PM_CPUIDLE,
50 	MTK_CPU_PM_SMP,
51 };
52 
53 #define MT_IRQ_REMAIN_MAX       32
54 #define MT_IRQ_REMAIN_CAT_LOG   BIT(31)
55 
56 struct mt_irqremain {
57 	unsigned int count;
58 	unsigned int irqs[MT_IRQ_REMAIN_MAX];
59 	unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
60 	unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
61 };
62 
63 typedef void (*plat_init_func)(unsigned int, uintptr_t);
64 struct plat_pm_smp_ctrl {
65 	plat_init_func init;
66 	int (*pwr_domain_on)(u_register_t mpidr);
67 	void (*pwr_domain_off)(const psci_power_state_t *target_state);
68 	void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
69 };
70 
71 struct plat_pm_pwr_ctrl {
72 	void (*pwr_domain_suspend)(const psci_power_state_t *target_state);
73 	void (*pwr_domain_on_finish_late)(
74 				const psci_power_state_t *target_state);
75 	void (*pwr_domain_suspend_finish)(
76 				const psci_power_state_t *target_state);
77 	int (*validate_power_state)(unsigned int power_state,
78 				    psci_power_state_t *req_state);
79 	void (*get_sys_suspend_power_state)(
80 				    psci_power_state_t *req_state);
81 	void (*pwr_domain_pwr_down_wfi)(
82 				const psci_power_state_t *req_state);
83 };
84 
85 struct plat_pm_reset_ctrl {
86 	__dead2 void (*system_off)();
87 	__dead2 void (*system_reset)();
88 	int (*system_reset2)(int is_vendor,
89 			     int reset_type,
90 			     u_register_t cookie);
91 };
92 
93 struct mtk_cpu_pm_info {
94 	unsigned int cpuid;
95 	unsigned int mode;
96 };
97 
98 struct mtk_cpu_pm_state {
99 	unsigned int afflv;
100 	unsigned int state_id;
101 	const psci_power_state_t *raw;
102 };
103 
104 struct mtk_cpupm_pwrstate {
105 	struct mtk_cpu_pm_info info;
106 	struct mtk_cpu_pm_state pwr;
107 };
108 
109 struct mtk_cpu_smp_ops {
110 	void (*init)(unsigned int cpu, uintptr_t sec_entrypoint);
111 	int (*cpu_pwr_on_prepare)(unsigned int cpu, uintptr_t entry);
112 	void (*cpu_on)(const struct mtk_cpupm_pwrstate *state);
113 	void (*cpu_off)(const struct mtk_cpupm_pwrstate *state);
114 	int (*invoke)(unsigned int funcID, void *priv);
115 };
116 
117 #define CPUPM_PWR_REQ_UID_MAGIC		0x1103BAAD
118 
119 #ifdef CPU_PM_PWR_REQ_DEBUG
120 #define DECLARE_CPUPM_PWR_REQ(var_name)\
121 	static struct cpupm_pwr_req var_name = {\
122 		.stat.name = #var_name,\
123 		.stat.uid = CPUPM_PWR_REQ_UID_MAGIC,\
124 		.stat.sta_req = 0,\
125 	}
126 #else
127 #define DECLARE_CPUPM_PWR_REQ(name)\
128 	static struct cpupm_pwr_req name = {\
129 		.stat.uid = CPUPM_PWR_REQ_UID_MAGIC,\
130 		.stat.sta_req = 0,\
131 	}
132 #endif
133 
134 #define CPUPM_PWR_REQ_ACTIVE(_cpupm_req) ({\
135 	int in_ret;\
136 	in_ret = plat_pm_invoke_func(MTK_CPU_PM_CPUIDLE,\
137 			    CPUPM_INVOKE_PWR_REQ_ACTIVE,\
138 			    &_cpupm_req);\
139 	in_ret; })
140 
141 #define CPUPM_PWR_REQ_ACQUIRE(_cpupm_req, _pm_req) ({\
142 	int in_ret;\
143 	_cpupm_req.req = _pm_req;\
144 	in_ret = plat_pm_invoke_func(MTK_CPU_PM_CPUIDLE,\
145 			    CPUPM_INVOKE_PWR_REQ_ACQUIRE,\
146 			    &_cpupm_req);\
147 	in_ret; })
148 
149 #define CPUPM_PWR_REQ_RELEASE(_cpupm_req, _pm_req) ({\
150 	int in_ret;\
151 	_cpupm_req.req = _pm_req;\
152 	in_ret = plat_pm_invoke_func(MTK_CPU_PM_CPUIDLE,\
153 			    CPUPM_INVOKE_PWR_REQ_RELASE,\
154 			    &_cpupm_req);\
155 	in_ret; })
156 
157 struct cpupm_pwr_stat_req {
158 	unsigned int sta_req;
159 	unsigned int uid;
160 #ifdef CPU_PM_PWR_REQ_DEBUG
161 	const char *name;
162 #endif
163 };
164 
165 struct cpupm_pwr_req {
166 	unsigned int req;
167 	struct cpupm_pwr_stat_req stat;
168 };
169 
170 struct cpupm_invoke_data {
171 	union {
172 		unsigned int v_u32;
173 		struct cpupm_pwr_req *req;
174 	} val;
175 };
176 
177 enum cpupm_invoke_func_id {
178 	/* Get regular active cpumask */
179 	CPUPM_INVOKE_WAKED_CPU = 0,
180 	CPUPM_INVOKE_PWR_REQ_ACTIVE,
181 	CPUPM_INVOKE_PWR_REQ_ACQUIRE,
182 	CPUPM_INVOKE_PWR_REQ_RELASE,
183 };
184 
185 #define MT_CPUPM_MCUSYS_REQ	(MT_CPUPM_PWR_DOMAIN_MCUSYS | \
186 				 MT_CPUPM_PWR_DOMAIN_MCUSYS_BY_CLUSTER)
187 #define MT_CPUPM_PWR_DOMAIN_CORE		BIT(0)
188 #define MT_CPUPM_PWR_DOMAIN_PERCORE_DSU		BIT(1)
189 #define MT_CPUPM_PWR_DOMAIN_PERCORE_DSU_MEM	BIT(2)
190 #define MT_CPUPM_PWR_DOMAIN_CLUSTER		BIT(3)
191 #define MT_CPUPM_PWR_DOMAIN_MCUSYS		BIT(4)
192 #define MT_CPUPM_PWR_DOMAIN_SUSPEND		BIT(5)
193 #define MT_CPUPM_PWR_DOMAIN_MCUSYS_BY_CLUSTER	BIT(6)
194 
195 enum mt_cpupm_pwr_domain {
196 	CPUPM_PWR_ON,
197 	CPUPM_PWR_OFF,
198 };
199 
200 #define mtk_pstate_type	unsigned int
201 
202 struct mtk_cpu_pm_ops {
203 	void (*init)(unsigned int cpu, uintptr_t sec_entrypoint);
204 
205 	unsigned int (*get_pstate)(enum mt_cpupm_pwr_domain domain,
206 				   const mtk_pstate_type psci_state,
207 				   const struct mtk_cpupm_pwrstate *state);
208 
209 	int (*pwr_state_valid)(unsigned int afflv, unsigned int state);
210 
211 	void (*cpu_suspend)(const struct mtk_cpupm_pwrstate *state);
212 	void (*cpu_resume)(const struct mtk_cpupm_pwrstate *state);
213 
214 	void (*cluster_suspend)(const struct mtk_cpupm_pwrstate *state);
215 	void (*cluster_resume)(const struct mtk_cpupm_pwrstate *state);
216 
217 	void (*mcusys_suspend)(const struct mtk_cpupm_pwrstate *state);
218 	void (*mcusys_resume)(const struct mtk_cpupm_pwrstate *state);
219 	int (*pwr_domain_pwr_down_wfi)(unsigned int cpu);
220 
221 	int (*invoke)(unsigned int funcID, void *priv);
222 };
223 
224 int register_cpu_pm_ops(unsigned int fn_flags, struct mtk_cpu_pm_ops *ops);
225 int register_cpu_smp_ops(unsigned int fn_flags, struct mtk_cpu_smp_ops *ops);
226 
227 struct mt_cpupm_event_data {
228 	unsigned int cpuid;
229 	unsigned int pwr_domain;
230 };
231 
232 /* Extension event for platform driver */
233 #if MTK_PUBEVENT_ENABLE
234 /* [PUB_EVENT] Core power on */
235 #define MT_CPUPM_SUBCRIBE_EVENT_PWR_ON(_fn) \
236 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_pwr_on, _fn)
237 
238 /* [PUB_EVENT] Core power off */
239 #define MT_CPUPM_SUBCRIBE_EVENT_PWR_OFF(_fn) \
240 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_pwr_off, _fn)
241 
242 /* [PUB_EVENT] Cluster power on */
243 #define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_ON(_fn) \
244 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_on, _fn)
245 
246 /* [PUB_EVENT] Cluster power off */
247 #define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_OFF(_fn) \
248 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_off, _fn)
249 
250 /* [PUB_EVENT] Mcusys power on */
251 #define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_ON(_fn) \
252 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_on, _fn)
253 
254 /* [PUB_EVENT] Mcusys power off */
255 #define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_OFF(_fn) \
256 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_off, _fn)
257 
258 /* [PUB_EVENT] el3 time sync */
259 #define MT_CPUPM_SUBCRIBE_EL3_UPTIME_SYNC_WITH_KERNEL(_fn) \
260 	SUBSCRIBE_TO_EVENT(el3_uptime_sync_with_kernel, _fn)
261 #else
262 #define MT_CPUPM_SUBCRIBE_EVENT_PWR_ON(_fn)
263 #define MT_CPUPM_SUBCRIBE_EVENT_PWR_OFF(_fn)
264 #define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_ON(_fn)
265 #define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_OFF(_fn)
266 #define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_ON(_fn)
267 #define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_OFF(_fn)
268 #define MT_CPUPM_SUBCRIBE_EL3_UPTIME_SYNC_WITH_KERNEL(_fn)
269 #endif
270 
271 /*
272  * Definition c-state power domain.
273  * bit 0:	Cluster
274  * bit 1:	CPU buck
275  * bit 2:	Mcusys
276  * bit 3:	Memory
277  * bit 4:	System pll
278  * bit 5:	System bus
279  * bit 6:	SoC 26m/DCXO
280  * bit 7:	Vcore buck
281  * bit 8~14:	Reserved
282  * bit 15:	Suspend
283  */
284 #define MT_PLAT_PWR_STATE_CLUSTER			0x0001
285 #define MT_PLAT_PWR_STATE_MCUSYS			0x0005
286 #define MT_PLAT_PWR_STATE_MCUSYS_BUCK			0x0007
287 #define MT_PLAT_PWR_STATE_SYSTEM_MEM			0x000F
288 #define MT_PLAT_PWR_STATE_SYSTEM_PLL			0x001F
289 #define MT_PLAT_PWR_STATE_SYSTEM_BUS			0x007F
290 #define MT_PLAT_PWR_STATE_SYSTEM_VCORE			0x00FF
291 #define MT_PLAT_PWR_STATE_SUSPEND			0x80FF
292 
293 #define IS_MT_PLAT_PWR_STATE(_state, _tar)		\
294 	(((_state) & _tar) == _tar)
295 #define IS_MT_PLAT_PWR_STATE_MCUSYS(state)		\
296 	IS_MT_PLAT_PWR_STATE(state, MT_PLAT_PWR_STATE_MCUSYS)
297 #define IS_MT_PLAT_PWR_STATE_SYSTEM(state)		((state) & 0x7ff8)
298 
299 #ifdef PLAT_AFFLV_SYSTEM
300 #define PLAT_MT_SYSTEM_SUSPEND		PLAT_AFFLV_SYSTEM
301 #else
302 #define PLAT_MT_SYSTEM_SUSPEND		PLAT_MAX_OFF_STATE
303 #endif
304 
305 #ifdef PLAT_AFFLV_CLUSTER
306 #define PLAT_MT_CPU_SUSPEND_CLUSTER	PLAT_AFFLV_CLUSTER
307 #else
308 #define PLAT_MT_CPU_SUSPEND_CLUSTER	PLAT_MAX_RET_STATE
309 #endif
310 
311 #ifdef PLAT_AFFLV_MCUSYS
312 #define PLAT_MT_CPU_SUSPEND_MCUSYS	PLAT_AFFLV_MCUSYS
313 #else
314 #define PLAT_MT_CPU_SUSPEND_MCUSYS	PLAT_MAX_RET_STATE
315 #endif
316 
317 #define IS_PLAT_SYSTEM_SUSPEND(aff)	((aff) == PLAT_MT_SYSTEM_SUSPEND)
318 #define IS_PLAT_SYSTEM_RETENTION(aff)	((aff) >= PLAT_MAX_RET_STATE)
319 
320 #define IS_PLAT_SUSPEND_ID(stateid) \
321 	((stateid) == MT_PLAT_PWR_STATE_SUSPEND)
322 
323 #define IS_PLAT_MCUSYSOFF_AFFLV(_afflv) \
324 	((_afflv) >= PLAT_MT_CPU_SUSPEND_MCUSYS)
325 
326 int plat_pm_ops_setup_pwr(struct plat_pm_pwr_ctrl *ops);
327 
328 int plat_pm_ops_setup_reset(struct plat_pm_reset_ctrl *ops);
329 
330 int plat_pm_ops_setup_smp(struct plat_pm_smp_ctrl *ops);
331 
332 uintptr_t plat_pm_get_warm_entry(void);
333 
334 int plat_pm_invoke_func(enum mtk_cpu_pm_mode mode, unsigned int id, void *priv);
335 
336 #endif
337