• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2019-2020, 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 
19 /*********************************************************************
20  * Target module IDs macros
21  ********************************************************************/
22 #define LIBPM_MODULE_ID		0x2
23 #define LOADER_MODULE_ID	0x7
24 
25 /* default shutdown/reboot scope is system(2) */
26 static unsigned int pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM;
27 
28 /**
29  * pm_get_shutdown_scope() - Get the currently set shutdown scope
30  *
31  * @return	Shutdown scope value
32  */
pm_get_shutdown_scope(void)33 unsigned int pm_get_shutdown_scope(void)
34 {
35 	return pm_shutdown_scope;
36 }
37 
38 /**
39  * Assigning of argument values into array elements.
40  */
41 #define PM_PACK_PAYLOAD1(pl, mid, arg0) {	\
42 	pl[0] = (uint32_t)((uint32_t)((arg0) & 0xFF) | (mid << 8)); \
43 }
44 
45 #define PM_PACK_PAYLOAD2(pl, mid, arg0, arg1) {		\
46 	pl[1] = (uint32_t)(arg1);			\
47 	PM_PACK_PAYLOAD1(pl, mid, arg0);		\
48 }
49 
50 #define PM_PACK_PAYLOAD3(pl, mid, arg0, arg1, arg2) {	\
51 	pl[2] = (uint32_t)(arg2);			\
52 	PM_PACK_PAYLOAD2(pl, mid, arg0, arg1);		\
53 }
54 
55 #define PM_PACK_PAYLOAD4(pl, mid, arg0, arg1, arg2, arg3) {	\
56 	pl[3] = (uint32_t)(arg3);				\
57 	PM_PACK_PAYLOAD3(pl, mid, arg0, arg1, arg2);		\
58 }
59 
60 #define PM_PACK_PAYLOAD5(pl, mid, arg0, arg1, arg2, arg3, arg4) {	\
61 	pl[4] = (uint32_t)(arg4);					\
62 	PM_PACK_PAYLOAD4(pl, mid, arg0, arg1, arg2, arg3);		\
63 }
64 
65 #define PM_PACK_PAYLOAD6(pl, mid, arg0, arg1, arg2, arg3, arg4, arg5) {	\
66 	pl[5] = (uint32_t)(arg5);					\
67 	PM_PACK_PAYLOAD5(pl, mid, arg0, arg1, arg2, arg3, arg4);	\
68 }
69 
70 /* PM API functions */
71 
72 /**
73  * pm_get_api_version() - Get version number of PMC PM firmware
74  * @version	Returns 32-bit version number of PMC Power Management Firmware
75  *
76  * @return	Returns status, either success or error+reason
77  */
pm_get_api_version(unsigned int * version)78 enum pm_ret_status pm_get_api_version(unsigned int *version)
79 {
80 	uint32_t payload[PAYLOAD_ARG_CNT];
81 
82 	/* Send request to the PMC */
83 	PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_GET_API_VERSION);
84 	return pm_ipi_send_sync(primary_proc, payload, version, 1);
85 }
86 
87 /**
88  * pm_init_finalize() - Call to notify PMC PM firmware that master has power
89  *			management enabled and that it has finished its
90  *			initialization
91  *
92  * @return	Status returned by the PMU firmware
93  */
pm_init_finalize(void)94 enum pm_ret_status pm_init_finalize(void)
95 {
96 	uint32_t payload[PAYLOAD_ARG_CNT];
97 
98 	/* Send request to the PMU */
99 	PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_INIT_FINALIZE);
100 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
101 }
102 
103 /**
104  * pm_self_suspend() - PM call for processor to suspend itself
105  * @nid		Node id of the processor or subsystem
106  * @latency	Requested maximum wakeup latency (not supported)
107  * @state	Requested state
108  * @address	Resume address
109  *
110  * This is a blocking call, it will return only once PMU has responded.
111  * On a wakeup, resume address will be automatically set by PMU.
112  *
113  * @return	Returns status, either success or error+reason
114  */
pm_self_suspend(uint32_t nid,unsigned int latency,unsigned int state,uintptr_t address)115 enum pm_ret_status pm_self_suspend(uint32_t nid,
116 				   unsigned int latency,
117 				   unsigned int state,
118 				   uintptr_t address)
119 {
120 	uint32_t payload[PAYLOAD_ARG_CNT];
121 	unsigned int cpuid = plat_my_core_pos();
122 	const struct pm_proc *proc = pm_get_proc(cpuid);
123 
124 	if (!proc) {
125 		WARN("Failed to get proc %d\n", cpuid);
126 		return PM_RET_ERROR_INTERNAL;
127 	}
128 
129 	/*
130 	 * Do client specific suspend operations
131 	 * (e.g. set powerdown request bit)
132 	 */
133 	pm_client_suspend(proc, state);
134 
135 	/* Send request to the PLM */
136 	PM_PACK_PAYLOAD6(payload, LIBPM_MODULE_ID, PM_SELF_SUSPEND,
137 			 proc->node_id, latency, state, address,
138 			 (address >> 32));
139 	return pm_ipi_send_sync(proc, payload, NULL, 0);
140 }
141 
142 /**
143  * pm_abort_suspend() - PM call to announce that a prior suspend request
144  *			is to be aborted.
145  * @reason	Reason for the abort
146  *
147  * Calling PU expects the PMU to abort the initiated suspend procedure.
148  * This is a non-blocking call without any acknowledge.
149  *
150  * @return	Returns status, either success or error+reason
151  */
pm_abort_suspend(enum pm_abort_reason reason)152 enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
153 {
154 	uint32_t payload[PAYLOAD_ARG_CNT];
155 
156 	/*
157 	 * Do client specific abort suspend operations
158 	 * (e.g. enable interrupts and clear powerdown request bit)
159 	 */
160 	pm_client_abort_suspend();
161 
162 	/* Send request to the PLM */
163 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_ABORT_SUSPEND, reason,
164 			 primary_proc->node_id);
165 	return pm_ipi_send(primary_proc, payload);
166 }
167 
168 /**
169  * pm_req_suspend() - PM call to request for another PU or subsystem to
170  *		      be suspended gracefully.
171  * @target	Node id of the targeted PU or subsystem
172  * @ack		Flag to specify whether acknowledge is requested
173  * @latency	Requested wakeup latency (not supported)
174  * @state	Requested state (not supported)
175  *
176  * @return	Returns status, either success or error+reason
177  */
pm_req_suspend(uint32_t target,uint8_t ack,unsigned int latency,unsigned int state)178 enum pm_ret_status pm_req_suspend(uint32_t target, uint8_t ack,
179 				  unsigned int latency, unsigned int state)
180 {
181 	uint32_t payload[PAYLOAD_ARG_CNT];
182 
183 	/* Send request to the PMU */
184 	PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, PM_REQ_SUSPEND, target,
185 			 latency, state);
186 	if (ack == IPI_BLOCKING)
187 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
188 	else
189 		return pm_ipi_send(primary_proc, payload);
190 }
191 
192 /**
193  * pm_req_wakeup() - PM call for processor to wake up selected processor
194  *		     or subsystem
195  * @target	Device ID of the processor or subsystem to wake up
196  * @set_address	Resume address presence indicator
197  *		1 - resume address specified, 0 - otherwise
198  * @address	Resume address
199  * @ack		Flag to specify whether acknowledge requested
200  *
201  * This API function is either used to power up another APU core for SMP
202  * (by PSCI) or to power up an entirely different PU or subsystem, such
203  * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
204  * automatically set by PMC.
205  *
206  * @return	Returns status, either success or error+reason
207  */
pm_req_wakeup(uint32_t target,uint32_t set_address,uintptr_t address,uint8_t ack)208 enum pm_ret_status pm_req_wakeup(uint32_t target, uint32_t set_address,
209 				 uintptr_t address, uint8_t ack)
210 {
211 	uint32_t payload[PAYLOAD_ARG_CNT];
212 
213 	/* Send request to the PMC to perform the wake of the PU */
214 	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_REQ_WAKEUP, target,
215 			 set_address, address, ack);
216 
217 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
218 }
219 
220 /**
221  * pm_request_device() - Request a device
222  * @device_id		Device ID
223  * @capabilities	Requested capabilities for the device
224  * @qos			Required Quality of Service
225  * @ack			Flag to specify whether acknowledge requested
226  *
227  * @return	Returns status, either success or error+reason
228  */
pm_request_device(uint32_t device_id,uint32_t capabilities,uint32_t qos,uint32_t ack)229 enum pm_ret_status pm_request_device(uint32_t device_id, uint32_t capabilities,
230 				     uint32_t qos, uint32_t ack)
231 {
232 	uint32_t payload[PAYLOAD_ARG_CNT];
233 
234 	/* Send request to the PMC */
235 	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_REQUEST_DEVICE,
236 			 device_id, capabilities, qos, ack);
237 
238 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
239 }
240 
241 /**
242  * pm_release_device() - Release a device
243  * @device_id		Device ID
244  *
245  * @return	Returns status, either success or error+reason
246  */
pm_release_device(uint32_t device_id)247 enum pm_ret_status pm_release_device(uint32_t device_id)
248 {
249 	uint32_t payload[PAYLOAD_ARG_CNT];
250 
251 	/* Send request to the PMC */
252 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_RELEASE_DEVICE,
253 			 device_id);
254 
255 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
256 }
257 
258 /**
259  * pm_set_requirement() - Set requirement for the device
260  * @device_id		Device ID
261  * @capabilities	Requested capabilities for the device
262  * @latency		Requested maximum latency
263  * @qos			Required Quality of Service
264  *
265  * @return	Returns status, either success or error+reason
266  */
pm_set_requirement(uint32_t device_id,uint32_t capabilities,uint32_t latency,uint32_t qos)267 enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities,
268 				      uint32_t latency, uint32_t qos)
269 {
270 	uint32_t payload[PAYLOAD_ARG_CNT];
271 
272 	/* Send request to the PMC */
273 	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_SET_REQUIREMENT,
274 			 device_id, capabilities, latency, qos);
275 
276 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
277 }
278 
279 /**
280  * pm_get_device_status() - Get device's status
281  * @device_id		Device ID
282  * @response		Buffer to store device status response
283  *
284  * @return	Returns status, either success or error+reason
285  */
pm_get_device_status(uint32_t device_id,uint32_t * response)286 enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response)
287 {
288 	uint32_t payload[PAYLOAD_ARG_CNT];
289 
290 	/* Send request to the PMC */
291 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_GET_DEVICE_STATUS,
292 			 device_id);
293 
294 	return pm_ipi_send_sync(primary_proc, payload, response, 3);
295 }
296 
297 /**
298  * pm_reset_assert() - Assert/De-assert reset
299  * @reset	Reset ID
300  * @assert	Assert (1) or de-assert (0)
301  *
302  * @return	Returns status, either success or error+reason
303  */
pm_reset_assert(uint32_t reset,bool assert)304 enum pm_ret_status pm_reset_assert(uint32_t reset, bool assert)
305 {
306 	uint32_t payload[PAYLOAD_ARG_CNT];
307 
308 	/* Send request to the PMC */
309 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_RESET_ASSERT, reset,
310 			 assert);
311 
312 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
313 }
314 
315 /**
316  * pm_reset_get_status() - Get current status of a reset line
317  * @reset	Reset ID
318  * @status	Returns current status of selected reset ID
319  *
320  * @return	Returns status, either success or error+reason
321  */
pm_reset_get_status(uint32_t reset,uint32_t * status)322 enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status)
323 {
324 	uint32_t payload[PAYLOAD_ARG_CNT];
325 
326 	/* Send request to the PMC */
327 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_RESET_ASSERT, reset);
328 
329 	return pm_ipi_send_sync(primary_proc, payload, status, 1);
330 }
331 
332 /**
333  * pm_get_callbackdata() - Read from IPI response buffer
334  * @data - array of PAYLOAD_ARG_CNT elements
335  *
336  * Read value from ipi buffer response buffer.
337  */
pm_get_callbackdata(uint32_t * data,size_t count)338 void pm_get_callbackdata(uint32_t *data, size_t count)
339 {
340 	/* Return if interrupt is not from PMU */
341 	if (!pm_ipi_irq_status(primary_proc))
342 		return;
343 
344 	pm_ipi_buff_read_callb(data, count);
345 	pm_ipi_irq_clear(primary_proc);
346 }
347 
348 /**
349  * pm_pinctrl_request() - Request a pin
350  * @pin		Pin ID
351  *
352  * @return	Returns status, either success or error+reason
353  */
pm_pinctrl_request(uint32_t pin)354 enum pm_ret_status pm_pinctrl_request(uint32_t pin)
355 {
356 	uint32_t payload[PAYLOAD_ARG_CNT];
357 
358 	/* Send request to the PMC */
359 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_PINCTRL_REQUEST, pin);
360 
361 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
362 }
363 
364 /**
365  * pm_pinctrl_release() - Release a pin
366  * @pin		Pin ID
367  *
368  * @return	Returns status, either success or error+reason
369  */
pm_pinctrl_release(uint32_t pin)370 enum pm_ret_status pm_pinctrl_release(uint32_t pin)
371 {
372 	uint32_t payload[PAYLOAD_ARG_CNT];
373 
374 	/* Send request to the PMC */
375 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_PINCTRL_RELEASE, pin);
376 
377 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
378 }
379 
380 /**
381  * pm_pinctrl_set_function() - Set pin function
382  * @pin		Pin ID
383  * @function	Function ID
384  *
385  * @return	Returns status, either success or error+reason
386  */
pm_pinctrl_set_function(uint32_t pin,uint32_t function)387 enum pm_ret_status pm_pinctrl_set_function(uint32_t pin, uint32_t function)
388 {
389 	uint32_t payload[PAYLOAD_ARG_CNT];
390 
391 	/* Send request to the PMC */
392 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_PINCTRL_SET_FUNCTION, pin,
393 			 function)
394 
395 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
396 }
397 
398 /**
399  * pm_pinctrl_get_function() - Get function set on the pin
400  * @pin		Pin ID
401  * @function	Function set on the pin
402  *
403  * @return	Returns status, either success or error+reason
404  */
pm_pinctrl_get_function(uint32_t pin,uint32_t * function)405 enum pm_ret_status pm_pinctrl_get_function(uint32_t pin, uint32_t *function)
406 {
407 	uint32_t payload[PAYLOAD_ARG_CNT];
408 
409 	/* Send request to the PMC */
410 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_PINCTRL_SET_FUNCTION,
411 			 pin);
412 
413 	return pm_ipi_send_sync(primary_proc, payload, function, 1);
414 }
415 
416 /**
417  * pm_pinctrl_set_pin_param() - Set configuration parameter for the pin
418  * @pin		Pin ID
419  * @param	Parameter ID
420  * @value	Parameter value
421  *
422  * @return	Returns status, either success or error+reason
423  */
pm_pinctrl_set_pin_param(uint32_t pin,uint32_t param,uint32_t value)424 enum pm_ret_status pm_pinctrl_set_pin_param(uint32_t pin, uint32_t param,
425 					    uint32_t value)
426 {
427 	uint32_t payload[PAYLOAD_ARG_CNT];
428 
429 	/* Send request to the PMC */
430 	PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, PM_PINCTRL_CONFIG_PARAM_SET,
431 			 pin, param, value);
432 
433 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
434 }
435 
436 /**
437  * pm_pinctrl_get_pin_param() - Get configuration parameter value for the pin
438  * @pin		Pin ID
439  * @param	Parameter ID
440  * @value	Buffer to store parameter value
441  *
442  * @return	Returns status, either success or error+reason
443  */
pm_pinctrl_get_pin_param(uint32_t pin,uint32_t param,uint32_t * value)444 enum pm_ret_status pm_pinctrl_get_pin_param(uint32_t pin, uint32_t param,
445 					    uint32_t *value)
446 {
447 	uint32_t payload[PAYLOAD_ARG_CNT];
448 
449 	/* Send request to the PMC */
450 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_PINCTRL_CONFIG_PARAM_GET,
451 			 pin, param);
452 
453 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
454 }
455 
456 /**
457  * pm_clock_enable() - Enable the clock
458  * @clk_id	Clock ID
459  *
460  * @return	Returns status, either success or error+reason
461  */
pm_clock_enable(uint32_t clk_id)462 enum pm_ret_status pm_clock_enable(uint32_t clk_id)
463 {
464 	uint32_t payload[PAYLOAD_ARG_CNT];
465 
466 	/* Send request to the PMC */
467 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_ENABLE, clk_id);
468 
469 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
470 }
471 
472 /**
473  * pm_clock_disable() - Disable the clock
474  * @clk_id	Clock ID
475  *
476  * @return	Returns status, either success or error+reason
477  */
pm_clock_disable(uint32_t clk_id)478 enum pm_ret_status pm_clock_disable(uint32_t clk_id)
479 {
480 	uint32_t payload[PAYLOAD_ARG_CNT];
481 
482 	/* Send request to the PMC */
483 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_DISABLE, clk_id);
484 
485 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
486 }
487 
488 /**
489  * pm_clock_get_state() - Get clock status
490  * @clk_id	Clock ID
491  * @state:	Buffer to store clock status (1: Enabled, 0:Disabled)
492  *
493  * @return	Returns status, either success or error+reason
494  */
pm_clock_get_state(uint32_t clk_id,uint32_t * state)495 enum pm_ret_status pm_clock_get_state(uint32_t clk_id, uint32_t *state)
496 {
497 	uint32_t payload[PAYLOAD_ARG_CNT];
498 
499 	/* Send request to the PMC */
500 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_GETSTATE, clk_id);
501 
502 	return pm_ipi_send_sync(primary_proc, payload, state, 1);
503 }
504 
505 /**
506  * pm_clock_set_divider() - Set divider for the clock
507  * @clk_id	Clock ID
508  * @divider	Divider value
509  *
510  * @return	Returns status, either success or error+reason
511  */
pm_clock_set_divider(uint32_t clk_id,uint32_t divider)512 enum pm_ret_status pm_clock_set_divider(uint32_t clk_id, uint32_t divider)
513 {
514 	uint32_t payload[PAYLOAD_ARG_CNT];
515 
516 	/* Send request to the PMC */
517 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_CLOCK_SETDIVIDER, clk_id,
518 			 divider);
519 
520 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
521 }
522 
523 /**
524  * pm_clock_get_divider() - Get divider value for the clock
525  * @clk_id	Clock ID
526  * @divider:	Buffer to store clock divider value
527  *
528  * @return	Returns status, either success or error+reason
529  */
pm_clock_get_divider(uint32_t clk_id,uint32_t * divider)530 enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider)
531 {
532 	uint32_t payload[PAYLOAD_ARG_CNT];
533 
534 	/* Send request to the PMC */
535 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_GETDIVIDER, clk_id);
536 
537 	return pm_ipi_send_sync(primary_proc, payload, divider, 1);
538 }
539 
540 /**
541  * pm_clock_set_parent() - Set parent for the clock
542  * @clk_id	Clock ID
543  * @parent	Parent ID
544  *
545  * @return	Returns status, either success or error+reason
546  */
pm_clock_set_parent(uint32_t clk_id,uint32_t parent)547 enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent)
548 {
549 	uint32_t payload[PAYLOAD_ARG_CNT];
550 
551 	/* Send request to the PMC */
552 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_CLOCK_SETPARENT, clk_id,
553 			 parent);
554 
555 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
556 }
557 
558 /**
559  * pm_clock_get_parent() - Get parent value for the clock
560  * @clk_id	Clock ID
561  * @parent:	Buffer to store clock parent value
562  *
563  * @return	Returns status, either success or error+reason
564  */
pm_clock_get_parent(uint32_t clk_id,uint32_t * parent)565 enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent)
566 {
567 	uint32_t payload[PAYLOAD_ARG_CNT];
568 
569 	/* Send request to the PMC */
570 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_GETPARENT, clk_id);
571 
572 	return pm_ipi_send_sync(primary_proc, payload, parent, 1);
573 }
574 /**
575  * pm_clock_get_rate() - Get the rate value for the clock
576  * @clk_id	Clock ID
577  * @rate:	Buffer to store clock rate value
578  *
579  * @return	Returns status, either success or error+reason
580  */
pm_clock_get_rate(uint32_t clk_id,uint32_t * clk_rate)581 enum pm_ret_status pm_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate)
582 {
583 	uint32_t payload[PAYLOAD_ARG_CNT];
584 
585 	/* Send request to the PMC */
586 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_CLOCK_GETRATE, clk_id);
587 
588 	return pm_ipi_send_sync(primary_proc, payload, clk_rate, 2);
589 }
590 
591 /**
592  * pm_pll_set_param() - Set PLL parameter
593  * @clk_id	PLL clock ID
594  * @param	PLL parameter ID
595  * @value	Value to set for PLL parameter
596  *
597  * @return	Returns status, either success or error+reason
598  */
pm_pll_set_param(uint32_t clk_id,uint32_t param,uint32_t value)599 enum pm_ret_status pm_pll_set_param(uint32_t clk_id, uint32_t param,
600 				    uint32_t value)
601 {
602 	uint32_t payload[PAYLOAD_ARG_CNT];
603 
604 	/* Send request to the PMC */
605 	PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, PM_PLL_SET_PARAMETER, clk_id,
606 			 param, value);
607 
608 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
609 }
610 
611 /**
612  * pm_pll_get_param() - Get PLL parameter value
613  * @clk_id	PLL clock ID
614  * @param	PLL parameter ID
615  * @value:	Buffer to store PLL parameter value
616  *
617  * @return	Returns status, either success or error+reason
618  */
pm_pll_get_param(uint32_t clk_id,uint32_t param,uint32_t * value)619 enum pm_ret_status pm_pll_get_param(uint32_t clk_id, uint32_t param,
620 				    uint32_t *value)
621 {
622 	uint32_t payload[PAYLOAD_ARG_CNT];
623 
624 	/* Send request to the PMC */
625 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_PLL_GET_PARAMETER, clk_id,
626 			 param);
627 
628 	return pm_ipi_send_sync(primary_proc, payload, value, 1);
629 }
630 
631 /**
632  * pm_pll_set_mode() - Set PLL mode
633  * @clk_id	PLL clock ID
634  * @mode	PLL mode
635  *
636  * @return	Returns status, either success or error+reason
637  */
pm_pll_set_mode(uint32_t clk_id,uint32_t mode)638 enum pm_ret_status pm_pll_set_mode(uint32_t clk_id, uint32_t mode)
639 {
640 	uint32_t payload[PAYLOAD_ARG_CNT];
641 
642 	/* Send request to the PMC */
643 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_PLL_SET_MODE, clk_id,
644 			 mode);
645 
646 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
647 }
648 
649 /**
650  * pm_pll_get_mode() - Get PLL mode
651  * @clk_id	PLL clock ID
652  * @mode:	Buffer to store PLL mode
653  *
654  * @return	Returns status, either success or error+reason
655  */
pm_pll_get_mode(uint32_t clk_id,uint32_t * mode)656 enum pm_ret_status pm_pll_get_mode(uint32_t clk_id, uint32_t *mode)
657 {
658 	uint32_t payload[PAYLOAD_ARG_CNT];
659 
660 	/* Send request to the PMC */
661 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_PLL_GET_MODE, clk_id);
662 
663 	return pm_ipi_send_sync(primary_proc, payload, mode, 1);
664 }
665 
666 /**
667  * pm_force_powerdown() - PM call to request for another PU or subsystem to
668  *			  be powered down forcefully
669  * @target	Device ID of the PU node to be forced powered down.
670  * @ack		Flag to specify whether acknowledge is requested
671  *
672  * @return	Returns status, either success or error+reason
673  */
pm_force_powerdown(uint32_t target,uint8_t ack)674 enum pm_ret_status pm_force_powerdown(uint32_t target, uint8_t ack)
675 {
676 	uint32_t payload[PAYLOAD_ARG_CNT];
677 
678 	/* Send request to the PMC */
679 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_FORCE_POWERDOWN, target,
680 			 ack);
681 
682 	if (ack == IPI_BLOCKING)
683 		return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
684 	else
685 		return pm_ipi_send(primary_proc, payload);
686 }
687 
688 /**
689  * pm_system_shutdown() - PM call to request a system shutdown or restart
690  * @type	Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
691  * @subtype	Scope: 0=APU-subsystem, 1=PS, 2=system
692  *
693  * @return	Returns status, either success or error+reason
694  */
pm_system_shutdown(uint32_t type,uint32_t subtype)695 enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
696 {
697 	uint32_t payload[PAYLOAD_ARG_CNT];
698 
699 	if (type == XPM_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
700 		/* Setting scope for subsequent PSCI reboot or shutdown */
701 		pm_shutdown_scope = subtype;
702 		return PM_RET_SUCCESS;
703 	}
704 
705 	/* Send request to the PMC */
706 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_SYSTEM_SHUTDOWN, type,
707 			 subtype);
708 
709 	return pm_ipi_send_non_blocking(primary_proc, payload);
710 }
711 
712 /**
713 * pm_query_data() -  PM API for querying firmware data
714 * @qid	The type of data to query
715 * @arg1	Argument 1 to requested query data call
716 * @arg2	Argument 2 to requested query data call
717 * @arg3	Argument 3 to requested query data call
718 * @data	Returned output data
719 *
720 * This function returns requested data.
721 */
pm_query_data(uint32_t qid,uint32_t arg1,uint32_t arg2,uint32_t arg3,uint32_t * data)722 enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
723 				 uint32_t arg3, uint32_t *data)
724 {
725 	uint32_t ret;
726 	uint32_t version;
727 	uint32_t payload[PAYLOAD_ARG_CNT];
728 	uint32_t fw_api_version;
729 
730 	/* Send request to the PMC */
731 	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_QUERY_DATA, qid, arg1,
732 			 arg2, arg3);
733 
734 	ret = pm_feature_check(PM_QUERY_DATA, &version);
735 	if (PM_RET_SUCCESS == ret) {
736 		fw_api_version = version & 0xFFFF ;
737 		if ((2U == fw_api_version) &&
738 		    ((XPM_QID_CLOCK_GET_NAME == qid) ||
739 		     (XPM_QID_PINCTRL_GET_FUNCTION_NAME == qid))) {
740 			ret = pm_ipi_send_sync(primary_proc, payload, data, 8);
741 			ret = data[0];
742 			data[0] = data[1];
743 			data[1] = data[2];
744 			data[2] = data[3];
745 		} else {
746 			ret = pm_ipi_send_sync(primary_proc, payload, data, 4);
747 		}
748 	}
749 	return ret;
750 }
751 /**
752  * pm_api_ioctl() -  PM IOCTL API for device control and configs
753  * @device_id	Device ID
754  * @ioctl_id	ID of the requested IOCTL
755  * @arg1	Argument 1 to requested IOCTL call
756  * @arg2	Argument 2 to requested IOCTL call
757  * @value	Returned output value
758  *
759  * This function calls IOCTL to firmware for device control and configuration.
760  *
761  * @return	Returns status, either success or error+reason
762  */
pm_api_ioctl(uint32_t device_id,uint32_t ioctl_id,uint32_t arg1,uint32_t arg2,uint32_t * value)763 enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id,
764 				uint32_t arg1, uint32_t arg2, uint32_t *value)
765 {
766 	uint32_t payload[PAYLOAD_ARG_CNT];
767 
768 	switch (ioctl_id) {
769 	case IOCTL_SET_PLL_FRAC_MODE:
770 		return pm_pll_set_mode(arg1, arg2);
771 	case IOCTL_GET_PLL_FRAC_MODE:
772 		return pm_pll_get_mode(arg1, value);
773 	case IOCTL_SET_PLL_FRAC_DATA:
774 		return pm_pll_set_param(arg1, PM_PLL_PARAM_DATA, arg2);
775 	case IOCTL_GET_PLL_FRAC_DATA:
776 		return pm_pll_get_param(arg1, PM_PLL_PARAM_DATA, value);
777 	default:
778 		/* Send request to the PMC */
779 		PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_IOCTL, device_id,
780 				 ioctl_id, arg1, arg2);
781 		return pm_ipi_send_sync(primary_proc, payload, value, 1);
782 	}
783 }
784 
785 /**
786  * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
787  * @target	Device id of the targeted PU or subsystem
788  * @wkup_node	Device id of the wakeup peripheral
789  * @enable	Enable or disable the specified peripheral as wake source
790  *
791  * @return	Returns status, either success or error+reason
792  */
pm_set_wakeup_source(uint32_t target,uint32_t wkup_device,uint8_t enable)793 enum pm_ret_status pm_set_wakeup_source(uint32_t target, uint32_t wkup_device,
794 					uint8_t enable)
795 {
796 	uint32_t payload[PAYLOAD_ARG_CNT];
797 
798 	PM_PACK_PAYLOAD4(payload, LIBPM_MODULE_ID, PM_SET_WAKEUP_SOURCE, target,
799 			 wkup_device, enable);
800 	return pm_ipi_send(primary_proc, payload);
801 }
802 
803 /**
804  * pm_get_chipid() - Read silicon ID registers
805  * @value       Buffer for return values. Must be large enough
806  *		to hold 8 bytes.
807  *
808  * @return      Returns silicon ID registers
809  */
pm_get_chipid(uint32_t * value)810 enum pm_ret_status pm_get_chipid(uint32_t *value)
811 {
812 	uint32_t payload[PAYLOAD_ARG_CNT];
813 
814 	/* Send request to the PMC */
815 	PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, PM_GET_CHIPID);
816 
817 	return pm_ipi_send_sync(primary_proc, payload, value, 2);
818 }
819 
820 /**
821  * pm_feature_check() - Returns the supported API version if supported
822  * @api_id	API ID to check
823  * @value	Returned supported API version
824  *
825  * @return	Returns status, either success or error+reason
826  */
pm_feature_check(uint32_t api_id,unsigned int * version)827 enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version)
828 {
829 	uint32_t payload[PAYLOAD_ARG_CNT], fw_api_version;
830 	uint32_t status;
831 
832 	switch (api_id) {
833 	case PM_GET_CALLBACK_DATA:
834 	case PM_GET_TRUSTZONE_VERSION:
835 	case PM_LOAD_PDI:
836 		*version = (PM_API_BASE_VERSION << 16);
837 		return PM_RET_SUCCESS;
838 	case PM_GET_API_VERSION:
839 	case PM_GET_DEVICE_STATUS:
840 	case PM_GET_OP_CHARACTERISTIC:
841 	case PM_REQ_SUSPEND:
842 	case PM_SELF_SUSPEND:
843 	case PM_FORCE_POWERDOWN:
844 	case PM_ABORT_SUSPEND:
845 	case PM_REQ_WAKEUP:
846 	case PM_SET_WAKEUP_SOURCE:
847 	case PM_SYSTEM_SHUTDOWN:
848 	case PM_REQUEST_DEVICE:
849 	case PM_RELEASE_DEVICE:
850 	case PM_SET_REQUIREMENT:
851 	case PM_RESET_ASSERT:
852 	case PM_RESET_GET_STATUS:
853 	case PM_GET_CHIPID:
854 	case PM_PINCTRL_REQUEST:
855 	case PM_PINCTRL_RELEASE:
856 	case PM_PINCTRL_GET_FUNCTION:
857 	case PM_PINCTRL_SET_FUNCTION:
858 	case PM_PINCTRL_CONFIG_PARAM_GET:
859 	case PM_PINCTRL_CONFIG_PARAM_SET:
860 	case PM_IOCTL:
861 	case PM_CLOCK_ENABLE:
862 	case PM_CLOCK_DISABLE:
863 	case PM_CLOCK_GETSTATE:
864 	case PM_CLOCK_SETDIVIDER:
865 	case PM_CLOCK_GETDIVIDER:
866 	case PM_CLOCK_SETPARENT:
867 	case PM_CLOCK_GETPARENT:
868 	case PM_CLOCK_GETRATE:
869 	case PM_PLL_SET_PARAMETER:
870 	case PM_PLL_GET_PARAMETER:
871 	case PM_PLL_SET_MODE:
872 	case PM_PLL_GET_MODE:
873 	case PM_FEATURE_CHECK:
874 	case PM_INIT_FINALIZE:
875 	case PM_SET_MAX_LATENCY:
876 	case PM_REGISTER_NOTIFIER:
877 		*version = (PM_API_BASE_VERSION << 16);
878 		break;
879 	case PM_QUERY_DATA:
880 		*version = (PM_API_QUERY_DATA_VERSION << 16);
881 		break;
882 	default:
883 		*version = 0U;
884 		return PM_RET_ERROR_NOFEATURE;
885 	}
886 
887 	PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_FEATURE_CHECK, api_id);
888 
889 	status = pm_ipi_send_sync(primary_proc, payload, &fw_api_version, 1);
890 	if (status != PM_RET_SUCCESS)
891 		return status;
892 
893 	*version |= fw_api_version;
894 
895 	return PM_RET_SUCCESS;
896 }
897 
898 /**
899  * pm_load_pdi() - Load the PDI
900  *
901  * This function provides support to load PDI from linux
902  *
903  * src:        Source device of pdi(DDR, OCM, SD etc)
904  * address_low: lower 32-bit Linear memory space address
905  * address_high: higher 32-bit Linear memory space address
906  *
907  * @return      Returns status, either success or error+reason
908  */
pm_load_pdi(uint32_t src,uint32_t address_low,uint32_t address_high)909 enum pm_ret_status pm_load_pdi(uint32_t src,
910 			       uint32_t address_low, uint32_t address_high)
911 {
912 	uint32_t payload[PAYLOAD_ARG_CNT];
913 
914 	/* Send request to the PMU */
915 	PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, PM_LOAD_PDI, src,
916 			 address_high, address_low);
917 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
918 }
919 
920 /**
921  * pm_get_op_characteristic() - PM call to request operating characteristics
922  *                              of a device
923  * @device_id   Device id
924  * @type        Type of the operating characteristic
925  *              (power, temperature and latency)
926  * @result      Returns the operating characteristic for the requested device,
927  *              specified by the type
928  *
929  * @return      Returns status, either success or error+reason
930  */
pm_get_op_characteristic(uint32_t device_id,enum pm_opchar_type type,uint32_t * result)931 enum pm_ret_status pm_get_op_characteristic(uint32_t device_id,
932 					    enum pm_opchar_type type,
933 					    uint32_t *result)
934 {
935 	uint32_t payload[PAYLOAD_ARG_CNT];
936 
937 	/* Send request to the PMC */
938 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_GET_OP_CHARACTERISTIC,
939 			 device_id, type);
940 	return pm_ipi_send_sync(primary_proc, payload, result, 1);
941 }
942 
943 /**
944  * pm_set_max_latency() - PM call to change in the maximum wake-up latency
945  *			  requirements for a specific device currently
946  *			  used by that CPU.
947  * @device_id	Device ID
948  * @latency	Latency value
949  *
950  * @return	Returns status, either success or error+reason
951  */
pm_set_max_latency(uint32_t device_id,uint32_t latency)952 enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency)
953 {
954 	uint32_t payload[PAYLOAD_ARG_CNT];
955 
956 	/* Send request to the PMC */
957 	PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_SET_MAX_LATENCY,
958 			 device_id, latency);
959 
960 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
961 }
962 
963 /**
964  * pm_register_notifier() - PM call to register a subsystem to be notified
965  * 			    about the device event
966  * @device_id	Device ID for the Node to which the event is related
967  * @event	Event in question
968  * @wake	Wake subsystem upon capturing the event if value 1
969  * @enable	Enable the registration for value 1, disable for value 0
970  *
971  * @return	Returns status, either success or error+reason
972  */
pm_register_notifier(uint32_t device_id,uint32_t event,uint32_t wake,uint32_t enable)973 enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
974 					uint32_t wake, uint32_t enable)
975 {
976 	uint32_t payload[PAYLOAD_ARG_CNT];
977 
978 	/* Send request to the PMC */
979 	PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_REGISTER_NOTIFIER,
980 			 device_id, event, wake, enable);
981 
982 	return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
983 }
984