1 /*
2  * Copyright (c) 2022, 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 
22 #define MTK_CPUPM_FN_PWR_LOCK_AQUIRE		BIT(0)
23 #define MTK_CPUPM_FN_INIT			BIT(1)
24 #define MTK_CPUPM_FN_PWR_STATE_VALID		BIT(2)
25 #define MTK_CPUPM_FN_PWR_ON_CORE_PREPARE	BIT(3)
26 #define MTK_CPUPM_FN_SUSPEND_CORE		BIT(4)
27 #define MTK_CPUPM_FN_RESUME_CORE		BIT(5)
28 #define MTK_CPUPM_FN_SUSPEND_CLUSTER		BIT(6)
29 #define MTK_CPUPM_FN_RESUME_CLUSTER		BIT(7)
30 #define MTK_CPUPM_FN_SUSPEND_MCUSYS		BIT(8)
31 #define MTK_CPUPM_FN_RESUME_MCUSYS		BIT(9)
32 #define MTK_CPUPM_FN_CPUPM_GET_PWR_STATE	BIT(10)
33 #define MTK_CPUPM_FN_SMP_INIT			BIT(11)
34 #define MTK_CPUPM_FN_SMP_CORE_ON		BIT(12)
35 #define MTK_CPUPM_FN_SMP_CORE_OFF		BIT(13)
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 
65 struct plat_pm_smp_ctrl {
66 	plat_init_func init;
67 	int (*pwr_domain_on)(u_register_t mpidr);
68 	void (*pwr_domain_off)(const psci_power_state_t *target_state);
69 	void (*pwr_domain_on_finish)(const psci_power_state_t *target_state);
70 };
71 
72 struct plat_pm_pwr_ctrl {
73 	void (*pwr_domain_suspend)(const psci_power_state_t *target_state);
74 	void (*pwr_domain_on_finish_late)(const psci_power_state_t *target_state);
75 	void (*pwr_domain_suspend_finish)(const psci_power_state_t *target_state);
76 	int (*validate_power_state)(unsigned int power_state, psci_power_state_t *req_state);
77 	void (*get_sys_suspend_power_state)(psci_power_state_t *req_state);
78 };
79 
80 struct plat_pm_reset_ctrl {
81 	__dead2 void (*system_off)();
82 	__dead2 void (*system_reset)();
83 	int (*system_reset2)(int is_vendor, int reset_type, u_register_t cookie);
84 };
85 
86 struct mtk_cpu_pm_info {
87 	unsigned int cpuid;
88 	unsigned int mode;
89 };
90 
91 struct mtk_cpu_pm_state {
92 	unsigned int afflv;
93 	unsigned int state_id;
94 	const psci_power_state_t *raw;
95 };
96 
97 struct mtk_cpupm_pwrstate {
98 	struct mtk_cpu_pm_info info;
99 	struct mtk_cpu_pm_state pwr;
100 };
101 
102 struct mtk_cpu_smp_ops {
103 	void (*init)(unsigned int cpu, uintptr_t sec_entrypoint);
104 	int (*cpu_pwr_on_prepare)(unsigned int cpu, uintptr_t entry);
105 	void (*cpu_on)(const struct mtk_cpupm_pwrstate *state);
106 	void (*cpu_off)(const struct mtk_cpupm_pwrstate *state);
107 	int (*invoke)(unsigned int funcID, void *priv);
108 };
109 
110 #define MT_CPUPM_PWR_DOMAIN_CORE		BIT(0)
111 #define MT_CPUPM_PWR_DOMAIN_PERCORE_DSU		BIT(1)
112 #define MT_CPUPM_PWR_DOMAIN_PERCORE_DSU_MEM	BIT(2)
113 #define MT_CPUPM_PWR_DOMAIN_CLUSTER		BIT(3)
114 #define MT_CPUPM_PWR_DOMAIN_MCUSYS		BIT(4)
115 #define MT_CPUPM_PWR_DOMAIN_SUSPEND		BIT(5)
116 
117 enum mt_cpupm_pwr_domain {
118 	CPUPM_PWR_ON,
119 	CPUPM_PWR_OFF,
120 };
121 
122 typedef	unsigned int mtk_pstate_type;
123 
124 struct mtk_cpu_pm_ops {
125 	void (*init)(unsigned int cpu, uintptr_t sec_entrypoint);
126 	unsigned int (*get_pstate)(enum mt_cpupm_pwr_domain domain,
127 				   const mtk_pstate_type psci_state,
128 				   const struct mtk_cpupm_pwrstate *state);
129 	int (*pwr_state_valid)(unsigned int afflv, unsigned int state);
130 	void (*cpu_suspend)(const struct mtk_cpupm_pwrstate *state);
131 	void (*cpu_resume)(const struct mtk_cpupm_pwrstate *state);
132 	void (*cluster_suspend)(const struct mtk_cpupm_pwrstate *state);
133 	void (*cluster_resume)(const struct mtk_cpupm_pwrstate *state);
134 	void (*mcusys_suspend)(const struct mtk_cpupm_pwrstate *state);
135 	void (*mcusys_resume)(const struct mtk_cpupm_pwrstate *state);
136 	int (*invoke)(unsigned int funcID, void *priv);
137 };
138 
139 int register_cpu_pm_ops(unsigned int fn_flags, struct mtk_cpu_pm_ops *ops);
140 int register_cpu_smp_ops(unsigned int fn_flags, struct mtk_cpu_smp_ops *ops);
141 
142 struct mt_cpupm_event_data {
143 	unsigned int cpuid;
144 	unsigned int pwr_domain;
145 };
146 
147 /* Extension event for platform driver */
148 #if MTK_PUBEVENT_ENABLE
149 /* [PUB_EVENT] Core power on */
150 #define MT_CPUPM_SUBCRIBE_EVENT_PWR_ON(_fn) \
151 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_pwr_on, _fn)
152 
153 /* [PUB_EVENT] Core power off */
154 #define MT_CPUPM_SUBCRIBE_EVENT_PWR_OFF(_fn) \
155 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_pwr_off, _fn)
156 
157 /* [PUB_EVENT] Cluster power on */
158 #define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_ON(_fn) \
159 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_on, _fn)
160 
161 /* [PUB_EVENT] Cluster power off */
162 #define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_OFF(_fn) \
163 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_off, _fn)
164 
165 /* [PUB_EVENT] Mcusys power on */
166 #define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_ON(_fn) \
167 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_on, _fn)
168 
169 /* [PUB_EVENT] Mcusys power off */
170 #define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_OFF(_fn) \
171 	SUBSCRIBE_TO_EVENT(mt_cpupm_publish_afflv_pwr_off, _fn)
172 
173 #else
174 #define MT_CPUPM_SUBCRIBE_EVENT_PWR_ON(_fn)
175 #define MT_CPUPM_SUBCRIBE_EVENT_PWR_OFF(_fn)
176 #define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_ON(_fn)
177 #define MT_CPUPM_SUBCRIBE_CLUSTER_PWR_OFF(_fn)
178 #define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_ON(_fn)
179 #define MT_CPUPM_SUBCRIBE_MCUSYS_PWR_OFF(_fn)
180 #endif
181 
182 /*
183  * Definition c-state power domain.
184  * bit[7:4] (main state id):
185  *  - 1: Cluster.
186  *  - 2: Mcusys.
187  *  - 3: Memory.
188  *  - 4: System pll.
189  *  - 5: System bus.
190  *  - 6: SoC 26m/DCXO.
191  *  - 7: Vcore buck.
192  *  - 15: Suspend.
193  * bit[3:0] (reserved for state_id extension):
194  *  - 4: CPU buck.
195  */
196 #define MT_PLAT_PWR_STATE_CLUSTER	(0x0010)
197 #define MT_PLAT_PWR_STATE_MCUSYS	(0x0020)
198 #define MT_PLAT_PWR_STATE_MCUSYS_BUCK	(0x0024)
199 #define MT_PLAT_PWR_STATE_SYSTEM_MEM	(0x0030)
200 #define MT_PLAT_PWR_STATE_SYSTEM_PLL	(0x0040)
201 #define MT_PLAT_PWR_STATE_SYSTEM_BUS	(0x0050)
202 #define MT_PLAT_PWR_STATE_SUSPEND	(0x00f0)
203 
204 #define IS_MT_PLAT_PWR_STATE(state, target_state)	((state & target_state) == target_state)
205 #define IS_MT_PLAT_PWR_STATE_MCUSYS(state)  IS_MT_PLAT_PWR_STATE(state, MT_PLAT_PWR_STATE_MCUSYS)
206 
207 #define PLAT_MT_SYSTEM_SUSPEND		PLAT_MAX_OFF_STATE
208 #define PLAT_MT_CPU_SUSPEND_CLUSTER	PLAT_MAX_RET_STATE
209 #define PLAT_MT_CPU_SUSPEND_MCUSYS	PLAT_MAX_RET_STATE
210 
211 #define IS_PLAT_SYSTEM_SUSPEND(aff)	(aff == PLAT_MT_SYSTEM_SUSPEND)
212 #define IS_PLAT_SYSTEM_RETENTION(aff)	(aff >= PLAT_MAX_RET_STATE)
213 
214 #define IS_PLAT_SUSPEND_ID(stateid)	(stateid == MT_PLAT_PWR_STATE_SUSPEND)
215 
216 #define IS_PLAT_MCUSYSOFF_AFFLV(afflv)	(afflv >= PLAT_MT_CPU_SUSPEND_MCUSYS)
217 
218 int plat_pm_ops_setup_pwr(struct plat_pm_pwr_ctrl *ops);
219 int plat_pm_ops_setup_reset(struct plat_pm_reset_ctrl *ops);
220 int plat_pm_ops_setup_smp(struct plat_pm_smp_ctrl *ops);
221 uintptr_t plat_pm_get_warm_entry(void);
222 
223 #endif
224