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