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