blob: f543193e4083aaa2781e3745a21e4d49fd6377a7 [file] [log] [blame]
Jay Buddhabhattic6daff02022-09-05 02:56:32 -07001/*
2 * Copyright (c) 2022, Xilinx, Inc. All rights reserved.
3 * Copyright (C) 2022, 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/mmio.h>
20#include <lib/utils.h>
21#include <plat/common/platform.h>
22
23#include <plat_ipi.h>
24#include <platform_def.h>
25#include "pm_api_sys.h"
26#include "pm_client.h"
27#include <versal_net_def.h>
28
29#define UNDEFINED_CPUID (~0)
30
31DEFINE_RENAME_SYSREG_RW_FUNCS(cpu_pwrctrl_val, S3_0_C15_C2_7)
32DEFINE_BAKERY_LOCK(pm_client_secure_lock);
33
34static const struct pm_ipi apu_ipi = {
35 .local_ipi_id = IPI_ID_APU,
36 .remote_ipi_id = IPI_ID_PMC,
37 .buffer_base = IPI_BUFFER_APU_BASE,
38};
39
40/* Order in pm_procs_all array must match cpu ids */
41static const struct pm_proc pm_procs_all[] = {
42 {
43 .node_id = PM_DEV_CLUSTER0_ACPU_0,
44 .ipi = &apu_ipi,
45 .pwrdn_mask = 0,
46 },
47 {
48 .node_id = PM_DEV_CLUSTER0_ACPU_1,
49 .ipi = &apu_ipi,
50 .pwrdn_mask = 0,
51 },
52 {
53 .node_id = PM_DEV_CLUSTER0_ACPU_2,
54 .ipi = &apu_ipi,
55 .pwrdn_mask = 0,
56 },
57 {
58 .node_id = PM_DEV_CLUSTER0_ACPU_3,
59 .ipi = &apu_ipi,
60 .pwrdn_mask = 0,
61 },
62 {
63 .node_id = PM_DEV_CLUSTER1_ACPU_0,
64 .ipi = &apu_ipi,
65 .pwrdn_mask = 0,
66 },
67 {
68 .node_id = PM_DEV_CLUSTER1_ACPU_1,
69 .ipi = &apu_ipi,
70 .pwrdn_mask = 0,
71 },
72 {
73 .node_id = PM_DEV_CLUSTER1_ACPU_2,
74 .ipi = &apu_ipi,
75 .pwrdn_mask = 0,
76 },
77 {
78 .node_id = PM_DEV_CLUSTER1_ACPU_3,
79 .ipi = &apu_ipi,
80 .pwrdn_mask = 0,
81 },
82 {
83 .node_id = PM_DEV_CLUSTER2_ACPU_0,
84 .ipi = &apu_ipi,
85 .pwrdn_mask = 0,
86 },
87 {
88 .node_id = PM_DEV_CLUSTER2_ACPU_1,
89 .ipi = &apu_ipi,
90 .pwrdn_mask = 0,
91 },
92 {
93 .node_id = PM_DEV_CLUSTER2_ACPU_2,
94 .ipi = &apu_ipi,
95 .pwrdn_mask = 0,
96 },
97 {
98 .node_id = PM_DEV_CLUSTER2_ACPU_3,
99 .ipi = &apu_ipi,
100 .pwrdn_mask = 0,
101 },
102 {
103 .node_id = PM_DEV_CLUSTER3_ACPU_0,
104 .ipi = &apu_ipi,
105 .pwrdn_mask = 0,
106 },
107 {
108 .node_id = PM_DEV_CLUSTER3_ACPU_1,
109 .ipi = &apu_ipi,
110 .pwrdn_mask = 0,
111 },
112 {
113 .node_id = PM_DEV_CLUSTER3_ACPU_2,
114 .ipi = &apu_ipi,
115 .pwrdn_mask = 0,
116 },
117 {
118 .node_id = PM_DEV_CLUSTER3_ACPU_3,
119 .ipi = &apu_ipi,
120 .pwrdn_mask = 0,
121 }
122};
123
124const struct pm_proc *primary_proc = &pm_procs_all[0];
125
126/**
127 * pm_get_proc() - returns pointer to the proc structure
128 * @param cpuid id of the cpu whose proc struct pointer should be returned
129 *
130 * @return pointer to a proc structure if proc is found, otherwise NULL
131 */
132const struct pm_proc *pm_get_proc(uint32_t cpuid)
133{
134 if (cpuid < ARRAY_SIZE(pm_procs_all)) {
135 return &pm_procs_all[cpuid];
136 }
137
138 NOTICE("ERROR: cpuid: %d proc NULL\n", cpuid);
139 return NULL;
140}
141
142/**
143 * pm_client_suspend() - Client-specific suspend actions
144 *
145 * This function should contain any PU-specific actions
146 * required prior to sending suspend request to PMU
147 * Actions taken depend on the state system is suspending to.
148 *
149 * @param proc processor which need to suspend
150 * @param state desired suspend state
151 */
152void pm_client_suspend(const struct pm_proc *proc, uint32_t state)
153{
154 uint32_t cpu_id = plat_my_core_pos();
155 uintptr_t val;
156
157 bakery_lock_get(&pm_client_secure_lock);
158
159 /* TODO: Set wakeup source */
160
161 val = read_cpu_pwrctrl_val();
162 val |= CORE_PWRDN_EN_BIT_MASK;
163 write_cpu_pwrctrl_val(val);
164
165 isb();
166
Jay Buddhabhattic2358652022-12-29 21:47:54 -0800167 /* Clear power down interrupt status before enabling */
168 mmio_write_32(APU_PCIL_CORE_X_ISR_POWER_REG(cpu_id),
169 APU_PCIL_CORE_X_ISR_POWER_MASK);
170 /* Enable power down interrupt */
Jay Buddhabhattic6daff02022-09-05 02:56:32 -0700171 mmio_write_32(APU_PCIL_CORE_X_IEN_POWER_REG(cpu_id),
172 APU_PCIL_CORE_X_IEN_POWER_MASK);
Jay Buddhabhatti69e474e2022-12-29 21:54:44 -0800173 /* Clear wakeup interrupt status before enabling */
174 mmio_write_32(APU_PCIL_CORE_X_ISR_WAKE_REG(cpu_id),
175 APU_PCIL_CORE_X_ISR_WAKE_MASK);
176 /* Enable wake interrupt */
177 mmio_write_32(APU_PCIL_CORE_X_IEN_WAKE_REG(cpu_id),
178 APU_PCIL_CORE_X_IEN_WAKE_MASK);
Jay Buddhabhattic6daff02022-09-05 02:56:32 -0700179
180 bakery_lock_release(&pm_client_secure_lock);
181}
182
183/**
184 * pm_get_cpuid() - get the local cpu ID for a global node ID
185 * @param nid node id of the processor
186 *
187 * @return the cpu ID (starting from 0) for the subsystem
188 */
189static uint32_t pm_get_cpuid(uint32_t nid)
190{
191 for (size_t i = 0; i < ARRAY_SIZE(pm_procs_all); i++) {
192 if (pm_procs_all[i].node_id == nid) {
193 return i;
194 }
195 }
196 return UNDEFINED_CPUID;
197}
198
199/**
200 * pm_client_wakeup() - Client-specific wakeup actions
201 *
202 * This function should contain any PU-specific actions
203 * required for waking up another APU core
204 *
205 * @param proc Processor which need to wakeup
206 */
207void pm_client_wakeup(const struct pm_proc *proc)
208{
209 uint32_t cpuid = pm_get_cpuid(proc->node_id);
Jay Buddhabhatti07d85c92022-12-29 22:15:19 -0800210 uintptr_t val;
Jay Buddhabhattic6daff02022-09-05 02:56:32 -0700211
212 if (cpuid == UNDEFINED_CPUID) {
213 return;
214 }
215
216 bakery_lock_get(&pm_client_secure_lock);
217
Jay Buddhabhatti07d85c92022-12-29 22:15:19 -0800218 /* Clear powerdown request */
219 val = read_cpu_pwrctrl_val();
220 val &= ~CORE_PWRDN_EN_BIT_MASK;
221 write_cpu_pwrctrl_val(val);
222
223 isb();
224
225 /* Disabled power down interrupt */
226 mmio_write_32(APU_PCIL_CORE_X_IDS_POWER_REG(cpuid),
227 APU_PCIL_CORE_X_IDS_POWER_MASK);
Jay Buddhabhattiedfadb72022-12-29 22:21:00 -0800228 /* Clear wakeup interrupt status before disabling */
229 mmio_write_32(APU_PCIL_CORE_X_ISR_WAKE_REG(cpuid),
230 APU_PCIL_CORE_X_ISR_WAKE_MASK);
231 /* Disable wake interrupt */
232 mmio_write_32(APU_PCIL_CORE_X_IDS_WAKE_REG(cpuid),
233 APU_PCIL_CORE_X_IDS_WAKE_MASK);
Jay Buddhabhattic6daff02022-09-05 02:56:32 -0700234
235 bakery_lock_release(&pm_client_secure_lock);
236}
237
238/**
239 * pm_client_abort_suspend() - Client-specific abort-suspend actions
240 *
241 * This function should contain any PU-specific actions
242 * required for aborting a prior suspend request
243 */
244void pm_client_abort_suspend(void)
245{
246 uint32_t cpu_id = plat_my_core_pos();
247 uintptr_t val;
248
249 /* Enable interrupts at processor level (for current cpu) */
250 gicv3_cpuif_enable(plat_my_core_pos());
251
252 bakery_lock_get(&pm_client_secure_lock);
253
254 /* Clear powerdown request */
255 val = read_cpu_pwrctrl_val();
256 val &= ~CORE_PWRDN_EN_BIT_MASK;
257 write_cpu_pwrctrl_val(val);
258
259 isb();
260
261 /* Disabled power down interrupt */
262 mmio_write_32(APU_PCIL_CORE_X_IDS_POWER_REG(cpu_id),
263 APU_PCIL_CORE_X_IDS_POWER_MASK);
264
265 bakery_lock_release(&pm_client_secure_lock);
266}