blob: 05293e95d993f2a71e908d64161fce1c10abe669 [file] [log] [blame]
developer90e10802024-12-28 21:25:21 +08001/*
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
37enum 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
48enum 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
56struct 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
63typedef void (*plat_init_func)(unsigned int, uintptr_t);
64struct 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
71struct 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);
Boyan Karatotevff8a6152024-10-21 07:36:31 +010081 void (*pwr_domain_pwr_down_wfi)(
developer90e10802024-12-28 21:25:21 +080082 const psci_power_state_t *req_state);
83};
84
85struct 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
93struct mtk_cpu_pm_info {
94 unsigned int cpuid;
95 unsigned int mode;
96};
97
98struct mtk_cpu_pm_state {
99 unsigned int afflv;
100 unsigned int state_id;
101 const psci_power_state_t *raw;
102};
103
104struct mtk_cpupm_pwrstate {
105 struct mtk_cpu_pm_info info;
106 struct mtk_cpu_pm_state pwr;
107};
108
109struct 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
157struct 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
165struct cpupm_pwr_req {
166 unsigned int req;
167 struct cpupm_pwr_stat_req stat;
168};
169
170struct cpupm_invoke_data {
171 union {
172 unsigned int v_u32;
173 struct cpupm_pwr_req *req;
174 } val;
175};
176
177enum 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
195enum mt_cpupm_pwr_domain {
196 CPUPM_PWR_ON,
197 CPUPM_PWR_OFF,
198};
199
200#define mtk_pstate_type unsigned int
201
202struct 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
224int register_cpu_pm_ops(unsigned int fn_flags, struct mtk_cpu_pm_ops *ops);
225int register_cpu_smp_ops(unsigned int fn_flags, struct mtk_cpu_smp_ops *ops);
226
227struct 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
326int plat_pm_ops_setup_pwr(struct plat_pm_pwr_ctrl *ops);
327
328int plat_pm_ops_setup_reset(struct plat_pm_reset_ctrl *ops);
329
330int plat_pm_ops_setup_smp(struct plat_pm_smp_ctrl *ops);
331
332uintptr_t plat_pm_get_warm_entry(void);
333
334int plat_pm_invoke_func(enum mtk_cpu_pm_mode mode, unsigned int id, void *priv);
335
336#endif