blob: eae881e223c1e6824d6004ec495e4e95d6fc382e [file] [log] [blame]
Tejas Patel9d09ff92019-01-08 01:46:35 -08001/*
Venkatesh Yadav Abbarapu95ecd452019-12-10 22:16:36 -05002 * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved.
Tejas Patel9d09ff92019-01-08 01:46:35 -08003 *
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"
Rajan Vaja030620d2020-11-23 04:13:54 -080017#include "pm_defs.h"
Tejas Patel9d09ff92019-01-08 01:46:35 -080018
19/*********************************************************************
20 * Target module IDs macros
21 ********************************************************************/
22#define LIBPM_MODULE_ID 0x2
23#define LOADER_MODULE_ID 0x7
24
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -080025/* default shutdown/reboot scope is system(2) */
26static 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 */
33unsigned int pm_get_shutdown_scope(void)
34{
35 return pm_shutdown_scope;
36}
37
Tejas Patel9d09ff92019-01-08 01:46:35 -080038/**
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
Tejas Patelfe0e10a2019-12-08 23:29:44 -080045#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
Tejas Patel9d09ff92019-01-08 01:46:35 -080070/* 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 */
78enum 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}
Tejas Patelfe0e10a2019-12-08 23:29:44 -080086
87/**
Ravi Patel476b5b12019-08-12 03:10:10 -070088 * 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 */
94enum 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/**
Tejas Patelfe0e10a2019-12-08 23:29:44 -0800104 * 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 */
115enum 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 */
152enum 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 */
178enum 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}
Tejas Patel41f3e0b2019-01-08 01:46:37 -0800191
192/**
Tejas Patel49cd8712019-01-23 14:18:51 +0530193 * 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 */
208enum 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/**
Tejas Patel41f3e0b2019-01-08 01:46:37 -0800221 * 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 */
229enum 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 */
247enum 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 */
267enum 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 */
286enum 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}
Tejas Patel87c4f3a2019-01-08 01:46:38 -0800296
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 */
304enum 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 */
322enum 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}
Tejas Patel20e92022019-01-08 01:46:39 -0800331
332/**
Rajan Vaja649e9242019-03-04 11:09:40 +0530333 * 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 */
338void 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/**
Tejas Patel20e92022019-01-08 01:46:39 -0800349 * pm_pinctrl_request() - Request a pin
350 * @pin Pin ID
351 *
352 * @return Returns status, either success or error+reason
353 */
354enum 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 */
370enum 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 */
387enum 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 */
405enum 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 */
424enum 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 */
444enum 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}
Tejas Patel1f56fb12019-01-08 01:46:40 -0800455
456/**
457 * pm_clock_enable() - Enable the clock
458 * @clk_id Clock ID
459 *
460 * @return Returns status, either success or error+reason
461 */
462enum 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 */
478enum 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 */
495enum 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 */
512enum 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 */
530enum 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 */
547enum 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 */
565enum 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}
Tejas Patel84275bf2020-09-01 04:43:53 -0700574/**
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 */
581enum 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}
Tejas Patel023116d2019-01-08 01:46:41 -0800590
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 */
599enum 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 */
619enum 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 */
638enum 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 */
656enum 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}
Tejas Patel6b282252019-01-10 03:03:47 -0800665
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 */
674enum 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
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800690 * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
Tejas Patel6b282252019-01-10 03:03:47 -0800691 * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
692 *
693 * @return Returns status, either success or error+reason
694 */
695enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
696{
697 uint32_t payload[PAYLOAD_ARG_CNT];
698
Saeed Nowshadic5a1bda2019-12-08 23:35:35 -0800699 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
Tejas Patel6b282252019-01-10 03:03:47 -0800705 /* 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}
Tejas Patel9141f442019-01-10 03:03:48 -0800711
712/**
Tejas Patela3e34ad2019-02-01 17:25:19 +0530713* 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*/
722enum pm_ret_status pm_query_data(uint32_t qid, uint32_t arg1, uint32_t arg2,
723 uint32_t arg3, uint32_t *data)
724{
Rajan Vaja030620d2020-11-23 04:13:54 -0800725 uint32_t ret;
726 uint32_t version;
Tejas Patela3e34ad2019-02-01 17:25:19 +0530727 uint32_t payload[PAYLOAD_ARG_CNT];
Rajan Vaja030620d2020-11-23 04:13:54 -0800728 uint32_t fw_api_version;
Tejas Patela3e34ad2019-02-01 17:25:19 +0530729
730 /* Send request to the PMC */
731 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_QUERY_DATA, qid, arg1,
732 arg2, arg3);
Rajan Vaja030620d2020-11-23 04:13:54 -0800733
734 ret = pm_feature_check(PM_QUERY_DATA, &version);
Manish Pandey3bc1bea2020-12-10 10:48:22 +0000735 if (PM_RET_SUCCESS == ret) {
Rajan Vaja030620d2020-11-23 04:13:54 -0800736 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;
Tejas Patela3e34ad2019-02-01 17:25:19 +0530750}
751/**
Tejas Patel9141f442019-01-10 03:03:48 -0800752 * 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 */
763enum 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}
Tejas Pateldb812052019-01-23 14:18:53 +0530784
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 */
793enum 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}
Ravi Patel22b0b492019-03-06 12:34:46 +0530802
803/**
Ravi Patelbd4aa5a2019-08-12 03:17:54 -0700804 * 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 */
810enum 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/**
Ravi Patel22b0b492019-03-06 12:34:46 +0530821 * 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 */
827enum 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:
Ravi Patel22b0b492019-03-06 12:34:46 +0530835 *version = (PM_API_BASE_VERSION << 16);
836 return PM_RET_SUCCESS;
837 case PM_GET_API_VERSION:
838 case PM_GET_DEVICE_STATUS:
Saeed Nowshadi2294b422019-06-03 10:22:35 -0700839 case PM_GET_OP_CHARACTERISTIC:
Ravi Patel22b0b492019-03-06 12:34:46 +0530840 case PM_REQ_SUSPEND:
841 case PM_SELF_SUSPEND:
842 case PM_FORCE_POWERDOWN:
843 case PM_ABORT_SUSPEND:
844 case PM_REQ_WAKEUP:
845 case PM_SET_WAKEUP_SOURCE:
846 case PM_SYSTEM_SHUTDOWN:
847 case PM_REQUEST_DEVICE:
848 case PM_RELEASE_DEVICE:
849 case PM_SET_REQUIREMENT:
850 case PM_RESET_ASSERT:
851 case PM_RESET_GET_STATUS:
Venkatesh Yadav Abbarapu95ecd452019-12-10 22:16:36 -0500852 case PM_GET_CHIPID:
Ravi Patel22b0b492019-03-06 12:34:46 +0530853 case PM_PINCTRL_REQUEST:
854 case PM_PINCTRL_RELEASE:
855 case PM_PINCTRL_GET_FUNCTION:
856 case PM_PINCTRL_SET_FUNCTION:
857 case PM_PINCTRL_CONFIG_PARAM_GET:
858 case PM_PINCTRL_CONFIG_PARAM_SET:
859 case PM_IOCTL:
Rajan Vaja030620d2020-11-23 04:13:54 -0800860 *version = (PM_API_BASE_VERSION << 16);
861 break;
Ravi Patel22b0b492019-03-06 12:34:46 +0530862 case PM_QUERY_DATA:
Rajan Vaja030620d2020-11-23 04:13:54 -0800863 *version = (PM_API_QUERY_DATA_VERSION << 16);
864 break;
Ravi Patel22b0b492019-03-06 12:34:46 +0530865 case PM_CLOCK_ENABLE:
866 case PM_CLOCK_DISABLE:
867 case PM_CLOCK_GETSTATE:
868 case PM_CLOCK_SETDIVIDER:
869 case PM_CLOCK_GETDIVIDER:
870 case PM_CLOCK_SETPARENT:
871 case PM_CLOCK_GETPARENT:
Tejas Patel84275bf2020-09-01 04:43:53 -0700872 case PM_CLOCK_GETRATE:
Ravi Patel22b0b492019-03-06 12:34:46 +0530873 case PM_PLL_SET_PARAMETER:
874 case PM_PLL_GET_PARAMETER:
875 case PM_PLL_SET_MODE:
876 case PM_PLL_GET_MODE:
877 case PM_FEATURE_CHECK:
Ravi Patel476b5b12019-08-12 03:10:10 -0700878 case PM_INIT_FINALIZE:
Tejas Patel5c154e12020-11-25 01:53:12 -0800879 case PM_SET_MAX_LATENCY:
Tejas Patel42015552020-11-25 01:56:57 -0800880 case PM_REGISTER_NOTIFIER:
Ravi Patel22b0b492019-03-06 12:34:46 +0530881 *version = (PM_API_BASE_VERSION << 16);
882 break;
Jolly Shahed05a712019-03-22 05:33:39 +0530883 case PM_LOAD_PDI:
884 *version = (PM_API_BASE_VERSION << 16);
885 return PM_RET_SUCCESS;
Ravi Patel22b0b492019-03-06 12:34:46 +0530886 default:
887 *version = 0U;
888 return PM_RET_ERROR_NOFEATURE;
889 }
890
891 PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, PM_FEATURE_CHECK, api_id);
892
893 status = pm_ipi_send_sync(primary_proc, payload, &fw_api_version, 1);
894 if (status != PM_RET_SUCCESS)
895 return status;
896
897 *version |= fw_api_version;
898
899 return PM_RET_SUCCESS;
900}
Jolly Shahed05a712019-03-22 05:33:39 +0530901
902/**
903 * pm_load_pdi() - Load the PDI
904 *
905 * This function provides support to load PDI from linux
906 *
907 * src: Source device of pdi(DDR, OCM, SD etc)
908 * address_low: lower 32-bit Linear memory space address
909 * address_high: higher 32-bit Linear memory space address
910 *
911 * @return Returns status, either success or error+reason
912 */
913enum pm_ret_status pm_load_pdi(uint32_t src,
914 uint32_t address_low, uint32_t address_high)
915{
916 uint32_t payload[PAYLOAD_ARG_CNT];
917
918 /* Send request to the PMU */
919 PM_PACK_PAYLOAD4(payload, LOADER_MODULE_ID, PM_LOAD_PDI, src,
920 address_high, address_low);
921 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
922}
Saeed Nowshadi2294b422019-06-03 10:22:35 -0700923
924/**
925 * pm_get_op_characteristic() - PM call to request operating characteristics
926 * of a device
927 * @device_id Device id
928 * @type Type of the operating characteristic
929 * (power, temperature and latency)
930 * @result Returns the operating characteristic for the requested device,
931 * specified by the type
932 *
933 * @return Returns status, either success or error+reason
934 */
935enum pm_ret_status pm_get_op_characteristic(uint32_t device_id,
936 enum pm_opchar_type type,
937 uint32_t *result)
938{
939 uint32_t payload[PAYLOAD_ARG_CNT];
940
941 /* Send request to the PMC */
942 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_GET_OP_CHARACTERISTIC,
943 device_id, type);
944 return pm_ipi_send_sync(primary_proc, payload, result, 1);
945}
Tejas Patel5c154e12020-11-25 01:53:12 -0800946
947/**
948 * pm_set_max_latency() - PM call to change in the maximum wake-up latency
949 * requirements for a specific device currently
950 * used by that CPU.
951 * @device_id Device ID
952 * @latency Latency value
953 *
954 * @return Returns status, either success or error+reason
955 */
956enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency)
957{
958 uint32_t payload[PAYLOAD_ARG_CNT];
959
960 /* Send request to the PMC */
961 PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, PM_SET_MAX_LATENCY,
962 device_id, latency);
963
964 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
965}
Tejas Patel42015552020-11-25 01:56:57 -0800966
967/**
968 * pm_register_notifier() - PM call to register a subsystem to be notified
969 * about the device event
970 * @device_id Device ID for the Node to which the event is related
971 * @event Event in question
972 * @wake Wake subsystem upon capturing the event if value 1
973 * @enable Enable the registration for value 1, disable for value 0
974 *
975 * @return Returns status, either success or error+reason
976 */
977enum pm_ret_status pm_register_notifier(uint32_t device_id, uint32_t event,
978 uint32_t wake, uint32_t enable)
979{
980 uint32_t payload[PAYLOAD_ARG_CNT];
981
982 /* Send request to the PMC */
983 PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, PM_REGISTER_NOTIFIER,
984 device_id, event, wake, enable);
985
986 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
987}