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