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