xref: /arm-trusted-firmware/plat/xilinx/common/pm_service/pm_api_sys.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved.
3*91f16700Schasinglulu  * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved.
4*91f16700Schasinglulu  *
5*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
6*91f16700Schasinglulu  */
7*91f16700Schasinglulu 
8*91f16700Schasinglulu /*
9*91f16700Schasinglulu  * Versal system level PM-API functions and communication with PMC via
10*91f16700Schasinglulu  * IPI interrupts
11*91f16700Schasinglulu  */
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #include <drivers/arm/gic_common.h>
14*91f16700Schasinglulu #include <lib/mmio.h>
15*91f16700Schasinglulu #include <lib/utils.h>
16*91f16700Schasinglulu #include <plat/common/platform.h>
17*91f16700Schasinglulu #include <platform_def.h>
18*91f16700Schasinglulu #include <pm_api_sys.h>
19*91f16700Schasinglulu #include <pm_client.h>
20*91f16700Schasinglulu #include <pm_common.h>
21*91f16700Schasinglulu #include <pm_defs.h>
22*91f16700Schasinglulu #include <pm_ipi.h>
23*91f16700Schasinglulu #include "pm_svc_main.h"
24*91f16700Schasinglulu 
25*91f16700Schasinglulu #define NUM_GICD_ISENABLER	((IRQ_MAX >> 5U) + 1U)
26*91f16700Schasinglulu 
27*91f16700Schasinglulu /* default shutdown/reboot scope is system(2) */
28*91f16700Schasinglulu static uint32_t pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
29*91f16700Schasinglulu 
30*91f16700Schasinglulu /**
31*91f16700Schasinglulu  * pm_get_shutdown_scope() - Get the currently set shutdown scope.
32*91f16700Schasinglulu  *
33*91f16700Schasinglulu  * Return: Shutdown scope value.
34*91f16700Schasinglulu  *
35*91f16700Schasinglulu  */
36*91f16700Schasinglulu uint32_t pm_get_shutdown_scope(void)
37*91f16700Schasinglulu {
38*91f16700Schasinglulu 	return pm_shutdown_scope;
39*91f16700Schasinglulu }
40*91f16700Schasinglulu 
41*91f16700Schasinglulu /* PM API functions */
42*91f16700Schasinglulu 
43*91f16700Schasinglulu /**
44*91f16700Schasinglulu  * pm_client_set_wakeup_sources - Set all devices with enabled interrupts as
45*91f16700Schasinglulu  *                                wake sources in the XilPM.
46*91f16700Schasinglulu  * @node_id: Node id of processor.
47*91f16700Schasinglulu  *
48*91f16700Schasinglulu  */
49*91f16700Schasinglulu void pm_client_set_wakeup_sources(uint32_t node_id)
50*91f16700Schasinglulu {
51*91f16700Schasinglulu 	uint32_t reg_num, device_id;
52*91f16700Schasinglulu 	uint8_t pm_wakeup_nodes_set[XPM_NODEIDX_DEV_MAX] = {0U};
53*91f16700Schasinglulu 	uint32_t isenabler1 = PLAT_GICD_BASE_VALUE + GICD_ISENABLER + 4U;
54*91f16700Schasinglulu 
55*91f16700Schasinglulu 	zeromem(&pm_wakeup_nodes_set, (u_register_t)sizeof(pm_wakeup_nodes_set));
56*91f16700Schasinglulu 
57*91f16700Schasinglulu 	for (reg_num = 0U; reg_num < NUM_GICD_ISENABLER; reg_num++) {
58*91f16700Schasinglulu 		uint32_t base_irq = reg_num << ISENABLER_SHIFT;
59*91f16700Schasinglulu 		uint32_t reg = mmio_read_32(isenabler1 + (reg_num << 2));
60*91f16700Schasinglulu 
61*91f16700Schasinglulu 		if (reg == 0U) {
62*91f16700Schasinglulu 			continue;
63*91f16700Schasinglulu 		}
64*91f16700Schasinglulu 
65*91f16700Schasinglulu 		while (reg != 0U) {
66*91f16700Schasinglulu 			enum pm_device_node_idx node_idx;
67*91f16700Schasinglulu 			uint32_t idx, irq, lowest_set = reg & (-reg);
68*91f16700Schasinglulu 			enum pm_ret_status ret;
69*91f16700Schasinglulu 
70*91f16700Schasinglulu 			idx = (uint32_t)__builtin_ctz(lowest_set);
71*91f16700Schasinglulu 			irq = base_irq + idx;
72*91f16700Schasinglulu 
73*91f16700Schasinglulu 			if (irq > IRQ_MAX) {
74*91f16700Schasinglulu 				break;
75*91f16700Schasinglulu 			}
76*91f16700Schasinglulu 
77*91f16700Schasinglulu 			node_idx = irq_to_pm_node_idx(irq);
78*91f16700Schasinglulu 			reg &= ~lowest_set;
79*91f16700Schasinglulu 
80*91f16700Schasinglulu 			if (node_idx > XPM_NODEIDX_DEV_MIN) {
81*91f16700Schasinglulu 				if (pm_wakeup_nodes_set[node_idx] == 0U) {
82*91f16700Schasinglulu 					/* Get device ID from node index */
83*91f16700Schasinglulu 					device_id = PERIPH_DEVID((uint32_t)node_idx);
84*91f16700Schasinglulu 					ret = pm_set_wakeup_source(node_id,
85*91f16700Schasinglulu 								   device_id, 1U,
86*91f16700Schasinglulu 								   SECURE_FLAG);
87*91f16700Schasinglulu 					pm_wakeup_nodes_set[node_idx] = (ret == PM_RET_SUCCESS) ?
88*91f16700Schasinglulu 										 1U : 0U;
89*91f16700Schasinglulu 				}
90*91f16700Schasinglulu 			}
91*91f16700Schasinglulu 		}
92*91f16700Schasinglulu 	}
93*91f16700Schasinglulu }
94*91f16700Schasinglulu 
95*91f16700Schasinglulu /**
96*91f16700Schasinglulu  * pm_handle_eemi_call() - PM call for processor to send eemi payload.
97*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
98*91f16700Schasinglulu  *        1 - Call from non-secure source.
99*91f16700Schasinglulu  * @x0: Arguments received per SMC64 standard.
100*91f16700Schasinglulu  * @x1: Arguments received per SMC64 standard.
101*91f16700Schasinglulu  * @x2: Arguments received per SMC64 standard.
102*91f16700Schasinglulu  * @x3: Arguments received per SMC64 standard.
103*91f16700Schasinglulu  * @x4: Arguments received per SMC64 standard.
104*91f16700Schasinglulu  * @x5: Arguments received per SMC64 standard.
105*91f16700Schasinglulu  * @result: Payload received from firmware.
106*91f16700Schasinglulu  *
107*91f16700Schasinglulu  * Return: PM_RET_SUCCESS on success or error code.
108*91f16700Schasinglulu  *
109*91f16700Schasinglulu  */
110*91f16700Schasinglulu enum pm_ret_status pm_handle_eemi_call(uint32_t flag, uint32_t x0, uint32_t x1,
111*91f16700Schasinglulu 				       uint32_t x2, uint32_t x3, uint32_t x4,
112*91f16700Schasinglulu 				       uint32_t x5, uint64_t *result)
113*91f16700Schasinglulu {
114*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT] = {0};
115*91f16700Schasinglulu 	uint32_t module_id;
116*91f16700Schasinglulu 
117*91f16700Schasinglulu 	module_id = (x0 & MODULE_ID_MASK) >> 8U;
118*91f16700Schasinglulu 
119*91f16700Schasinglulu 	//default module id is for LIBPM
120*91f16700Schasinglulu 	if (module_id == 0) {
121*91f16700Schasinglulu 		module_id = LIBPM_MODULE_ID;
122*91f16700Schasinglulu 	}
123*91f16700Schasinglulu 
124*91f16700Schasinglulu 	PM_PACK_PAYLOAD6(payload, module_id, flag, x0, x1, x2, x3, x4, x5);
125*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, (uint32_t *)result, PAYLOAD_ARG_CNT);
126*91f16700Schasinglulu }
127*91f16700Schasinglulu 
128*91f16700Schasinglulu /**
129*91f16700Schasinglulu  * pm_self_suspend() - PM call for processor to suspend itself
130*91f16700Schasinglulu  * @nid: Node id of the processor or subsystem.
131*91f16700Schasinglulu  * @latency: Requested maximum wakeup latency (not supported).
132*91f16700Schasinglulu  * @state: Requested state.
133*91f16700Schasinglulu  * @address: Resume address.
134*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
135*91f16700Schasinglulu  *        1 - Call from non-secure source.
136*91f16700Schasinglulu  *
137*91f16700Schasinglulu  * This is a blocking call, it will return only once PMU has responded.
138*91f16700Schasinglulu  * On a wakeup, resume address will be automatically set by PMU.
139*91f16700Schasinglulu  *
140*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
141*91f16700Schasinglulu  *
142*91f16700Schasinglulu  */
143*91f16700Schasinglulu enum pm_ret_status pm_self_suspend(uint32_t nid,
144*91f16700Schasinglulu 				   uint32_t latency,
145*91f16700Schasinglulu 				   uint32_t state,
146*91f16700Schasinglulu 				   uintptr_t address, uint32_t flag)
147*91f16700Schasinglulu {
148*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
149*91f16700Schasinglulu 	uint32_t cpuid = plat_my_core_pos();
150*91f16700Schasinglulu 	const struct pm_proc *proc = pm_get_proc(cpuid);
151*91f16700Schasinglulu 
152*91f16700Schasinglulu 	if (proc == NULL) {
153*91f16700Schasinglulu 		WARN("Failed to get proc %d\n", cpuid);
154*91f16700Schasinglulu 		return PM_RET_ERROR_INTERNAL;
155*91f16700Schasinglulu 	}
156*91f16700Schasinglulu 
157*91f16700Schasinglulu 	/*
158*91f16700Schasinglulu 	 * Do client specific suspend operations
159*91f16700Schasinglulu 	 * (e.g. set powerdown request bit)
160*91f16700Schasinglulu 	 */
161*91f16700Schasinglulu 	pm_client_suspend(proc, state);
162*91f16700Schasinglulu 
163*91f16700Schasinglulu 	/* Send request to the PLM */
164*91f16700Schasinglulu 	PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, flag, PM_SELF_SUSPEND,
165*91f16700Schasinglulu 			 proc->node_id, latency, state, address,
166*91f16700Schasinglulu 			 (address >> 32));
167*91f16700Schasinglulu 	return pm_ipi_send_sync(proc, payload, NULL, 0);
168*91f16700Schasinglulu }
169*91f16700Schasinglulu 
170*91f16700Schasinglulu /**
171*91f16700Schasinglulu  * pm_abort_suspend() - PM call to announce that a prior suspend request
172*91f16700Schasinglulu  *                      is to be aborted.
173*91f16700Schasinglulu  * @reason: Reason for the abort.
174*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
175*91f16700Schasinglulu  *        1 - Call from non-secure source.
176*91f16700Schasinglulu  *
177*91f16700Schasinglulu  * Calling PU expects the PMU to abort the initiated suspend procedure.
178*91f16700Schasinglulu  * This is a non-blocking call without any acknowledge.
179*91f16700Schasinglulu  *
180*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
181*91f16700Schasinglulu  *
182*91f16700Schasinglulu  */
183*91f16700Schasinglulu enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason, uint32_t flag)
184*91f16700Schasinglulu {
185*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
186*91f16700Schasinglulu 
187*91f16700Schasinglulu 	/*
188*91f16700Schasinglulu 	 * Do client specific abort suspend operations
189*91f16700Schasinglulu 	 * (e.g. enable interrupts and clear powerdown request bit)
190*91f16700Schasinglulu 	 */
191*91f16700Schasinglulu 	pm_client_abort_suspend();
192*91f16700Schasinglulu 
193*91f16700Schasinglulu 	/* Send request to the PLM */
194*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_ABORT_SUSPEND,
195*91f16700Schasinglulu 			 reason, primary_proc->node_id);
196*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
197*91f16700Schasinglulu }
198*91f16700Schasinglulu 
199*91f16700Schasinglulu /**
200*91f16700Schasinglulu  * pm_req_suspend() - PM call to request for another PU or subsystem to
201*91f16700Schasinglulu  *                    be suspended gracefully.
202*91f16700Schasinglulu  * @target: Node id of the targeted PU or subsystem.
203*91f16700Schasinglulu  * @ack: Flag to specify whether acknowledge is requested.
204*91f16700Schasinglulu  * @latency: Requested wakeup latency (not supported)
205*91f16700Schasinglulu  * @state: Requested state (not supported).
206*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
207*91f16700Schasinglulu  *        1 - Call from non-secure source.
208*91f16700Schasinglulu  *
209*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
210*91f16700Schasinglulu  *
211*91f16700Schasinglulu  */
212*91f16700Schasinglulu enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack,
213*91f16700Schasinglulu 				  uint32_t latency, uint32_t state,
214*91f16700Schasinglulu 				  uint32_t flag)
215*91f16700Schasinglulu {
216*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
217*91f16700Schasinglulu 
218*91f16700Schasinglulu 	/* Send request to the PMU */
219*91f16700Schasinglulu 	PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_REQ_SUSPEND, target,
220*91f16700Schasinglulu 			 latency, state);
221*91f16700Schasinglulu 	if (ack == IPI_BLOCKING) {
222*91f16700Schasinglulu 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
223*91f16700Schasinglulu 	} else {
224*91f16700Schasinglulu 		return pm_ipi_send(primary_proc, payload);
225*91f16700Schasinglulu 	}
226*91f16700Schasinglulu }
227*91f16700Schasinglulu 
228*91f16700Schasinglulu /**
229*91f16700Schasinglulu  * pm_req_wakeup() - PM call for processor to wake up selected processor
230*91f16700Schasinglulu  *                   or subsystem.
231*91f16700Schasinglulu  * @target: Device ID of the processor or subsystem to wake up.
232*91f16700Schasinglulu  * @set_address: Resume address presence indicator.
233*91f16700Schasinglulu  *               1 - resume address specified, 0 - otherwise.
234*91f16700Schasinglulu  * @address: Resume address.
235*91f16700Schasinglulu  * @ack: Flag to specify whether acknowledge requested.
236*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
237*91f16700Schasinglulu  *        1 - Call from non-secure source.
238*91f16700Schasinglulu  *
239*91f16700Schasinglulu  * This API function is either used to power up another APU core for SMP
240*91f16700Schasinglulu  * (by PSCI) or to power up an entirely different PU or subsystem, such
241*91f16700Schasinglulu  * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
242*91f16700Schasinglulu  * automatically set by PMC.
243*91f16700Schasinglulu  *
244*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
245*91f16700Schasinglulu  *
246*91f16700Schasinglulu  */
247*91f16700Schasinglulu enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address,
248*91f16700Schasinglulu 				 uintptr_t address, uint8_t ack, uint32_t flag)
249*91f16700Schasinglulu {
250*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
251*91f16700Schasinglulu 
252*91f16700Schasinglulu 	/* Send request to the PMC to perform the wake of the PU */
253*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQ_WAKEUP, target,
254*91f16700Schasinglulu 			 set_address, address, ack);
255*91f16700Schasinglulu 
256*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
257*91f16700Schasinglulu }
258*91f16700Schasinglulu 
259*91f16700Schasinglulu /**
260*91f16700Schasinglulu  * pm_get_callbackdata() - Read from IPI response buffer.
261*91f16700Schasinglulu  * @data: array of PAYLOAD_ARG_CNT elements.
262*91f16700Schasinglulu  * @count: Number of values to return.
263*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
264*91f16700Schasinglulu  *        1 - Call from non-secure source.
265*91f16700Schasinglulu  * @ack: 0 - Do not ack IPI after reading payload.
266*91f16700Schasinglulu  *       1 - Ack IPI after reading payload.
267*91f16700Schasinglulu  *
268*91f16700Schasinglulu  * Read value from ipi buffer response buffer.
269*91f16700Schasinglulu  * Return: Returns status, either success or error.
270*91f16700Schasinglulu  *
271*91f16700Schasinglulu  */
272*91f16700Schasinglulu enum pm_ret_status pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag, uint32_t ack)
273*91f16700Schasinglulu {
274*91f16700Schasinglulu 	enum pm_ret_status ret = PM_RET_SUCCESS;
275*91f16700Schasinglulu 	/* Return if interrupt is not from PMU */
276*91f16700Schasinglulu 	if (pm_ipi_irq_status(primary_proc) == 0) {
277*91f16700Schasinglulu 		return ret;
278*91f16700Schasinglulu 	}
279*91f16700Schasinglulu 
280*91f16700Schasinglulu 	ret = pm_ipi_buff_read_callb(data, count);
281*91f16700Schasinglulu 
282*91f16700Schasinglulu 	if (ack != 0U) {
283*91f16700Schasinglulu 		pm_ipi_irq_clear(primary_proc);
284*91f16700Schasinglulu 	}
285*91f16700Schasinglulu 
286*91f16700Schasinglulu 	return ret;
287*91f16700Schasinglulu }
288*91f16700Schasinglulu 
289*91f16700Schasinglulu /**
290*91f16700Schasinglulu  * pm_pll_set_param() - Set PLL parameter.
291*91f16700Schasinglulu  * @clk_id: PLL clock ID.
292*91f16700Schasinglulu  * @param: PLL parameter ID.
293*91f16700Schasinglulu  * @value: Value to set for PLL parameter.
294*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
295*91f16700Schasinglulu  *        1 - Call from non-secure source.
296*91f16700Schasinglulu  *
297*91f16700Schasinglulu  * This API is deprecated and maintained here for backward compatibility.
298*91f16700Schasinglulu  * New use of this API should be avoided for versal platform.
299*91f16700Schasinglulu  * This API and its use cases will be removed for versal platform.
300*91f16700Schasinglulu  *
301*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
302*91f16700Schasinglulu  *
303*91f16700Schasinglulu  */
304*91f16700Schasinglulu enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
305*91f16700Schasinglulu 				    uint32_t value, uint32_t flag)
306*91f16700Schasinglulu {
307*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
308*91f16700Schasinglulu 
309*91f16700Schasinglulu 	/* Send request to the PMC */
310*91f16700Schasinglulu 	PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_PARAMETER,
311*91f16700Schasinglulu 			 clk_id, param, value);
312*91f16700Schasinglulu 
313*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
314*91f16700Schasinglulu }
315*91f16700Schasinglulu 
316*91f16700Schasinglulu /**
317*91f16700Schasinglulu  * pm_pll_get_param() - Get PLL parameter value.
318*91f16700Schasinglulu  * @clk_id: PLL clock ID.
319*91f16700Schasinglulu  * @param: PLL parameter ID.
320*91f16700Schasinglulu  * @value: Buffer to store PLL parameter value.
321*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
322*91f16700Schasinglulu  *        1 - Call from non-secure source.
323*91f16700Schasinglulu  *
324*91f16700Schasinglulu  * This API is deprecated and maintained here for backward compatibility.
325*91f16700Schasinglulu  * New use of this API should be avoided for versal platform.
326*91f16700Schasinglulu  * This API and its use cases will be removed for versal platform.
327*91f16700Schasinglulu  *
328*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
329*91f16700Schasinglulu  *
330*91f16700Schasinglulu  */
331*91f16700Schasinglulu enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
332*91f16700Schasinglulu 				    uint32_t *value, uint32_t flag)
333*91f16700Schasinglulu {
334*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
335*91f16700Schasinglulu 
336*91f16700Schasinglulu 	/* Send request to the PMC */
337*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_PARAMETER,
338*91f16700Schasinglulu 			 clk_id, param);
339*91f16700Schasinglulu 
340*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
341*91f16700Schasinglulu }
342*91f16700Schasinglulu 
343*91f16700Schasinglulu /**
344*91f16700Schasinglulu  * pm_pll_set_mode() - Set PLL mode.
345*91f16700Schasinglulu  * @clk_id: PLL clock ID.
346*91f16700Schasinglulu  * @mode: PLL mode.
347*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
348*91f16700Schasinglulu  *        1 - Call from non-secure source.
349*91f16700Schasinglulu  *
350*91f16700Schasinglulu  * This API is deprecated and maintained here for backward compatibility.
351*91f16700Schasinglulu  * New use of this API should be avoided for versal platform.
352*91f16700Schasinglulu  * This API and its use cases will be removed for versal platform.
353*91f16700Schasinglulu  *
354*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
355*91f16700Schasinglulu  *
356*91f16700Schasinglulu  */
357*91f16700Schasinglulu enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode,
358*91f16700Schasinglulu 				   uint32_t flag)
359*91f16700Schasinglulu {
360*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
361*91f16700Schasinglulu 
362*91f16700Schasinglulu 	/* Send request to the PMC */
363*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_PLL_SET_MODE,
364*91f16700Schasinglulu 			 clk_id, mode);
365*91f16700Schasinglulu 
366*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
367*91f16700Schasinglulu }
368*91f16700Schasinglulu 
369*91f16700Schasinglulu /**
370*91f16700Schasinglulu  * pm_pll_get_mode() - Get PLL mode.
371*91f16700Schasinglulu  * @clk_id: PLL clock ID.
372*91f16700Schasinglulu  * @mode: Buffer to store PLL mode.
373*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
374*91f16700Schasinglulu  *        1 - Call from non-secure source.
375*91f16700Schasinglulu  *
376*91f16700Schasinglulu  * This API is deprecated and maintained here for backward compatibility.
377*91f16700Schasinglulu  * New use of this API should be avoided for versal platform.
378*91f16700Schasinglulu  * This API and its use cases will be removed for versal platform.
379*91f16700Schasinglulu  *
380*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
381*91f16700Schasinglulu  *
382*91f16700Schasinglulu  */
383*91f16700Schasinglulu enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode,
384*91f16700Schasinglulu 				   uint32_t flag)
385*91f16700Schasinglulu {
386*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
387*91f16700Schasinglulu 
388*91f16700Schasinglulu 	/* Send request to the PMC */
389*91f16700Schasinglulu 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PLL_GET_MODE,
390*91f16700Schasinglulu 			 clk_id);
391*91f16700Schasinglulu 
392*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, mode, 1);
393*91f16700Schasinglulu }
394*91f16700Schasinglulu 
395*91f16700Schasinglulu /**
396*91f16700Schasinglulu  * pm_force_powerdown() - PM call to request for another PU or subsystem to
397*91f16700Schasinglulu  *                        be powered down forcefully.
398*91f16700Schasinglulu  * @target: Device ID of the PU node to be forced powered down.
399*91f16700Schasinglulu  * @ack: Flag to specify whether acknowledge is requested
400*91f16700Schasinglulu  * @flag: 0 - Call from secure source
401*91f16700Schasinglulu  *        1 - Call from non-secure source
402*91f16700Schasinglulu  *
403*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
404*91f16700Schasinglulu  *
405*91f16700Schasinglulu  */
406*91f16700Schasinglulu enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack,
407*91f16700Schasinglulu 				      uint32_t flag)
408*91f16700Schasinglulu {
409*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
410*91f16700Schasinglulu 
411*91f16700Schasinglulu 	/* Send request to the PMC */
412*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_FORCE_POWERDOWN,
413*91f16700Schasinglulu 			 target, ack);
414*91f16700Schasinglulu 
415*91f16700Schasinglulu 	if (ack == IPI_BLOCKING) {
416*91f16700Schasinglulu 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
417*91f16700Schasinglulu 	} else {
418*91f16700Schasinglulu 		return pm_ipi_send(primary_proc, payload);
419*91f16700Schasinglulu 	}
420*91f16700Schasinglulu }
421*91f16700Schasinglulu 
422*91f16700Schasinglulu /**
423*91f16700Schasinglulu  * pm_system_shutdown() - PM call to request a system shutdown or restart.
424*91f16700Schasinglulu  * @type: Shutdown or restart? 0=shutdown, 1=restart, 2=setscope.
425*91f16700Schasinglulu  * @subtype: Scope: 0=APU-subsystem, 1=PS, 2=system.
426*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
427*91f16700Schasinglulu  *        1 - Call from non-secure source.
428*91f16700Schasinglulu  *
429*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
430*91f16700Schasinglulu  *
431*91f16700Schasinglulu  */
432*91f16700Schasinglulu enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype,
433*91f16700Schasinglulu 				      uint32_t flag)
434*91f16700Schasinglulu {
435*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
436*91f16700Schasinglulu 
437*91f16700Schasinglulu 	if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
438*91f16700Schasinglulu 		/* Setting scope for subsequent PSCI reboot or shutdown */
439*91f16700Schasinglulu 		pm_shutdown_scope = subtype;
440*91f16700Schasinglulu 		return PM_RET_SUCCESS;
441*91f16700Schasinglulu 	}
442*91f16700Schasinglulu 
443*91f16700Schasinglulu 	/* Send request to the PMC */
444*91f16700Schasinglulu 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SYSTEM_SHUTDOWN,
445*91f16700Schasinglulu 			 type, subtype);
446*91f16700Schasinglulu 
447*91f16700Schasinglulu 	return pm_ipi_send_non_blocking(primary_proc, payload);
448*91f16700Schasinglulu }
449*91f16700Schasinglulu 
450*91f16700Schasinglulu /**
451*91f16700Schasinglulu  * pm_query_data() -  PM API for querying firmware data.
452*91f16700Schasinglulu  * @qid: The type of data to query.
453*91f16700Schasinglulu  * @arg1: Argument 1 to requested query data call.
454*91f16700Schasinglulu  * @arg2: Argument 2 to requested query data call.
455*91f16700Schasinglulu  * @arg3: Argument 3 to requested query data call.
456*91f16700Schasinglulu  * @data: Returned output data.
457*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
458*91f16700Schasinglulu  *        1 - Call from non-secure source.
459*91f16700Schasinglulu  *
460*91f16700Schasinglulu  * This API is deprecated and maintained here for backward compatibility.
461*91f16700Schasinglulu  * New use of this API should be avoided for versal platform.
462*91f16700Schasinglulu  * This API and its use cases will be removed for versal platform.
463*91f16700Schasinglulu  *
464*91f16700Schasinglulu  * Return: 0 if success else non-zero error code of type
465*91f16700Schasinglulu  *         enum pm_ret_status.
466*91f16700Schasinglulu  *
467*91f16700Schasinglulu  */
468*91f16700Schasinglulu enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
469*91f16700Schasinglulu 				 uint32_t arg3, uint32_t *data, uint32_t flag)
470*91f16700Schasinglulu {
471*91f16700Schasinglulu 	uint32_t ret;
472*91f16700Schasinglulu 	uint32_t version[PAYLOAD_ARG_CNT] = {0};
473*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
474*91f16700Schasinglulu 	uint32_t fw_api_version;
475*91f16700Schasinglulu 
476*91f16700Schasinglulu 	/* Send request to the PMC */
477*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_QUERY_DATA, qid,
478*91f16700Schasinglulu 			 arg1, arg2, arg3);
479*91f16700Schasinglulu 
480*91f16700Schasinglulu 	ret = pm_feature_check((uint32_t)PM_QUERY_DATA, &version[0], flag);
481*91f16700Schasinglulu 	if (ret == PM_RET_SUCCESS) {
482*91f16700Schasinglulu 		fw_api_version = version[0] & 0xFFFFU;
483*91f16700Schasinglulu 		if ((fw_api_version == 2U) &&
484*91f16700Schasinglulu 		    ((qid == XPM_QID_CLOCK_GET_NAME) ||
485*91f16700Schasinglulu 		     (qid == XPM_QID_PINCTRL_GET_FUNCTION_NAME))) {
486*91f16700Schasinglulu 			ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT);
487*91f16700Schasinglulu 			if (ret == PM_RET_SUCCESS) {
488*91f16700Schasinglulu 				ret = data[0];
489*91f16700Schasinglulu 				data[0] = data[1];
490*91f16700Schasinglulu 				data[1] = data[2];
491*91f16700Schasinglulu 				data[2] = data[3];
492*91f16700Schasinglulu 			}
493*91f16700Schasinglulu 		} else {
494*91f16700Schasinglulu 			ret = pm_ipi_send_sync(primary_proc, payload, data, PAYLOAD_ARG_CNT);
495*91f16700Schasinglulu 		}
496*91f16700Schasinglulu 	}
497*91f16700Schasinglulu 	return ret;
498*91f16700Schasinglulu }
499*91f16700Schasinglulu /**
500*91f16700Schasinglulu  * pm_api_ioctl() -  PM IOCTL API for device control and configs.
501*91f16700Schasinglulu  * @device_id: Device ID.
502*91f16700Schasinglulu  * @ioctl_id: ID of the requested IOCTL.
503*91f16700Schasinglulu  * @arg1: Argument 1 to requested IOCTL call.
504*91f16700Schasinglulu  * @arg2: Argument 2 to requested IOCTL call.
505*91f16700Schasinglulu  * @arg3: Argument 3 to requested IOCTL call.
506*91f16700Schasinglulu  * @value: Returned output value.
507*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
508*91f16700Schasinglulu  *        1 - Call from non-secure source.
509*91f16700Schasinglulu  *
510*91f16700Schasinglulu  * This API is deprecated and maintained here for backward compatibility.
511*91f16700Schasinglulu  * New use of this API should be avoided for versal platform.
512*91f16700Schasinglulu  * This API and its use cases will be removed for versal platform.
513*91f16700Schasinglulu  *
514*91f16700Schasinglulu  * This function calls IOCTL to firmware for device control and configuration.
515*91f16700Schasinglulu  *
516*91f16700Schasinglulu  * Return: Returns status, either 0 on success or non-zero error code
517*91f16700Schasinglulu  *         of type enum pm_ret_status.
518*91f16700Schasinglulu  *
519*91f16700Schasinglulu  */
520*91f16700Schasinglulu enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
521*91f16700Schasinglulu 				uint32_t arg1, uint32_t arg2, uint32_t arg3,
522*91f16700Schasinglulu 				uint32_t *value, uint32_t flag)
523*91f16700Schasinglulu {
524*91f16700Schasinglulu 	enum pm_ret_status ret;
525*91f16700Schasinglulu 
526*91f16700Schasinglulu 	switch (ioctl_id) {
527*91f16700Schasinglulu 	case IOCTL_SET_PLL_FRAC_MODE:
528*91f16700Schasinglulu 		ret =  pm_pll_set_mode(arg1, arg2, flag);
529*91f16700Schasinglulu 		break;
530*91f16700Schasinglulu 	case IOCTL_GET_PLL_FRAC_MODE:
531*91f16700Schasinglulu 		ret =  pm_pll_get_mode(arg1, value, flag);
532*91f16700Schasinglulu 		break;
533*91f16700Schasinglulu 	case IOCTL_SET_PLL_FRAC_DATA:
534*91f16700Schasinglulu 		ret =  pm_pll_set_param(arg1, (uint32_t)PM_PLL_PARAM_DATA, arg2, flag);
535*91f16700Schasinglulu 		break;
536*91f16700Schasinglulu 	case IOCTL_GET_PLL_FRAC_DATA:
537*91f16700Schasinglulu 		ret =  pm_pll_get_param(arg1, (uint32_t)PM_PLL_PARAM_DATA, value, flag);
538*91f16700Schasinglulu 		break;
539*91f16700Schasinglulu 	case IOCTL_SET_SGI:
540*91f16700Schasinglulu 		/* Get the sgi number */
541*91f16700Schasinglulu 		ret = pm_register_sgi(arg1, arg2);
542*91f16700Schasinglulu 		if (ret != 0) {
543*91f16700Schasinglulu 			return PM_RET_ERROR_ARGS;
544*91f16700Schasinglulu 		}
545*91f16700Schasinglulu 		ret = PM_RET_SUCCESS;
546*91f16700Schasinglulu 		break;
547*91f16700Schasinglulu 	default:
548*91f16700Schasinglulu 		return PM_RET_ERROR_NOTSUPPORTED;
549*91f16700Schasinglulu 	}
550*91f16700Schasinglulu 
551*91f16700Schasinglulu 	return ret;
552*91f16700Schasinglulu }
553*91f16700Schasinglulu 
554*91f16700Schasinglulu /**
555*91f16700Schasinglulu  * pm_set_wakeup_source() - PM call to specify the wakeup source while
556*91f16700Schasinglulu  *                          suspended.
557*91f16700Schasinglulu  * @target: Device id of the targeted PU or subsystem
558*91f16700Schasinglulu  * @wkup_device: Device id of the wakeup peripheral
559*91f16700Schasinglulu  * @enable: Enable or disable the specified peripheral as wake source
560*91f16700Schasinglulu  * @flag: 0 - Call from secure source
561*91f16700Schasinglulu  *        1 - Call from non-secure source
562*91f16700Schasinglulu  *
563*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
564*91f16700Schasinglulu  *
565*91f16700Schasinglulu  */
566*91f16700Schasinglulu enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device,
567*91f16700Schasinglulu 					uint8_t enable, uint32_t flag)
568*91f16700Schasinglulu {
569*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
570*91f16700Schasinglulu 
571*91f16700Schasinglulu 	PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, flag, PM_SET_WAKEUP_SOURCE,
572*91f16700Schasinglulu 			 target, wkup_device, enable);
573*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
574*91f16700Schasinglulu }
575*91f16700Schasinglulu 
576*91f16700Schasinglulu /**
577*91f16700Schasinglulu  * pm_feature_check() - Returns the supported API version if supported.
578*91f16700Schasinglulu  * @api_id: API ID to check.
579*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
580*91f16700Schasinglulu  *        1 - Call from non-secure source.
581*91f16700Schasinglulu  * @ret_payload: pointer to array of PAYLOAD_ARG_CNT number of
582*91f16700Schasinglulu  *               words Returned supported API version and bitmasks
583*91f16700Schasinglulu  *               for IOCTL and QUERY ID
584*91f16700Schasinglulu  *
585*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
586*91f16700Schasinglulu  *
587*91f16700Schasinglulu  */
588*91f16700Schasinglulu enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *ret_payload,
589*91f16700Schasinglulu 				    uint32_t flag)
590*91f16700Schasinglulu {
591*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
592*91f16700Schasinglulu 	uint32_t module_id;
593*91f16700Schasinglulu 
594*91f16700Schasinglulu 	/* Return version of API which are implemented in TF-A only */
595*91f16700Schasinglulu 	switch (api_id) {
596*91f16700Schasinglulu 	case PM_GET_CALLBACK_DATA:
597*91f16700Schasinglulu 	case PM_GET_TRUSTZONE_VERSION:
598*91f16700Schasinglulu 		ret_payload[0] = PM_API_VERSION_2;
599*91f16700Schasinglulu 		return PM_RET_SUCCESS;
600*91f16700Schasinglulu 	case TF_A_PM_REGISTER_SGI:
601*91f16700Schasinglulu 		ret_payload[0] = PM_API_BASE_VERSION;
602*91f16700Schasinglulu 		return PM_RET_SUCCESS;
603*91f16700Schasinglulu 	default:
604*91f16700Schasinglulu 		break;
605*91f16700Schasinglulu 	}
606*91f16700Schasinglulu 
607*91f16700Schasinglulu 	module_id = (api_id & MODULE_ID_MASK) >> 8U;
608*91f16700Schasinglulu 
609*91f16700Schasinglulu 	/*
610*91f16700Schasinglulu 	 * feature check should be done only for LIBPM module
611*91f16700Schasinglulu 	 * If module_id is 0, then we consider it LIBPM module as default id
612*91f16700Schasinglulu 	 */
613*91f16700Schasinglulu 	if ((module_id > 0) && (module_id != LIBPM_MODULE_ID)) {
614*91f16700Schasinglulu 		return PM_RET_SUCCESS;
615*91f16700Schasinglulu 	}
616*91f16700Schasinglulu 
617*91f16700Schasinglulu 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag,
618*91f16700Schasinglulu 			 PM_FEATURE_CHECK, api_id);
619*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, ret_payload, PAYLOAD_ARG_CNT);
620*91f16700Schasinglulu }
621*91f16700Schasinglulu 
622*91f16700Schasinglulu /**
623*91f16700Schasinglulu  * pm_load_pdi() - Load the PDI. This function provides support to load
624*91f16700Schasinglulu  *                 PDI from linux.
625*91f16700Schasinglulu  *
626*91f16700Schasinglulu  * @src: Source device of pdi(DDR, OCM, SD etc).
627*91f16700Schasinglulu  * @address_low: lower 32-bit Linear memory space address.
628*91f16700Schasinglulu  * @address_high: higher 32-bit Linear memory space address.
629*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
630*91f16700Schasinglulu  *        1 - Call from non-secure source.
631*91f16700Schasinglulu  *
632*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
633*91f16700Schasinglulu  *
634*91f16700Schasinglulu  */
635*91f16700Schasinglulu enum pm_ret_status pm_load_pdi(uint32_t src, uint32_t address_low,
636*91f16700Schasinglulu 			       uint32_t address_high, uint32_t flag)
637*91f16700Schasinglulu {
638*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
639*91f16700Schasinglulu 
640*91f16700Schasinglulu 	/* Send request to the PMU */
641*91f16700Schasinglulu 	PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, flag, PM_LOAD_PDI, src,
642*91f16700Schasinglulu 			 address_high, address_low);
643*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
644*91f16700Schasinglulu }
645*91f16700Schasinglulu 
646*91f16700Schasinglulu /**
647*91f16700Schasinglulu  * pm_register_notifier() - PM call to register a subsystem to be notified
648*91f16700Schasinglulu  *                          about the device event.
649*91f16700Schasinglulu  * @device_id: Device ID for the Node to which the event is related.
650*91f16700Schasinglulu  * @event: Event in question.
651*91f16700Schasinglulu  * @wake: Wake subsystem upon capturing the event if value 1.
652*91f16700Schasinglulu  * @enable: Enable the registration for value 1, disable for value 0.
653*91f16700Schasinglulu  * @flag: 0 - Call from secure source.
654*91f16700Schasinglulu  *        1 - Call from non-secure source.
655*91f16700Schasinglulu  *
656*91f16700Schasinglulu  * Return: Returns status, either success or error+reason.
657*91f16700Schasinglulu  *
658*91f16700Schasinglulu  */
659*91f16700Schasinglulu enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
660*91f16700Schasinglulu 					uint32_t wake, uint32_t enable,
661*91f16700Schasinglulu 					uint32_t flag)
662*91f16700Schasinglulu {
663*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
664*91f16700Schasinglulu 
665*91f16700Schasinglulu 	/* Send request to the PMC */
666*91f16700Schasinglulu 	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REGISTER_NOTIFIER,
667*91f16700Schasinglulu 			 device_id, event, wake, enable);
668*91f16700Schasinglulu 
669*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
670*91f16700Schasinglulu }
671*91f16700Schasinglulu 
672*91f16700Schasinglulu /**
673*91f16700Schasinglulu  * pm_get_chipid() - Read silicon ID registers.
674*91f16700Schasinglulu  * @value: Buffer for two 32bit words.
675*91f16700Schasinglulu  *
676*91f16700Schasinglulu  * Return: Returns status, either success or error+reason and,
677*91f16700Schasinglulu  *         optionally, @value.
678*91f16700Schasinglulu  */
679*91f16700Schasinglulu enum pm_ret_status pm_get_chipid(uint32_t *value)
680*91f16700Schasinglulu {
681*91f16700Schasinglulu 	uint32_t payload[PAYLOAD_ARG_CNT];
682*91f16700Schasinglulu 
683*91f16700Schasinglulu 	PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, SECURE_FLAG, PM_GET_CHIPID);
684*91f16700Schasinglulu 
685*91f16700Schasinglulu 	return pm_ipi_send_sync(primary_proc, payload, value, 2);
686*91f16700Schasinglulu }
687