blob: 5d9408cd58471f9ab9008cdc2888f388dd64ac9e [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
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -080068#define EM_PACK_PAYLOAD1(pl, arg0) { \
69 pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \
70}
71
Soren Brinkmann76fcae32016-03-06 20:16:27 -080072/**
73 * pm_self_suspend() - PM call for processor to suspend itself
74 * @nid Node id of the processor or subsystem
75 * @latency Requested maximum wakeup latency (not supported)
Filip Drazic0bd9d0c2016-07-20 17:17:39 +020076 * @state Requested state
Soren Brinkmann76fcae32016-03-06 20:16:27 -080077 * @address Resume address
78 *
79 * This is a blocking call, it will return only once PMU has responded.
80 * On a wakeup, resume address will be automatically set by PMU.
81 *
82 * @return Returns status, either success or error+reason
83 */
84enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
85 unsigned int latency,
86 unsigned int state,
87 uintptr_t address)
88{
89 uint32_t payload[PAYLOAD_ARG_CNT];
90 unsigned int cpuid = plat_my_core_pos();
91 const struct pm_proc *proc = pm_get_proc(cpuid);
92
93 /*
94 * Do client specific suspend operations
95 * (e.g. set powerdown request bit)
96 */
Filip Drazic4c0765a2016-07-26 12:11:33 +020097 pm_client_suspend(proc, state);
Soren Brinkmann76fcae32016-03-06 20:16:27 -080098 /* Send request to the PMU */
99 PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
100 state, address, (address >> 32));
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700101 return pm_ipi_send_sync(proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800102}
103
104/**
105 * pm_req_suspend() - PM call to request for another PU or subsystem to
106 * be suspended gracefully.
107 * @target Node id of the targeted PU or subsystem
108 * @ack Flag to specify whether acknowledge is requested
109 * @latency Requested wakeup latency (not supported)
110 * @state Requested state (not supported)
111 *
112 * @return Returns status, either success or error+reason
113 */
114enum pm_ret_status pm_req_suspend(enum pm_node_id target,
115 enum pm_request_ack ack,
116 unsigned int latency, unsigned int state)
117{
118 uint32_t payload[PAYLOAD_ARG_CNT];
119
120 /* Send request to the PMU */
121 PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
122 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700123 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800124 else
125 return pm_ipi_send(primary_proc, payload);
126}
127
128/**
129 * pm_req_wakeup() - PM call for processor to wake up selected processor
130 * or subsystem
131 * @target Node id of the processor or subsystem to wake up
132 * @ack Flag to specify whether acknowledge requested
133 * @set_address Resume address presence indicator
134 * 1 resume address specified, 0 otherwise
135 * @address Resume address
136 *
137 * This API function is either used to power up another APU core for SMP
138 * (by PSCI) or to power up an entirely different PU or subsystem, such
139 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
140 * automatically set by PMU.
141 *
142 * @return Returns status, either success or error+reason
143 */
144enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
145 unsigned int set_address,
146 uintptr_t address,
147 enum pm_request_ack ack)
148{
149 uint32_t payload[PAYLOAD_ARG_CNT];
150 uint64_t encoded_address;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800151
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800152
153 /* encode set Address into 1st bit of address */
154 encoded_address = address;
155 encoded_address |= !!set_address;
156
157 /* Send request to the PMU to perform the wake of the PU */
158 PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
159 encoded_address >> 32, ack);
160
161 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700162 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800163 else
164 return pm_ipi_send(primary_proc, payload);
165}
166
167/**
168 * pm_force_powerdown() - PM call to request for another PU or subsystem to
169 * be powered down forcefully
170 * @target Node id of the targeted PU or subsystem
171 * @ack Flag to specify whether acknowledge is requested
172 *
173 * @return Returns status, either success or error+reason
174 */
175enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
176 enum pm_request_ack ack)
177{
178 uint32_t payload[PAYLOAD_ARG_CNT];
179
180 /* Send request to the PMU */
181 PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
182
183 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700184 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800185 else
186 return pm_ipi_send(primary_proc, payload);
187}
188
189/**
190 * pm_abort_suspend() - PM call to announce that a prior suspend request
191 * is to be aborted.
192 * @reason Reason for the abort
193 *
194 * Calling PU expects the PMU to abort the initiated suspend procedure.
195 * This is a non-blocking call without any acknowledge.
196 *
197 * @return Returns status, either success or error+reason
198 */
199enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
200{
201 uint32_t payload[PAYLOAD_ARG_CNT];
202
203 /*
204 * Do client specific abort suspend operations
205 * (e.g. enable interrupts and clear powerdown request bit)
206 */
207 pm_client_abort_suspend();
208 /* Send request to the PMU */
209 /* TODO: allow passing the node ID of the affected CPU */
210 PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
211 primary_proc->node_id);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700212 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800213}
214
215/**
216 * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
217 * @target Node id of the targeted PU or subsystem
218 * @wkup_node Node id of the wakeup peripheral
219 * @enable Enable or disable the specified peripheral as wake source
220 *
221 * @return Returns status, either success or error+reason
222 */
223enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
224 enum pm_node_id wkup_node,
225 unsigned int enable)
226{
227 uint32_t payload[PAYLOAD_ARG_CNT];
228
229 PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
230 enable);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700231 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800232}
233
234/**
235 * pm_system_shutdown() - PM call to request a system shutdown or restart
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530236 * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
237 * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800238 *
239 * @return Returns status, either success or error+reason
240 */
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700241enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800242{
243 uint32_t payload[PAYLOAD_ARG_CNT];
244
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530245 if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
246 /* Setting scope for subsequent PSCI reboot or shutdown */
247 pm_shutdown_scope = subtype;
248 return PM_RET_SUCCESS;
249 }
250
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700251 PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
Tejas Patelaf4b10e2018-02-09 02:42:59 -0800252 return pm_ipi_send_non_blocking(primary_proc, payload);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800253}
254
255/* APIs for managing PM slaves: */
256
257/**
258 * pm_req_node() - PM call to request a node with specific capabilities
259 * @nid Node id of the slave
260 * @capabilities Requested capabilities of the slave
261 * @qos Quality of service (not supported)
262 * @ack Flag to specify whether acknowledge is requested
263 *
264 * @return Returns status, either success or error+reason
265 */
266enum pm_ret_status pm_req_node(enum pm_node_id nid,
267 unsigned int capabilities,
268 unsigned int qos,
269 enum pm_request_ack ack)
270{
271 uint32_t payload[PAYLOAD_ARG_CNT];
272
273 PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
274
275 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700276 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800277 else
278 return pm_ipi_send(primary_proc, payload);
279}
280
281/**
282 * pm_set_requirement() - PM call to set requirement for PM slaves
283 * @nid Node id of the slave
284 * @capabilities Requested capabilities of the slave
285 * @qos Quality of service (not supported)
286 * @ack Flag to specify whether acknowledge is requested
287 *
288 * This API function is to be used for slaves a PU already has requested
289 *
290 * @return Returns status, either success or error+reason
291 */
292enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
293 unsigned int capabilities,
294 unsigned int qos,
295 enum pm_request_ack ack)
296{
297 uint32_t payload[PAYLOAD_ARG_CNT];
298
299 PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
300 ack);
301
302 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700303 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800304 else
305 return pm_ipi_send(primary_proc, payload);
306}
307
308/**
309 * pm_release_node() - PM call to release a node
310 * @nid Node id of the slave
311 *
312 * @return Returns status, either success or error+reason
313 */
314enum pm_ret_status pm_release_node(enum pm_node_id nid)
315{
316 uint32_t payload[PAYLOAD_ARG_CNT];
317
318 PM_PACK_PAYLOAD2(payload, PM_RELEASE_NODE, nid);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700319 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800320}
321
322/**
323 * pm_set_max_latency() - PM call to set wakeup latency requirements
324 * @nid Node id of the slave
325 * @latency Requested maximum wakeup latency
326 *
327 * @return Returns status, either success or error+reason
328 */
329enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
330 unsigned int latency)
331{
332 uint32_t payload[PAYLOAD_ARG_CNT];
333
334 PM_PACK_PAYLOAD3(payload, PM_SET_MAX_LATENCY, nid, latency);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700335 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800336}
337
338/* Miscellaneous API functions */
339
340/**
341 * pm_get_api_version() - Get version number of PMU PM firmware
342 * @version Returns 32-bit version number of PMU Power Management Firmware
343 *
344 * @return Returns status, either success or error+reason
345 */
346enum pm_ret_status pm_get_api_version(unsigned int *version)
347{
348 uint32_t payload[PAYLOAD_ARG_CNT];
349
350 /* Send request to the PMU */
351 PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700352 return pm_ipi_send_sync(primary_proc, payload, version, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800353}
354
355/**
356 * pm_set_configuration() - PM call to set system configuration
357 * @phys_addr Physical 32-bit address of data structure in memory
358 *
359 * @return Returns status, either success or error+reason
360 */
361enum pm_ret_status pm_set_configuration(unsigned int phys_addr)
362{
Luca Ceresolif00986c2019-02-28 22:15:35 +0100363 uint32_t payload[PAYLOAD_ARG_CNT];
364
365 PM_PACK_PAYLOAD2(payload, PM_SET_CONFIGURATION, phys_addr);
366 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800367}
368
369/**
Filip Drazicf2ddd912017-03-15 11:50:47 +0100370 * pm_init_finalize() - Call to notify PMU firmware that master has power
371 * management enabled and that it has finished its
372 * initialization
373 *
374 * @return Status returned by the PMU firmware
375 */
376enum pm_ret_status pm_init_finalize(void)
377{
378 uint32_t payload[PAYLOAD_ARG_CNT];
379
380 /* Send request to the PMU */
381 PM_PACK_PAYLOAD1(payload, PM_INIT_FINALIZE);
382 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
383}
384
385/**
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100386 * pm_get_node_status() - PM call to request a node's current status
387 * @nid Node id
388 * @ret_buff Buffer for the return values:
389 * [0] - Current power state of the node
390 * [1] - Current requirements for the node (slave nodes only)
391 * [2] - Current usage status for the node (slave nodes only)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800392 *
393 * @return Returns status, either success or error+reason
394 */
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100395enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
396 uint32_t *ret_buff)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800397{
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800398 uint32_t payload[PAYLOAD_ARG_CNT];
399
400 PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100401 return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800402}
403
404/**
405 * pm_register_notifier() - Register the PU to be notified of PM events
406 * @nid Node id of the slave
407 * @event The event to be notified about
408 * @wake Wake up on event
409 * @enable Enable or disable the notifier
410 *
411 * @return Returns status, either success or error+reason
412 */
413enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
414 unsigned int event,
415 unsigned int wake,
416 unsigned int enable)
417{
Anes Hadziahmetagicc95ae092016-05-12 16:17:34 +0200418 uint32_t payload[PAYLOAD_ARG_CNT];
419
420 PM_PACK_PAYLOAD5(payload, PM_REGISTER_NOTIFIER,
421 nid, event, wake, enable);
422
Soren Brinkmanna1b0a902016-09-30 11:30:21 -0700423 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800424}
425
426/**
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200427 * pm_get_op_characteristic() - PM call to request operating characteristics
428 * of a node
429 * @nid Node id of the slave
430 * @type Type of the operating characteristic
431 * (power, temperature and latency)
432 * @result Returns the operating characteristic for the requested node,
433 * specified by the type
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800434 *
435 * @return Returns status, either success or error+reason
436 */
437enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid,
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200438 enum pm_opchar_type type,
439 uint32_t *result)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800440{
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200441 uint32_t payload[PAYLOAD_ARG_CNT];
442
443 /* Send request to the PMU */
444 PM_PACK_PAYLOAD3(payload, PM_GET_OP_CHARACTERISTIC, nid, type);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700445 return pm_ipi_send_sync(primary_proc, payload, result, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800446}
447
448/* Direct-Control API functions */
449
450/**
451 * pm_reset_assert() - Assert reset
452 * @reset Reset ID
453 * @assert Assert (1) or de-assert (0)
454 *
455 * @return Returns status, either success or error+reason
456 */
457enum pm_ret_status pm_reset_assert(unsigned int reset,
458 unsigned int assert)
459{
460 uint32_t payload[PAYLOAD_ARG_CNT];
461
462 /* Send request to the PMU */
463 PM_PACK_PAYLOAD3(payload, PM_RESET_ASSERT, reset, assert);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700464 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800465}
466
467/**
468 * pm_reset_get_status() - Get current status of a reset line
469 * @reset Reset ID
470 * @reset_status Returns current status of selected reset line
471 *
472 * @return Returns status, either success or error+reason
473 */
474enum pm_ret_status pm_reset_get_status(unsigned int reset,
475 unsigned int *reset_status)
476{
477 uint32_t payload[PAYLOAD_ARG_CNT];
478
479 /* Send request to the PMU */
480 PM_PACK_PAYLOAD2(payload, PM_RESET_GET_STATUS, reset);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700481 return pm_ipi_send_sync(primary_proc, payload, reset_status, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800482}
483
484/**
485 * pm_mmio_write() - Perform write to protected mmio
486 * @address Address to write to
487 * @mask Mask to apply
488 * @value Value to write
489 *
490 * This function provides access to PM-related control registers
491 * that may not be directly accessible by a particular PU.
492 *
493 * @return Returns status, either success or error+reason
494 */
495enum pm_ret_status pm_mmio_write(uintptr_t address,
496 unsigned int mask,
497 unsigned int value)
498{
499 uint32_t payload[PAYLOAD_ARG_CNT];
500
501 /* Send request to the PMU */
502 PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700503 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800504}
505
506/**
507 * pm_mmio_read() - Read value from protected mmio
508 * @address Address to write to
509 * @value Value to write
510 *
511 * This function provides access to PM-related control registers
512 * that may not be directly accessible by a particular PU.
513 *
514 * @return Returns status, either success or error+reason
515 */
516enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
517{
518 uint32_t payload[PAYLOAD_ARG_CNT];
519
520 /* Send request to the PMU */
521 PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700522 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800523}
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530524
525/**
526 * pm_fpga_load() - Load the bitstream into the PL.
527 *
528 * This function provides access to the xilfpga library to load
529 * the Bit-stream into PL.
530 *
531 * address_low: lower 32-bit Linear memory space address
532 *
533 * address_high: higher 32-bit Linear memory space address
534 *
535 * size: Number of 32bit words
536 *
537 * @return Returns status, either success or error+reason
538 */
539enum pm_ret_status pm_fpga_load(uint32_t address_low,
540 uint32_t address_high,
541 uint32_t size,
542 uint32_t flags)
543{
544 uint32_t payload[PAYLOAD_ARG_CNT];
545
546 /* Send request to the PMU */
547 PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
548 size, flags);
Siva Durga Prasad Paladugubf83b9c2018-02-07 13:13:01 +0530549 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530550}
551
552/**
553 * pm_fpga_get_status() - Read value from fpga status register
554 * @value Value to read
555 *
556 * This function provides access to the xilfpga library to get
557 * the fpga status
558 * @return Returns status, either success or error+reason
559 */
560enum pm_ret_status pm_fpga_get_status(unsigned int *value)
561{
562 uint32_t payload[PAYLOAD_ARG_CNT];
563
564 /* Send request to the PMU */
565 PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700566 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530567}
Soren Brinkmanncb366812016-09-22 12:21:11 -0700568
569/**
570 * pm_get_chipid() - Read silicon ID registers
571 * @value Buffer for return values. Must be large enough
572 * to hold 8 bytes.
573 *
574 * @return Returns silicon ID registers
575 */
576enum pm_ret_status pm_get_chipid(uint32_t *value)
577{
578 uint32_t payload[PAYLOAD_ARG_CNT];
579
580 /* Send request to the PMU */
581 PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
582 return pm_ipi_send_sync(primary_proc, payload, value, 2);
583}
Soren Brinkmann84f0af42016-09-30 14:24:25 -0700584
585/**
Siva Durga Prasad Paladugude93d982018-04-30 15:49:27 +0530586 * pm_secure_rsaaes() - Load the secure images.
587 *
588 * This function provides access to the xilsecure library to load
589 * the authenticated, encrypted, and authenicated/encrypted images.
590 *
591 * address_low: lower 32-bit Linear memory space address
592 *
593 * address_high: higher 32-bit Linear memory space address
594 *
595 * size: Number of 32bit words
596 *
597 * @return Returns status, either success or error+reason
598 */
599enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
600 uint32_t address_high,
601 uint32_t size,
602 uint32_t flags)
603{
604 uint32_t payload[PAYLOAD_ARG_CNT];
605
606 /* Send request to the PMU */
607 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
608 size, flags);
609 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
610}
611
612/**
Siva Durga Prasad Paladugu8bd905b2018-09-04 18:05:50 +0530613 * pm_aes_engine() - Aes data blob encryption/decryption
614 * This function provides access to the xilsecure library to
615 * encrypt/decrypt data blobs.
616 *
617 * address_low: lower 32-bit address of the AesParams structure
618 *
619 * address_high: higher 32-bit address of the AesParams structure
620 *
621 * value: Returned output value
622 *
623 * @return Returns status, either success or error+reason
624 */
625enum pm_ret_status pm_aes_engine(uint32_t address_high,
626 uint32_t address_low,
627 uint32_t *value)
628{
629 uint32_t payload[PAYLOAD_ARG_CNT];
630
631 /* Send request to the PMU */
632 PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
633 return pm_ipi_send_sync(primary_proc, payload, value, 1);
634}
635
636/**
Rajan Vaja02d18422019-03-04 11:09:39 +0530637 * pm_get_callbackdata() - Read from IPI response buffer
638 * @data - array of PAYLOAD_ARG_CNT elements
639 *
640 * Read value from ipi buffer response buffer.
641 */
642void pm_get_callbackdata(uint32_t *data, size_t count)
643{
644 /* Return if interrupt is not from PMU */
645 if (!pm_ipi_irq_status(primary_proc))
646 return;
647
648 pm_ipi_buff_read_callb(data, count);
649 pm_ipi_irq_clear(primary_proc);
650}
651
652/**
Rajan Vaja83687612018-01-17 02:39:20 -0800653 * pm_pinctrl_request() - Request Pin from firmware
654 * @pin Pin number to request
655 *
656 * This function requests pin from firmware.
657 *
658 * @return Returns status, either success or error+reason.
659 */
660enum pm_ret_status pm_pinctrl_request(unsigned int pin)
661{
Mirela Simonovicedefb042018-09-13 12:49:45 +0200662 uint32_t payload[PAYLOAD_ARG_CNT];
663
664 /* Send request to the PMU */
665 PM_PACK_PAYLOAD2(payload, PM_PINCTRL_REQUEST, pin);
666 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800667}
668
669/**
670 * pm_pinctrl_release() - Release Pin from firmware
671 * @pin Pin number to release
672 *
673 * This function releases pin from firmware.
674 *
675 * @return Returns status, either success or error+reason.
676 */
677enum pm_ret_status pm_pinctrl_release(unsigned int pin)
678{
Mirela Simonovicedefb042018-09-13 12:49:45 +0200679 uint32_t payload[PAYLOAD_ARG_CNT];
680
681 /* Send request to the PMU */
682 PM_PACK_PAYLOAD2(payload, PM_PINCTRL_RELEASE, pin);
683 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800684}
685
686/**
687 * pm_pinctrl_get_function() - Read function id set for the given pin
688 * @pin Pin number
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200689 * @fid ID of function currently set for given pin
Rajan Vaja83687612018-01-17 02:39:20 -0800690 *
691 * This function provides the function currently set for the given pin.
692 *
693 * @return Returns status, either success or error+reason
694 */
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200695enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, unsigned int *fid)
Rajan Vaja83687612018-01-17 02:39:20 -0800696{
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200697 uint32_t payload[PAYLOAD_ARG_CNT];
698
699 PM_PACK_PAYLOAD2(payload, PM_PINCTRL_GET_FUNCTION, pin);
700 return pm_ipi_send_sync(primary_proc, payload, fid, 1);
Rajan Vaja83687612018-01-17 02:39:20 -0800701}
702
703/**
704 * pm_pinctrl_set_function() - Set function id set for the given pin
705 * @pin Pin number
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200706 * @fid ID of function to set for given pin
Rajan Vaja83687612018-01-17 02:39:20 -0800707 *
708 * @return Returns status, either success or error+reason
709 */
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200710enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, unsigned int fid)
Rajan Vaja83687612018-01-17 02:39:20 -0800711{
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200712 uint32_t payload[PAYLOAD_ARG_CNT];
713
714 /* Send request to the PMU */
715 PM_PACK_PAYLOAD3(payload, PM_PINCTRL_SET_FUNCTION, pin, fid);
716 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800717}
718
719/**
720 * pm_pinctrl_get_config() - Read value of requested config param for given pin
721 * @pin Pin number
722 * @param Parameter values to be read
723 * @value Buffer for configuration Parameter value
724 *
725 * This function provides the configuration parameter value for the given pin.
726 *
727 * @return Returns status, either success or error+reason
728 */
729enum pm_ret_status pm_pinctrl_get_config(unsigned int pin,
730 unsigned int param,
731 unsigned int *value)
732{
Mirela Simonovic4dadd9c2020-11-22 23:31:14 -0800733 uint32_t payload[PAYLOAD_ARG_CNT];
734
735 PM_PACK_PAYLOAD3(payload, PM_PINCTRL_CONFIG_PARAM_GET, pin, param);
736 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Rajan Vaja83687612018-01-17 02:39:20 -0800737}
738
739/**
Mirela Simonovic4dadd9c2020-11-22 23:31:14 -0800740 * pm_pinctrl_set_config() - Set value of requested config param for given pin
Rajan Vaja83687612018-01-17 02:39:20 -0800741 * @pin Pin number
742 * @param Parameter to set
743 * @value Parameter value to set
744 *
Rajan Vaja83687612018-01-17 02:39:20 -0800745 * @return Returns status, either success or error+reason
746 */
747enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
748 unsigned int param,
749 unsigned int value)
750{
Mirela Simonovic4dadd9c2020-11-22 23:31:14 -0800751 uint32_t payload[PAYLOAD_ARG_CNT];
752
753 /* Send request to the PMU */
754 PM_PACK_PAYLOAD4(payload, PM_PINCTRL_CONFIG_PARAM_SET, pin, param,
755 value);
756 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800757}
Rajan Vaja5529a012018-01-17 02:39:23 -0800758
759/**
760 * pm_ioctl() - PM IOCTL API for device control and configs
761 * @node_id Node ID of the device
762 * @ioctl_id ID of the requested IOCTL
763 * @arg1 Argument 1 to requested IOCTL call
764 * @arg2 Argument 2 to requested IOCTL call
765 * @out Returned output value
766 *
767 * This function calls IOCTL to firmware for device control and configuration.
768 *
769 * @return Returns status, either success or error+reason
770 */
771enum pm_ret_status pm_ioctl(enum pm_node_id nid,
772 unsigned int ioctl_id,
773 unsigned int arg1,
774 unsigned int arg2,
775 unsigned int *value)
776{
777 return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
778}
Rajan Vaja35116132018-01-17 02:39:25 -0800779
780/**
Rajan Vajab34deca2019-03-20 01:13:21 +0530781 * pm_clock_get_max_divisor - PM call to get max divisor
782 * @clock_id Clock ID
783 * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2)
784 * @max_div Maximum supported divisor
785 *
786 * This function is used by master to get maximum supported value.
787 *
788 * Return: Returns status, either success or error+reason.
789 */
790static enum pm_ret_status pm_clock_get_max_divisor(unsigned int clock_id,
791 uint8_t div_type,
792 uint32_t *max_div)
793{
794 return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
795}
796
797/**
Rajan Vajada959402018-07-20 03:16:27 -0700798 * pm_clock_get_num_clocks - PM call to request number of clocks
799 * @nclockss: Number of clocks
800 *
801 * This function is used by master to get number of clocks.
802 *
803 * Return: Returns status, either success or error+reason.
804 */
805static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
806{
807 return pm_api_clock_get_num_clocks(nclocks);
808}
809
810/**
Rajan Vaja35116132018-01-17 02:39:25 -0800811 * pm_clock_get_name() - PM call to request a clock's name
812 * @clock_id Clock ID
813 * @name Name of clock (max 16 bytes)
814 *
815 * This function is used by master to get nmae of clock specified
816 * by given clock ID.
Rajan Vaja35116132018-01-17 02:39:25 -0800817 */
Rajan Vajacd825682020-11-23 21:33:39 -0800818static void pm_clock_get_name(unsigned int clock_id, char *name)
Rajan Vaja35116132018-01-17 02:39:25 -0800819{
Rajan Vajacd825682020-11-23 21:33:39 -0800820 pm_api_clock_get_name(clock_id, name);
Rajan Vaja35116132018-01-17 02:39:25 -0800821}
822
823/**
824 * pm_clock_get_topology() - PM call to request a clock's topology
825 * @clock_id Clock ID
826 * @index Topology index for next toplogy node
827 * @topology Buffer to store nodes in topology and flags
828 *
829 * This function is used by master to get topology information for the
830 * clock specified by given clock ID. Each response would return 3
831 * topology nodes. To get next nodes, caller needs to call this API with
832 * index of next node. Index starts from 0.
833 *
834 * @return Returns status, either success or error+reason
835 */
836static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id,
837 unsigned int index,
838 uint32_t *topology)
839{
840 return pm_api_clock_get_topology(clock_id, index, topology);
841}
842
843/**
844 * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
845 * parameters for fixed clock
846 * @clock_id Clock ID
847 * @mul Multiplication value
848 * @div Divisor value
849 *
850 * This function is used by master to get fixed factor parameers for the
851 * fixed clock. This API is application only for the fixed clock.
852 *
853 * @return Returns status, either success or error+reason
854 */
855static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id,
856 uint32_t *mul,
857 uint32_t *div)
858{
859 return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
860}
861
862/**
863 * pm_clock_get_parents() - PM call to request a clock's first 3 parents
864 * @clock_id Clock ID
865 * @index Index of next parent
866 * @parents Parents of the given clock
867 *
868 * This function is used by master to get clock's parents information.
869 * This API will return 3 parents with a single response. To get other
870 * parents, master should call same API in loop with new parent index
871 * till error is returned.
872 *
873 * E.g First call should have index 0 which will return parents 0, 1 and
874 * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
875 * so on.
876 *
877 * @return Returns status, either success or error+reason
878 */
879static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id,
880 unsigned int index,
881 uint32_t *parents)
882{
883 return pm_api_clock_get_parents(clock_id, index, parents);
884}
885
886/**
887 * pm_clock_get_attributes() - PM call to request a clock's attributes
888 * @clock_id Clock ID
889 * @attr Clock attributes
890 *
891 * This function is used by master to get clock's attributes
892 * (e.g. valid, clock type, etc).
893 *
894 * @return Returns status, either success or error+reason
895 */
896static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
897 uint32_t *attr)
898{
899 return pm_api_clock_get_attributes(clock_id, attr);
900}
901
902/**
Jolly Shaha5209802019-01-04 11:45:59 -0800903 * pm_clock_gate() - Configure clock gate
904 * @clock_id Id of the clock to be configured
905 * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
906 *
907 * @return Error if an argument is not valid or status as returned by the
908 * PM controller (PMU)
909 */
910static enum pm_ret_status pm_clock_gate(unsigned int clock_id,
911 unsigned char enable)
912{
913 uint32_t payload[PAYLOAD_ARG_CNT];
914 enum pm_ret_status status;
915 enum pm_api_id api_id;
916
917 /* Check if clock ID is valid and return an error if it is not */
918 status = pm_clock_id_is_valid(clock_id);
919 if (status != PM_RET_SUCCESS)
920 return status;
921
922 if (enable)
923 api_id = PM_CLOCK_ENABLE;
924 else
925 api_id = PM_CLOCK_DISABLE;
926
927 /* Send request to the PMU */
928 PM_PACK_PAYLOAD2(payload, api_id, clock_id);
Mirela Simonovic64514a72018-08-24 17:09:07 +0200929 status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
930
931 /* If action fails due to the lack of permissions filter the error */
932 if (status == PM_RET_ERROR_ACCESS)
933 status = PM_RET_SUCCESS;
934
935 return status;
Jolly Shaha5209802019-01-04 11:45:59 -0800936}
937
938/**
Rajan Vaja35116132018-01-17 02:39:25 -0800939 * pm_clock_enable() - Enable the clock for given id
940 * @clock_id: Id of the clock to be enabled
941 *
942 * This function is used by master to enable the clock
943 * including peripherals and PLL clocks.
944 *
Jolly Shaha5209802019-01-04 11:45:59 -0800945 * @return: Error if an argument is not valid or status as returned by the
946 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -0800947 */
Rajan Vaja35116132018-01-17 02:39:25 -0800948enum pm_ret_status pm_clock_enable(unsigned int clock_id)
949{
Jolly Shaha5209802019-01-04 11:45:59 -0800950 struct pm_pll *pll;
951
952 /* First try to handle it as a PLL */
953 pll = pm_clock_get_pll(clock_id);
954 if (pll)
955 return pm_clock_pll_enable(pll);
956
957 /* It's an on-chip clock, PMU should configure clock's gate */
958 return pm_clock_gate(clock_id, 1);
Rajan Vaja35116132018-01-17 02:39:25 -0800959}
960
961/**
962 * pm_clock_disable - Disable the clock for given id
963 * @clock_id: Id of the clock to be disable
964 *
965 * This function is used by master to disable the clock
966 * including peripherals and PLL clocks.
967 *
Jolly Shaha9057a02019-01-02 12:54:40 -0800968 * @return: Error if an argument is not valid or status as returned by the
969 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -0800970 */
Rajan Vaja35116132018-01-17 02:39:25 -0800971enum pm_ret_status pm_clock_disable(unsigned int clock_id)
972{
Jolly Shaha9057a02019-01-02 12:54:40 -0800973 struct pm_pll *pll;
974
975 /* First try to handle it as a PLL */
976 pll = pm_clock_get_pll(clock_id);
977 if (pll)
978 return pm_clock_pll_disable(pll);
979
980 /* It's an on-chip clock, PMU should configure clock's gate */
981 return pm_clock_gate(clock_id, 0);
Rajan Vaja35116132018-01-17 02:39:25 -0800982}
983
984/**
985 * pm_clock_getstate - Get the clock state for given id
986 * @clock_id: Id of the clock to be queried
987 * @state: 1/0 (Enabled/Disabled)
988 *
989 * This function is used by master to get the state of clock
990 * including peripherals and PLL clocks.
991 *
992 * Return: Returns status, either success or error+reason.
993 */
994enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
995 unsigned int *state)
996{
Jolly Shah99e8ac92019-01-02 12:55:41 -0800997 struct pm_pll *pll;
998 uint32_t payload[PAYLOAD_ARG_CNT];
999 enum pm_ret_status status;
1000
1001 /* First try to handle it as a PLL */
1002 pll = pm_clock_get_pll(clock_id);
1003 if (pll)
1004 return pm_clock_pll_get_state(pll, state);
1005
1006 /* Check if clock ID is a valid on-chip clock */
1007 status = pm_clock_id_is_valid(clock_id);
1008 if (status != PM_RET_SUCCESS)
1009 return status;
1010
1011 /* Send request to the PMU */
1012 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
1013 return pm_ipi_send_sync(primary_proc, payload, state, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001014}
1015
1016/**
1017 * pm_clock_setdivider - Set the clock divider for given id
1018 * @clock_id: Id of the clock
1019 * @divider: divider value
1020 *
1021 * This function is used by master to set divider for any clock
1022 * to achieve desired rate.
1023 *
1024 * Return: Returns status, either success or error+reason.
1025 */
1026enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
1027 unsigned int divider)
1028{
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001029 enum pm_ret_status status;
1030 enum pm_node_id nid;
1031 enum pm_clock_div_id div_id;
1032 uint32_t payload[PAYLOAD_ARG_CNT];
1033 const uint32_t div0 = 0xFFFF0000;
1034 const uint32_t div1 = 0x0000FFFF;
1035 uint32_t val;
1036
1037 /* Get PLL node ID using PLL clock ID */
1038 status = pm_clock_get_pll_node_id(clock_id, &nid);
1039 if (status == PM_RET_SUCCESS)
1040 return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1041
1042 /* Check if clock ID is a valid on-chip clock */
1043 status = pm_clock_id_is_valid(clock_id);
1044 if (status != PM_RET_SUCCESS)
1045 return status;
1046
1047 if (div0 == (divider & div0)) {
1048 div_id = PM_CLOCK_DIV0_ID;
1049 val = divider & ~div0;
1050 } else if (div1 == (divider & div1)) {
1051 div_id = PM_CLOCK_DIV1_ID;
1052 val = (divider & ~div1) >> 16;
1053 } else {
1054 return PM_RET_ERROR_ARGS;
1055 }
1056
1057 /* Send request to the PMU */
1058 PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
1059 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001060}
1061
1062/**
1063 * pm_clock_getdivider - Get the clock divider for given id
1064 * @clock_id: Id of the clock
1065 * @divider: divider value
1066 *
1067 * This function is used by master to get divider values
1068 * for any clock.
1069 *
1070 * Return: Returns status, either success or error+reason.
1071 */
1072enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
1073 unsigned int *divider)
1074{
Jolly Shah4dd11762019-01-04 11:53:37 -08001075 enum pm_ret_status status;
1076 enum pm_node_id nid;
1077 uint32_t payload[PAYLOAD_ARG_CNT];
1078 uint32_t val;
1079
1080 /* Get PLL node ID using PLL clock ID */
1081 status = pm_clock_get_pll_node_id(clock_id, &nid);
1082 if (status == PM_RET_SUCCESS)
1083 return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1084
1085 /* Check if clock ID is a valid on-chip clock */
1086 status = pm_clock_id_is_valid(clock_id);
1087 if (status != PM_RET_SUCCESS)
1088 return status;
1089
1090 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
1091 /* Send request to the PMU to get div0 */
1092 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1093 PM_CLOCK_DIV0_ID);
1094 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1095 if (status != PM_RET_SUCCESS)
1096 return status;
1097 *divider = val;
1098 }
1099
1100 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
1101 /* Send request to the PMU to get div1 */
1102 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1103 PM_CLOCK_DIV1_ID);
1104 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1105 if (status != PM_RET_SUCCESS)
1106 return status;
1107 *divider |= val << 16;
1108 }
1109
1110 return status;
Rajan Vaja35116132018-01-17 02:39:25 -08001111}
1112
1113/**
1114 * pm_clock_setrate - Set the clock rate for given id
1115 * @clock_id: Id of the clock
1116 * @rate: rate value in hz
1117 *
1118 * This function is used by master to set rate for any clock.
1119 *
1120 * Return: Returns status, either success or error+reason.
1121 */
1122enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
1123 uint64_t rate)
1124{
Jolly Shahc1391812019-01-02 13:39:30 -08001125 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001126}
1127
1128/**
1129 * pm_clock_getrate - Get the clock rate for given id
1130 * @clock_id: Id of the clock
1131 * @rate: rate value in hz
1132 *
1133 * This function is used by master to get rate
1134 * for any clock.
1135 *
1136 * Return: Returns status, either success or error+reason.
1137 */
1138enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
1139 uint64_t *rate)
1140{
Jolly Shahc1391812019-01-02 13:39:30 -08001141 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001142}
1143
1144/**
1145 * pm_clock_setparent - Set the clock parent for given id
1146 * @clock_id: Id of the clock
Jolly Shah407fc0a2019-01-04 11:57:40 -08001147 * @parent_index: Index of the parent clock into clock's parents array
Rajan Vaja35116132018-01-17 02:39:25 -08001148 *
1149 * This function is used by master to set parent for any clock.
1150 *
1151 * Return: Returns status, either success or error+reason.
1152 */
1153enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
Jolly Shah407fc0a2019-01-04 11:57:40 -08001154 unsigned int parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001155{
Jolly Shah407fc0a2019-01-04 11:57:40 -08001156 struct pm_pll *pll;
1157 uint32_t payload[PAYLOAD_ARG_CNT];
1158 enum pm_ret_status status;
1159
1160 /* First try to handle it as a PLL */
1161 pll = pm_clock_get_pll_by_related_clk(clock_id);
1162 if (pll)
1163 return pm_clock_pll_set_parent(pll, clock_id, parent_index);
1164
1165 /* Check if clock ID is a valid on-chip clock */
1166 status = pm_clock_id_is_valid(clock_id);
1167 if (status != PM_RET_SUCCESS)
1168 return status;
1169
1170 /* Send request to the PMU */
1171 PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
1172 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001173}
1174
1175/**
1176 * pm_clock_getparent - Get the clock parent for given id
1177 * @clock_id: Id of the clock
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001178 * @parent_index: parent index
Rajan Vaja35116132018-01-17 02:39:25 -08001179 *
1180 * This function is used by master to get parent index
1181 * for any clock.
1182 *
1183 * Return: Returns status, either success or error+reason.
1184 */
1185enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001186 unsigned int *parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001187{
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001188 struct pm_pll *pll;
1189 uint32_t payload[PAYLOAD_ARG_CNT];
1190 enum pm_ret_status status;
1191
1192 /* First try to handle it as a PLL */
1193 pll = pm_clock_get_pll_by_related_clk(clock_id);
1194 if (pll)
1195 return pm_clock_pll_get_parent(pll, clock_id, parent_index);
1196
1197 /* Check if clock ID is a valid on-chip clock */
1198 status = pm_clock_id_is_valid(clock_id);
1199 if (status != PM_RET_SUCCESS)
1200 return status;
1201
1202 /* Send request to the PMU */
1203 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
1204 return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001205}
1206
1207/**
Rajan Vajad5dd8362018-01-30 04:16:31 -08001208 * pm_pinctrl_get_num_pins - PM call to request number of pins
1209 * @npins: Number of pins
1210 *
1211 * This function is used by master to get number of pins
1212 *
1213 * Return: Returns status, either success or error+reason.
1214 */
1215static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
1216{
1217 return pm_api_pinctrl_get_num_pins(npins);
1218}
1219
1220/**
1221 * pm_pinctrl_get_num_functions - PM call to request number of functions
1222 * @nfuncs: Number of functions
1223 *
1224 * This function is used by master to get number of functions
1225 *
1226 * Return: Returns status, either success or error+reason.
1227 */
1228static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
1229{
1230 return pm_api_pinctrl_get_num_functions(nfuncs);
1231}
1232
1233/**
1234 * pm_pinctrl_get_num_function_groups - PM call to request number of
1235 * function groups
1236 * @fid: Id of function
1237 * @ngroups: Number of function groups
1238 *
1239 * This function is used by master to get number of function groups specified
1240 * by given function Id
1241 *
1242 * Return: Returns status, either success or error+reason.
1243 */
1244static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid,
1245 uint32_t *ngroups)
1246{
1247 return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
1248}
1249
1250/**
1251 * pm_pinctrl_get_function_name - PM call to request function name
1252 * @fid: Id of function
1253 * @name: Name of function
1254 *
1255 * This function is used by master to get name of function specified
1256 * by given function Id
Rajan Vajad5dd8362018-01-30 04:16:31 -08001257 */
Rajan Vajacd825682020-11-23 21:33:39 -08001258static void pm_pinctrl_get_function_name(unsigned int fid, char *name)
Rajan Vajad5dd8362018-01-30 04:16:31 -08001259{
Rajan Vajacd825682020-11-23 21:33:39 -08001260 pm_api_pinctrl_get_function_name(fid, name);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001261}
1262
1263/**
1264 * pm_pinctrl_get_function_groups - PM call to request function groups
1265 * @fid: Id of function
1266 * @index: Index of next function groups
1267 * @groups: Function groups
1268 *
1269 * This function is used by master to get function groups specified
1270 * by given function Id. This API will return 6 function groups with
1271 * a single response. To get other function groups, master should call
1272 * same API in loop with new function groups index till error is returned.
1273 *
1274 * E.g First call should have index 0 which will return function groups
1275 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1276 * function groups 6, 7, 8, 9, 10 and 11 and so on.
1277 *
1278 * Return: Returns status, either success or error+reason.
1279 */
1280static enum pm_ret_status pm_pinctrl_get_function_groups(unsigned int fid,
1281 unsigned int index,
1282 uint16_t *groups)
1283{
1284 return pm_api_pinctrl_get_function_groups(fid, index, groups);
1285}
1286
1287/**
1288 * pm_pinctrl_get_pin_groups - PM call to request pin groups
1289 * @pin_id: Id of pin
1290 * @index: Index of next pin groups
1291 * @groups: pin groups
1292 *
1293 * This function is used by master to get pin groups specified
1294 * by given pin Id. This API will return 6 pin groups with
1295 * a single response. To get other pin groups, master should call
1296 * same API in loop with new pin groups index till error is returned.
1297 *
1298 * E.g First call should have index 0 which will return pin groups
1299 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1300 * pin groups 6, 7, 8, 9, 10 and 11 and so on.
1301 *
1302 * Return: Returns status, either success or error+reason.
1303 */
1304static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id,
1305 unsigned int index,
1306 uint16_t *groups)
1307{
1308 return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
1309}
1310
1311/**
Rajan Vaja35116132018-01-17 02:39:25 -08001312 * pm_query_data() - PM API for querying firmware data
1313 * @arg1 Argument 1 to requested IOCTL call
1314 * @arg2 Argument 2 to requested IOCTL call
1315 * @arg3 Argument 3 to requested IOCTL call
1316 * @arg4 Argument 4 to requested IOCTL call
1317 * @data Returned output data
1318 *
1319 * This function returns requested data.
Rajan Vaja35116132018-01-17 02:39:25 -08001320 */
Rajan Vajacd825682020-11-23 21:33:39 -08001321void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
1322 unsigned int arg3, unsigned int *data)
Rajan Vaja35116132018-01-17 02:39:25 -08001323{
Rajan Vaja35116132018-01-17 02:39:25 -08001324 switch (qid) {
1325 case PM_QID_CLOCK_GET_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001326 pm_clock_get_name(arg1, (char *)data);
Rajan Vaja35116132018-01-17 02:39:25 -08001327 break;
1328 case PM_QID_CLOCK_GET_TOPOLOGY:
Rajan Vajacd825682020-11-23 21:33:39 -08001329 data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001330 break;
1331 case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
Rajan Vajacd825682020-11-23 21:33:39 -08001332 data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
1333 &data[2]);
Rajan Vaja35116132018-01-17 02:39:25 -08001334 break;
1335 case PM_QID_CLOCK_GET_PARENTS:
Rajan Vajacd825682020-11-23 21:33:39 -08001336 data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001337 break;
1338 case PM_QID_CLOCK_GET_ATTRIBUTES:
Rajan Vajacd825682020-11-23 21:33:39 -08001339 data[0] = pm_clock_get_attributes(arg1, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001340 break;
Rajan Vajad5dd8362018-01-30 04:16:31 -08001341 case PM_QID_PINCTRL_GET_NUM_PINS:
Rajan Vajacd825682020-11-23 21:33:39 -08001342 data[0] = pm_pinctrl_get_num_pins(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001343 break;
1344 case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
Rajan Vajacd825682020-11-23 21:33:39 -08001345 data[0] = pm_pinctrl_get_num_functions(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001346 break;
1347 case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001348 data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001349 break;
1350 case PM_QID_PINCTRL_GET_FUNCTION_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001351 pm_pinctrl_get_function_name(arg1, (char *)data);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001352 break;
1353 case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001354 data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
1355 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001356 break;
1357 case PM_QID_PINCTRL_GET_PIN_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001358 data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
1359 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001360 break;
Rajan Vajada959402018-07-20 03:16:27 -07001361 case PM_QID_CLOCK_GET_NUM_CLOCKS:
Rajan Vajacd825682020-11-23 21:33:39 -08001362 data[0] = pm_clock_get_num_clocks(&data[1]);
Rajan Vajada959402018-07-20 03:16:27 -07001363 break;
Rajan Vajab34deca2019-03-20 01:13:21 +05301364
1365 case PM_QID_CLOCK_GET_MAX_DIVISOR:
Rajan Vajacd825682020-11-23 21:33:39 -08001366 data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
Rajan Vajab34deca2019-03-20 01:13:21 +05301367 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001368 default:
Rajan Vajacd825682020-11-23 21:33:39 -08001369 data[0] = PM_RET_ERROR_ARGS;
Rajan Vaja35116132018-01-17 02:39:25 -08001370 WARN("Unimplemented query service call: 0x%x\n", qid);
1371 }
Rajan Vaja35116132018-01-17 02:39:25 -08001372}
Siva Durga Prasad Paladuguf3994cc2018-05-01 11:12:55 +05301373
1374enum pm_ret_status pm_sha_hash(uint32_t address_high,
1375 uint32_t address_low,
1376 uint32_t size,
1377 uint32_t flags)
1378{
1379 uint32_t payload[PAYLOAD_ARG_CNT];
1380
1381 /* Send request to the PMU */
1382 PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
1383 size, flags);
1384 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1385}
1386
1387enum pm_ret_status pm_rsa_core(uint32_t address_high,
1388 uint32_t address_low,
1389 uint32_t size,
1390 uint32_t flags)
1391{
1392 uint32_t payload[PAYLOAD_ARG_CNT];
1393
1394 /* Send request to the PMU */
1395 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
1396 size, flags);
1397 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1398}
Siva Durga Prasad Paladugua4ed4b22018-04-30 20:06:58 +05301399
1400enum pm_ret_status pm_secure_image(uint32_t address_low,
1401 uint32_t address_high,
1402 uint32_t key_lo,
1403 uint32_t key_hi,
1404 uint32_t *value)
1405{
1406 uint32_t payload[PAYLOAD_ARG_CNT];
1407
1408 /* Send request to the PMU */
1409 PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
1410 key_hi, key_lo);
1411 return pm_ipi_send_sync(primary_proc, payload, value, 2);
1412}
Siva Durga Prasad Paladugu7c6516a2018-09-04 17:41:34 +05301413
1414/**
1415 * pm_fpga_read - Perform the fpga configuration readback
1416 *
1417 * @reg_numframes: Configuration register offset (or) Number of frames to read
1418 * @address_low: lower 32-bit Linear memory space address
1419 * @address_high: higher 32-bit Linear memory space address
1420 * @readback_type: Type of fpga readback operation
1421 * 0 -- Configuration Register readback
1422 * 1 -- Configuration Data readback
1423 * @value: Value to read
1424 *
1425 * This function provides access to the xilfpga library to read
1426 * the PL configuration.
1427 *
1428 * Return: Returns status, either success or error+reason.
1429 */
1430enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
1431 uint32_t address_low,
1432 uint32_t address_high,
1433 uint32_t readback_type,
1434 uint32_t *value)
1435{
1436 uint32_t payload[PAYLOAD_ARG_CNT];
1437
1438 /* Send request to the PMU */
1439 PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
1440 address_high, readback_type);
1441 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1442}
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001443
1444/*
1445 * pm_pll_set_parameter() - Set the PLL parameter value
1446 * @nid Node id of the target PLL
1447 * @param_id ID of the PLL parameter
1448 * @value Parameter value to be set
1449 *
1450 * Setting the parameter will have physical effect once the PLL mode is set to
1451 * integer or fractional.
1452 *
1453 * @return Error if an argument is not valid or status as returned by the
1454 * PM controller (PMU)
1455 */
1456enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
1457 enum pm_pll_param param_id,
1458 unsigned int value)
1459{
1460 uint32_t payload[PAYLOAD_ARG_CNT];
1461
1462 /* Check if given node ID is a PLL node */
1463 if (nid < NODE_APLL || nid > NODE_IOPLL)
1464 return PM_RET_ERROR_ARGS;
1465
1466 /* Check if parameter ID is valid and return an error if it's not */
1467 if (param_id >= PM_PLL_PARAM_MAX)
1468 return PM_RET_ERROR_ARGS;
1469
1470 /* Send request to the PMU */
1471 PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
1472 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1473}
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001474
1475/**
1476 * pm_pll_get_parameter() - Get the PLL parameter value
1477 * @nid Node id of the target PLL
1478 * @param_id ID of the PLL parameter
1479 * @value Location to store the parameter value
1480 *
1481 * @return Error if an argument is not valid or status as returned by the
1482 * PM controller (PMU)
1483 */
1484enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
1485 enum pm_pll_param param_id,
1486 unsigned int *value)
1487{
1488 uint32_t payload[PAYLOAD_ARG_CNT];
1489
1490 /* Check if given node ID is a PLL node */
1491 if (nid < NODE_APLL || nid > NODE_IOPLL)
1492 return PM_RET_ERROR_ARGS;
1493
1494 /* Check if parameter ID is valid and return an error if it's not */
1495 if (param_id >= PM_PLL_PARAM_MAX)
1496 return PM_RET_ERROR_ARGS;
1497
1498 /* Send request to the PMU */
1499 PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
1500 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1501}
Jolly Shah1f0d5852019-01-04 11:32:31 -08001502
1503/**
1504 * pm_pll_set_mode() - Set the PLL mode
1505 * @nid Node id of the target PLL
1506 * @mode PLL mode to be set
1507 *
1508 * If reset mode is set the PM controller will first bypass the PLL and then
1509 * assert the reset. If integer or fractional mode is set the PM controller will
1510 * ensure that the complete PLL programming sequence is satisfied. After this
1511 * function returns success the PLL is locked and its bypass is deasserted.
1512 *
1513 * @return Error if an argument is not valid or status as returned by the
1514 * PM controller (PMU)
1515 */
1516enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
1517{
1518 uint32_t payload[PAYLOAD_ARG_CNT];
1519
1520 /* Check if given node ID is a PLL node */
1521 if (nid < NODE_APLL || nid > NODE_IOPLL)
1522 return PM_RET_ERROR_ARGS;
1523
1524 /* Check if PLL mode is valid */
1525 if (mode >= PM_PLL_MODE_MAX)
1526 return PM_RET_ERROR_ARGS;
1527
1528 /* Send request to the PMU */
1529 PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
1530 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1531}
Jolly Shah141421e2019-01-04 11:35:48 -08001532
1533/**
1534 * pm_pll_get_mode() - Get the PLL mode
1535 * @nid Node id of the target PLL
1536 * @mode Location to store the mode of the PLL
1537 *
1538 * @return Error if an argument is not valid or status as returned by the
1539 * PM controller (PMU)
1540 */
1541enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
1542{
1543 uint32_t payload[PAYLOAD_ARG_CNT];
1544
1545 /* Check if given node ID is a PLL node */
1546 if (nid < NODE_APLL || nid > NODE_IOPLL)
1547 return PM_RET_ERROR_ARGS;
1548
1549 /* Send request to the PMU */
1550 PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
1551 return pm_ipi_send_sync(primary_proc, payload, mode, 1);
1552}
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001553
1554/**
1555 * pm_register_access() - PM API for register read/write access data
1556 *
1557 * @register_access_id Register_access_id which says register read/write
1558 *
1559 * @address Address of the register to be accessed
1560 *
1561 * @mask Mask value to be used while writing value
1562 *
1563 * @value Value to be written to register
1564 *
1565 * @out Returned output data
1566 *
1567 * This function returns requested data.
1568 *
1569 * @return Returns status, either success or error+reason
1570 */
1571enum pm_ret_status pm_register_access(unsigned int register_access_id,
1572 unsigned int address,
1573 unsigned int mask,
1574 unsigned int value,
1575 unsigned int *out)
1576{
1577 enum pm_ret_status ret;
1578
1579 if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
1580 ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
1581 ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
1582 ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE))
1583 return PM_RET_ERROR_ACCESS;
1584
1585 switch (register_access_id) {
1586 case CONFIG_REG_WRITE:
1587 ret = pm_mmio_write(address, mask, value);
1588 break;
1589 case CONFIG_REG_READ:
1590 ret = pm_mmio_read(address, out);
1591 break;
1592 default:
1593 ret = PM_RET_ERROR_ARGS;
1594 WARN("Unimplemented register_access call\n\r");
1595 }
1596 return ret;
1597}
VNSL Durgadeb1a362020-11-23 04:46:04 -08001598
1599/**
1600 * pm_efuse_access() - To program or read efuse bits.
1601 *
1602 * This function provides access to the xilskey library to program/read
1603 * efuse bits.
1604 *
1605 * address_low: lower 32-bit Linear memory space address
1606 * address_high: higher 32-bit Linear memory space address
1607 *
1608 * value: Returned output value
1609 *
1610 * @return Returns status, either success or error+reason
1611 *
1612 */
1613enum pm_ret_status pm_efuse_access(uint32_t address_high,
1614 uint32_t address_low,
1615 uint32_t *value)
1616{
1617 uint32_t payload[PAYLOAD_ARG_CNT];
1618
1619 /* Send request to the PMU */
1620 PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
1621
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -08001622 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1623}
1624
1625enum pm_ret_status em_set_action(unsigned int *value)
1626{
1627 uint32_t payload[PAYLOAD_ARG_CNT];
1628
1629 /* Send request to the PMU */
1630 EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
1631 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1632}
1633
1634enum pm_ret_status em_remove_action(unsigned int *value)
1635{
1636 uint32_t payload[PAYLOAD_ARG_CNT];
1637
1638 /* Send request to the PMU */
1639 EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
1640 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1641}
1642
1643enum pm_ret_status em_send_errors(unsigned int *value)
1644{
1645 uint32_t payload[PAYLOAD_ARG_CNT];
1646
1647 /* Send request to the PMU */
1648 EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
VNSL Durgadeb1a362020-11-23 04:46:04 -08001649 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1650}
Ronak Jain42d6f392021-08-11 00:26:28 -07001651
1652/**
1653 * pm_feature_config() - feature configuration at runtime
1654 *
1655 * This function is used to send IPI request to PMUFW to configure feature
1656 * at runtime. The feature can be enable or disable as well as the feature
1657 * can be configure at runtime using an IOCTL call.
1658 *
1659 * @ioctl_id The ioctl id for the feature configuration
1660 * @config_id The config id of the feature to be configured
1661 * @value The value to be configured
1662 * @response Return to reference pointer
1663 *
1664 * @return Returns 0 on success or error value on failure
1665 */
1666enum pm_ret_status pm_feature_config(unsigned int ioctl_id,
1667 unsigned int config_id,
1668 unsigned int value,
1669 unsigned int *response)
1670{
1671 uint32_t payload[PAYLOAD_ARG_CNT];
1672
1673 /* Send request to the PMU */
1674 PM_PACK_PAYLOAD5(payload, PM_IOCTL, 0, ioctl_id, config_id, value);
1675
1676 if (ioctl_id == IOCTL_GET_FEATURE_CONFIG) {
1677 return pm_ipi_send_sync(primary_proc, payload, response, 1);
1678 } else if (ioctl_id == IOCTL_SET_FEATURE_CONFIG) {
1679 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1680 } else {
1681 return PM_RET_ERROR_ARGS;
1682 }
1683}