blob: 1ec06f9d00372761b3d8a6835de99caabdbe43c0 [file] [log] [blame]
Soren Brinkmann76fcae32016-03-06 20:16:27 -08001/*
Rajan Vaja02d18422019-03-04 11:09:39 +05302 * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
Soren Brinkmann76fcae32016-03-06 20:16:27 -08003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soren Brinkmann76fcae32016-03-06 20:16:27 -08005 */
6
7/*
8 * ZynqMP system level PM-API functions and communication with PMU via
9 * IPI interrupts
10 */
11
12#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013#include <plat/common/platform.h>
14
Rajan Vaja35116132018-01-17 02:39:25 -080015#include "pm_api_clock.h"
Rajan Vaja5529a012018-01-17 02:39:23 -080016#include "pm_api_ioctl.h"
Rajan Vaja0ac2be12018-01-17 02:39:21 -080017#include "pm_api_pinctrl.h"
Isla Mitchelle3631462017-07-14 10:46:32 +010018#include "pm_api_sys.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080019#include "pm_client.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080020#include "pm_common.h"
Isla Mitchelle3631462017-07-14 10:46:32 +010021#include "pm_ipi.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080022
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +053023/* default shutdown/reboot scope is system(2) */
24static unsigned int pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
25
26/**
27 * pm_get_shutdown_scope() - Get the currently set shutdown scope
28 *
29 * @return Shutdown scope value
30 */
31unsigned int pm_get_shutdown_scope(void)
32{
33 return pm_shutdown_scope;
34}
35
Soren Brinkmann76fcae32016-03-06 20:16:27 -080036/**
37 * Assigning of argument values into array elements.
38 */
39#define PM_PACK_PAYLOAD1(pl, arg0) { \
40 pl[0] = (uint32_t)(arg0); \
41}
42
43#define PM_PACK_PAYLOAD2(pl, arg0, arg1) { \
44 pl[1] = (uint32_t)(arg1); \
45 PM_PACK_PAYLOAD1(pl, arg0); \
46}
47
48#define PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2) { \
49 pl[2] = (uint32_t)(arg2); \
50 PM_PACK_PAYLOAD2(pl, arg0, arg1); \
51}
52
53#define PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3) { \
54 pl[3] = (uint32_t)(arg3); \
55 PM_PACK_PAYLOAD3(pl, arg0, arg1, arg2); \
56}
57
58#define PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4) { \
59 pl[4] = (uint32_t)(arg4); \
60 PM_PACK_PAYLOAD4(pl, arg0, arg1, arg2, arg3); \
61}
62
63#define PM_PACK_PAYLOAD6(pl, arg0, arg1, arg2, arg3, arg4, arg5) { \
64 pl[5] = (uint32_t)(arg5); \
65 PM_PACK_PAYLOAD5(pl, arg0, arg1, arg2, arg3, arg4); \
66}
67
68/**
69 * pm_self_suspend() - PM call for processor to suspend itself
70 * @nid Node id of the processor or subsystem
71 * @latency Requested maximum wakeup latency (not supported)
Filip Drazic0bd9d0c2016-07-20 17:17:39 +020072 * @state Requested state
Soren Brinkmann76fcae32016-03-06 20:16:27 -080073 * @address Resume address
74 *
75 * This is a blocking call, it will return only once PMU has responded.
76 * On a wakeup, resume address will be automatically set by PMU.
77 *
78 * @return Returns status, either success or error+reason
79 */
80enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
81 unsigned int latency,
82 unsigned int state,
83 uintptr_t address)
84{
85 uint32_t payload[PAYLOAD_ARG_CNT];
86 unsigned int cpuid = plat_my_core_pos();
87 const struct pm_proc *proc = pm_get_proc(cpuid);
88
89 /*
90 * Do client specific suspend operations
91 * (e.g. set powerdown request bit)
92 */
Filip Drazic4c0765a2016-07-26 12:11:33 +020093 pm_client_suspend(proc, state);
Soren Brinkmann76fcae32016-03-06 20:16:27 -080094 /* Send request to the PMU */
95 PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
96 state, address, (address >> 32));
Soren Brinkmannd6c9e032016-09-22 11:35:47 -070097 return pm_ipi_send_sync(proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -080098}
99
100/**
101 * pm_req_suspend() - PM call to request for another PU or subsystem to
102 * be suspended gracefully.
103 * @target Node id of the targeted PU or subsystem
104 * @ack Flag to specify whether acknowledge is requested
105 * @latency Requested wakeup latency (not supported)
106 * @state Requested state (not supported)
107 *
108 * @return Returns status, either success or error+reason
109 */
110enum pm_ret_status pm_req_suspend(enum pm_node_id target,
111 enum pm_request_ack ack,
112 unsigned int latency, unsigned int state)
113{
114 uint32_t payload[PAYLOAD_ARG_CNT];
115
116 /* Send request to the PMU */
117 PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
118 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700119 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800120 else
121 return pm_ipi_send(primary_proc, payload);
122}
123
124/**
125 * pm_req_wakeup() - PM call for processor to wake up selected processor
126 * or subsystem
127 * @target Node id of the processor or subsystem to wake up
128 * @ack Flag to specify whether acknowledge requested
129 * @set_address Resume address presence indicator
130 * 1 resume address specified, 0 otherwise
131 * @address Resume address
132 *
133 * This API function is either used to power up another APU core for SMP
134 * (by PSCI) or to power up an entirely different PU or subsystem, such
135 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
136 * automatically set by PMU.
137 *
138 * @return Returns status, either success or error+reason
139 */
140enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
141 unsigned int set_address,
142 uintptr_t address,
143 enum pm_request_ack ack)
144{
145 uint32_t payload[PAYLOAD_ARG_CNT];
146 uint64_t encoded_address;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800147
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800148
149 /* encode set Address into 1st bit of address */
150 encoded_address = address;
151 encoded_address |= !!set_address;
152
153 /* Send request to the PMU to perform the wake of the PU */
154 PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
155 encoded_address >> 32, ack);
156
157 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700158 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800159 else
160 return pm_ipi_send(primary_proc, payload);
161}
162
163/**
164 * pm_force_powerdown() - PM call to request for another PU or subsystem to
165 * be powered down forcefully
166 * @target Node id of the targeted PU or subsystem
167 * @ack Flag to specify whether acknowledge is requested
168 *
169 * @return Returns status, either success or error+reason
170 */
171enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
172 enum pm_request_ack ack)
173{
174 uint32_t payload[PAYLOAD_ARG_CNT];
175
176 /* Send request to the PMU */
177 PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
178
179 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700180 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800181 else
182 return pm_ipi_send(primary_proc, payload);
183}
184
185/**
186 * pm_abort_suspend() - PM call to announce that a prior suspend request
187 * is to be aborted.
188 * @reason Reason for the abort
189 *
190 * Calling PU expects the PMU to abort the initiated suspend procedure.
191 * This is a non-blocking call without any acknowledge.
192 *
193 * @return Returns status, either success or error+reason
194 */
195enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
196{
197 uint32_t payload[PAYLOAD_ARG_CNT];
198
199 /*
200 * Do client specific abort suspend operations
201 * (e.g. enable interrupts and clear powerdown request bit)
202 */
203 pm_client_abort_suspend();
204 /* Send request to the PMU */
205 /* TODO: allow passing the node ID of the affected CPU */
206 PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
207 primary_proc->node_id);
208 return pm_ipi_send(primary_proc, payload);
209}
210
211/**
212 * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
213 * @target Node id of the targeted PU or subsystem
214 * @wkup_node Node id of the wakeup peripheral
215 * @enable Enable or disable the specified peripheral as wake source
216 *
217 * @return Returns status, either success or error+reason
218 */
219enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
220 enum pm_node_id wkup_node,
221 unsigned int enable)
222{
223 uint32_t payload[PAYLOAD_ARG_CNT];
224
225 PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
226 enable);
227 return pm_ipi_send(primary_proc, payload);
228}
229
230/**
231 * pm_system_shutdown() - PM call to request a system shutdown or restart
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530232 * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
233 * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800234 *
235 * @return Returns status, either success or error+reason
236 */
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700237enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800238{
239 uint32_t payload[PAYLOAD_ARG_CNT];
240
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530241 if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
242 /* Setting scope for subsequent PSCI reboot or shutdown */
243 pm_shutdown_scope = subtype;
244 return PM_RET_SUCCESS;
245 }
246
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700247 PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
Tejas Patelaf4b10e2018-02-09 02:42:59 -0800248 return pm_ipi_send_non_blocking(primary_proc, payload);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800249}
250
251/* APIs for managing PM slaves: */
252
253/**
254 * pm_req_node() - PM call to request a node with specific capabilities
255 * @nid Node id of the slave
256 * @capabilities Requested capabilities of the slave
257 * @qos Quality of service (not supported)
258 * @ack Flag to specify whether acknowledge is requested
259 *
260 * @return Returns status, either success or error+reason
261 */
262enum pm_ret_status pm_req_node(enum pm_node_id nid,
263 unsigned int capabilities,
264 unsigned int qos,
265 enum pm_request_ack ack)
266{
267 uint32_t payload[PAYLOAD_ARG_CNT];
268
269 PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
270
271 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700272 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800273 else
274 return pm_ipi_send(primary_proc, payload);
275}
276
277/**
278 * pm_set_requirement() - PM call to set requirement for PM slaves
279 * @nid Node id of the slave
280 * @capabilities Requested capabilities of the slave
281 * @qos Quality of service (not supported)
282 * @ack Flag to specify whether acknowledge is requested
283 *
284 * This API function is to be used for slaves a PU already has requested
285 *
286 * @return Returns status, either success or error+reason
287 */
288enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
289 unsigned int capabilities,
290 unsigned int qos,
291 enum pm_request_ack ack)
292{
293 uint32_t payload[PAYLOAD_ARG_CNT];
294
295 PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
296 ack);
297
298 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700299 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800300 else
301 return pm_ipi_send(primary_proc, payload);
302}
303
304/**
305 * pm_release_node() - PM call to release a node
306 * @nid Node id of the slave
307 *
308 * @return Returns status, either success or error+reason
309 */
310enum pm_ret_status pm_release_node(enum pm_node_id nid)
311{
312 uint32_t payload[PAYLOAD_ARG_CNT];
313
314 PM_PACK_PAYLOAD2(payload, PM_RELEASE_NODE, nid);
315 return pm_ipi_send(primary_proc, payload);
316}
317
318/**
319 * pm_set_max_latency() - PM call to set wakeup latency requirements
320 * @nid Node id of the slave
321 * @latency Requested maximum wakeup latency
322 *
323 * @return Returns status, either success or error+reason
324 */
325enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
326 unsigned int latency)
327{
328 uint32_t payload[PAYLOAD_ARG_CNT];
329
330 PM_PACK_PAYLOAD3(payload, PM_SET_MAX_LATENCY, nid, latency);
331 return pm_ipi_send(primary_proc, payload);
332}
333
334/* Miscellaneous API functions */
335
336/**
337 * pm_get_api_version() - Get version number of PMU PM firmware
338 * @version Returns 32-bit version number of PMU Power Management Firmware
339 *
340 * @return Returns status, either success or error+reason
341 */
342enum pm_ret_status pm_get_api_version(unsigned int *version)
343{
344 uint32_t payload[PAYLOAD_ARG_CNT];
345
346 /* Send request to the PMU */
347 PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700348 return pm_ipi_send_sync(primary_proc, payload, version, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800349}
350
351/**
352 * pm_set_configuration() - PM call to set system configuration
353 * @phys_addr Physical 32-bit address of data structure in memory
354 *
355 * @return Returns status, either success or error+reason
356 */
357enum pm_ret_status pm_set_configuration(unsigned int phys_addr)
358{
Luca Ceresolif00986c2019-02-28 22:15:35 +0100359 uint32_t payload[PAYLOAD_ARG_CNT];
360
361 PM_PACK_PAYLOAD2(payload, PM_SET_CONFIGURATION, phys_addr);
362 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800363}
364
365/**
Filip Drazicf2ddd912017-03-15 11:50:47 +0100366 * pm_init_finalize() - Call to notify PMU firmware that master has power
367 * management enabled and that it has finished its
368 * initialization
369 *
370 * @return Status returned by the PMU firmware
371 */
372enum pm_ret_status pm_init_finalize(void)
373{
374 uint32_t payload[PAYLOAD_ARG_CNT];
375
376 /* Send request to the PMU */
377 PM_PACK_PAYLOAD1(payload, PM_INIT_FINALIZE);
378 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
379}
380
381/**
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100382 * pm_get_node_status() - PM call to request a node's current status
383 * @nid Node id
384 * @ret_buff Buffer for the return values:
385 * [0] - Current power state of the node
386 * [1] - Current requirements for the node (slave nodes only)
387 * [2] - Current usage status for the node (slave nodes only)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800388 *
389 * @return Returns status, either success or error+reason
390 */
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100391enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
392 uint32_t *ret_buff)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800393{
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800394 uint32_t payload[PAYLOAD_ARG_CNT];
395
396 PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100397 return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800398}
399
400/**
401 * pm_register_notifier() - Register the PU to be notified of PM events
402 * @nid Node id of the slave
403 * @event The event to be notified about
404 * @wake Wake up on event
405 * @enable Enable or disable the notifier
406 *
407 * @return Returns status, either success or error+reason
408 */
409enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
410 unsigned int event,
411 unsigned int wake,
412 unsigned int enable)
413{
Anes Hadziahmetagicc95ae092016-05-12 16:17:34 +0200414 uint32_t payload[PAYLOAD_ARG_CNT];
415
416 PM_PACK_PAYLOAD5(payload, PM_REGISTER_NOTIFIER,
417 nid, event, wake, enable);
418
Soren Brinkmanna1b0a902016-09-30 11:30:21 -0700419 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800420}
421
422/**
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200423 * pm_get_op_characteristic() - PM call to request operating characteristics
424 * of a node
425 * @nid Node id of the slave
426 * @type Type of the operating characteristic
427 * (power, temperature and latency)
428 * @result Returns the operating characteristic for the requested node,
429 * specified by the type
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800430 *
431 * @return Returns status, either success or error+reason
432 */
433enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid,
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200434 enum pm_opchar_type type,
435 uint32_t *result)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800436{
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200437 uint32_t payload[PAYLOAD_ARG_CNT];
438
439 /* Send request to the PMU */
440 PM_PACK_PAYLOAD3(payload, PM_GET_OP_CHARACTERISTIC, nid, type);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700441 return pm_ipi_send_sync(primary_proc, payload, result, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800442}
443
444/* Direct-Control API functions */
445
446/**
447 * pm_reset_assert() - Assert reset
448 * @reset Reset ID
449 * @assert Assert (1) or de-assert (0)
450 *
451 * @return Returns status, either success or error+reason
452 */
453enum pm_ret_status pm_reset_assert(unsigned int reset,
454 unsigned int assert)
455{
456 uint32_t payload[PAYLOAD_ARG_CNT];
457
458 /* Send request to the PMU */
459 PM_PACK_PAYLOAD3(payload, PM_RESET_ASSERT, reset, assert);
460 return pm_ipi_send(primary_proc, payload);
461}
462
463/**
464 * pm_reset_get_status() - Get current status of a reset line
465 * @reset Reset ID
466 * @reset_status Returns current status of selected reset line
467 *
468 * @return Returns status, either success or error+reason
469 */
470enum pm_ret_status pm_reset_get_status(unsigned int reset,
471 unsigned int *reset_status)
472{
473 uint32_t payload[PAYLOAD_ARG_CNT];
474
475 /* Send request to the PMU */
476 PM_PACK_PAYLOAD2(payload, PM_RESET_GET_STATUS, reset);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700477 return pm_ipi_send_sync(primary_proc, payload, reset_status, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800478}
479
480/**
481 * pm_mmio_write() - Perform write to protected mmio
482 * @address Address to write to
483 * @mask Mask to apply
484 * @value Value to write
485 *
486 * This function provides access to PM-related control registers
487 * that may not be directly accessible by a particular PU.
488 *
489 * @return Returns status, either success or error+reason
490 */
491enum pm_ret_status pm_mmio_write(uintptr_t address,
492 unsigned int mask,
493 unsigned int value)
494{
495 uint32_t payload[PAYLOAD_ARG_CNT];
496
497 /* Send request to the PMU */
498 PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700499 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800500}
501
502/**
503 * pm_mmio_read() - Read value from protected mmio
504 * @address Address to write to
505 * @value Value to write
506 *
507 * This function provides access to PM-related control registers
508 * that may not be directly accessible by a particular PU.
509 *
510 * @return Returns status, either success or error+reason
511 */
512enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
513{
514 uint32_t payload[PAYLOAD_ARG_CNT];
515
516 /* Send request to the PMU */
517 PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700518 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800519}
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530520
521/**
522 * pm_fpga_load() - Load the bitstream into the PL.
523 *
524 * This function provides access to the xilfpga library to load
525 * the Bit-stream into PL.
526 *
527 * address_low: lower 32-bit Linear memory space address
528 *
529 * address_high: higher 32-bit Linear memory space address
530 *
531 * size: Number of 32bit words
532 *
533 * @return Returns status, either success or error+reason
534 */
535enum pm_ret_status pm_fpga_load(uint32_t address_low,
536 uint32_t address_high,
537 uint32_t size,
538 uint32_t flags)
539{
540 uint32_t payload[PAYLOAD_ARG_CNT];
541
542 /* Send request to the PMU */
543 PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
544 size, flags);
Siva Durga Prasad Paladugubf83b9c2018-02-07 13:13:01 +0530545 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530546}
547
548/**
549 * pm_fpga_get_status() - Read value from fpga status register
550 * @value Value to read
551 *
552 * This function provides access to the xilfpga library to get
553 * the fpga status
554 * @return Returns status, either success or error+reason
555 */
556enum pm_ret_status pm_fpga_get_status(unsigned int *value)
557{
558 uint32_t payload[PAYLOAD_ARG_CNT];
559
560 /* Send request to the PMU */
561 PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700562 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530563}
Soren Brinkmanncb366812016-09-22 12:21:11 -0700564
565/**
566 * pm_get_chipid() - Read silicon ID registers
567 * @value Buffer for return values. Must be large enough
568 * to hold 8 bytes.
569 *
570 * @return Returns silicon ID registers
571 */
572enum pm_ret_status pm_get_chipid(uint32_t *value)
573{
574 uint32_t payload[PAYLOAD_ARG_CNT];
575
576 /* Send request to the PMU */
577 PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
578 return pm_ipi_send_sync(primary_proc, payload, value, 2);
579}
Soren Brinkmann84f0af42016-09-30 14:24:25 -0700580
581/**
Siva Durga Prasad Paladugude93d982018-04-30 15:49:27 +0530582 * pm_secure_rsaaes() - Load the secure images.
583 *
584 * This function provides access to the xilsecure library to load
585 * the authenticated, encrypted, and authenicated/encrypted images.
586 *
587 * address_low: lower 32-bit Linear memory space address
588 *
589 * address_high: higher 32-bit Linear memory space address
590 *
591 * size: Number of 32bit words
592 *
593 * @return Returns status, either success or error+reason
594 */
595enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
596 uint32_t address_high,
597 uint32_t size,
598 uint32_t flags)
599{
600 uint32_t payload[PAYLOAD_ARG_CNT];
601
602 /* Send request to the PMU */
603 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
604 size, flags);
605 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
606}
607
608/**
Siva Durga Prasad Paladugu8bd905b2018-09-04 18:05:50 +0530609 * pm_aes_engine() - Aes data blob encryption/decryption
610 * This function provides access to the xilsecure library to
611 * encrypt/decrypt data blobs.
612 *
613 * address_low: lower 32-bit address of the AesParams structure
614 *
615 * address_high: higher 32-bit address of the AesParams structure
616 *
617 * value: Returned output value
618 *
619 * @return Returns status, either success or error+reason
620 */
621enum pm_ret_status pm_aes_engine(uint32_t address_high,
622 uint32_t address_low,
623 uint32_t *value)
624{
625 uint32_t payload[PAYLOAD_ARG_CNT];
626
627 /* Send request to the PMU */
628 PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
629 return pm_ipi_send_sync(primary_proc, payload, value, 1);
630}
631
632/**
Rajan Vaja02d18422019-03-04 11:09:39 +0530633 * pm_get_callbackdata() - Read from IPI response buffer
634 * @data - array of PAYLOAD_ARG_CNT elements
635 *
636 * Read value from ipi buffer response buffer.
637 */
638void pm_get_callbackdata(uint32_t *data, size_t count)
639{
640 /* Return if interrupt is not from PMU */
641 if (!pm_ipi_irq_status(primary_proc))
642 return;
643
644 pm_ipi_buff_read_callb(data, count);
645 pm_ipi_irq_clear(primary_proc);
646}
647
648/**
Rajan Vaja83687612018-01-17 02:39:20 -0800649 * pm_pinctrl_request() - Request Pin from firmware
650 * @pin Pin number to request
651 *
652 * This function requests pin from firmware.
653 *
654 * @return Returns status, either success or error+reason.
655 */
656enum pm_ret_status pm_pinctrl_request(unsigned int pin)
657{
Mirela Simonovicedefb042018-09-13 12:49:45 +0200658 uint32_t payload[PAYLOAD_ARG_CNT];
659
660 /* Send request to the PMU */
661 PM_PACK_PAYLOAD2(payload, PM_PINCTRL_REQUEST, pin);
662 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800663}
664
665/**
666 * pm_pinctrl_release() - Release Pin from firmware
667 * @pin Pin number to release
668 *
669 * This function releases pin from firmware.
670 *
671 * @return Returns status, either success or error+reason.
672 */
673enum pm_ret_status pm_pinctrl_release(unsigned int pin)
674{
Mirela Simonovicedefb042018-09-13 12:49:45 +0200675 uint32_t payload[PAYLOAD_ARG_CNT];
676
677 /* Send request to the PMU */
678 PM_PACK_PAYLOAD2(payload, PM_PINCTRL_RELEASE, pin);
679 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800680}
681
682/**
683 * pm_pinctrl_get_function() - Read function id set for the given pin
684 * @pin Pin number
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200685 * @fid ID of function currently set for given pin
Rajan Vaja83687612018-01-17 02:39:20 -0800686 *
687 * This function provides the function currently set for the given pin.
688 *
689 * @return Returns status, either success or error+reason
690 */
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200691enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, unsigned int *fid)
Rajan Vaja83687612018-01-17 02:39:20 -0800692{
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200693 uint32_t payload[PAYLOAD_ARG_CNT];
694
695 PM_PACK_PAYLOAD2(payload, PM_PINCTRL_GET_FUNCTION, pin);
696 return pm_ipi_send_sync(primary_proc, payload, fid, 1);
Rajan Vaja83687612018-01-17 02:39:20 -0800697}
698
699/**
700 * pm_pinctrl_set_function() - Set function id set for the given pin
701 * @pin Pin number
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200702 * @fid ID of function to set for given pin
Rajan Vaja83687612018-01-17 02:39:20 -0800703 *
704 * @return Returns status, either success or error+reason
705 */
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200706enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, unsigned int fid)
Rajan Vaja83687612018-01-17 02:39:20 -0800707{
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200708 uint32_t payload[PAYLOAD_ARG_CNT];
709
710 /* Send request to the PMU */
711 PM_PACK_PAYLOAD3(payload, PM_PINCTRL_SET_FUNCTION, pin, fid);
712 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800713}
714
715/**
716 * pm_pinctrl_get_config() - Read value of requested config param for given pin
717 * @pin Pin number
718 * @param Parameter values to be read
719 * @value Buffer for configuration Parameter value
720 *
721 * This function provides the configuration parameter value for the given pin.
722 *
723 * @return Returns status, either success or error+reason
724 */
725enum pm_ret_status pm_pinctrl_get_config(unsigned int pin,
726 unsigned int param,
727 unsigned int *value)
728{
Mirela Simonovic4dadd9c2020-11-22 23:31:14 -0800729 uint32_t payload[PAYLOAD_ARG_CNT];
730
731 PM_PACK_PAYLOAD3(payload, PM_PINCTRL_CONFIG_PARAM_GET, pin, param);
732 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Rajan Vaja83687612018-01-17 02:39:20 -0800733}
734
735/**
Mirela Simonovic4dadd9c2020-11-22 23:31:14 -0800736 * pm_pinctrl_set_config() - Set value of requested config param for given pin
Rajan Vaja83687612018-01-17 02:39:20 -0800737 * @pin Pin number
738 * @param Parameter to set
739 * @value Parameter value to set
740 *
Rajan Vaja83687612018-01-17 02:39:20 -0800741 * @return Returns status, either success or error+reason
742 */
743enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
744 unsigned int param,
745 unsigned int value)
746{
Mirela Simonovic4dadd9c2020-11-22 23:31:14 -0800747 uint32_t payload[PAYLOAD_ARG_CNT];
748
749 /* Send request to the PMU */
750 PM_PACK_PAYLOAD4(payload, PM_PINCTRL_CONFIG_PARAM_SET, pin, param,
751 value);
752 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800753}
Rajan Vaja5529a012018-01-17 02:39:23 -0800754
755/**
756 * pm_ioctl() - PM IOCTL API for device control and configs
757 * @node_id Node ID of the device
758 * @ioctl_id ID of the requested IOCTL
759 * @arg1 Argument 1 to requested IOCTL call
760 * @arg2 Argument 2 to requested IOCTL call
761 * @out Returned output value
762 *
763 * This function calls IOCTL to firmware for device control and configuration.
764 *
765 * @return Returns status, either success or error+reason
766 */
767enum pm_ret_status pm_ioctl(enum pm_node_id nid,
768 unsigned int ioctl_id,
769 unsigned int arg1,
770 unsigned int arg2,
771 unsigned int *value)
772{
773 return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
774}
Rajan Vaja35116132018-01-17 02:39:25 -0800775
776/**
Rajan Vajab34deca2019-03-20 01:13:21 +0530777 * pm_clock_get_max_divisor - PM call to get max divisor
778 * @clock_id Clock ID
779 * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2)
780 * @max_div Maximum supported divisor
781 *
782 * This function is used by master to get maximum supported value.
783 *
784 * Return: Returns status, either success or error+reason.
785 */
786static enum pm_ret_status pm_clock_get_max_divisor(unsigned int clock_id,
787 uint8_t div_type,
788 uint32_t *max_div)
789{
790 return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
791}
792
793/**
Rajan Vajada959402018-07-20 03:16:27 -0700794 * pm_clock_get_num_clocks - PM call to request number of clocks
795 * @nclockss: Number of clocks
796 *
797 * This function is used by master to get number of clocks.
798 *
799 * Return: Returns status, either success or error+reason.
800 */
801static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
802{
803 return pm_api_clock_get_num_clocks(nclocks);
804}
805
806/**
Rajan Vaja35116132018-01-17 02:39:25 -0800807 * pm_clock_get_name() - PM call to request a clock's name
808 * @clock_id Clock ID
809 * @name Name of clock (max 16 bytes)
810 *
811 * This function is used by master to get nmae of clock specified
812 * by given clock ID.
Rajan Vaja35116132018-01-17 02:39:25 -0800813 */
Rajan Vajacd825682020-11-23 21:33:39 -0800814static void pm_clock_get_name(unsigned int clock_id, char *name)
Rajan Vaja35116132018-01-17 02:39:25 -0800815{
Rajan Vajacd825682020-11-23 21:33:39 -0800816 pm_api_clock_get_name(clock_id, name);
Rajan Vaja35116132018-01-17 02:39:25 -0800817}
818
819/**
820 * pm_clock_get_topology() - PM call to request a clock's topology
821 * @clock_id Clock ID
822 * @index Topology index for next toplogy node
823 * @topology Buffer to store nodes in topology and flags
824 *
825 * This function is used by master to get topology information for the
826 * clock specified by given clock ID. Each response would return 3
827 * topology nodes. To get next nodes, caller needs to call this API with
828 * index of next node. Index starts from 0.
829 *
830 * @return Returns status, either success or error+reason
831 */
832static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id,
833 unsigned int index,
834 uint32_t *topology)
835{
836 return pm_api_clock_get_topology(clock_id, index, topology);
837}
838
839/**
840 * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
841 * parameters for fixed clock
842 * @clock_id Clock ID
843 * @mul Multiplication value
844 * @div Divisor value
845 *
846 * This function is used by master to get fixed factor parameers for the
847 * fixed clock. This API is application only for the fixed clock.
848 *
849 * @return Returns status, either success or error+reason
850 */
851static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id,
852 uint32_t *mul,
853 uint32_t *div)
854{
855 return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
856}
857
858/**
859 * pm_clock_get_parents() - PM call to request a clock's first 3 parents
860 * @clock_id Clock ID
861 * @index Index of next parent
862 * @parents Parents of the given clock
863 *
864 * This function is used by master to get clock's parents information.
865 * This API will return 3 parents with a single response. To get other
866 * parents, master should call same API in loop with new parent index
867 * till error is returned.
868 *
869 * E.g First call should have index 0 which will return parents 0, 1 and
870 * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
871 * so on.
872 *
873 * @return Returns status, either success or error+reason
874 */
875static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id,
876 unsigned int index,
877 uint32_t *parents)
878{
879 return pm_api_clock_get_parents(clock_id, index, parents);
880}
881
882/**
883 * pm_clock_get_attributes() - PM call to request a clock's attributes
884 * @clock_id Clock ID
885 * @attr Clock attributes
886 *
887 * This function is used by master to get clock's attributes
888 * (e.g. valid, clock type, etc).
889 *
890 * @return Returns status, either success or error+reason
891 */
892static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
893 uint32_t *attr)
894{
895 return pm_api_clock_get_attributes(clock_id, attr);
896}
897
898/**
Jolly Shaha5209802019-01-04 11:45:59 -0800899 * pm_clock_gate() - Configure clock gate
900 * @clock_id Id of the clock to be configured
901 * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
902 *
903 * @return Error if an argument is not valid or status as returned by the
904 * PM controller (PMU)
905 */
906static enum pm_ret_status pm_clock_gate(unsigned int clock_id,
907 unsigned char enable)
908{
909 uint32_t payload[PAYLOAD_ARG_CNT];
910 enum pm_ret_status status;
911 enum pm_api_id api_id;
912
913 /* Check if clock ID is valid and return an error if it is not */
914 status = pm_clock_id_is_valid(clock_id);
915 if (status != PM_RET_SUCCESS)
916 return status;
917
918 if (enable)
919 api_id = PM_CLOCK_ENABLE;
920 else
921 api_id = PM_CLOCK_DISABLE;
922
923 /* Send request to the PMU */
924 PM_PACK_PAYLOAD2(payload, api_id, clock_id);
Mirela Simonovic64514a72018-08-24 17:09:07 +0200925 status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
926
927 /* If action fails due to the lack of permissions filter the error */
928 if (status == PM_RET_ERROR_ACCESS)
929 status = PM_RET_SUCCESS;
930
931 return status;
Jolly Shaha5209802019-01-04 11:45:59 -0800932}
933
934/**
Rajan Vaja35116132018-01-17 02:39:25 -0800935 * pm_clock_enable() - Enable the clock for given id
936 * @clock_id: Id of the clock to be enabled
937 *
938 * This function is used by master to enable the clock
939 * including peripherals and PLL clocks.
940 *
Jolly Shaha5209802019-01-04 11:45:59 -0800941 * @return: Error if an argument is not valid or status as returned by the
942 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -0800943 */
Rajan Vaja35116132018-01-17 02:39:25 -0800944enum pm_ret_status pm_clock_enable(unsigned int clock_id)
945{
Jolly Shaha5209802019-01-04 11:45:59 -0800946 struct pm_pll *pll;
947
948 /* First try to handle it as a PLL */
949 pll = pm_clock_get_pll(clock_id);
950 if (pll)
951 return pm_clock_pll_enable(pll);
952
953 /* It's an on-chip clock, PMU should configure clock's gate */
954 return pm_clock_gate(clock_id, 1);
Rajan Vaja35116132018-01-17 02:39:25 -0800955}
956
957/**
958 * pm_clock_disable - Disable the clock for given id
959 * @clock_id: Id of the clock to be disable
960 *
961 * This function is used by master to disable the clock
962 * including peripherals and PLL clocks.
963 *
Jolly Shaha9057a02019-01-02 12:54:40 -0800964 * @return: Error if an argument is not valid or status as returned by the
965 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -0800966 */
Rajan Vaja35116132018-01-17 02:39:25 -0800967enum pm_ret_status pm_clock_disable(unsigned int clock_id)
968{
Jolly Shaha9057a02019-01-02 12:54:40 -0800969 struct pm_pll *pll;
970
971 /* First try to handle it as a PLL */
972 pll = pm_clock_get_pll(clock_id);
973 if (pll)
974 return pm_clock_pll_disable(pll);
975
976 /* It's an on-chip clock, PMU should configure clock's gate */
977 return pm_clock_gate(clock_id, 0);
Rajan Vaja35116132018-01-17 02:39:25 -0800978}
979
980/**
981 * pm_clock_getstate - Get the clock state for given id
982 * @clock_id: Id of the clock to be queried
983 * @state: 1/0 (Enabled/Disabled)
984 *
985 * This function is used by master to get the state of clock
986 * including peripherals and PLL clocks.
987 *
988 * Return: Returns status, either success or error+reason.
989 */
990enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
991 unsigned int *state)
992{
Jolly Shah99e8ac92019-01-02 12:55:41 -0800993 struct pm_pll *pll;
994 uint32_t payload[PAYLOAD_ARG_CNT];
995 enum pm_ret_status status;
996
997 /* First try to handle it as a PLL */
998 pll = pm_clock_get_pll(clock_id);
999 if (pll)
1000 return pm_clock_pll_get_state(pll, state);
1001
1002 /* Check if clock ID is a valid on-chip clock */
1003 status = pm_clock_id_is_valid(clock_id);
1004 if (status != PM_RET_SUCCESS)
1005 return status;
1006
1007 /* Send request to the PMU */
1008 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
1009 return pm_ipi_send_sync(primary_proc, payload, state, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001010}
1011
1012/**
1013 * pm_clock_setdivider - Set the clock divider for given id
1014 * @clock_id: Id of the clock
1015 * @divider: divider value
1016 *
1017 * This function is used by master to set divider for any clock
1018 * to achieve desired rate.
1019 *
1020 * Return: Returns status, either success or error+reason.
1021 */
1022enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
1023 unsigned int divider)
1024{
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001025 enum pm_ret_status status;
1026 enum pm_node_id nid;
1027 enum pm_clock_div_id div_id;
1028 uint32_t payload[PAYLOAD_ARG_CNT];
1029 const uint32_t div0 = 0xFFFF0000;
1030 const uint32_t div1 = 0x0000FFFF;
1031 uint32_t val;
1032
1033 /* Get PLL node ID using PLL clock ID */
1034 status = pm_clock_get_pll_node_id(clock_id, &nid);
1035 if (status == PM_RET_SUCCESS)
1036 return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1037
1038 /* Check if clock ID is a valid on-chip clock */
1039 status = pm_clock_id_is_valid(clock_id);
1040 if (status != PM_RET_SUCCESS)
1041 return status;
1042
1043 if (div0 == (divider & div0)) {
1044 div_id = PM_CLOCK_DIV0_ID;
1045 val = divider & ~div0;
1046 } else if (div1 == (divider & div1)) {
1047 div_id = PM_CLOCK_DIV1_ID;
1048 val = (divider & ~div1) >> 16;
1049 } else {
1050 return PM_RET_ERROR_ARGS;
1051 }
1052
1053 /* Send request to the PMU */
1054 PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
1055 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001056}
1057
1058/**
1059 * pm_clock_getdivider - Get the clock divider for given id
1060 * @clock_id: Id of the clock
1061 * @divider: divider value
1062 *
1063 * This function is used by master to get divider values
1064 * for any clock.
1065 *
1066 * Return: Returns status, either success or error+reason.
1067 */
1068enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
1069 unsigned int *divider)
1070{
Jolly Shah4dd11762019-01-04 11:53:37 -08001071 enum pm_ret_status status;
1072 enum pm_node_id nid;
1073 uint32_t payload[PAYLOAD_ARG_CNT];
1074 uint32_t val;
1075
1076 /* Get PLL node ID using PLL clock ID */
1077 status = pm_clock_get_pll_node_id(clock_id, &nid);
1078 if (status == PM_RET_SUCCESS)
1079 return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1080
1081 /* Check if clock ID is a valid on-chip clock */
1082 status = pm_clock_id_is_valid(clock_id);
1083 if (status != PM_RET_SUCCESS)
1084 return status;
1085
1086 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
1087 /* Send request to the PMU to get div0 */
1088 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1089 PM_CLOCK_DIV0_ID);
1090 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1091 if (status != PM_RET_SUCCESS)
1092 return status;
1093 *divider = val;
1094 }
1095
1096 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
1097 /* Send request to the PMU to get div1 */
1098 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1099 PM_CLOCK_DIV1_ID);
1100 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1101 if (status != PM_RET_SUCCESS)
1102 return status;
1103 *divider |= val << 16;
1104 }
1105
1106 return status;
Rajan Vaja35116132018-01-17 02:39:25 -08001107}
1108
1109/**
1110 * pm_clock_setrate - Set the clock rate for given id
1111 * @clock_id: Id of the clock
1112 * @rate: rate value in hz
1113 *
1114 * This function is used by master to set rate for any clock.
1115 *
1116 * Return: Returns status, either success or error+reason.
1117 */
1118enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
1119 uint64_t rate)
1120{
Jolly Shahc1391812019-01-02 13:39:30 -08001121 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001122}
1123
1124/**
1125 * pm_clock_getrate - Get the clock rate for given id
1126 * @clock_id: Id of the clock
1127 * @rate: rate value in hz
1128 *
1129 * This function is used by master to get rate
1130 * for any clock.
1131 *
1132 * Return: Returns status, either success or error+reason.
1133 */
1134enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
1135 uint64_t *rate)
1136{
Jolly Shahc1391812019-01-02 13:39:30 -08001137 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001138}
1139
1140/**
1141 * pm_clock_setparent - Set the clock parent for given id
1142 * @clock_id: Id of the clock
Jolly Shah407fc0a2019-01-04 11:57:40 -08001143 * @parent_index: Index of the parent clock into clock's parents array
Rajan Vaja35116132018-01-17 02:39:25 -08001144 *
1145 * This function is used by master to set parent for any clock.
1146 *
1147 * Return: Returns status, either success or error+reason.
1148 */
1149enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
Jolly Shah407fc0a2019-01-04 11:57:40 -08001150 unsigned int parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001151{
Jolly Shah407fc0a2019-01-04 11:57:40 -08001152 struct pm_pll *pll;
1153 uint32_t payload[PAYLOAD_ARG_CNT];
1154 enum pm_ret_status status;
1155
1156 /* First try to handle it as a PLL */
1157 pll = pm_clock_get_pll_by_related_clk(clock_id);
1158 if (pll)
1159 return pm_clock_pll_set_parent(pll, clock_id, parent_index);
1160
1161 /* Check if clock ID is a valid on-chip clock */
1162 status = pm_clock_id_is_valid(clock_id);
1163 if (status != PM_RET_SUCCESS)
1164 return status;
1165
1166 /* Send request to the PMU */
1167 PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
1168 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001169}
1170
1171/**
1172 * pm_clock_getparent - Get the clock parent for given id
1173 * @clock_id: Id of the clock
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001174 * @parent_index: parent index
Rajan Vaja35116132018-01-17 02:39:25 -08001175 *
1176 * This function is used by master to get parent index
1177 * for any clock.
1178 *
1179 * Return: Returns status, either success or error+reason.
1180 */
1181enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001182 unsigned int *parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001183{
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001184 struct pm_pll *pll;
1185 uint32_t payload[PAYLOAD_ARG_CNT];
1186 enum pm_ret_status status;
1187
1188 /* First try to handle it as a PLL */
1189 pll = pm_clock_get_pll_by_related_clk(clock_id);
1190 if (pll)
1191 return pm_clock_pll_get_parent(pll, clock_id, parent_index);
1192
1193 /* Check if clock ID is a valid on-chip clock */
1194 status = pm_clock_id_is_valid(clock_id);
1195 if (status != PM_RET_SUCCESS)
1196 return status;
1197
1198 /* Send request to the PMU */
1199 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
1200 return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001201}
1202
1203/**
Rajan Vajad5dd8362018-01-30 04:16:31 -08001204 * pm_pinctrl_get_num_pins - PM call to request number of pins
1205 * @npins: Number of pins
1206 *
1207 * This function is used by master to get number of pins
1208 *
1209 * Return: Returns status, either success or error+reason.
1210 */
1211static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
1212{
1213 return pm_api_pinctrl_get_num_pins(npins);
1214}
1215
1216/**
1217 * pm_pinctrl_get_num_functions - PM call to request number of functions
1218 * @nfuncs: Number of functions
1219 *
1220 * This function is used by master to get number of functions
1221 *
1222 * Return: Returns status, either success or error+reason.
1223 */
1224static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
1225{
1226 return pm_api_pinctrl_get_num_functions(nfuncs);
1227}
1228
1229/**
1230 * pm_pinctrl_get_num_function_groups - PM call to request number of
1231 * function groups
1232 * @fid: Id of function
1233 * @ngroups: Number of function groups
1234 *
1235 * This function is used by master to get number of function groups specified
1236 * by given function Id
1237 *
1238 * Return: Returns status, either success or error+reason.
1239 */
1240static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid,
1241 uint32_t *ngroups)
1242{
1243 return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
1244}
1245
1246/**
1247 * pm_pinctrl_get_function_name - PM call to request function name
1248 * @fid: Id of function
1249 * @name: Name of function
1250 *
1251 * This function is used by master to get name of function specified
1252 * by given function Id
Rajan Vajad5dd8362018-01-30 04:16:31 -08001253 */
Rajan Vajacd825682020-11-23 21:33:39 -08001254static void pm_pinctrl_get_function_name(unsigned int fid, char *name)
Rajan Vajad5dd8362018-01-30 04:16:31 -08001255{
Rajan Vajacd825682020-11-23 21:33:39 -08001256 pm_api_pinctrl_get_function_name(fid, name);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001257}
1258
1259/**
1260 * pm_pinctrl_get_function_groups - PM call to request function groups
1261 * @fid: Id of function
1262 * @index: Index of next function groups
1263 * @groups: Function groups
1264 *
1265 * This function is used by master to get function groups specified
1266 * by given function Id. This API will return 6 function groups with
1267 * a single response. To get other function groups, master should call
1268 * same API in loop with new function groups index till error is returned.
1269 *
1270 * E.g First call should have index 0 which will return function groups
1271 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1272 * function groups 6, 7, 8, 9, 10 and 11 and so on.
1273 *
1274 * Return: Returns status, either success or error+reason.
1275 */
1276static enum pm_ret_status pm_pinctrl_get_function_groups(unsigned int fid,
1277 unsigned int index,
1278 uint16_t *groups)
1279{
1280 return pm_api_pinctrl_get_function_groups(fid, index, groups);
1281}
1282
1283/**
1284 * pm_pinctrl_get_pin_groups - PM call to request pin groups
1285 * @pin_id: Id of pin
1286 * @index: Index of next pin groups
1287 * @groups: pin groups
1288 *
1289 * This function is used by master to get pin groups specified
1290 * by given pin Id. This API will return 6 pin groups with
1291 * a single response. To get other pin groups, master should call
1292 * same API in loop with new pin groups index till error is returned.
1293 *
1294 * E.g First call should have index 0 which will return pin groups
1295 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1296 * pin groups 6, 7, 8, 9, 10 and 11 and so on.
1297 *
1298 * Return: Returns status, either success or error+reason.
1299 */
1300static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id,
1301 unsigned int index,
1302 uint16_t *groups)
1303{
1304 return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
1305}
1306
1307/**
Rajan Vaja35116132018-01-17 02:39:25 -08001308 * pm_query_data() - PM API for querying firmware data
1309 * @arg1 Argument 1 to requested IOCTL call
1310 * @arg2 Argument 2 to requested IOCTL call
1311 * @arg3 Argument 3 to requested IOCTL call
1312 * @arg4 Argument 4 to requested IOCTL call
1313 * @data Returned output data
1314 *
1315 * This function returns requested data.
Rajan Vaja35116132018-01-17 02:39:25 -08001316 */
Rajan Vajacd825682020-11-23 21:33:39 -08001317void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
1318 unsigned int arg3, unsigned int *data)
Rajan Vaja35116132018-01-17 02:39:25 -08001319{
Rajan Vaja35116132018-01-17 02:39:25 -08001320 switch (qid) {
1321 case PM_QID_CLOCK_GET_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001322 pm_clock_get_name(arg1, (char *)data);
Rajan Vaja35116132018-01-17 02:39:25 -08001323 break;
1324 case PM_QID_CLOCK_GET_TOPOLOGY:
Rajan Vajacd825682020-11-23 21:33:39 -08001325 data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001326 break;
1327 case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
Rajan Vajacd825682020-11-23 21:33:39 -08001328 data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
1329 &data[2]);
Rajan Vaja35116132018-01-17 02:39:25 -08001330 break;
1331 case PM_QID_CLOCK_GET_PARENTS:
Rajan Vajacd825682020-11-23 21:33:39 -08001332 data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001333 break;
1334 case PM_QID_CLOCK_GET_ATTRIBUTES:
Rajan Vajacd825682020-11-23 21:33:39 -08001335 data[0] = pm_clock_get_attributes(arg1, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001336 break;
Rajan Vajad5dd8362018-01-30 04:16:31 -08001337 case PM_QID_PINCTRL_GET_NUM_PINS:
Rajan Vajacd825682020-11-23 21:33:39 -08001338 data[0] = pm_pinctrl_get_num_pins(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001339 break;
1340 case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
Rajan Vajacd825682020-11-23 21:33:39 -08001341 data[0] = pm_pinctrl_get_num_functions(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001342 break;
1343 case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001344 data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001345 break;
1346 case PM_QID_PINCTRL_GET_FUNCTION_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001347 pm_pinctrl_get_function_name(arg1, (char *)data);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001348 break;
1349 case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001350 data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
1351 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001352 break;
1353 case PM_QID_PINCTRL_GET_PIN_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001354 data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
1355 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001356 break;
Rajan Vajada959402018-07-20 03:16:27 -07001357 case PM_QID_CLOCK_GET_NUM_CLOCKS:
Rajan Vajacd825682020-11-23 21:33:39 -08001358 data[0] = pm_clock_get_num_clocks(&data[1]);
Rajan Vajada959402018-07-20 03:16:27 -07001359 break;
Rajan Vajab34deca2019-03-20 01:13:21 +05301360
1361 case PM_QID_CLOCK_GET_MAX_DIVISOR:
Rajan Vajacd825682020-11-23 21:33:39 -08001362 data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
Rajan Vajab34deca2019-03-20 01:13:21 +05301363 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001364 default:
Rajan Vajacd825682020-11-23 21:33:39 -08001365 data[0] = PM_RET_ERROR_ARGS;
Rajan Vaja35116132018-01-17 02:39:25 -08001366 WARN("Unimplemented query service call: 0x%x\n", qid);
1367 }
Rajan Vaja35116132018-01-17 02:39:25 -08001368}
Siva Durga Prasad Paladuguf3994cc2018-05-01 11:12:55 +05301369
1370enum pm_ret_status pm_sha_hash(uint32_t address_high,
1371 uint32_t address_low,
1372 uint32_t size,
1373 uint32_t flags)
1374{
1375 uint32_t payload[PAYLOAD_ARG_CNT];
1376
1377 /* Send request to the PMU */
1378 PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
1379 size, flags);
1380 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1381}
1382
1383enum pm_ret_status pm_rsa_core(uint32_t address_high,
1384 uint32_t address_low,
1385 uint32_t size,
1386 uint32_t flags)
1387{
1388 uint32_t payload[PAYLOAD_ARG_CNT];
1389
1390 /* Send request to the PMU */
1391 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
1392 size, flags);
1393 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1394}
Siva Durga Prasad Paladugua4ed4b22018-04-30 20:06:58 +05301395
1396enum pm_ret_status pm_secure_image(uint32_t address_low,
1397 uint32_t address_high,
1398 uint32_t key_lo,
1399 uint32_t key_hi,
1400 uint32_t *value)
1401{
1402 uint32_t payload[PAYLOAD_ARG_CNT];
1403
1404 /* Send request to the PMU */
1405 PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
1406 key_hi, key_lo);
1407 return pm_ipi_send_sync(primary_proc, payload, value, 2);
1408}
Siva Durga Prasad Paladugu7c6516a2018-09-04 17:41:34 +05301409
1410/**
1411 * pm_fpga_read - Perform the fpga configuration readback
1412 *
1413 * @reg_numframes: Configuration register offset (or) Number of frames to read
1414 * @address_low: lower 32-bit Linear memory space address
1415 * @address_high: higher 32-bit Linear memory space address
1416 * @readback_type: Type of fpga readback operation
1417 * 0 -- Configuration Register readback
1418 * 1 -- Configuration Data readback
1419 * @value: Value to read
1420 *
1421 * This function provides access to the xilfpga library to read
1422 * the PL configuration.
1423 *
1424 * Return: Returns status, either success or error+reason.
1425 */
1426enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
1427 uint32_t address_low,
1428 uint32_t address_high,
1429 uint32_t readback_type,
1430 uint32_t *value)
1431{
1432 uint32_t payload[PAYLOAD_ARG_CNT];
1433
1434 /* Send request to the PMU */
1435 PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
1436 address_high, readback_type);
1437 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1438}
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001439
1440/*
1441 * pm_pll_set_parameter() - Set the PLL parameter value
1442 * @nid Node id of the target PLL
1443 * @param_id ID of the PLL parameter
1444 * @value Parameter value to be set
1445 *
1446 * Setting the parameter will have physical effect once the PLL mode is set to
1447 * integer or fractional.
1448 *
1449 * @return Error if an argument is not valid or status as returned by the
1450 * PM controller (PMU)
1451 */
1452enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
1453 enum pm_pll_param param_id,
1454 unsigned int value)
1455{
1456 uint32_t payload[PAYLOAD_ARG_CNT];
1457
1458 /* Check if given node ID is a PLL node */
1459 if (nid < NODE_APLL || nid > NODE_IOPLL)
1460 return PM_RET_ERROR_ARGS;
1461
1462 /* Check if parameter ID is valid and return an error if it's not */
1463 if (param_id >= PM_PLL_PARAM_MAX)
1464 return PM_RET_ERROR_ARGS;
1465
1466 /* Send request to the PMU */
1467 PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
1468 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1469}
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001470
1471/**
1472 * pm_pll_get_parameter() - Get the PLL parameter value
1473 * @nid Node id of the target PLL
1474 * @param_id ID of the PLL parameter
1475 * @value Location to store the parameter value
1476 *
1477 * @return Error if an argument is not valid or status as returned by the
1478 * PM controller (PMU)
1479 */
1480enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
1481 enum pm_pll_param param_id,
1482 unsigned int *value)
1483{
1484 uint32_t payload[PAYLOAD_ARG_CNT];
1485
1486 /* Check if given node ID is a PLL node */
1487 if (nid < NODE_APLL || nid > NODE_IOPLL)
1488 return PM_RET_ERROR_ARGS;
1489
1490 /* Check if parameter ID is valid and return an error if it's not */
1491 if (param_id >= PM_PLL_PARAM_MAX)
1492 return PM_RET_ERROR_ARGS;
1493
1494 /* Send request to the PMU */
1495 PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
1496 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1497}
Jolly Shah1f0d5852019-01-04 11:32:31 -08001498
1499/**
1500 * pm_pll_set_mode() - Set the PLL mode
1501 * @nid Node id of the target PLL
1502 * @mode PLL mode to be set
1503 *
1504 * If reset mode is set the PM controller will first bypass the PLL and then
1505 * assert the reset. If integer or fractional mode is set the PM controller will
1506 * ensure that the complete PLL programming sequence is satisfied. After this
1507 * function returns success the PLL is locked and its bypass is deasserted.
1508 *
1509 * @return Error if an argument is not valid or status as returned by the
1510 * PM controller (PMU)
1511 */
1512enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
1513{
1514 uint32_t payload[PAYLOAD_ARG_CNT];
1515
1516 /* Check if given node ID is a PLL node */
1517 if (nid < NODE_APLL || nid > NODE_IOPLL)
1518 return PM_RET_ERROR_ARGS;
1519
1520 /* Check if PLL mode is valid */
1521 if (mode >= PM_PLL_MODE_MAX)
1522 return PM_RET_ERROR_ARGS;
1523
1524 /* Send request to the PMU */
1525 PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
1526 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1527}
Jolly Shah141421e2019-01-04 11:35:48 -08001528
1529/**
1530 * pm_pll_get_mode() - Get the PLL mode
1531 * @nid Node id of the target PLL
1532 * @mode Location to store the mode of the PLL
1533 *
1534 * @return Error if an argument is not valid or status as returned by the
1535 * PM controller (PMU)
1536 */
1537enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
1538{
1539 uint32_t payload[PAYLOAD_ARG_CNT];
1540
1541 /* Check if given node ID is a PLL node */
1542 if (nid < NODE_APLL || nid > NODE_IOPLL)
1543 return PM_RET_ERROR_ARGS;
1544
1545 /* Send request to the PMU */
1546 PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
1547 return pm_ipi_send_sync(primary_proc, payload, mode, 1);
1548}