xref: /rk3399_ARM-atf/plat/xilinx/versal_net/pm_service/pm_client.c (revision 047b1b9afce13993db8363f55be6e0cbfb69bf0d)
1 /*
2  * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
3  * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 /*
9  * APU specific definition of processors in the subsystem as well as functions
10  * for getting information about and changing state of the APU.
11  */
12 
13 #include <assert.h>
14 
15 #include <drivers/arm/gic.h>
16 #include <lib/bakery_lock.h>
17 #include <lib/mmio.h>
18 #include <lib/spinlock.h>
19 #include <lib/utils.h>
20 #include <plat/common/platform.h>
21 
22 #include <plat_ipi.h>
23 #include <platform_def.h>
24 #include "pm_api_sys.h"
25 #include "pm_client.h"
26 #include <versal_net_def.h>
27 
28 #define UNDEFINED_CPUID		(~0U)
29 
DEFINE_RENAME_SYSREG_RW_FUNCS(cpu_pwrctrl_val,S3_0_C15_C2_7)30 DEFINE_RENAME_SYSREG_RW_FUNCS(cpu_pwrctrl_val, S3_0_C15_C2_7)
31 
32 spinlock_t pm_client_secure_lock;
33 static inline void pm_client_lock_get(void)
34 {
35 	spin_lock(&pm_client_secure_lock);
36 }
37 
pm_client_lock_release(void)38 static inline void pm_client_lock_release(void)
39 {
40 	spin_unlock(&pm_client_secure_lock);
41 }
42 
43 static const struct pm_ipi apu_ipi = {
44 	.local_ipi_id = IPI_LOCAL_ID,
45 	.remote_ipi_id = IPI_REMOTE_ID,
46 	.buffer_base = IPI_BUFFER_LOCAL_BASE,
47 };
48 
49 /* Order in pm_procs_all array must match cpu ids */
50 static const struct pm_proc pm_procs_all[] = {
51 	{
52 		.node_id = PM_DEV_CLUSTER0_ACPU_0,
53 		.ipi = &apu_ipi,
54 		.pwrdn_mask = 0,
55 	},
56 	{
57 		.node_id = PM_DEV_CLUSTER0_ACPU_1,
58 		.ipi = &apu_ipi,
59 		.pwrdn_mask = 0,
60 	},
61 	{
62 		.node_id = PM_DEV_CLUSTER0_ACPU_2,
63 		.ipi = &apu_ipi,
64 		.pwrdn_mask = 0,
65 	},
66 	{
67 		.node_id = PM_DEV_CLUSTER0_ACPU_3,
68 		.ipi = &apu_ipi,
69 		.pwrdn_mask = 0,
70 	},
71 	{
72 		.node_id = PM_DEV_CLUSTER1_ACPU_0,
73 		.ipi = &apu_ipi,
74 		.pwrdn_mask = 0,
75 	},
76 	{
77 		.node_id = PM_DEV_CLUSTER1_ACPU_1,
78 		.ipi = &apu_ipi,
79 		.pwrdn_mask = 0,
80 	},
81 	{
82 		.node_id = PM_DEV_CLUSTER1_ACPU_2,
83 		.ipi = &apu_ipi,
84 		.pwrdn_mask = 0,
85 	},
86 	{
87 		.node_id = PM_DEV_CLUSTER1_ACPU_3,
88 		.ipi = &apu_ipi,
89 		.pwrdn_mask = 0,
90 	},
91 	{
92 		.node_id = PM_DEV_CLUSTER2_ACPU_0,
93 		.ipi = &apu_ipi,
94 		.pwrdn_mask = 0,
95 	},
96 	{
97 		.node_id = PM_DEV_CLUSTER2_ACPU_1,
98 		.ipi = &apu_ipi,
99 		.pwrdn_mask = 0,
100 	},
101 	{
102 		.node_id = PM_DEV_CLUSTER2_ACPU_2,
103 		.ipi = &apu_ipi,
104 		.pwrdn_mask = 0,
105 	},
106 	{
107 		.node_id = PM_DEV_CLUSTER2_ACPU_3,
108 		.ipi = &apu_ipi,
109 		.pwrdn_mask = 0,
110 	},
111 	{
112 		.node_id = PM_DEV_CLUSTER3_ACPU_0,
113 		.ipi = &apu_ipi,
114 		.pwrdn_mask = 0,
115 	},
116 	{
117 		.node_id = PM_DEV_CLUSTER3_ACPU_1,
118 		.ipi = &apu_ipi,
119 		.pwrdn_mask = 0,
120 	},
121 	{
122 		.node_id = PM_DEV_CLUSTER3_ACPU_2,
123 		.ipi = &apu_ipi,
124 		.pwrdn_mask = 0,
125 	},
126 	{
127 		.node_id = PM_DEV_CLUSTER3_ACPU_3,
128 		.ipi = &apu_ipi,
129 		.pwrdn_mask = 0,
130 	}
131 };
132 
133 const struct pm_proc *primary_proc = &pm_procs_all[0];
134 
135 /**
136  * pm_get_proc() - returns pointer to the proc structure.
137  * @cpuid: id of the cpu whose proc struct pointer should be returned.
138  *
139  * Return: Pointer to a proc structure if proc is found, otherwise NULL.
140  *
141  */
pm_get_proc(uint32_t cpuid)142 const struct pm_proc *pm_get_proc(uint32_t cpuid)
143 {
144 	if (cpuid < ARRAY_SIZE(pm_procs_all)) {
145 		return &pm_procs_all[cpuid];
146 	}
147 
148 	NOTICE("ERROR: cpuid: %d proc NULL\n", cpuid);
149 	return NULL;
150 }
151 
152 /**
153  * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number.
154  * @irq: Interrupt number.
155  *
156  * Return: PM node index corresponding to the specified interrupt.
157  *
158  */
irq_to_pm_node_idx(uint32_t irq)159 enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
160 {
161 	enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN;
162 
163 	assert(irq <= IRQ_MAX);
164 
165 	switch (irq) {
166 	case 20:
167 		dev_idx = XPM_NODEIDX_DEV_GPIO;
168 		break;
169 	case 21:
170 		dev_idx = XPM_NODEIDX_DEV_I2C_0;
171 		break;
172 	case 22:
173 		dev_idx = XPM_NODEIDX_DEV_I2C_1;
174 		break;
175 	case 23:
176 		dev_idx = XPM_NODEIDX_DEV_SPI_0;
177 		break;
178 	case 24:
179 		dev_idx = XPM_NODEIDX_DEV_SPI_1;
180 		break;
181 	case 25:
182 		dev_idx = XPM_NODEIDX_DEV_UART_0;
183 		break;
184 	case 26:
185 		dev_idx = XPM_NODEIDX_DEV_UART_1;
186 		break;
187 	case 27:
188 		dev_idx = XPM_NODEIDX_DEV_CAN_FD_0;
189 		break;
190 	case 28:
191 		dev_idx = XPM_NODEIDX_DEV_CAN_FD_1;
192 		break;
193 	case 29:
194 	case 30:
195 	case 31:
196 	case 32:
197 	case 33:
198 	case 98:
199 		dev_idx = XPM_NODEIDX_DEV_USB_0;
200 		break;
201 	case 34:
202 	case 35:
203 	case 36:
204 	case 37:
205 	case 38:
206 	case 99:
207 		dev_idx = XPM_NODEIDX_DEV_USB_1;
208 		break;
209 	case 39:
210 	case 40:
211 		dev_idx = XPM_NODEIDX_DEV_GEM_0;
212 		break;
213 	case 41:
214 	case 42:
215 		dev_idx = XPM_NODEIDX_DEV_GEM_1;
216 		break;
217 	case 43:
218 	case 44:
219 	case 45:
220 		dev_idx = XPM_NODEIDX_DEV_TTC_0;
221 		break;
222 	case 46:
223 	case 47:
224 	case 48:
225 		dev_idx = XPM_NODEIDX_DEV_TTC_1;
226 		break;
227 	case 49:
228 	case 50:
229 	case 51:
230 		dev_idx = XPM_NODEIDX_DEV_TTC_2;
231 		break;
232 	case 52:
233 	case 53:
234 	case 54:
235 		dev_idx = XPM_NODEIDX_DEV_TTC_3;
236 		break;
237 	case 72:
238 		dev_idx = XPM_NODEIDX_DEV_ADMA_0;
239 		break;
240 	case 73:
241 		dev_idx = XPM_NODEIDX_DEV_ADMA_1;
242 		break;
243 	case 74:
244 		dev_idx = XPM_NODEIDX_DEV_ADMA_2;
245 		break;
246 	case 75:
247 		dev_idx = XPM_NODEIDX_DEV_ADMA_3;
248 		break;
249 	case 76:
250 		dev_idx = XPM_NODEIDX_DEV_ADMA_4;
251 		break;
252 	case 77:
253 		dev_idx = XPM_NODEIDX_DEV_ADMA_5;
254 		break;
255 	case 78:
256 		dev_idx = XPM_NODEIDX_DEV_ADMA_6;
257 		break;
258 	case 79:
259 		dev_idx = XPM_NODEIDX_DEV_ADMA_7;
260 		break;
261 	case 184:
262 	case 185:
263 		dev_idx = XPM_NODEIDX_DEV_SDIO_0;
264 		break;
265 	case 186:
266 	case 187:
267 		dev_idx = XPM_NODEIDX_DEV_SDIO_1;
268 		break;
269 	case 200:
270 		dev_idx = XPM_NODEIDX_DEV_RTC;
271 		break;
272 	default:
273 		dev_idx = XPM_NODEIDX_DEV_MIN;
274 		break;
275 	}
276 
277 	return dev_idx;
278 }
279 
280 /**
281  * pm_client_suspend() - Client-specific suspend actions. This function
282  *                       should contain any PU-specific actions required
283  *                       prior to sending suspend request to PMU. Actions
284  *                       taken depend on the state system is suspending to.
285  * @proc: processor which need to suspend.
286  * @state: desired suspend state.
287  * @flag: 0 - Call from secure source.
288  *	  1 - Call from non-secure source.
289  *
290  */
pm_client_suspend(const struct pm_proc * proc,uint32_t state,uint32_t flag)291 void pm_client_suspend(const struct pm_proc *proc, uint32_t state, uint32_t flag)
292 {
293 	uint32_t cpu_id = plat_my_core_pos();
294 	uintptr_t val;
295 
296 	pm_client_lock_get();
297 
298 	if (state == PM_STATE_SUSPEND_TO_RAM) {
299 		pm_client_set_wakeup_sources((uint32_t)proc->node_id, flag);
300 	}
301 
302 	val = read_cpu_pwrctrl_val();
303 	val |= CORE_PWRDN_EN_BIT_MASK;
304 	write_cpu_pwrctrl_val(val);
305 
306 	isb();
307 
308 	/* Enable power down interrupt */
309 	mmio_write_32(APU_PCIL_CORE_X_IEN_POWER_REG(cpu_id),
310 		      APU_PCIL_CORE_X_IEN_POWER_MASK);
311 	/* Enable wake interrupt */
312 	mmio_write_32(APU_PCIL_CORE_X_IEN_WAKE_REG(cpu_id),
313 		      APU_PCIL_CORE_X_IEN_WAKE_MASK);
314 
315 	pm_client_lock_release();
316 }
317 
318 /**
319  * pm_get_cpuid() - get the local cpu ID for a global node ID.
320  * @nid: node id of the processor.
321  *
322  * Return: the cpu ID (starting from 0) for the subsystem.
323  *
324  */
pm_get_cpuid(uint32_t nid)325 static uint32_t pm_get_cpuid(uint32_t nid)
326 {
327 	uint32_t ret = UNDEFINED_CPUID;
328 	uint32_t i;
329 
330 	for (i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
331 		if (pm_procs_all[i].node_id == nid) {
332 			ret = i;
333 			break;
334 		}
335 	}
336 	return ret;
337 }
338 
339 /**
340  * pm_client_wakeup() - Client-specific wakeup actions.
341  * @proc: Processor which need to wakeup.
342  *
343  * This function should contain any PU-specific actions
344  * required for waking up another APU core.
345  *
346  */
pm_client_wakeup(const struct pm_proc * proc)347 void pm_client_wakeup(const struct pm_proc *proc)
348 {
349 	uint32_t cpuid = pm_get_cpuid(proc->node_id);
350 	uintptr_t val;
351 
352 	if (cpuid == UNDEFINED_CPUID) {
353 		return;
354 	}
355 
356 	pm_client_lock_get();
357 
358 	/* Clear powerdown request */
359 	val = read_cpu_pwrctrl_val();
360 	val &= ~CORE_PWRDN_EN_BIT_MASK;
361 	write_cpu_pwrctrl_val(val);
362 
363 	isb();
364 
365 	/* Disabled power down interrupt */
366 	mmio_write_32(APU_PCIL_CORE_X_IDS_POWER_REG(cpuid),
367 			APU_PCIL_CORE_X_IDS_POWER_MASK);
368 	/* Disable wake interrupt */
369 	mmio_write_32(APU_PCIL_CORE_X_IDS_WAKE_REG(cpuid),
370 		      APU_PCIL_CORE_X_IDS_WAKE_MASK);
371 
372 	pm_client_lock_release();
373 }
374