1 /*
2 * Copyright (c) 2019-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_common.h>
16 #include <drivers/arm/gicv3.h>
17 #include <lib/bakery_lock.h>
18 #include <lib/mmio.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 "pm_defs.h"
27 #include <versal_def.h>
28
29 #define UNDEFINED_CPUID (~0U)
30
31 static DEFINE_BAKERY_LOCK(pm_client_secure_lock);
32
33 static const struct pm_ipi apu_ipi = {
34 .local_ipi_id = IPI_LOCAL_ID,
35 .remote_ipi_id = IPI_REMOTE_ID,
36 .buffer_base = IPI_BUFFER_LOCAL_BASE,
37 };
38
39 /* Order in pm_procs_all array must match cpu ids */
40 static const struct pm_proc pm_procs_all[] = {
41 {
42 .node_id = XPM_DEVID_ACPU_0,
43 .ipi = &apu_ipi,
44 .pwrdn_mask = APU_0_PWRCTL_CPUPWRDWNREQ_MASK,
45 },
46 {
47 .node_id = XPM_DEVID_ACPU_1,
48 .ipi = &apu_ipi,
49 .pwrdn_mask = APU_1_PWRCTL_CPUPWRDWNREQ_MASK,
50 }
51 };
52
53 const struct pm_proc *primary_proc = &pm_procs_all[0];
54
55 /**
56 * irq_to_pm_node_idx - Get PM node index corresponding to the interrupt number.
57 * @irq: Interrupt number
58 *
59 * Return: PM node index corresponding to the specified interrupt.
60 *
61 */
irq_to_pm_node_idx(uint32_t irq)62 enum pm_device_node_idx irq_to_pm_node_idx(uint32_t irq)
63 {
64 enum pm_device_node_idx dev_idx = XPM_NODEIDX_DEV_MIN;
65
66 assert(irq <= IRQ_MAX);
67
68 switch (irq) {
69 case 13:
70 dev_idx = XPM_NODEIDX_DEV_GPIO;
71 break;
72 case 14:
73 dev_idx = XPM_NODEIDX_DEV_I2C_0;
74 break;
75 case 15:
76 dev_idx = XPM_NODEIDX_DEV_I2C_1;
77 break;
78 case 16:
79 dev_idx = XPM_NODEIDX_DEV_SPI_0;
80 break;
81 case 17:
82 dev_idx = XPM_NODEIDX_DEV_SPI_1;
83 break;
84 case 18:
85 dev_idx = XPM_NODEIDX_DEV_UART_0;
86 break;
87 case 19:
88 dev_idx = XPM_NODEIDX_DEV_UART_1;
89 break;
90 case 20:
91 dev_idx = XPM_NODEIDX_DEV_CAN_FD_0;
92 break;
93 case 21:
94 dev_idx = XPM_NODEIDX_DEV_CAN_FD_1;
95 break;
96 case 22:
97 case 23:
98 case 24:
99 case 25:
100 case 26:
101 dev_idx = XPM_NODEIDX_DEV_USB_0;
102 break;
103 case 37:
104 case 38:
105 case 39:
106 dev_idx = XPM_NODEIDX_DEV_TTC_0;
107 break;
108 case 40:
109 case 41:
110 case 42:
111 dev_idx = XPM_NODEIDX_DEV_TTC_1;
112 break;
113 case 43:
114 case 44:
115 case 45:
116 dev_idx = XPM_NODEIDX_DEV_TTC_2;
117 break;
118 case 46:
119 case 47:
120 case 48:
121 dev_idx = XPM_NODEIDX_DEV_TTC_3;
122 break;
123 case 56:
124 case 57:
125 dev_idx = XPM_NODEIDX_DEV_GEM_0;
126 break;
127 case 58:
128 case 59:
129 dev_idx = XPM_NODEIDX_DEV_GEM_1;
130 break;
131 case 60:
132 dev_idx = XPM_NODEIDX_DEV_ADMA_0;
133 break;
134 case 61:
135 dev_idx = XPM_NODEIDX_DEV_ADMA_1;
136 break;
137 case 62:
138 dev_idx = XPM_NODEIDX_DEV_ADMA_2;
139 break;
140 case 63:
141 dev_idx = XPM_NODEIDX_DEV_ADMA_3;
142 break;
143 case 64:
144 dev_idx = XPM_NODEIDX_DEV_ADMA_4;
145 break;
146 case 65:
147 dev_idx = XPM_NODEIDX_DEV_ADMA_5;
148 break;
149 case 66:
150 dev_idx = XPM_NODEIDX_DEV_ADMA_6;
151 break;
152 case 67:
153 dev_idx = XPM_NODEIDX_DEV_ADMA_7;
154 break;
155 case 74:
156 dev_idx = XPM_NODEIDX_DEV_USB_0;
157 break;
158 case 122:
159 dev_idx = XPM_NODEIDX_DEV_GPIO_PMC;
160 break;
161 case 126:
162 case 127:
163 dev_idx = XPM_NODEIDX_DEV_SDIO_0;
164 break;
165 case 128:
166 case 129:
167 dev_idx = XPM_NODEIDX_DEV_SDIO_1;
168 break;
169 case 142:
170 dev_idx = XPM_NODEIDX_DEV_RTC;
171 break;
172 default:
173 dev_idx = XPM_NODEIDX_DEV_MIN;
174 break;
175 }
176
177 return dev_idx;
178 }
179
180 /**
181 * pm_client_suspend() - Client-specific suspend actions.
182 * @proc: processor which need to suspend.
183 * @state: desired suspend state.
184 * @flag: 0 - Call from secure source.
185 * 1 - Call from non-secure source.
186 *
187 * This function should contain any PU-specific actions
188 * required prior to sending suspend request to PMU
189 * Actions taken depend on the state system is suspending to.
190 *
191 */
pm_client_suspend(const struct pm_proc * proc,uint32_t state,uint32_t flag)192 void pm_client_suspend(const struct pm_proc *proc, uint32_t state, uint32_t flag)
193 {
194 bakery_lock_get(&pm_client_secure_lock);
195
196 if (state == PM_STATE_SUSPEND_TO_RAM) {
197 pm_client_set_wakeup_sources((uint32_t)proc->node_id, flag);
198 }
199
200 /* Set powerdown request */
201 mmio_write_32(FPD_APU_PWRCTL, mmio_read_32(FPD_APU_PWRCTL) |
202 (uint32_t)proc->pwrdn_mask);
203
204 bakery_lock_release(&pm_client_secure_lock);
205 }
206
207 /**
208 * pm_get_cpuid() - get the local cpu ID for a global node ID.
209 * @nid: node id of the processor.
210 *
211 * Return: the cpu ID (starting from 0) for the subsystem.
212 *
213 */
pm_get_cpuid(uint32_t nid)214 static uint32_t pm_get_cpuid(uint32_t nid)
215 {
216 uint32_t ret = UNDEFINED_CPUID;
217 uint32_t i;
218
219 for (i = 0U; i < ARRAY_SIZE(pm_procs_all); i++) {
220 if (pm_procs_all[i].node_id == nid) {
221 ret = i;
222 break;
223 }
224 }
225 return ret;
226 }
227
228 /**
229 * pm_client_wakeup() - Client-specific wakeup actions.
230 * @proc: Processor which need to wakeup.
231 *
232 * This function should contain any PU-specific actions
233 * required for waking up another APU core.
234 *
235 */
pm_client_wakeup(const struct pm_proc * proc)236 void pm_client_wakeup(const struct pm_proc *proc)
237 {
238 uint32_t cpuid = pm_get_cpuid(proc->node_id);
239
240 if (cpuid == UNDEFINED_CPUID) {
241 return;
242 }
243
244 bakery_lock_get(&pm_client_secure_lock);
245
246 /* clear powerdown bit for affected cpu */
247 uint32_t val = mmio_read_32(FPD_APU_PWRCTL);
248 val &= ~(proc->pwrdn_mask);
249 mmio_write_32(FPD_APU_PWRCTL, val);
250
251 bakery_lock_release(&pm_client_secure_lock);
252 }
253
254 /**
255 * pm_get_proc() - returns pointer to the proc structure.
256 * @cpuid: id of the cpu whose proc struct pointer should be returned.
257 *
258 * Return: pointer to a proc structure if proc is found, otherwise NULL.
259 *
260 */
pm_get_proc(uint32_t cpuid)261 const struct pm_proc *pm_get_proc(uint32_t cpuid)
262 {
263 if (cpuid < ARRAY_SIZE(pm_procs_all)) {
264 return &pm_procs_all[cpuid];
265 }
266
267 return NULL;
268 }
269