blob: 216bc98017e9810c0082b8121d4a914b5235170d [file] [log] [blame]
Tejas Patel9d09ff92019-01-08 01:46:35 -08001/*
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>
Tejas Patelfe0e10a2019-12-08 23:29:44 -080014#include <plat/common/platform.h>
Tejas Patel9d09ff92019-01-08 01:46:35 -080015#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
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -080024/* default shutdown/reboot scope is system(2) */
25static 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 */
32unsigned int pm_get_shutdown_scope(void)
33{
34 return pm_shutdown_scope;
35}
36
Tejas Patel9d09ff92019-01-08 01:46:35 -080037/**
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
Tejas Patelfe0e10a2019-12-08 23:29:44 -080044#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
Tejas Patel9d09ff92019-01-08 01:46:35 -080069/* 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 */
77enum 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}
Tejas Patelfe0e10a2019-12-08 23:29:44 -080085
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 */
98enum 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 */
135enum 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 */
161enum 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}
Tejas Patel41f3e0b2019-01-08 01:46:37 -0800174
175/**
Tejas Patel49cd8712019-01-23 14:18:51 +0530176 * 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 */
191enum 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/**
Tejas Patel41f3e0b2019-01-08 01:46:37 -0800204 * 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 */
212enum 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 */
230enum 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 */
250enum 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 */
269enum 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}
Tejas Patel87c4f3a2019-01-08 01:46:38 -0800279
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 */
287enum 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 */
305enum 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}
Tejas Patel20e92022019-01-08 01:46:39 -0800314
315/**
Rajan Vaja649e9242019-03-04 11:09:40 +0530316 * 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 */
321void 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/**
Tejas Patel20e92022019-01-08 01:46:39 -0800332 * pm_pinctrl_request() - Request a pin
333 * @pin Pin ID
334 *
335 * @return Returns status, either success or error+reason
336 */
337enum 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 */
353enum 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 */
370enum 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 */
388enum 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 */
407enum 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 */
427enum 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}
Tejas Patel1f56fb12019-01-08 01:46:40 -0800438
439/**
440 * pm_clock_enable() - Enable the clock
441 * @clk_id Clock ID
442 *
443 * @return Returns status, either success or error+reason
444 */
445enum 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 */
461enum 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 */
478enum 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 */
495enum 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 */
513enum 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 */
530enum 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 */
548enum 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}
Tejas Patel023116d2019-01-08 01:46:41 -0800557
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 */
566enum 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 */
586enum 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 */
605enum 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 */
623enum 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}
Tejas Patel6b282252019-01-10 03:03:47 -0800632
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 */
641enum 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
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800657 * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
Tejas Patel6b282252019-01-10 03:03:47 -0800658 * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
659 *
660 * @return Returns status, either success or error+reason
661 */
662enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
663{
664 uint32_t payload[PAYLOAD_ARG_CNT];
665
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800666 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
Tejas Patel6b282252019-01-10 03:03:47 -0800672 /* 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}
Tejas Patel9141f442019-01-10 03:03:48 -0800678
679/**
Tejas Patela3e34ad2019-02-01 17:25:19 +0530680* 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*/
689enum 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/**
Tejas Patel9141f442019-01-10 03:03:48 -0800700 * 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 */
711enum 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}
Tejas Pateldb812052019-01-23 14:18:53 +0530732
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 */
741enum 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}