blob: f9af451c06eb9015f81702631f3cb4000557b8e0 [file] [log] [blame]
Soren Brinkmann76fcae32016-03-06 20:16:27 -08001/*
Ronak Jain52de5942022-01-20 23:11:18 -08002 * Copyright (c) 2013-2022, 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
Ronak Jain325bad12021-12-21 01:39:59 -080023#define PM_QUERY_FEATURE_BITMASK ( \
24 (1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \
25 (1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) | \
26 (1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \
27 (1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \
28 (1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \
29 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \
30 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \
31 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \
32 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \
33 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \
34 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \
35 (1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \
36 (1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR))
37
38/**
39 * struct eemi_api_dependency - Dependent EEMI APIs which are implemented
40 * on both the ATF and firmware
41 *
42 * @id: EEMI API id or IOCTL id to be checked
43 * @api_id: Dependent EEMI API
44 */
45typedef struct __attribute__((packed)) {
46 uint8_t id;
47 uint8_t api_id;
48} eemi_api_dependency;
49
50/* Dependent APIs for ATF to check their version from firmware */
51static const eemi_api_dependency api_dep_table[] = {
52 {
53 .id = PM_SELF_SUSPEND,
54 .api_id = PM_SELF_SUSPEND,
55 },
56 {
57 .id = PM_REQ_WAKEUP,
58 .api_id = PM_REQ_WAKEUP,
59 },
60 {
61 .id = PM_ABORT_SUSPEND,
62 .api_id = PM_ABORT_SUSPEND,
63 },
64 {
65 .id = PM_SET_WAKEUP_SOURCE,
66 .api_id = PM_SET_WAKEUP_SOURCE,
67 },
68 {
69 .id = PM_SYSTEM_SHUTDOWN,
70 .api_id = PM_SYSTEM_SHUTDOWN,
71 },
72 {
73 .id = PM_GET_API_VERSION,
74 .api_id = PM_GET_API_VERSION,
75 },
76 {
77 .id = PM_CLOCK_ENABLE,
78 .api_id = PM_PLL_SET_MODE,
79 },
80 {
81 .id = PM_CLOCK_ENABLE,
82 .api_id = PM_CLOCK_ENABLE,
83 },
84 {
85 .id = PM_CLOCK_DISABLE,
86 .api_id = PM_PLL_SET_MODE,
87 },
88 {
89 .id = PM_CLOCK_DISABLE,
90 .api_id = PM_CLOCK_DISABLE,
91 },
92 {
93 .id = PM_CLOCK_GETSTATE,
94 .api_id = PM_PLL_GET_MODE,
95 },
96 {
97 .id = PM_CLOCK_GETSTATE,
98 .api_id = PM_CLOCK_GETSTATE,
99 },
100 {
101 .id = PM_CLOCK_SETDIVIDER,
102 .api_id = PM_PLL_SET_PARAMETER,
103 },
104 {
105 .id = PM_CLOCK_SETDIVIDER,
106 .api_id = PM_CLOCK_SETDIVIDER,
107 },
108 {
109 .id = PM_CLOCK_GETDIVIDER,
110 .api_id = PM_PLL_GET_PARAMETER,
111 },
112 {
113 .id = PM_CLOCK_GETDIVIDER,
114 .api_id = PM_CLOCK_GETDIVIDER,
115 },
116 {
117 .id = PM_CLOCK_SETPARENT,
118 .api_id = PM_PLL_SET_PARAMETER,
119 },
120 {
121 .id = PM_CLOCK_SETPARENT,
122 .api_id = PM_CLOCK_SETPARENT,
123 },
124 {
125 .id = PM_CLOCK_GETPARENT,
126 .api_id = PM_PLL_GET_PARAMETER,
127 },
128 {
129 .id = PM_CLOCK_GETPARENT,
130 .api_id = PM_CLOCK_GETPARENT,
131 },
132 {
133 .id = PM_PLL_SET_PARAMETER,
134 .api_id = PM_PLL_SET_PARAMETER,
135 },
136 {
137 .id = PM_PLL_GET_PARAMETER,
138 .api_id = PM_PLL_GET_PARAMETER,
139 },
140 {
141 .id = PM_PLL_SET_MODE,
142 .api_id = PM_PLL_SET_MODE,
143 },
144 {
145 .id = PM_PLL_GET_MODE,
146 .api_id = PM_PLL_GET_MODE,
147 },
148 {
149 .id = PM_REGISTER_ACCESS,
150 .api_id = PM_MMIO_WRITE,
151 },
152 {
153 .id = PM_REGISTER_ACCESS,
154 .api_id = PM_MMIO_READ,
155 },
156 {
157 .id = PM_FEATURE_CHECK,
158 .api_id = PM_FEATURE_CHECK,
159 },
160 {
161 .id = IOCTL_SET_TAPDELAY_BYPASS,
162 .api_id = PM_MMIO_WRITE,
163 },
164 {
165 .id = IOCTL_SET_SGMII_MODE,
166 .api_id = PM_MMIO_WRITE,
167 },
168 {
169 .id = IOCTL_SD_DLL_RESET,
170 .api_id = PM_MMIO_WRITE,
171 },
172 {
173 .id = IOCTL_SET_SD_TAPDELAY,
174 .api_id = PM_MMIO_WRITE,
175 },
176 {
177 .id = IOCTL_SET_SD_TAPDELAY,
178 .api_id = PM_MMIO_READ,
179 },
180 {
181 .id = IOCTL_SET_PLL_FRAC_DATA,
182 .api_id = PM_PLL_SET_PARAMETER,
183 },
184 {
185 .id = IOCTL_GET_PLL_FRAC_DATA,
186 .api_id = PM_PLL_GET_PARAMETER,
187 },
188 {
189 .id = IOCTL_WRITE_GGS,
190 .api_id = PM_MMIO_WRITE,
191 },
192 {
193 .id = IOCTL_READ_GGS,
194 .api_id = PM_MMIO_READ,
195 },
196 {
197 .id = IOCTL_WRITE_PGGS,
198 .api_id = PM_MMIO_WRITE,
199 },
200 {
201 .id = IOCTL_READ_PGGS,
202 .api_id = PM_MMIO_READ,
203 },
204 {
205 .id = IOCTL_ULPI_RESET,
206 .api_id = PM_MMIO_WRITE,
207 },
208 {
209 .id = IOCTL_SET_BOOT_HEALTH_STATUS,
210 .api_id = PM_MMIO_WRITE,
211 },
212 {
213 .id = IOCTL_AFI,
214 .api_id = PM_MMIO_WRITE,
215 },
216};
217
218/* Expected firmware API version to ATF */
219static const uint8_t atf_expected_ver_id[] = {
220 [PM_SELF_SUSPEND] = FW_API_BASE_VERSION,
221 [PM_REQ_WAKEUP] = FW_API_BASE_VERSION,
222 [PM_ABORT_SUSPEND] = FW_API_BASE_VERSION,
223 [PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION,
224 [PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION,
225 [PM_GET_API_VERSION] = FW_API_BASE_VERSION,
226 [PM_PLL_SET_MODE] = FW_API_BASE_VERSION,
227 [PM_PLL_GET_MODE] = FW_API_BASE_VERSION,
228 [PM_CLOCK_ENABLE] = FW_API_BASE_VERSION,
229 [PM_CLOCK_DISABLE] = FW_API_BASE_VERSION,
230 [PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION,
231 [PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION,
232 [PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION,
233 [PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION,
234 [PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION,
235 [PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION,
236 [PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION,
237 [PM_MMIO_WRITE] = FW_API_BASE_VERSION,
238 [PM_MMIO_READ] = FW_API_BASE_VERSION,
239 [PM_FEATURE_CHECK] = FW_API_VERSION_2,
240};
241
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530242/* default shutdown/reboot scope is system(2) */
243static unsigned int pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
244
245/**
246 * pm_get_shutdown_scope() - Get the currently set shutdown scope
247 *
248 * @return Shutdown scope value
249 */
250unsigned int pm_get_shutdown_scope(void)
251{
252 return pm_shutdown_scope;
253}
254
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -0800255#define EM_PACK_PAYLOAD1(pl, arg0) { \
256 pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \
257}
258
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800259/**
260 * pm_self_suspend() - PM call for processor to suspend itself
261 * @nid Node id of the processor or subsystem
262 * @latency Requested maximum wakeup latency (not supported)
Filip Drazic0bd9d0c2016-07-20 17:17:39 +0200263 * @state Requested state
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800264 * @address Resume address
265 *
266 * This is a blocking call, it will return only once PMU has responded.
267 * On a wakeup, resume address will be automatically set by PMU.
268 *
269 * @return Returns status, either success or error+reason
270 */
271enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
272 unsigned int latency,
273 unsigned int state,
274 uintptr_t address)
275{
276 uint32_t payload[PAYLOAD_ARG_CNT];
277 unsigned int cpuid = plat_my_core_pos();
278 const struct pm_proc *proc = pm_get_proc(cpuid);
279
280 /*
281 * Do client specific suspend operations
282 * (e.g. set powerdown request bit)
283 */
Filip Drazic4c0765a2016-07-26 12:11:33 +0200284 pm_client_suspend(proc, state);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800285 /* Send request to the PMU */
286 PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
287 state, address, (address >> 32));
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700288 return pm_ipi_send_sync(proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800289}
290
291/**
292 * pm_req_suspend() - PM call to request for another PU or subsystem to
293 * be suspended gracefully.
294 * @target Node id of the targeted PU or subsystem
295 * @ack Flag to specify whether acknowledge is requested
296 * @latency Requested wakeup latency (not supported)
297 * @state Requested state (not supported)
298 *
299 * @return Returns status, either success or error+reason
300 */
301enum pm_ret_status pm_req_suspend(enum pm_node_id target,
302 enum pm_request_ack ack,
303 unsigned int latency, unsigned int state)
304{
305 uint32_t payload[PAYLOAD_ARG_CNT];
306
307 /* Send request to the PMU */
308 PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
309 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700310 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800311 else
312 return pm_ipi_send(primary_proc, payload);
313}
314
315/**
316 * pm_req_wakeup() - PM call for processor to wake up selected processor
317 * or subsystem
318 * @target Node id of the processor or subsystem to wake up
319 * @ack Flag to specify whether acknowledge requested
320 * @set_address Resume address presence indicator
321 * 1 resume address specified, 0 otherwise
322 * @address Resume address
323 *
324 * This API function is either used to power up another APU core for SMP
325 * (by PSCI) or to power up an entirely different PU or subsystem, such
326 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
327 * automatically set by PMU.
328 *
329 * @return Returns status, either success or error+reason
330 */
331enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
332 unsigned int set_address,
333 uintptr_t address,
334 enum pm_request_ack ack)
335{
336 uint32_t payload[PAYLOAD_ARG_CNT];
337 uint64_t encoded_address;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800338
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800339
340 /* encode set Address into 1st bit of address */
341 encoded_address = address;
342 encoded_address |= !!set_address;
343
344 /* Send request to the PMU to perform the wake of the PU */
345 PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
346 encoded_address >> 32, ack);
347
348 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700349 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800350 else
351 return pm_ipi_send(primary_proc, payload);
352}
353
354/**
355 * pm_force_powerdown() - PM call to request for another PU or subsystem to
356 * be powered down forcefully
357 * @target Node id of the targeted PU or subsystem
358 * @ack Flag to specify whether acknowledge is requested
359 *
360 * @return Returns status, either success or error+reason
361 */
362enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
363 enum pm_request_ack ack)
364{
365 uint32_t payload[PAYLOAD_ARG_CNT];
366
367 /* Send request to the PMU */
368 PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
369
370 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700371 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800372 else
373 return pm_ipi_send(primary_proc, payload);
374}
375
376/**
377 * pm_abort_suspend() - PM call to announce that a prior suspend request
378 * is to be aborted.
379 * @reason Reason for the abort
380 *
381 * Calling PU expects the PMU to abort the initiated suspend procedure.
382 * This is a non-blocking call without any acknowledge.
383 *
384 * @return Returns status, either success or error+reason
385 */
386enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
387{
388 uint32_t payload[PAYLOAD_ARG_CNT];
389
390 /*
391 * Do client specific abort suspend operations
392 * (e.g. enable interrupts and clear powerdown request bit)
393 */
394 pm_client_abort_suspend();
395 /* Send request to the PMU */
396 /* TODO: allow passing the node ID of the affected CPU */
397 PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
398 primary_proc->node_id);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700399 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800400}
401
402/**
403 * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
404 * @target Node id of the targeted PU or subsystem
405 * @wkup_node Node id of the wakeup peripheral
406 * @enable Enable or disable the specified peripheral as wake source
407 *
408 * @return Returns status, either success or error+reason
409 */
410enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
411 enum pm_node_id wkup_node,
412 unsigned int enable)
413{
414 uint32_t payload[PAYLOAD_ARG_CNT];
415
416 PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
417 enable);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700418 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800419}
420
421/**
422 * pm_system_shutdown() - PM call to request a system shutdown or restart
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530423 * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
424 * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800425 *
426 * @return Returns status, either success or error+reason
427 */
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700428enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800429{
430 uint32_t payload[PAYLOAD_ARG_CNT];
431
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530432 if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
433 /* Setting scope for subsequent PSCI reboot or shutdown */
434 pm_shutdown_scope = subtype;
435 return PM_RET_SUCCESS;
436 }
437
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700438 PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
Tejas Patelaf4b10e2018-02-09 02:42:59 -0800439 return pm_ipi_send_non_blocking(primary_proc, payload);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800440}
441
442/* APIs for managing PM slaves: */
443
444/**
445 * pm_req_node() - PM call to request a node with specific capabilities
446 * @nid Node id of the slave
447 * @capabilities Requested capabilities of the slave
448 * @qos Quality of service (not supported)
449 * @ack Flag to specify whether acknowledge is requested
450 *
451 * @return Returns status, either success or error+reason
452 */
453enum pm_ret_status pm_req_node(enum pm_node_id nid,
454 unsigned int capabilities,
455 unsigned int qos,
456 enum pm_request_ack ack)
457{
458 uint32_t payload[PAYLOAD_ARG_CNT];
459
460 PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
461
462 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700463 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800464 else
465 return pm_ipi_send(primary_proc, payload);
466}
467
468/**
469 * pm_set_requirement() - PM call to set requirement for PM slaves
470 * @nid Node id of the slave
471 * @capabilities Requested capabilities of the slave
472 * @qos Quality of service (not supported)
473 * @ack Flag to specify whether acknowledge is requested
474 *
475 * This API function is to be used for slaves a PU already has requested
476 *
477 * @return Returns status, either success or error+reason
478 */
479enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
480 unsigned int capabilities,
481 unsigned int qos,
482 enum pm_request_ack ack)
483{
484 uint32_t payload[PAYLOAD_ARG_CNT];
485
486 PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
487 ack);
488
489 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700490 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800491 else
492 return pm_ipi_send(primary_proc, payload);
493}
494
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800495/* Miscellaneous API functions */
496
497/**
498 * pm_get_api_version() - Get version number of PMU PM firmware
499 * @version Returns 32-bit version number of PMU Power Management Firmware
500 *
501 * @return Returns status, either success or error+reason
502 */
503enum pm_ret_status pm_get_api_version(unsigned int *version)
504{
505 uint32_t payload[PAYLOAD_ARG_CNT];
506
507 /* Send request to the PMU */
508 PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700509 return pm_ipi_send_sync(primary_proc, payload, version, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800510}
511
512/**
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100513 * pm_get_node_status() - PM call to request a node's current status
514 * @nid Node id
515 * @ret_buff Buffer for the return values:
516 * [0] - Current power state of the node
517 * [1] - Current requirements for the node (slave nodes only)
518 * [2] - Current usage status for the node (slave nodes only)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800519 *
520 * @return Returns status, either success or error+reason
521 */
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100522enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
523 uint32_t *ret_buff)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800524{
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800525 uint32_t payload[PAYLOAD_ARG_CNT];
526
527 PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100528 return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800529}
530
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800531/**
532 * pm_mmio_write() - Perform write to protected mmio
533 * @address Address to write to
534 * @mask Mask to apply
535 * @value Value to write
536 *
537 * This function provides access to PM-related control registers
538 * that may not be directly accessible by a particular PU.
539 *
540 * @return Returns status, either success or error+reason
541 */
542enum pm_ret_status pm_mmio_write(uintptr_t address,
543 unsigned int mask,
544 unsigned int value)
545{
546 uint32_t payload[PAYLOAD_ARG_CNT];
547
548 /* Send request to the PMU */
549 PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700550 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800551}
552
553/**
554 * pm_mmio_read() - Read value from protected mmio
555 * @address Address to write to
556 * @value Value to write
557 *
558 * This function provides access to PM-related control registers
559 * that may not be directly accessible by a particular PU.
560 *
561 * @return Returns status, either success or error+reason
562 */
563enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
564{
565 uint32_t payload[PAYLOAD_ARG_CNT];
566
567 /* Send request to the PMU */
568 PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700569 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800570}
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530571
572/**
573 * pm_fpga_load() - Load the bitstream into the PL.
574 *
575 * This function provides access to the xilfpga library to load
576 * the Bit-stream into PL.
577 *
578 * address_low: lower 32-bit Linear memory space address
579 *
580 * address_high: higher 32-bit Linear memory space address
581 *
582 * size: Number of 32bit words
583 *
584 * @return Returns status, either success or error+reason
585 */
586enum pm_ret_status pm_fpga_load(uint32_t address_low,
587 uint32_t address_high,
588 uint32_t size,
589 uint32_t flags)
590{
591 uint32_t payload[PAYLOAD_ARG_CNT];
592
593 /* Send request to the PMU */
594 PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
595 size, flags);
Siva Durga Prasad Paladugubf83b9c2018-02-07 13:13:01 +0530596 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530597}
598
599/**
600 * pm_fpga_get_status() - Read value from fpga status register
601 * @value Value to read
602 *
603 * This function provides access to the xilfpga library to get
604 * the fpga status
605 * @return Returns status, either success or error+reason
606 */
607enum pm_ret_status pm_fpga_get_status(unsigned int *value)
608{
609 uint32_t payload[PAYLOAD_ARG_CNT];
610
611 /* Send request to the PMU */
612 PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700613 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530614}
Soren Brinkmanncb366812016-09-22 12:21:11 -0700615
616/**
617 * pm_get_chipid() - Read silicon ID registers
618 * @value Buffer for return values. Must be large enough
619 * to hold 8 bytes.
620 *
621 * @return Returns silicon ID registers
622 */
623enum pm_ret_status pm_get_chipid(uint32_t *value)
624{
625 uint32_t payload[PAYLOAD_ARG_CNT];
626
627 /* Send request to the PMU */
628 PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
629 return pm_ipi_send_sync(primary_proc, payload, value, 2);
630}
Soren Brinkmann84f0af42016-09-30 14:24:25 -0700631
632/**
Siva Durga Prasad Paladugude93d982018-04-30 15:49:27 +0530633 * pm_secure_rsaaes() - Load the secure images.
634 *
635 * This function provides access to the xilsecure library to load
636 * the authenticated, encrypted, and authenicated/encrypted images.
637 *
638 * address_low: lower 32-bit Linear memory space address
639 *
640 * address_high: higher 32-bit Linear memory space address
641 *
642 * size: Number of 32bit words
643 *
644 * @return Returns status, either success or error+reason
645 */
646enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
647 uint32_t address_high,
648 uint32_t size,
649 uint32_t flags)
650{
651 uint32_t payload[PAYLOAD_ARG_CNT];
652
653 /* Send request to the PMU */
654 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
655 size, flags);
656 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
657}
658
659/**
Siva Durga Prasad Paladugu8bd905b2018-09-04 18:05:50 +0530660 * pm_aes_engine() - Aes data blob encryption/decryption
661 * This function provides access to the xilsecure library to
662 * encrypt/decrypt data blobs.
663 *
664 * address_low: lower 32-bit address of the AesParams structure
665 *
666 * address_high: higher 32-bit address of the AesParams structure
667 *
668 * value: Returned output value
669 *
670 * @return Returns status, either success or error+reason
671 */
672enum pm_ret_status pm_aes_engine(uint32_t address_high,
673 uint32_t address_low,
674 uint32_t *value)
675{
676 uint32_t payload[PAYLOAD_ARG_CNT];
677
678 /* Send request to the PMU */
679 PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
680 return pm_ipi_send_sync(primary_proc, payload, value, 1);
681}
682
683/**
Rajan Vaja02d18422019-03-04 11:09:39 +0530684 * pm_get_callbackdata() - Read from IPI response buffer
685 * @data - array of PAYLOAD_ARG_CNT elements
686 *
687 * Read value from ipi buffer response buffer.
688 */
689void pm_get_callbackdata(uint32_t *data, size_t count)
690{
691 /* Return if interrupt is not from PMU */
692 if (!pm_ipi_irq_status(primary_proc))
693 return;
694
695 pm_ipi_buff_read_callb(data, count);
696 pm_ipi_irq_clear(primary_proc);
697}
698
699/**
Rajan Vaja5529a012018-01-17 02:39:23 -0800700 * pm_ioctl() - PM IOCTL API for device control and configs
701 * @node_id Node ID of the device
702 * @ioctl_id ID of the requested IOCTL
703 * @arg1 Argument 1 to requested IOCTL call
704 * @arg2 Argument 2 to requested IOCTL call
705 * @out Returned output value
706 *
707 * This function calls IOCTL to firmware for device control and configuration.
708 *
709 * @return Returns status, either success or error+reason
710 */
711enum pm_ret_status pm_ioctl(enum pm_node_id nid,
712 unsigned int ioctl_id,
713 unsigned int arg1,
714 unsigned int arg2,
715 unsigned int *value)
716{
717 return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
718}
Rajan Vaja35116132018-01-17 02:39:25 -0800719
720/**
Ronak Jain325bad12021-12-21 01:39:59 -0800721 * fw_api_version() - Returns API version implemented in firmware
722 * @api_id API ID to check
723 * @version Returned supported API version
724 * @len Number of words to be returned
725 *
726 * @return Returns status, either success or error+reason
727 */
728static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version,
729 uint32_t len)
730{
731 uint32_t payload[PAYLOAD_ARG_CNT];
732
733 PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id);
734 return pm_ipi_send_sync(primary_proc, payload, version, len);
735}
736
737/**
738 * check_api_dependency() - API to check dependent EEMI API version
739 * @id EEMI API ID to check
740 *
741 * @return Returns status, either success or error+reason
742 */
743enum pm_ret_status check_api_dependency(uint8_t id)
744{
745 uint8_t i;
746 uint32_t version;
747 int ret;
748
749 for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
750 if (api_dep_table[i].id == id) {
751 if (api_dep_table[i].api_id == 0U) {
752 break;
753 }
754
755 ret = fw_api_version(api_dep_table[i].api_id,
756 &version, 1);
757 if (ret != PM_RET_SUCCESS) {
758 return ret;
759 }
760
761 /* Check if fw version matches ATF expected version */
762 if (version != atf_expected_ver_id[api_dep_table[i].api_id]) {
763 return PM_RET_ERROR_NOTSUPPORTED;
764 }
765 }
766 }
767
768 return PM_RET_SUCCESS;
769}
770
771/**
772 * feature_check_atf() - These are API's completely implemented in ATF
773 * @api_id API ID to check
774 * @version Returned supported API version
775 *
776 * @return Returns status, either success or error+reason
777 */
778static enum pm_ret_status feature_check_atf(uint32_t api_id, uint32_t *version,
779 uint32_t *bit_mask)
780{
781 switch (api_id) {
782 case PM_QUERY_DATA:
783 *version = ATF_API_BASE_VERSION;
784 bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
785 bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
786 return PM_RET_SUCCESS;
787 case PM_GET_CALLBACK_DATA:
788 case PM_GET_TRUSTZONE_VERSION:
789 case PM_SET_SUSPEND_MODE:
790 *version = ATF_API_BASE_VERSION;
791 return PM_RET_SUCCESS;
792 default:
793 return PM_RET_ERROR_NO_FEATURE;
794 }
795}
796
797/**
798 * get_atf_version_for_partial_apis() - Return ATF version for partially
799 * implemented APIs
800 * @api_id API ID to check
801 * @version Returned supported API version
802 *
803 * @return Returns status, either success or error+reason
804 */
805static enum pm_ret_status get_atf_version_for_partial_apis(uint32_t api_id,
806 uint32_t *version)
807{
808 switch (api_id) {
809 case PM_SELF_SUSPEND:
810 case PM_REQ_WAKEUP:
811 case PM_ABORT_SUSPEND:
812 case PM_SET_WAKEUP_SOURCE:
813 case PM_SYSTEM_SHUTDOWN:
814 case PM_GET_API_VERSION:
815 case PM_CLOCK_ENABLE:
816 case PM_CLOCK_DISABLE:
817 case PM_CLOCK_GETSTATE:
818 case PM_CLOCK_SETDIVIDER:
819 case PM_CLOCK_GETDIVIDER:
820 case PM_CLOCK_SETPARENT:
821 case PM_CLOCK_GETPARENT:
822 case PM_PLL_SET_PARAMETER:
823 case PM_PLL_GET_PARAMETER:
824 case PM_PLL_SET_MODE:
825 case PM_PLL_GET_MODE:
826 case PM_REGISTER_ACCESS:
827 *version = ATF_API_BASE_VERSION;
828 return PM_RET_SUCCESS;
829 case PM_FEATURE_CHECK:
830 *version = FW_API_VERSION_2;
831 return PM_RET_SUCCESS;
832 default:
833 return PM_RET_ERROR_ARGS;
834 }
835}
836
837/**
838 * feature_check_partial() - These are API's partially implemented in
839 * ATF and firmware both
840 * @api_id API ID to check
841 * @version Returned supported API version
842 *
843 * @return Returns status, either success or error+reason
844 */
845static enum pm_ret_status feature_check_partial(uint32_t api_id,
846 uint32_t *version)
847{
848 uint32_t status;
849
850 switch (api_id) {
851 case PM_SELF_SUSPEND:
852 case PM_REQ_WAKEUP:
853 case PM_ABORT_SUSPEND:
854 case PM_SET_WAKEUP_SOURCE:
855 case PM_SYSTEM_SHUTDOWN:
856 case PM_GET_API_VERSION:
857 case PM_CLOCK_ENABLE:
858 case PM_CLOCK_DISABLE:
859 case PM_CLOCK_GETSTATE:
860 case PM_CLOCK_SETDIVIDER:
861 case PM_CLOCK_GETDIVIDER:
862 case PM_CLOCK_SETPARENT:
863 case PM_CLOCK_GETPARENT:
864 case PM_PLL_SET_PARAMETER:
865 case PM_PLL_GET_PARAMETER:
866 case PM_PLL_SET_MODE:
867 case PM_PLL_GET_MODE:
868 case PM_REGISTER_ACCESS:
869 case PM_FEATURE_CHECK:
870 status = check_api_dependency(api_id);
871 if (status != PM_RET_SUCCESS) {
872 return status;
873 }
874 return get_atf_version_for_partial_apis(api_id, version);
875 default:
876 return PM_RET_ERROR_NO_FEATURE;
877 }
878}
879
880/**
881 * pm_feature_check() - Returns the supported API version if supported
882 * @api_id API ID to check
883 * @version Returned supported API version
884 * @bit_mask Returned supported IOCTL id version
885 * @len Number of bytes to be returned in bit_mask variable
886 *
887 * @return Returns status, either success or error+reason
888 */
889enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
890 uint32_t *bit_mask, uint8_t len)
891{
892 uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
893 uint32_t status;
894
895 /* Get API version implemented in ATF */
896 status = feature_check_atf(api_id, version, bit_mask);
897 if (status != PM_RET_ERROR_NO_FEATURE) {
898 return status;
899 }
900
901 /* Get API version implemented by firmware and ATF both */
902 status = feature_check_partial(api_id, version);
903 if (status != PM_RET_ERROR_NO_FEATURE) {
904 return status;
905 }
906
907 /* Get API version implemented by firmware */
908 status = fw_api_version(api_id, ret_payload, 3);
909 /* IOCTL call may return failure whose ID is not implemented in
910 * firmware but implemented in ATF
911 */
912 if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) {
913 return status;
914 }
915
916 *version = ret_payload[0];
917
918 /* Update IOCTL bit mask which are implemented in ATF */
919 if (api_id == PM_IOCTL) {
920 if (len < 2) {
921 return PM_RET_ERROR_ARGS;
922 }
923 bit_mask[0] = ret_payload[1];
924 bit_mask[1] = ret_payload[2];
925 /* Get IOCTL's implemented by ATF */
926 status = atf_ioctl_bitmask(bit_mask);
927 } else {
928 /* Requires for MISRA */
929 }
930
931 return status;
932}
933
934/**
Rajan Vajab34deca2019-03-20 01:13:21 +0530935 * pm_clock_get_max_divisor - PM call to get max divisor
936 * @clock_id Clock ID
937 * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2)
938 * @max_div Maximum supported divisor
939 *
940 * This function is used by master to get maximum supported value.
941 *
942 * Return: Returns status, either success or error+reason.
943 */
944static enum pm_ret_status pm_clock_get_max_divisor(unsigned int clock_id,
945 uint8_t div_type,
946 uint32_t *max_div)
947{
948 return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
949}
950
951/**
Rajan Vajada959402018-07-20 03:16:27 -0700952 * pm_clock_get_num_clocks - PM call to request number of clocks
953 * @nclockss: Number of clocks
954 *
955 * This function is used by master to get number of clocks.
956 *
957 * Return: Returns status, either success or error+reason.
958 */
959static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
960{
961 return pm_api_clock_get_num_clocks(nclocks);
962}
963
964/**
Rajan Vaja35116132018-01-17 02:39:25 -0800965 * pm_clock_get_name() - PM call to request a clock's name
966 * @clock_id Clock ID
967 * @name Name of clock (max 16 bytes)
968 *
969 * This function is used by master to get nmae of clock specified
970 * by given clock ID.
Rajan Vaja35116132018-01-17 02:39:25 -0800971 */
Rajan Vajacd825682020-11-23 21:33:39 -0800972static void pm_clock_get_name(unsigned int clock_id, char *name)
Rajan Vaja35116132018-01-17 02:39:25 -0800973{
Rajan Vajacd825682020-11-23 21:33:39 -0800974 pm_api_clock_get_name(clock_id, name);
Rajan Vaja35116132018-01-17 02:39:25 -0800975}
976
977/**
978 * pm_clock_get_topology() - PM call to request a clock's topology
979 * @clock_id Clock ID
980 * @index Topology index for next toplogy node
981 * @topology Buffer to store nodes in topology and flags
982 *
983 * This function is used by master to get topology information for the
984 * clock specified by given clock ID. Each response would return 3
985 * topology nodes. To get next nodes, caller needs to call this API with
986 * index of next node. Index starts from 0.
987 *
988 * @return Returns status, either success or error+reason
989 */
990static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id,
991 unsigned int index,
992 uint32_t *topology)
993{
994 return pm_api_clock_get_topology(clock_id, index, topology);
995}
996
997/**
998 * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
999 * parameters for fixed clock
1000 * @clock_id Clock ID
1001 * @mul Multiplication value
1002 * @div Divisor value
1003 *
1004 * This function is used by master to get fixed factor parameers for the
1005 * fixed clock. This API is application only for the fixed clock.
1006 *
1007 * @return Returns status, either success or error+reason
1008 */
1009static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id,
1010 uint32_t *mul,
1011 uint32_t *div)
1012{
1013 return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
1014}
1015
1016/**
1017 * pm_clock_get_parents() - PM call to request a clock's first 3 parents
1018 * @clock_id Clock ID
1019 * @index Index of next parent
1020 * @parents Parents of the given clock
1021 *
1022 * This function is used by master to get clock's parents information.
1023 * This API will return 3 parents with a single response. To get other
1024 * parents, master should call same API in loop with new parent index
1025 * till error is returned.
1026 *
1027 * E.g First call should have index 0 which will return parents 0, 1 and
1028 * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
1029 * so on.
1030 *
1031 * @return Returns status, either success or error+reason
1032 */
1033static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id,
1034 unsigned int index,
1035 uint32_t *parents)
1036{
1037 return pm_api_clock_get_parents(clock_id, index, parents);
1038}
1039
1040/**
1041 * pm_clock_get_attributes() - PM call to request a clock's attributes
1042 * @clock_id Clock ID
1043 * @attr Clock attributes
1044 *
1045 * This function is used by master to get clock's attributes
1046 * (e.g. valid, clock type, etc).
1047 *
1048 * @return Returns status, either success or error+reason
1049 */
1050static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
1051 uint32_t *attr)
1052{
1053 return pm_api_clock_get_attributes(clock_id, attr);
1054}
1055
1056/**
Jolly Shaha5209802019-01-04 11:45:59 -08001057 * pm_clock_gate() - Configure clock gate
1058 * @clock_id Id of the clock to be configured
1059 * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
1060 *
1061 * @return Error if an argument is not valid or status as returned by the
1062 * PM controller (PMU)
1063 */
1064static enum pm_ret_status pm_clock_gate(unsigned int clock_id,
1065 unsigned char enable)
1066{
1067 uint32_t payload[PAYLOAD_ARG_CNT];
1068 enum pm_ret_status status;
1069 enum pm_api_id api_id;
1070
1071 /* Check if clock ID is valid and return an error if it is not */
1072 status = pm_clock_id_is_valid(clock_id);
1073 if (status != PM_RET_SUCCESS)
1074 return status;
1075
1076 if (enable)
1077 api_id = PM_CLOCK_ENABLE;
1078 else
1079 api_id = PM_CLOCK_DISABLE;
1080
1081 /* Send request to the PMU */
1082 PM_PACK_PAYLOAD2(payload, api_id, clock_id);
Mirela Simonovic64514a72018-08-24 17:09:07 +02001083 status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1084
1085 /* If action fails due to the lack of permissions filter the error */
1086 if (status == PM_RET_ERROR_ACCESS)
1087 status = PM_RET_SUCCESS;
1088
1089 return status;
Jolly Shaha5209802019-01-04 11:45:59 -08001090}
1091
1092/**
Rajan Vaja35116132018-01-17 02:39:25 -08001093 * pm_clock_enable() - Enable the clock for given id
1094 * @clock_id: Id of the clock to be enabled
1095 *
1096 * This function is used by master to enable the clock
1097 * including peripherals and PLL clocks.
1098 *
Jolly Shaha5209802019-01-04 11:45:59 -08001099 * @return: Error if an argument is not valid or status as returned by the
1100 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -08001101 */
Rajan Vaja35116132018-01-17 02:39:25 -08001102enum pm_ret_status pm_clock_enable(unsigned int clock_id)
1103{
Jolly Shaha5209802019-01-04 11:45:59 -08001104 struct pm_pll *pll;
1105
1106 /* First try to handle it as a PLL */
1107 pll = pm_clock_get_pll(clock_id);
1108 if (pll)
1109 return pm_clock_pll_enable(pll);
1110
1111 /* It's an on-chip clock, PMU should configure clock's gate */
1112 return pm_clock_gate(clock_id, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001113}
1114
1115/**
1116 * pm_clock_disable - Disable the clock for given id
1117 * @clock_id: Id of the clock to be disable
1118 *
1119 * This function is used by master to disable the clock
1120 * including peripherals and PLL clocks.
1121 *
Jolly Shaha9057a02019-01-02 12:54:40 -08001122 * @return: Error if an argument is not valid or status as returned by the
1123 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -08001124 */
Rajan Vaja35116132018-01-17 02:39:25 -08001125enum pm_ret_status pm_clock_disable(unsigned int clock_id)
1126{
Jolly Shaha9057a02019-01-02 12:54:40 -08001127 struct pm_pll *pll;
1128
1129 /* First try to handle it as a PLL */
1130 pll = pm_clock_get_pll(clock_id);
1131 if (pll)
1132 return pm_clock_pll_disable(pll);
1133
1134 /* It's an on-chip clock, PMU should configure clock's gate */
1135 return pm_clock_gate(clock_id, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001136}
1137
1138/**
1139 * pm_clock_getstate - Get the clock state for given id
1140 * @clock_id: Id of the clock to be queried
1141 * @state: 1/0 (Enabled/Disabled)
1142 *
1143 * This function is used by master to get the state of clock
1144 * including peripherals and PLL clocks.
1145 *
1146 * Return: Returns status, either success or error+reason.
1147 */
1148enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
1149 unsigned int *state)
1150{
Jolly Shah99e8ac92019-01-02 12:55:41 -08001151 struct pm_pll *pll;
1152 uint32_t payload[PAYLOAD_ARG_CNT];
1153 enum pm_ret_status status;
1154
1155 /* First try to handle it as a PLL */
1156 pll = pm_clock_get_pll(clock_id);
1157 if (pll)
1158 return pm_clock_pll_get_state(pll, state);
1159
1160 /* Check if clock ID is a valid on-chip clock */
1161 status = pm_clock_id_is_valid(clock_id);
1162 if (status != PM_RET_SUCCESS)
1163 return status;
1164
1165 /* Send request to the PMU */
1166 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
1167 return pm_ipi_send_sync(primary_proc, payload, state, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001168}
1169
1170/**
1171 * pm_clock_setdivider - Set the clock divider for given id
1172 * @clock_id: Id of the clock
1173 * @divider: divider value
1174 *
1175 * This function is used by master to set divider for any clock
1176 * to achieve desired rate.
1177 *
1178 * Return: Returns status, either success or error+reason.
1179 */
1180enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
1181 unsigned int divider)
1182{
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001183 enum pm_ret_status status;
1184 enum pm_node_id nid;
1185 enum pm_clock_div_id div_id;
1186 uint32_t payload[PAYLOAD_ARG_CNT];
1187 const uint32_t div0 = 0xFFFF0000;
1188 const uint32_t div1 = 0x0000FFFF;
1189 uint32_t val;
1190
1191 /* Get PLL node ID using PLL clock ID */
1192 status = pm_clock_get_pll_node_id(clock_id, &nid);
1193 if (status == PM_RET_SUCCESS)
1194 return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1195
1196 /* Check if clock ID is a valid on-chip clock */
1197 status = pm_clock_id_is_valid(clock_id);
1198 if (status != PM_RET_SUCCESS)
1199 return status;
1200
1201 if (div0 == (divider & div0)) {
1202 div_id = PM_CLOCK_DIV0_ID;
1203 val = divider & ~div0;
1204 } else if (div1 == (divider & div1)) {
1205 div_id = PM_CLOCK_DIV1_ID;
1206 val = (divider & ~div1) >> 16;
1207 } else {
1208 return PM_RET_ERROR_ARGS;
1209 }
1210
1211 /* Send request to the PMU */
1212 PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
1213 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001214}
1215
1216/**
1217 * pm_clock_getdivider - Get the clock divider for given id
1218 * @clock_id: Id of the clock
1219 * @divider: divider value
1220 *
1221 * This function is used by master to get divider values
1222 * for any clock.
1223 *
1224 * Return: Returns status, either success or error+reason.
1225 */
1226enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
1227 unsigned int *divider)
1228{
Jolly Shah4dd11762019-01-04 11:53:37 -08001229 enum pm_ret_status status;
1230 enum pm_node_id nid;
1231 uint32_t payload[PAYLOAD_ARG_CNT];
1232 uint32_t val;
1233
1234 /* Get PLL node ID using PLL clock ID */
1235 status = pm_clock_get_pll_node_id(clock_id, &nid);
1236 if (status == PM_RET_SUCCESS)
1237 return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1238
1239 /* Check if clock ID is a valid on-chip clock */
1240 status = pm_clock_id_is_valid(clock_id);
1241 if (status != PM_RET_SUCCESS)
1242 return status;
1243
1244 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
1245 /* Send request to the PMU to get div0 */
1246 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1247 PM_CLOCK_DIV0_ID);
1248 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1249 if (status != PM_RET_SUCCESS)
1250 return status;
1251 *divider = val;
1252 }
1253
1254 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
1255 /* Send request to the PMU to get div1 */
1256 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1257 PM_CLOCK_DIV1_ID);
1258 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1259 if (status != PM_RET_SUCCESS)
1260 return status;
1261 *divider |= val << 16;
1262 }
1263
1264 return status;
Rajan Vaja35116132018-01-17 02:39:25 -08001265}
1266
1267/**
1268 * pm_clock_setrate - Set the clock rate for given id
1269 * @clock_id: Id of the clock
1270 * @rate: rate value in hz
1271 *
1272 * This function is used by master to set rate for any clock.
1273 *
1274 * Return: Returns status, either success or error+reason.
1275 */
1276enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
1277 uint64_t rate)
1278{
Jolly Shahc1391812019-01-02 13:39:30 -08001279 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001280}
1281
1282/**
1283 * pm_clock_getrate - Get the clock rate for given id
1284 * @clock_id: Id of the clock
1285 * @rate: rate value in hz
1286 *
1287 * This function is used by master to get rate
1288 * for any clock.
1289 *
1290 * Return: Returns status, either success or error+reason.
1291 */
1292enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
1293 uint64_t *rate)
1294{
Jolly Shahc1391812019-01-02 13:39:30 -08001295 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001296}
1297
1298/**
1299 * pm_clock_setparent - Set the clock parent for given id
1300 * @clock_id: Id of the clock
Jolly Shah407fc0a2019-01-04 11:57:40 -08001301 * @parent_index: Index of the parent clock into clock's parents array
Rajan Vaja35116132018-01-17 02:39:25 -08001302 *
1303 * This function is used by master to set parent for any clock.
1304 *
1305 * Return: Returns status, either success or error+reason.
1306 */
1307enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
Jolly Shah407fc0a2019-01-04 11:57:40 -08001308 unsigned int parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001309{
Jolly Shah407fc0a2019-01-04 11:57:40 -08001310 struct pm_pll *pll;
1311 uint32_t payload[PAYLOAD_ARG_CNT];
1312 enum pm_ret_status status;
1313
1314 /* First try to handle it as a PLL */
1315 pll = pm_clock_get_pll_by_related_clk(clock_id);
1316 if (pll)
1317 return pm_clock_pll_set_parent(pll, clock_id, parent_index);
1318
1319 /* Check if clock ID is a valid on-chip clock */
1320 status = pm_clock_id_is_valid(clock_id);
1321 if (status != PM_RET_SUCCESS)
1322 return status;
1323
1324 /* Send request to the PMU */
1325 PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
1326 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001327}
1328
1329/**
1330 * pm_clock_getparent - Get the clock parent for given id
1331 * @clock_id: Id of the clock
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001332 * @parent_index: parent index
Rajan Vaja35116132018-01-17 02:39:25 -08001333 *
1334 * This function is used by master to get parent index
1335 * for any clock.
1336 *
1337 * Return: Returns status, either success or error+reason.
1338 */
1339enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001340 unsigned int *parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001341{
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001342 struct pm_pll *pll;
1343 uint32_t payload[PAYLOAD_ARG_CNT];
1344 enum pm_ret_status status;
1345
1346 /* First try to handle it as a PLL */
1347 pll = pm_clock_get_pll_by_related_clk(clock_id);
1348 if (pll)
1349 return pm_clock_pll_get_parent(pll, clock_id, parent_index);
1350
1351 /* Check if clock ID is a valid on-chip clock */
1352 status = pm_clock_id_is_valid(clock_id);
1353 if (status != PM_RET_SUCCESS)
1354 return status;
1355
1356 /* Send request to the PMU */
1357 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
1358 return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001359}
1360
1361/**
Rajan Vajad5dd8362018-01-30 04:16:31 -08001362 * pm_pinctrl_get_num_pins - PM call to request number of pins
1363 * @npins: Number of pins
1364 *
1365 * This function is used by master to get number of pins
1366 *
1367 * Return: Returns status, either success or error+reason.
1368 */
1369static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
1370{
1371 return pm_api_pinctrl_get_num_pins(npins);
1372}
1373
1374/**
1375 * pm_pinctrl_get_num_functions - PM call to request number of functions
1376 * @nfuncs: Number of functions
1377 *
1378 * This function is used by master to get number of functions
1379 *
1380 * Return: Returns status, either success or error+reason.
1381 */
1382static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
1383{
1384 return pm_api_pinctrl_get_num_functions(nfuncs);
1385}
1386
1387/**
1388 * pm_pinctrl_get_num_function_groups - PM call to request number of
1389 * function groups
1390 * @fid: Id of function
1391 * @ngroups: Number of function groups
1392 *
1393 * This function is used by master to get number of function groups specified
1394 * by given function Id
1395 *
1396 * Return: Returns status, either success or error+reason.
1397 */
1398static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid,
1399 uint32_t *ngroups)
1400{
1401 return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
1402}
1403
1404/**
1405 * pm_pinctrl_get_function_name - PM call to request function name
1406 * @fid: Id of function
1407 * @name: Name of function
1408 *
1409 * This function is used by master to get name of function specified
1410 * by given function Id
Rajan Vajad5dd8362018-01-30 04:16:31 -08001411 */
Rajan Vajacd825682020-11-23 21:33:39 -08001412static void pm_pinctrl_get_function_name(unsigned int fid, char *name)
Rajan Vajad5dd8362018-01-30 04:16:31 -08001413{
Rajan Vajacd825682020-11-23 21:33:39 -08001414 pm_api_pinctrl_get_function_name(fid, name);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001415}
1416
1417/**
1418 * pm_pinctrl_get_function_groups - PM call to request function groups
1419 * @fid: Id of function
1420 * @index: Index of next function groups
1421 * @groups: Function groups
1422 *
1423 * This function is used by master to get function groups specified
1424 * by given function Id. This API will return 6 function groups with
1425 * a single response. To get other function groups, master should call
1426 * same API in loop with new function groups index till error is returned.
1427 *
1428 * E.g First call should have index 0 which will return function groups
1429 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1430 * function groups 6, 7, 8, 9, 10 and 11 and so on.
1431 *
1432 * Return: Returns status, either success or error+reason.
1433 */
1434static enum pm_ret_status pm_pinctrl_get_function_groups(unsigned int fid,
1435 unsigned int index,
1436 uint16_t *groups)
1437{
1438 return pm_api_pinctrl_get_function_groups(fid, index, groups);
1439}
1440
1441/**
1442 * pm_pinctrl_get_pin_groups - PM call to request pin groups
1443 * @pin_id: Id of pin
1444 * @index: Index of next pin groups
1445 * @groups: pin groups
1446 *
1447 * This function is used by master to get pin groups specified
1448 * by given pin Id. This API will return 6 pin groups with
1449 * a single response. To get other pin groups, master should call
1450 * same API in loop with new pin groups index till error is returned.
1451 *
1452 * E.g First call should have index 0 which will return pin groups
1453 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1454 * pin groups 6, 7, 8, 9, 10 and 11 and so on.
1455 *
1456 * Return: Returns status, either success or error+reason.
1457 */
1458static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id,
1459 unsigned int index,
1460 uint16_t *groups)
1461{
1462 return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
1463}
1464
1465/**
Rajan Vaja35116132018-01-17 02:39:25 -08001466 * pm_query_data() - PM API for querying firmware data
1467 * @arg1 Argument 1 to requested IOCTL call
1468 * @arg2 Argument 2 to requested IOCTL call
1469 * @arg3 Argument 3 to requested IOCTL call
1470 * @arg4 Argument 4 to requested IOCTL call
1471 * @data Returned output data
1472 *
1473 * This function returns requested data.
Rajan Vaja35116132018-01-17 02:39:25 -08001474 */
Rajan Vajacd825682020-11-23 21:33:39 -08001475void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
1476 unsigned int arg3, unsigned int *data)
Rajan Vaja35116132018-01-17 02:39:25 -08001477{
Rajan Vaja35116132018-01-17 02:39:25 -08001478 switch (qid) {
1479 case PM_QID_CLOCK_GET_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001480 pm_clock_get_name(arg1, (char *)data);
Rajan Vaja35116132018-01-17 02:39:25 -08001481 break;
1482 case PM_QID_CLOCK_GET_TOPOLOGY:
Rajan Vajacd825682020-11-23 21:33:39 -08001483 data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001484 break;
1485 case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
Rajan Vajacd825682020-11-23 21:33:39 -08001486 data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
1487 &data[2]);
Rajan Vaja35116132018-01-17 02:39:25 -08001488 break;
1489 case PM_QID_CLOCK_GET_PARENTS:
Rajan Vajacd825682020-11-23 21:33:39 -08001490 data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001491 break;
1492 case PM_QID_CLOCK_GET_ATTRIBUTES:
Rajan Vajacd825682020-11-23 21:33:39 -08001493 data[0] = pm_clock_get_attributes(arg1, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001494 break;
Rajan Vajad5dd8362018-01-30 04:16:31 -08001495 case PM_QID_PINCTRL_GET_NUM_PINS:
Rajan Vajacd825682020-11-23 21:33:39 -08001496 data[0] = pm_pinctrl_get_num_pins(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001497 break;
1498 case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
Rajan Vajacd825682020-11-23 21:33:39 -08001499 data[0] = pm_pinctrl_get_num_functions(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001500 break;
1501 case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001502 data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001503 break;
1504 case PM_QID_PINCTRL_GET_FUNCTION_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001505 pm_pinctrl_get_function_name(arg1, (char *)data);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001506 break;
1507 case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001508 data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
1509 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001510 break;
1511 case PM_QID_PINCTRL_GET_PIN_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001512 data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
1513 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001514 break;
Rajan Vajada959402018-07-20 03:16:27 -07001515 case PM_QID_CLOCK_GET_NUM_CLOCKS:
Rajan Vajacd825682020-11-23 21:33:39 -08001516 data[0] = pm_clock_get_num_clocks(&data[1]);
Rajan Vajada959402018-07-20 03:16:27 -07001517 break;
Rajan Vajab34deca2019-03-20 01:13:21 +05301518
1519 case PM_QID_CLOCK_GET_MAX_DIVISOR:
Rajan Vajacd825682020-11-23 21:33:39 -08001520 data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
Rajan Vajab34deca2019-03-20 01:13:21 +05301521 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001522 default:
Rajan Vajacd825682020-11-23 21:33:39 -08001523 data[0] = PM_RET_ERROR_ARGS;
Rajan Vaja35116132018-01-17 02:39:25 -08001524 WARN("Unimplemented query service call: 0x%x\n", qid);
1525 }
Rajan Vaja35116132018-01-17 02:39:25 -08001526}
Siva Durga Prasad Paladuguf3994cc2018-05-01 11:12:55 +05301527
1528enum pm_ret_status pm_sha_hash(uint32_t address_high,
1529 uint32_t address_low,
1530 uint32_t size,
1531 uint32_t flags)
1532{
1533 uint32_t payload[PAYLOAD_ARG_CNT];
1534
1535 /* Send request to the PMU */
1536 PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
1537 size, flags);
1538 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1539}
1540
1541enum pm_ret_status pm_rsa_core(uint32_t address_high,
1542 uint32_t address_low,
1543 uint32_t size,
1544 uint32_t flags)
1545{
1546 uint32_t payload[PAYLOAD_ARG_CNT];
1547
1548 /* Send request to the PMU */
1549 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
1550 size, flags);
1551 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1552}
Siva Durga Prasad Paladugua4ed4b22018-04-30 20:06:58 +05301553
1554enum pm_ret_status pm_secure_image(uint32_t address_low,
1555 uint32_t address_high,
1556 uint32_t key_lo,
1557 uint32_t key_hi,
1558 uint32_t *value)
1559{
1560 uint32_t payload[PAYLOAD_ARG_CNT];
1561
1562 /* Send request to the PMU */
1563 PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
1564 key_hi, key_lo);
1565 return pm_ipi_send_sync(primary_proc, payload, value, 2);
1566}
Siva Durga Prasad Paladugu7c6516a2018-09-04 17:41:34 +05301567
1568/**
1569 * pm_fpga_read - Perform the fpga configuration readback
1570 *
1571 * @reg_numframes: Configuration register offset (or) Number of frames to read
1572 * @address_low: lower 32-bit Linear memory space address
1573 * @address_high: higher 32-bit Linear memory space address
1574 * @readback_type: Type of fpga readback operation
1575 * 0 -- Configuration Register readback
1576 * 1 -- Configuration Data readback
1577 * @value: Value to read
1578 *
1579 * This function provides access to the xilfpga library to read
1580 * the PL configuration.
1581 *
1582 * Return: Returns status, either success or error+reason.
1583 */
1584enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
1585 uint32_t address_low,
1586 uint32_t address_high,
1587 uint32_t readback_type,
1588 uint32_t *value)
1589{
1590 uint32_t payload[PAYLOAD_ARG_CNT];
1591
1592 /* Send request to the PMU */
1593 PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
1594 address_high, readback_type);
1595 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1596}
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001597
1598/*
1599 * pm_pll_set_parameter() - Set the PLL parameter value
1600 * @nid Node id of the target PLL
1601 * @param_id ID of the PLL parameter
1602 * @value Parameter value to be set
1603 *
1604 * Setting the parameter will have physical effect once the PLL mode is set to
1605 * integer or fractional.
1606 *
1607 * @return Error if an argument is not valid or status as returned by the
1608 * PM controller (PMU)
1609 */
1610enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
1611 enum pm_pll_param param_id,
1612 unsigned int value)
1613{
1614 uint32_t payload[PAYLOAD_ARG_CNT];
1615
1616 /* Check if given node ID is a PLL node */
1617 if (nid < NODE_APLL || nid > NODE_IOPLL)
1618 return PM_RET_ERROR_ARGS;
1619
1620 /* Check if parameter ID is valid and return an error if it's not */
1621 if (param_id >= PM_PLL_PARAM_MAX)
1622 return PM_RET_ERROR_ARGS;
1623
1624 /* Send request to the PMU */
1625 PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
1626 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1627}
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001628
1629/**
1630 * pm_pll_get_parameter() - Get the PLL parameter value
1631 * @nid Node id of the target PLL
1632 * @param_id ID of the PLL parameter
1633 * @value Location to store the parameter value
1634 *
1635 * @return Error if an argument is not valid or status as returned by the
1636 * PM controller (PMU)
1637 */
1638enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
1639 enum pm_pll_param param_id,
1640 unsigned int *value)
1641{
1642 uint32_t payload[PAYLOAD_ARG_CNT];
1643
1644 /* Check if given node ID is a PLL node */
1645 if (nid < NODE_APLL || nid > NODE_IOPLL)
1646 return PM_RET_ERROR_ARGS;
1647
1648 /* Check if parameter ID is valid and return an error if it's not */
1649 if (param_id >= PM_PLL_PARAM_MAX)
1650 return PM_RET_ERROR_ARGS;
1651
1652 /* Send request to the PMU */
1653 PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
1654 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1655}
Jolly Shah1f0d5852019-01-04 11:32:31 -08001656
1657/**
1658 * pm_pll_set_mode() - Set the PLL mode
1659 * @nid Node id of the target PLL
1660 * @mode PLL mode to be set
1661 *
1662 * If reset mode is set the PM controller will first bypass the PLL and then
1663 * assert the reset. If integer or fractional mode is set the PM controller will
1664 * ensure that the complete PLL programming sequence is satisfied. After this
1665 * function returns success the PLL is locked and its bypass is deasserted.
1666 *
1667 * @return Error if an argument is not valid or status as returned by the
1668 * PM controller (PMU)
1669 */
1670enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
1671{
1672 uint32_t payload[PAYLOAD_ARG_CNT];
1673
1674 /* Check if given node ID is a PLL node */
1675 if (nid < NODE_APLL || nid > NODE_IOPLL)
1676 return PM_RET_ERROR_ARGS;
1677
1678 /* Check if PLL mode is valid */
1679 if (mode >= PM_PLL_MODE_MAX)
1680 return PM_RET_ERROR_ARGS;
1681
1682 /* Send request to the PMU */
1683 PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
1684 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1685}
Jolly Shah141421e2019-01-04 11:35:48 -08001686
1687/**
1688 * pm_pll_get_mode() - Get the PLL mode
1689 * @nid Node id of the target PLL
1690 * @mode Location to store the mode of the PLL
1691 *
1692 * @return Error if an argument is not valid or status as returned by the
1693 * PM controller (PMU)
1694 */
1695enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
1696{
1697 uint32_t payload[PAYLOAD_ARG_CNT];
1698
1699 /* Check if given node ID is a PLL node */
1700 if (nid < NODE_APLL || nid > NODE_IOPLL)
1701 return PM_RET_ERROR_ARGS;
1702
1703 /* Send request to the PMU */
1704 PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
1705 return pm_ipi_send_sync(primary_proc, payload, mode, 1);
1706}
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001707
1708/**
1709 * pm_register_access() - PM API for register read/write access data
1710 *
1711 * @register_access_id Register_access_id which says register read/write
1712 *
1713 * @address Address of the register to be accessed
1714 *
1715 * @mask Mask value to be used while writing value
1716 *
1717 * @value Value to be written to register
1718 *
1719 * @out Returned output data
1720 *
1721 * This function returns requested data.
1722 *
1723 * @return Returns status, either success or error+reason
1724 */
1725enum pm_ret_status pm_register_access(unsigned int register_access_id,
1726 unsigned int address,
1727 unsigned int mask,
1728 unsigned int value,
1729 unsigned int *out)
1730{
1731 enum pm_ret_status ret;
1732
1733 if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
1734 ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
1735 ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
1736 ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE))
1737 return PM_RET_ERROR_ACCESS;
1738
1739 switch (register_access_id) {
1740 case CONFIG_REG_WRITE:
1741 ret = pm_mmio_write(address, mask, value);
1742 break;
1743 case CONFIG_REG_READ:
1744 ret = pm_mmio_read(address, out);
1745 break;
1746 default:
1747 ret = PM_RET_ERROR_ARGS;
1748 WARN("Unimplemented register_access call\n\r");
1749 }
1750 return ret;
1751}
VNSL Durgadeb1a362020-11-23 04:46:04 -08001752
1753/**
1754 * pm_efuse_access() - To program or read efuse bits.
1755 *
1756 * This function provides access to the xilskey library to program/read
1757 * efuse bits.
1758 *
1759 * address_low: lower 32-bit Linear memory space address
1760 * address_high: higher 32-bit Linear memory space address
1761 *
1762 * value: Returned output value
1763 *
1764 * @return Returns status, either success or error+reason
1765 *
1766 */
1767enum pm_ret_status pm_efuse_access(uint32_t address_high,
1768 uint32_t address_low,
1769 uint32_t *value)
1770{
1771 uint32_t payload[PAYLOAD_ARG_CNT];
1772
1773 /* Send request to the PMU */
1774 PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
1775
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -08001776 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1777}
1778
1779enum pm_ret_status em_set_action(unsigned int *value)
1780{
1781 uint32_t payload[PAYLOAD_ARG_CNT];
1782
1783 /* Send request to the PMU */
1784 EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
1785 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1786}
1787
1788enum pm_ret_status em_remove_action(unsigned int *value)
1789{
1790 uint32_t payload[PAYLOAD_ARG_CNT];
1791
1792 /* Send request to the PMU */
1793 EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
1794 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1795}
1796
1797enum pm_ret_status em_send_errors(unsigned int *value)
1798{
1799 uint32_t payload[PAYLOAD_ARG_CNT];
1800
1801 /* Send request to the PMU */
1802 EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
VNSL Durgadeb1a362020-11-23 04:46:04 -08001803 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1804}