blob: 63916b883069a826dd6662c0a4c34230d6bdcdc0 [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.
Ronak Jain11b084a2023-02-13 04:48:06 -08003 * Copyright (c) 2022-2023, Advanced Micro Devices Inc. All rights reserved.
Soren Brinkmann76fcae32016-03-06 20:16:27 -08004 *
dp-armfa3cf0b2017-05-03 09:38:09 +01005 * SPDX-License-Identifier: BSD-3-Clause
Soren Brinkmann76fcae32016-03-06 20:16:27 -08006 */
7
8/*
9 * ZynqMP system level PM-API functions and communication with PMU via
10 * IPI interrupts
11 */
12
13#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000014#include <plat/common/platform.h>
15
Rajan Vaja35116132018-01-17 02:39:25 -080016#include "pm_api_clock.h"
Rajan Vaja5529a012018-01-17 02:39:23 -080017#include "pm_api_ioctl.h"
Rajan Vaja0ac2be12018-01-17 02:39:21 -080018#include "pm_api_pinctrl.h"
Isla Mitchelle3631462017-07-14 10:46:32 +010019#include "pm_api_sys.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080020#include "pm_client.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080021#include "pm_common.h"
Isla Mitchelle3631462017-07-14 10:46:32 +010022#include "pm_ipi.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080023
Ronak Jain325bad12021-12-21 01:39:59 -080024#define PM_QUERY_FEATURE_BITMASK ( \
25 (1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \
26 (1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) | \
27 (1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \
28 (1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \
29 (1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \
30 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \
31 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \
32 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \
33 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \
34 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \
35 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \
36 (1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \
37 (1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR))
38
39/**
40 * struct eemi_api_dependency - Dependent EEMI APIs which are implemented
41 * on both the ATF and firmware
42 *
43 * @id: EEMI API id or IOCTL id to be checked
44 * @api_id: Dependent EEMI API
45 */
46typedef struct __attribute__((packed)) {
47 uint8_t id;
48 uint8_t api_id;
49} eemi_api_dependency;
50
51/* Dependent APIs for ATF to check their version from firmware */
52static const eemi_api_dependency api_dep_table[] = {
53 {
54 .id = PM_SELF_SUSPEND,
55 .api_id = PM_SELF_SUSPEND,
56 },
57 {
58 .id = PM_REQ_WAKEUP,
59 .api_id = PM_REQ_WAKEUP,
60 },
61 {
62 .id = PM_ABORT_SUSPEND,
63 .api_id = PM_ABORT_SUSPEND,
64 },
65 {
66 .id = PM_SET_WAKEUP_SOURCE,
67 .api_id = PM_SET_WAKEUP_SOURCE,
68 },
69 {
70 .id = PM_SYSTEM_SHUTDOWN,
71 .api_id = PM_SYSTEM_SHUTDOWN,
72 },
73 {
74 .id = PM_GET_API_VERSION,
75 .api_id = PM_GET_API_VERSION,
76 },
77 {
78 .id = PM_CLOCK_ENABLE,
79 .api_id = PM_PLL_SET_MODE,
80 },
81 {
82 .id = PM_CLOCK_ENABLE,
83 .api_id = PM_CLOCK_ENABLE,
84 },
85 {
86 .id = PM_CLOCK_DISABLE,
87 .api_id = PM_PLL_SET_MODE,
88 },
89 {
90 .id = PM_CLOCK_DISABLE,
91 .api_id = PM_CLOCK_DISABLE,
92 },
93 {
94 .id = PM_CLOCK_GETSTATE,
95 .api_id = PM_PLL_GET_MODE,
96 },
97 {
98 .id = PM_CLOCK_GETSTATE,
99 .api_id = PM_CLOCK_GETSTATE,
100 },
101 {
102 .id = PM_CLOCK_SETDIVIDER,
103 .api_id = PM_PLL_SET_PARAMETER,
104 },
105 {
106 .id = PM_CLOCK_SETDIVIDER,
107 .api_id = PM_CLOCK_SETDIVIDER,
108 },
109 {
110 .id = PM_CLOCK_GETDIVIDER,
111 .api_id = PM_PLL_GET_PARAMETER,
112 },
113 {
114 .id = PM_CLOCK_GETDIVIDER,
115 .api_id = PM_CLOCK_GETDIVIDER,
116 },
117 {
118 .id = PM_CLOCK_SETPARENT,
119 .api_id = PM_PLL_SET_PARAMETER,
120 },
121 {
122 .id = PM_CLOCK_SETPARENT,
123 .api_id = PM_CLOCK_SETPARENT,
124 },
125 {
126 .id = PM_CLOCK_GETPARENT,
127 .api_id = PM_PLL_GET_PARAMETER,
128 },
129 {
130 .id = PM_CLOCK_GETPARENT,
131 .api_id = PM_CLOCK_GETPARENT,
132 },
133 {
134 .id = PM_PLL_SET_PARAMETER,
135 .api_id = PM_PLL_SET_PARAMETER,
136 },
137 {
138 .id = PM_PLL_GET_PARAMETER,
139 .api_id = PM_PLL_GET_PARAMETER,
140 },
141 {
142 .id = PM_PLL_SET_MODE,
143 .api_id = PM_PLL_SET_MODE,
144 },
145 {
146 .id = PM_PLL_GET_MODE,
147 .api_id = PM_PLL_GET_MODE,
148 },
149 {
150 .id = PM_REGISTER_ACCESS,
151 .api_id = PM_MMIO_WRITE,
152 },
153 {
154 .id = PM_REGISTER_ACCESS,
155 .api_id = PM_MMIO_READ,
156 },
157 {
158 .id = PM_FEATURE_CHECK,
159 .api_id = PM_FEATURE_CHECK,
160 },
161 {
162 .id = IOCTL_SET_TAPDELAY_BYPASS,
163 .api_id = PM_MMIO_WRITE,
164 },
165 {
166 .id = IOCTL_SET_SGMII_MODE,
167 .api_id = PM_MMIO_WRITE,
168 },
169 {
170 .id = IOCTL_SD_DLL_RESET,
171 .api_id = PM_MMIO_WRITE,
172 },
173 {
174 .id = IOCTL_SET_SD_TAPDELAY,
175 .api_id = PM_MMIO_WRITE,
176 },
177 {
178 .id = IOCTL_SET_SD_TAPDELAY,
179 .api_id = PM_MMIO_READ,
180 },
181 {
182 .id = IOCTL_SET_PLL_FRAC_DATA,
183 .api_id = PM_PLL_SET_PARAMETER,
184 },
185 {
186 .id = IOCTL_GET_PLL_FRAC_DATA,
187 .api_id = PM_PLL_GET_PARAMETER,
188 },
189 {
190 .id = IOCTL_WRITE_GGS,
191 .api_id = PM_MMIO_WRITE,
192 },
193 {
194 .id = IOCTL_READ_GGS,
195 .api_id = PM_MMIO_READ,
196 },
197 {
198 .id = IOCTL_WRITE_PGGS,
199 .api_id = PM_MMIO_WRITE,
200 },
201 {
202 .id = IOCTL_READ_PGGS,
203 .api_id = PM_MMIO_READ,
204 },
205 {
206 .id = IOCTL_ULPI_RESET,
207 .api_id = PM_MMIO_WRITE,
208 },
209 {
210 .id = IOCTL_SET_BOOT_HEALTH_STATUS,
211 .api_id = PM_MMIO_WRITE,
212 },
213 {
214 .id = IOCTL_AFI,
215 .api_id = PM_MMIO_WRITE,
216 },
217};
218
219/* Expected firmware API version to ATF */
220static const uint8_t atf_expected_ver_id[] = {
221 [PM_SELF_SUSPEND] = FW_API_BASE_VERSION,
222 [PM_REQ_WAKEUP] = FW_API_BASE_VERSION,
223 [PM_ABORT_SUSPEND] = FW_API_BASE_VERSION,
224 [PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION,
225 [PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION,
226 [PM_GET_API_VERSION] = FW_API_BASE_VERSION,
227 [PM_PLL_SET_MODE] = FW_API_BASE_VERSION,
228 [PM_PLL_GET_MODE] = FW_API_BASE_VERSION,
229 [PM_CLOCK_ENABLE] = FW_API_BASE_VERSION,
230 [PM_CLOCK_DISABLE] = FW_API_BASE_VERSION,
231 [PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION,
232 [PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION,
233 [PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION,
234 [PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION,
235 [PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION,
236 [PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION,
237 [PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION,
238 [PM_MMIO_WRITE] = FW_API_BASE_VERSION,
239 [PM_MMIO_READ] = FW_API_BASE_VERSION,
240 [PM_FEATURE_CHECK] = FW_API_VERSION_2,
241};
242
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530243/* default shutdown/reboot scope is system(2) */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530244static uint32_t pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530245
246/**
247 * pm_get_shutdown_scope() - Get the currently set shutdown scope
248 *
249 * @return Shutdown scope value
250 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530251uint32_t pm_get_shutdown_scope(void)
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530252{
253 return pm_shutdown_scope;
254}
255
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -0800256#define EM_PACK_PAYLOAD1(pl, arg0) { \
257 pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \
258}
259
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800260/**
261 * pm_self_suspend() - PM call for processor to suspend itself
262 * @nid Node id of the processor or subsystem
263 * @latency Requested maximum wakeup latency (not supported)
Filip Drazic0bd9d0c2016-07-20 17:17:39 +0200264 * @state Requested state
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800265 * @address Resume address
266 *
267 * This is a blocking call, it will return only once PMU has responded.
268 * On a wakeup, resume address will be automatically set by PMU.
269 *
270 * @return Returns status, either success or error+reason
271 */
272enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530273 uint32_t latency,
274 uint32_t state,
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800275 uintptr_t address)
276{
277 uint32_t payload[PAYLOAD_ARG_CNT];
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530278 uint32_t cpuid = plat_my_core_pos();
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800279 const struct pm_proc *proc = pm_get_proc(cpuid);
280
281 /*
282 * Do client specific suspend operations
283 * (e.g. set powerdown request bit)
284 */
Filip Drazic4c0765a2016-07-26 12:11:33 +0200285 pm_client_suspend(proc, state);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800286 /* Send request to the PMU */
287 PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
288 state, address, (address >> 32));
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700289 return pm_ipi_send_sync(proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800290}
291
292/**
293 * pm_req_suspend() - PM call to request for another PU or subsystem to
294 * be suspended gracefully.
295 * @target Node id of the targeted PU or subsystem
296 * @ack Flag to specify whether acknowledge is requested
297 * @latency Requested wakeup latency (not supported)
298 * @state Requested state (not supported)
299 *
300 * @return Returns status, either success or error+reason
301 */
302enum pm_ret_status pm_req_suspend(enum pm_node_id target,
303 enum pm_request_ack ack,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530304 uint32_t latency, uint32_t state)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800305{
306 uint32_t payload[PAYLOAD_ARG_CNT];
307
308 /* Send request to the PMU */
309 PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530310 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700311 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530312 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800313 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530314 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800315}
316
317/**
318 * pm_req_wakeup() - PM call for processor to wake up selected processor
319 * or subsystem
320 * @target Node id of the processor or subsystem to wake up
321 * @ack Flag to specify whether acknowledge requested
322 * @set_address Resume address presence indicator
323 * 1 resume address specified, 0 otherwise
324 * @address Resume address
325 *
326 * This API function is either used to power up another APU core for SMP
327 * (by PSCI) or to power up an entirely different PU or subsystem, such
328 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
329 * automatically set by PMU.
330 *
331 * @return Returns status, either success or error+reason
332 */
333enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530334 uint32_t set_address,
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800335 uintptr_t address,
336 enum pm_request_ack ack)
337{
338 uint32_t payload[PAYLOAD_ARG_CNT];
339 uint64_t encoded_address;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800340
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800341
342 /* encode set Address into 1st bit of address */
343 encoded_address = address;
344 encoded_address |= !!set_address;
345
346 /* Send request to the PMU to perform the wake of the PU */
347 PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
348 encoded_address >> 32, ack);
349
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530350 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700351 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530352 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800353 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530354 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800355}
356
357/**
358 * pm_force_powerdown() - PM call to request for another PU or subsystem to
359 * be powered down forcefully
360 * @target Node id of the targeted PU or subsystem
361 * @ack Flag to specify whether acknowledge is requested
362 *
363 * @return Returns status, either success or error+reason
364 */
365enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
366 enum pm_request_ack ack)
367{
368 uint32_t payload[PAYLOAD_ARG_CNT];
369
370 /* Send request to the PMU */
371 PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
372
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530373 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700374 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530375 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800376 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530377 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800378}
379
380/**
381 * pm_abort_suspend() - PM call to announce that a prior suspend request
382 * is to be aborted.
383 * @reason Reason for the abort
384 *
385 * Calling PU expects the PMU to abort the initiated suspend procedure.
386 * This is a non-blocking call without any acknowledge.
387 *
388 * @return Returns status, either success or error+reason
389 */
390enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
391{
392 uint32_t payload[PAYLOAD_ARG_CNT];
393
394 /*
395 * Do client specific abort suspend operations
396 * (e.g. enable interrupts and clear powerdown request bit)
397 */
398 pm_client_abort_suspend();
399 /* Send request to the PMU */
400 /* TODO: allow passing the node ID of the affected CPU */
401 PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
402 primary_proc->node_id);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700403 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800404}
405
406/**
407 * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
408 * @target Node id of the targeted PU or subsystem
409 * @wkup_node Node id of the wakeup peripheral
410 * @enable Enable or disable the specified peripheral as wake source
411 *
412 * @return Returns status, either success or error+reason
413 */
414enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
415 enum pm_node_id wkup_node,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530416 uint32_t enable)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800417{
418 uint32_t payload[PAYLOAD_ARG_CNT];
419
420 PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
421 enable);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700422 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800423}
424
425/**
426 * pm_system_shutdown() - PM call to request a system shutdown or restart
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530427 * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
428 * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800429 *
430 * @return Returns status, either success or error+reason
431 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530432enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t subtype)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800433{
434 uint32_t payload[PAYLOAD_ARG_CNT];
435
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530436 if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
437 /* Setting scope for subsequent PSCI reboot or shutdown */
438 pm_shutdown_scope = subtype;
439 return PM_RET_SUCCESS;
440 }
441
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700442 PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
Tejas Patelaf4b10e2018-02-09 02:42:59 -0800443 return pm_ipi_send_non_blocking(primary_proc, payload);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800444}
445
446/* APIs for managing PM slaves: */
447
448/**
449 * pm_req_node() - PM call to request a node with specific capabilities
450 * @nid Node id of the slave
451 * @capabilities Requested capabilities of the slave
452 * @qos Quality of service (not supported)
453 * @ack Flag to specify whether acknowledge is requested
454 *
455 * @return Returns status, either success or error+reason
456 */
457enum pm_ret_status pm_req_node(enum pm_node_id nid,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530458 uint32_t capabilities,
459 uint32_t qos,
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800460 enum pm_request_ack ack)
461{
462 uint32_t payload[PAYLOAD_ARG_CNT];
463
464 PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
465
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530466 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700467 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530468 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800469 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530470 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800471}
472
473/**
474 * pm_set_requirement() - PM call to set requirement for PM slaves
475 * @nid Node id of the slave
476 * @capabilities Requested capabilities of the slave
477 * @qos Quality of service (not supported)
478 * @ack Flag to specify whether acknowledge is requested
479 *
480 * This API function is to be used for slaves a PU already has requested
481 *
482 * @return Returns status, either success or error+reason
483 */
484enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530485 uint32_t capabilities,
486 uint32_t qos,
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800487 enum pm_request_ack ack)
488{
489 uint32_t payload[PAYLOAD_ARG_CNT];
490
491 PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
492 ack);
493
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530494 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700495 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530496 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800497 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530498 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800499}
500
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800501/* Miscellaneous API functions */
502
503/**
504 * pm_get_api_version() - Get version number of PMU PM firmware
505 * @version Returns 32-bit version number of PMU Power Management Firmware
506 *
507 * @return Returns status, either success or error+reason
508 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530509enum pm_ret_status pm_get_api_version(uint32_t *version)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800510{
511 uint32_t payload[PAYLOAD_ARG_CNT];
512
513 /* Send request to the PMU */
514 PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700515 return pm_ipi_send_sync(primary_proc, payload, version, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800516}
517
518/**
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100519 * pm_get_node_status() - PM call to request a node's current status
520 * @nid Node id
521 * @ret_buff Buffer for the return values:
522 * [0] - Current power state of the node
523 * [1] - Current requirements for the node (slave nodes only)
524 * [2] - Current usage status for the node (slave nodes only)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800525 *
526 * @return Returns status, either success or error+reason
527 */
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100528enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
529 uint32_t *ret_buff)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800530{
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800531 uint32_t payload[PAYLOAD_ARG_CNT];
532
533 PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100534 return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800535}
536
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800537/**
538 * pm_mmio_write() - Perform write to protected mmio
539 * @address Address to write to
540 * @mask Mask to apply
541 * @value Value to write
542 *
543 * This function provides access to PM-related control registers
544 * that may not be directly accessible by a particular PU.
545 *
546 * @return Returns status, either success or error+reason
547 */
548enum pm_ret_status pm_mmio_write(uintptr_t address,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530549 uint32_t mask,
550 uint32_t value)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800551{
552 uint32_t payload[PAYLOAD_ARG_CNT];
553
554 /* Send request to the PMU */
555 PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700556 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800557}
558
559/**
560 * pm_mmio_read() - Read value from protected mmio
561 * @address Address to write to
562 * @value Value to write
563 *
564 * This function provides access to PM-related control registers
565 * that may not be directly accessible by a particular PU.
566 *
567 * @return Returns status, either success or error+reason
568 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530569enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800570{
571 uint32_t payload[PAYLOAD_ARG_CNT];
572
573 /* Send request to the PMU */
574 PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700575 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800576}
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530577
578/**
579 * pm_fpga_load() - Load the bitstream into the PL.
580 *
581 * This function provides access to the xilfpga library to load
582 * the Bit-stream into PL.
583 *
584 * address_low: lower 32-bit Linear memory space address
585 *
586 * address_high: higher 32-bit Linear memory space address
587 *
588 * size: Number of 32bit words
589 *
590 * @return Returns status, either success or error+reason
591 */
592enum pm_ret_status pm_fpga_load(uint32_t address_low,
593 uint32_t address_high,
594 uint32_t size,
595 uint32_t flags)
596{
597 uint32_t payload[PAYLOAD_ARG_CNT];
598
599 /* Send request to the PMU */
600 PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
601 size, flags);
Siva Durga Prasad Paladugubf83b9c2018-02-07 13:13:01 +0530602 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530603}
604
605/**
606 * pm_fpga_get_status() - Read value from fpga status register
607 * @value Value to read
608 *
609 * This function provides access to the xilfpga library to get
610 * the fpga status
611 * @return Returns status, either success or error+reason
612 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530613enum pm_ret_status pm_fpga_get_status(uint32_t *value)
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530614{
615 uint32_t payload[PAYLOAD_ARG_CNT];
616
617 /* Send request to the PMU */
618 PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700619 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530620}
Soren Brinkmanncb366812016-09-22 12:21:11 -0700621
622/**
623 * pm_get_chipid() - Read silicon ID registers
624 * @value Buffer for return values. Must be large enough
625 * to hold 8 bytes.
626 *
627 * @return Returns silicon ID registers
628 */
629enum pm_ret_status pm_get_chipid(uint32_t *value)
630{
631 uint32_t payload[PAYLOAD_ARG_CNT];
632
633 /* Send request to the PMU */
634 PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
635 return pm_ipi_send_sync(primary_proc, payload, value, 2);
636}
Soren Brinkmann84f0af42016-09-30 14:24:25 -0700637
638/**
Siva Durga Prasad Paladugude93d982018-04-30 15:49:27 +0530639 * pm_secure_rsaaes() - Load the secure images.
640 *
641 * This function provides access to the xilsecure library to load
642 * the authenticated, encrypted, and authenicated/encrypted images.
643 *
644 * address_low: lower 32-bit Linear memory space address
645 *
646 * address_high: higher 32-bit Linear memory space address
647 *
648 * size: Number of 32bit words
649 *
650 * @return Returns status, either success or error+reason
651 */
652enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
653 uint32_t address_high,
654 uint32_t size,
655 uint32_t flags)
656{
657 uint32_t payload[PAYLOAD_ARG_CNT];
658
659 /* Send request to the PMU */
660 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
661 size, flags);
662 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
663}
664
665/**
Siva Durga Prasad Paladugu8bd905b2018-09-04 18:05:50 +0530666 * pm_aes_engine() - Aes data blob encryption/decryption
667 * This function provides access to the xilsecure library to
668 * encrypt/decrypt data blobs.
669 *
670 * address_low: lower 32-bit address of the AesParams structure
671 *
672 * address_high: higher 32-bit address of the AesParams structure
673 *
674 * value: Returned output value
675 *
676 * @return Returns status, either success or error+reason
677 */
678enum pm_ret_status pm_aes_engine(uint32_t address_high,
679 uint32_t address_low,
680 uint32_t *value)
681{
682 uint32_t payload[PAYLOAD_ARG_CNT];
683
684 /* Send request to the PMU */
685 PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
686 return pm_ipi_send_sync(primary_proc, payload, value, 1);
687}
688
689/**
Rajan Vaja02d18422019-03-04 11:09:39 +0530690 * pm_get_callbackdata() - Read from IPI response buffer
691 * @data - array of PAYLOAD_ARG_CNT elements
692 *
693 * Read value from ipi buffer response buffer.
694 */
695void pm_get_callbackdata(uint32_t *data, size_t count)
696{
697 /* Return if interrupt is not from PMU */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530698 if (!pm_ipi_irq_status(primary_proc)) {
Rajan Vaja02d18422019-03-04 11:09:39 +0530699 return;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530700 }
Rajan Vaja02d18422019-03-04 11:09:39 +0530701
702 pm_ipi_buff_read_callb(data, count);
703 pm_ipi_irq_clear(primary_proc);
704}
705
706/**
Rajan Vaja5529a012018-01-17 02:39:23 -0800707 * pm_ioctl() - PM IOCTL API for device control and configs
708 * @node_id Node ID of the device
709 * @ioctl_id ID of the requested IOCTL
710 * @arg1 Argument 1 to requested IOCTL call
711 * @arg2 Argument 2 to requested IOCTL call
712 * @out Returned output value
713 *
714 * This function calls IOCTL to firmware for device control and configuration.
715 *
716 * @return Returns status, either success or error+reason
717 */
718enum pm_ret_status pm_ioctl(enum pm_node_id nid,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530719 uint32_t ioctl_id,
720 uint32_t arg1,
721 uint32_t arg2,
722 uint32_t *value)
Rajan Vaja5529a012018-01-17 02:39:23 -0800723{
724 return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
725}
Rajan Vaja35116132018-01-17 02:39:25 -0800726
727/**
Ronak Jain325bad12021-12-21 01:39:59 -0800728 * fw_api_version() - Returns API version implemented in firmware
729 * @api_id API ID to check
730 * @version Returned supported API version
731 * @len Number of words to be returned
732 *
733 * @return Returns status, either success or error+reason
734 */
735static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version,
736 uint32_t len)
737{
738 uint32_t payload[PAYLOAD_ARG_CNT];
739
740 PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id);
741 return pm_ipi_send_sync(primary_proc, payload, version, len);
742}
743
744/**
745 * check_api_dependency() - API to check dependent EEMI API version
746 * @id EEMI API ID to check
747 *
748 * @return Returns status, either success or error+reason
749 */
750enum pm_ret_status check_api_dependency(uint8_t id)
751{
752 uint8_t i;
753 uint32_t version;
754 int ret;
755
756 for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
757 if (api_dep_table[i].id == id) {
758 if (api_dep_table[i].api_id == 0U) {
759 break;
760 }
761
762 ret = fw_api_version(api_dep_table[i].api_id,
763 &version, 1);
764 if (ret != PM_RET_SUCCESS) {
765 return ret;
766 }
767
768 /* Check if fw version matches ATF expected version */
769 if (version != atf_expected_ver_id[api_dep_table[i].api_id]) {
770 return PM_RET_ERROR_NOTSUPPORTED;
771 }
772 }
773 }
774
775 return PM_RET_SUCCESS;
776}
777
778/**
779 * feature_check_atf() - These are API's completely implemented in ATF
780 * @api_id API ID to check
781 * @version Returned supported API version
782 *
783 * @return Returns status, either success or error+reason
784 */
785static enum pm_ret_status feature_check_atf(uint32_t api_id, uint32_t *version,
786 uint32_t *bit_mask)
787{
788 switch (api_id) {
789 case PM_QUERY_DATA:
Ronak Jain11b084a2023-02-13 04:48:06 -0800790 *version = TFA_API_QUERY_DATA_VERSION;
Ronak Jain325bad12021-12-21 01:39:59 -0800791 bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
792 bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
793 return PM_RET_SUCCESS;
794 case PM_GET_CALLBACK_DATA:
795 case PM_GET_TRUSTZONE_VERSION:
796 case PM_SET_SUSPEND_MODE:
797 *version = ATF_API_BASE_VERSION;
798 return PM_RET_SUCCESS;
799 default:
800 return PM_RET_ERROR_NO_FEATURE;
801 }
802}
803
804/**
805 * get_atf_version_for_partial_apis() - Return ATF version for partially
806 * implemented APIs
807 * @api_id API ID to check
808 * @version Returned supported API version
809 *
810 * @return Returns status, either success or error+reason
811 */
812static enum pm_ret_status get_atf_version_for_partial_apis(uint32_t api_id,
813 uint32_t *version)
814{
815 switch (api_id) {
816 case PM_SELF_SUSPEND:
817 case PM_REQ_WAKEUP:
818 case PM_ABORT_SUSPEND:
819 case PM_SET_WAKEUP_SOURCE:
820 case PM_SYSTEM_SHUTDOWN:
821 case PM_GET_API_VERSION:
822 case PM_CLOCK_ENABLE:
823 case PM_CLOCK_DISABLE:
824 case PM_CLOCK_GETSTATE:
825 case PM_CLOCK_SETDIVIDER:
826 case PM_CLOCK_GETDIVIDER:
827 case PM_CLOCK_SETPARENT:
828 case PM_CLOCK_GETPARENT:
829 case PM_PLL_SET_PARAMETER:
830 case PM_PLL_GET_PARAMETER:
831 case PM_PLL_SET_MODE:
832 case PM_PLL_GET_MODE:
833 case PM_REGISTER_ACCESS:
834 *version = ATF_API_BASE_VERSION;
835 return PM_RET_SUCCESS;
836 case PM_FEATURE_CHECK:
837 *version = FW_API_VERSION_2;
838 return PM_RET_SUCCESS;
839 default:
840 return PM_RET_ERROR_ARGS;
841 }
842}
843
844/**
845 * feature_check_partial() - These are API's partially implemented in
846 * ATF and firmware both
847 * @api_id API ID to check
848 * @version Returned supported API version
849 *
850 * @return Returns status, either success or error+reason
851 */
852static enum pm_ret_status feature_check_partial(uint32_t api_id,
853 uint32_t *version)
854{
855 uint32_t status;
856
857 switch (api_id) {
858 case PM_SELF_SUSPEND:
859 case PM_REQ_WAKEUP:
860 case PM_ABORT_SUSPEND:
861 case PM_SET_WAKEUP_SOURCE:
862 case PM_SYSTEM_SHUTDOWN:
863 case PM_GET_API_VERSION:
864 case PM_CLOCK_ENABLE:
865 case PM_CLOCK_DISABLE:
866 case PM_CLOCK_GETSTATE:
867 case PM_CLOCK_SETDIVIDER:
868 case PM_CLOCK_GETDIVIDER:
869 case PM_CLOCK_SETPARENT:
870 case PM_CLOCK_GETPARENT:
871 case PM_PLL_SET_PARAMETER:
872 case PM_PLL_GET_PARAMETER:
873 case PM_PLL_SET_MODE:
874 case PM_PLL_GET_MODE:
875 case PM_REGISTER_ACCESS:
876 case PM_FEATURE_CHECK:
877 status = check_api_dependency(api_id);
878 if (status != PM_RET_SUCCESS) {
879 return status;
880 }
881 return get_atf_version_for_partial_apis(api_id, version);
882 default:
883 return PM_RET_ERROR_NO_FEATURE;
884 }
885}
886
887/**
888 * pm_feature_check() - Returns the supported API version if supported
889 * @api_id API ID to check
890 * @version Returned supported API version
891 * @bit_mask Returned supported IOCTL id version
892 * @len Number of bytes to be returned in bit_mask variable
893 *
894 * @return Returns status, either success or error+reason
895 */
896enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
897 uint32_t *bit_mask, uint8_t len)
898{
899 uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
900 uint32_t status;
901
902 /* Get API version implemented in ATF */
903 status = feature_check_atf(api_id, version, bit_mask);
904 if (status != PM_RET_ERROR_NO_FEATURE) {
905 return status;
906 }
907
908 /* Get API version implemented by firmware and ATF both */
909 status = feature_check_partial(api_id, version);
910 if (status != PM_RET_ERROR_NO_FEATURE) {
911 return status;
912 }
913
914 /* Get API version implemented by firmware */
915 status = fw_api_version(api_id, ret_payload, 3);
916 /* IOCTL call may return failure whose ID is not implemented in
917 * firmware but implemented in ATF
918 */
919 if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) {
920 return status;
921 }
922
923 *version = ret_payload[0];
924
925 /* Update IOCTL bit mask which are implemented in ATF */
926 if (api_id == PM_IOCTL) {
927 if (len < 2) {
928 return PM_RET_ERROR_ARGS;
929 }
930 bit_mask[0] = ret_payload[1];
931 bit_mask[1] = ret_payload[2];
932 /* Get IOCTL's implemented by ATF */
933 status = atf_ioctl_bitmask(bit_mask);
934 } else {
935 /* Requires for MISRA */
936 }
937
938 return status;
939}
940
941/**
Rajan Vajab34deca2019-03-20 01:13:21 +0530942 * pm_clock_get_max_divisor - PM call to get max divisor
943 * @clock_id Clock ID
944 * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2)
945 * @max_div Maximum supported divisor
946 *
947 * This function is used by master to get maximum supported value.
948 *
949 * Return: Returns status, either success or error+reason.
950 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530951static enum pm_ret_status pm_clock_get_max_divisor(uint32_t clock_id,
Rajan Vajab34deca2019-03-20 01:13:21 +0530952 uint8_t div_type,
953 uint32_t *max_div)
954{
955 return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
956}
957
958/**
Rajan Vajada959402018-07-20 03:16:27 -0700959 * pm_clock_get_num_clocks - PM call to request number of clocks
960 * @nclockss: Number of clocks
961 *
962 * This function is used by master to get number of clocks.
963 *
964 * Return: Returns status, either success or error+reason.
965 */
966static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
967{
968 return pm_api_clock_get_num_clocks(nclocks);
969}
970
971/**
Rajan Vaja35116132018-01-17 02:39:25 -0800972 * pm_clock_get_name() - PM call to request a clock's name
973 * @clock_id Clock ID
974 * @name Name of clock (max 16 bytes)
975 *
976 * This function is used by master to get nmae of clock specified
977 * by given clock ID.
Rajan Vaja35116132018-01-17 02:39:25 -0800978 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530979static void pm_clock_get_name(uint32_t clock_id, char *name)
Rajan Vaja35116132018-01-17 02:39:25 -0800980{
Rajan Vajacd825682020-11-23 21:33:39 -0800981 pm_api_clock_get_name(clock_id, name);
Rajan Vaja35116132018-01-17 02:39:25 -0800982}
983
984/**
985 * pm_clock_get_topology() - PM call to request a clock's topology
986 * @clock_id Clock ID
987 * @index Topology index for next toplogy node
988 * @topology Buffer to store nodes in topology and flags
989 *
990 * This function is used by master to get topology information for the
991 * clock specified by given clock ID. Each response would return 3
992 * topology nodes. To get next nodes, caller needs to call this API with
993 * index of next node. Index starts from 0.
994 *
995 * @return Returns status, either success or error+reason
996 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530997static enum pm_ret_status pm_clock_get_topology(uint32_t clock_id,
998 uint32_t index,
Rajan Vaja35116132018-01-17 02:39:25 -0800999 uint32_t *topology)
1000{
1001 return pm_api_clock_get_topology(clock_id, index, topology);
1002}
1003
1004/**
1005 * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
1006 * parameters for fixed clock
1007 * @clock_id Clock ID
1008 * @mul Multiplication value
1009 * @div Divisor value
1010 *
1011 * This function is used by master to get fixed factor parameers for the
1012 * fixed clock. This API is application only for the fixed clock.
1013 *
1014 * @return Returns status, either success or error+reason
1015 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301016static enum pm_ret_status pm_clock_get_fixedfactor_params(uint32_t clock_id,
Rajan Vaja35116132018-01-17 02:39:25 -08001017 uint32_t *mul,
1018 uint32_t *div)
1019{
1020 return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
1021}
1022
1023/**
1024 * pm_clock_get_parents() - PM call to request a clock's first 3 parents
1025 * @clock_id Clock ID
1026 * @index Index of next parent
1027 * @parents Parents of the given clock
1028 *
1029 * This function is used by master to get clock's parents information.
1030 * This API will return 3 parents with a single response. To get other
1031 * parents, master should call same API in loop with new parent index
1032 * till error is returned.
1033 *
1034 * E.g First call should have index 0 which will return parents 0, 1 and
1035 * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
1036 * so on.
1037 *
1038 * @return Returns status, either success or error+reason
1039 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301040static enum pm_ret_status pm_clock_get_parents(uint32_t clock_id,
1041 uint32_t index,
Rajan Vaja35116132018-01-17 02:39:25 -08001042 uint32_t *parents)
1043{
1044 return pm_api_clock_get_parents(clock_id, index, parents);
1045}
1046
1047/**
1048 * pm_clock_get_attributes() - PM call to request a clock's attributes
1049 * @clock_id Clock ID
1050 * @attr Clock attributes
1051 *
1052 * This function is used by master to get clock's attributes
1053 * (e.g. valid, clock type, etc).
1054 *
1055 * @return Returns status, either success or error+reason
1056 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301057static enum pm_ret_status pm_clock_get_attributes(uint32_t clock_id,
Rajan Vaja35116132018-01-17 02:39:25 -08001058 uint32_t *attr)
1059{
1060 return pm_api_clock_get_attributes(clock_id, attr);
1061}
1062
1063/**
Jolly Shaha5209802019-01-04 11:45:59 -08001064 * pm_clock_gate() - Configure clock gate
1065 * @clock_id Id of the clock to be configured
1066 * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
1067 *
1068 * @return Error if an argument is not valid or status as returned by the
1069 * PM controller (PMU)
1070 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301071static enum pm_ret_status pm_clock_gate(uint32_t clock_id,
1072 uint8_t enable)
Jolly Shaha5209802019-01-04 11:45:59 -08001073{
1074 uint32_t payload[PAYLOAD_ARG_CNT];
1075 enum pm_ret_status status;
1076 enum pm_api_id api_id;
1077
1078 /* Check if clock ID is valid and return an error if it is not */
1079 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301080 if (status != PM_RET_SUCCESS) {
Jolly Shaha5209802019-01-04 11:45:59 -08001081 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301082 }
Jolly Shaha5209802019-01-04 11:45:59 -08001083
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301084 if (enable) {
Jolly Shaha5209802019-01-04 11:45:59 -08001085 api_id = PM_CLOCK_ENABLE;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301086 } else {
Jolly Shaha5209802019-01-04 11:45:59 -08001087 api_id = PM_CLOCK_DISABLE;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301088 }
Jolly Shaha5209802019-01-04 11:45:59 -08001089
1090 /* Send request to the PMU */
1091 PM_PACK_PAYLOAD2(payload, api_id, clock_id);
Mirela Simonovic64514a72018-08-24 17:09:07 +02001092 status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1093
1094 /* If action fails due to the lack of permissions filter the error */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301095 if (status == PM_RET_ERROR_ACCESS) {
Mirela Simonovic64514a72018-08-24 17:09:07 +02001096 status = PM_RET_SUCCESS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301097 }
Mirela Simonovic64514a72018-08-24 17:09:07 +02001098
1099 return status;
Jolly Shaha5209802019-01-04 11:45:59 -08001100}
1101
1102/**
Rajan Vaja35116132018-01-17 02:39:25 -08001103 * pm_clock_enable() - Enable the clock for given id
1104 * @clock_id: Id of the clock to be enabled
1105 *
1106 * This function is used by master to enable the clock
1107 * including peripherals and PLL clocks.
1108 *
Jolly Shaha5209802019-01-04 11:45:59 -08001109 * @return: Error if an argument is not valid or status as returned by the
1110 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -08001111 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301112enum pm_ret_status pm_clock_enable(uint32_t clock_id)
Rajan Vaja35116132018-01-17 02:39:25 -08001113{
Jolly Shaha5209802019-01-04 11:45:59 -08001114 struct pm_pll *pll;
1115
1116 /* First try to handle it as a PLL */
1117 pll = pm_clock_get_pll(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301118 if (pll) {
Jolly Shaha5209802019-01-04 11:45:59 -08001119 return pm_clock_pll_enable(pll);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301120 }
Jolly Shaha5209802019-01-04 11:45:59 -08001121
1122 /* It's an on-chip clock, PMU should configure clock's gate */
1123 return pm_clock_gate(clock_id, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001124}
1125
1126/**
1127 * pm_clock_disable - Disable the clock for given id
1128 * @clock_id: Id of the clock to be disable
1129 *
1130 * This function is used by master to disable the clock
1131 * including peripherals and PLL clocks.
1132 *
Jolly Shaha9057a02019-01-02 12:54:40 -08001133 * @return: Error if an argument is not valid or status as returned by the
1134 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -08001135 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301136enum pm_ret_status pm_clock_disable(uint32_t clock_id)
Rajan Vaja35116132018-01-17 02:39:25 -08001137{
Jolly Shaha9057a02019-01-02 12:54:40 -08001138 struct pm_pll *pll;
1139
1140 /* First try to handle it as a PLL */
1141 pll = pm_clock_get_pll(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301142 if (pll) {
Jolly Shaha9057a02019-01-02 12:54:40 -08001143 return pm_clock_pll_disable(pll);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301144 }
Jolly Shaha9057a02019-01-02 12:54:40 -08001145
1146 /* It's an on-chip clock, PMU should configure clock's gate */
1147 return pm_clock_gate(clock_id, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001148}
1149
1150/**
1151 * pm_clock_getstate - Get the clock state for given id
1152 * @clock_id: Id of the clock to be queried
1153 * @state: 1/0 (Enabled/Disabled)
1154 *
1155 * This function is used by master to get the state of clock
1156 * including peripherals and PLL clocks.
1157 *
1158 * Return: Returns status, either success or error+reason.
1159 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301160enum pm_ret_status pm_clock_getstate(uint32_t clock_id,
1161 uint32_t *state)
Rajan Vaja35116132018-01-17 02:39:25 -08001162{
Jolly Shah99e8ac92019-01-02 12:55:41 -08001163 struct pm_pll *pll;
1164 uint32_t payload[PAYLOAD_ARG_CNT];
1165 enum pm_ret_status status;
1166
1167 /* First try to handle it as a PLL */
1168 pll = pm_clock_get_pll(clock_id);
1169 if (pll)
1170 return pm_clock_pll_get_state(pll, state);
1171
1172 /* Check if clock ID is a valid on-chip clock */
1173 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301174 if (status != PM_RET_SUCCESS) {
Jolly Shah99e8ac92019-01-02 12:55:41 -08001175 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301176 }
Jolly Shah99e8ac92019-01-02 12:55:41 -08001177
1178 /* Send request to the PMU */
1179 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
1180 return pm_ipi_send_sync(primary_proc, payload, state, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001181}
1182
1183/**
1184 * pm_clock_setdivider - Set the clock divider for given id
1185 * @clock_id: Id of the clock
1186 * @divider: divider value
1187 *
1188 * This function is used by master to set divider for any clock
1189 * to achieve desired rate.
1190 *
1191 * Return: Returns status, either success or error+reason.
1192 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301193enum pm_ret_status pm_clock_setdivider(uint32_t clock_id,
1194 uint32_t divider)
Rajan Vaja35116132018-01-17 02:39:25 -08001195{
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001196 enum pm_ret_status status;
1197 enum pm_node_id nid;
1198 enum pm_clock_div_id div_id;
1199 uint32_t payload[PAYLOAD_ARG_CNT];
1200 const uint32_t div0 = 0xFFFF0000;
1201 const uint32_t div1 = 0x0000FFFF;
1202 uint32_t val;
1203
1204 /* Get PLL node ID using PLL clock ID */
1205 status = pm_clock_get_pll_node_id(clock_id, &nid);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301206 if (status == PM_RET_SUCCESS) {
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001207 return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301208 }
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001209
1210 /* Check if clock ID is a valid on-chip clock */
1211 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301212 if (status != PM_RET_SUCCESS) {
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001213 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301214 }
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001215
1216 if (div0 == (divider & div0)) {
1217 div_id = PM_CLOCK_DIV0_ID;
1218 val = divider & ~div0;
1219 } else if (div1 == (divider & div1)) {
1220 div_id = PM_CLOCK_DIV1_ID;
1221 val = (divider & ~div1) >> 16;
1222 } else {
1223 return PM_RET_ERROR_ARGS;
1224 }
1225
1226 /* Send request to the PMU */
1227 PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
1228 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001229}
1230
1231/**
1232 * pm_clock_getdivider - Get the clock divider for given id
1233 * @clock_id: Id of the clock
1234 * @divider: divider value
1235 *
1236 * This function is used by master to get divider values
1237 * for any clock.
1238 *
1239 * Return: Returns status, either success or error+reason.
1240 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301241enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
1242 uint32_t *divider)
Rajan Vaja35116132018-01-17 02:39:25 -08001243{
Jolly Shah4dd11762019-01-04 11:53:37 -08001244 enum pm_ret_status status;
1245 enum pm_node_id nid;
1246 uint32_t payload[PAYLOAD_ARG_CNT];
1247 uint32_t val;
1248
1249 /* Get PLL node ID using PLL clock ID */
1250 status = pm_clock_get_pll_node_id(clock_id, &nid);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301251 if (status == PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001252 return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301253 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001254
1255 /* Check if clock ID is a valid on-chip clock */
1256 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301257 if (status != PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001258 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301259 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001260
1261 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
1262 /* Send request to the PMU to get div0 */
1263 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1264 PM_CLOCK_DIV0_ID);
1265 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301266 if (status != PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001267 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301268 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001269 *divider = val;
1270 }
1271
1272 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
1273 /* Send request to the PMU to get div1 */
1274 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1275 PM_CLOCK_DIV1_ID);
1276 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301277 if (status != PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001278 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301279 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001280 *divider |= val << 16;
1281 }
1282
1283 return status;
Rajan Vaja35116132018-01-17 02:39:25 -08001284}
1285
1286/**
1287 * pm_clock_setrate - Set the clock rate for given id
1288 * @clock_id: Id of the clock
1289 * @rate: rate value in hz
1290 *
1291 * This function is used by master to set rate for any clock.
1292 *
1293 * Return: Returns status, either success or error+reason.
1294 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301295enum pm_ret_status pm_clock_setrate(uint32_t clock_id,
Rajan Vaja35116132018-01-17 02:39:25 -08001296 uint64_t rate)
1297{
Jolly Shahc1391812019-01-02 13:39:30 -08001298 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001299}
1300
1301/**
1302 * pm_clock_getrate - Get the clock rate for given id
1303 * @clock_id: Id of the clock
1304 * @rate: rate value in hz
1305 *
1306 * This function is used by master to get rate
1307 * for any clock.
1308 *
1309 * Return: Returns status, either success or error+reason.
1310 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301311enum pm_ret_status pm_clock_getrate(uint32_t clock_id,
Rajan Vaja35116132018-01-17 02:39:25 -08001312 uint64_t *rate)
1313{
Jolly Shahc1391812019-01-02 13:39:30 -08001314 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001315}
1316
1317/**
1318 * pm_clock_setparent - Set the clock parent for given id
1319 * @clock_id: Id of the clock
Jolly Shah407fc0a2019-01-04 11:57:40 -08001320 * @parent_index: Index of the parent clock into clock's parents array
Rajan Vaja35116132018-01-17 02:39:25 -08001321 *
1322 * This function is used by master to set parent for any clock.
1323 *
1324 * Return: Returns status, either success or error+reason.
1325 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301326enum pm_ret_status pm_clock_setparent(uint32_t clock_id,
1327 uint32_t parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001328{
Jolly Shah407fc0a2019-01-04 11:57:40 -08001329 struct pm_pll *pll;
1330 uint32_t payload[PAYLOAD_ARG_CNT];
1331 enum pm_ret_status status;
1332
1333 /* First try to handle it as a PLL */
1334 pll = pm_clock_get_pll_by_related_clk(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301335 if (pll) {
Jolly Shah407fc0a2019-01-04 11:57:40 -08001336 return pm_clock_pll_set_parent(pll, clock_id, parent_index);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301337 }
Jolly Shah407fc0a2019-01-04 11:57:40 -08001338
1339 /* Check if clock ID is a valid on-chip clock */
1340 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301341 if (status != PM_RET_SUCCESS) {
Jolly Shah407fc0a2019-01-04 11:57:40 -08001342 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301343 }
Jolly Shah407fc0a2019-01-04 11:57:40 -08001344
1345 /* Send request to the PMU */
1346 PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
1347 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001348}
1349
1350/**
1351 * pm_clock_getparent - Get the clock parent for given id
1352 * @clock_id: Id of the clock
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001353 * @parent_index: parent index
Rajan Vaja35116132018-01-17 02:39:25 -08001354 *
1355 * This function is used by master to get parent index
1356 * for any clock.
1357 *
1358 * Return: Returns status, either success or error+reason.
1359 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301360enum pm_ret_status pm_clock_getparent(uint32_t clock_id,
1361 uint32_t *parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001362{
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001363 struct pm_pll *pll;
1364 uint32_t payload[PAYLOAD_ARG_CNT];
1365 enum pm_ret_status status;
1366
1367 /* First try to handle it as a PLL */
1368 pll = pm_clock_get_pll_by_related_clk(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301369 if (pll) {
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001370 return pm_clock_pll_get_parent(pll, clock_id, parent_index);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301371 }
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001372
1373 /* Check if clock ID is a valid on-chip clock */
1374 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301375 if (status != PM_RET_SUCCESS) {
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001376 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301377 }
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001378
1379 /* Send request to the PMU */
1380 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
1381 return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001382}
1383
1384/**
Rajan Vajad5dd8362018-01-30 04:16:31 -08001385 * pm_pinctrl_get_num_pins - PM call to request number of pins
1386 * @npins: Number of pins
1387 *
1388 * This function is used by master to get number of pins
1389 *
1390 * Return: Returns status, either success or error+reason.
1391 */
1392static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
1393{
1394 return pm_api_pinctrl_get_num_pins(npins);
1395}
1396
1397/**
1398 * pm_pinctrl_get_num_functions - PM call to request number of functions
1399 * @nfuncs: Number of functions
1400 *
1401 * This function is used by master to get number of functions
1402 *
1403 * Return: Returns status, either success or error+reason.
1404 */
1405static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
1406{
1407 return pm_api_pinctrl_get_num_functions(nfuncs);
1408}
1409
1410/**
1411 * pm_pinctrl_get_num_function_groups - PM call to request number of
1412 * function groups
1413 * @fid: Id of function
1414 * @ngroups: Number of function groups
1415 *
1416 * This function is used by master to get number of function groups specified
1417 * by given function Id
1418 *
1419 * Return: Returns status, either success or error+reason.
1420 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301421static enum pm_ret_status pm_pinctrl_get_num_function_groups(uint32_t fid,
Rajan Vajad5dd8362018-01-30 04:16:31 -08001422 uint32_t *ngroups)
1423{
1424 return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
1425}
1426
1427/**
1428 * pm_pinctrl_get_function_name - PM call to request function name
1429 * @fid: Id of function
1430 * @name: Name of function
1431 *
1432 * This function is used by master to get name of function specified
1433 * by given function Id
Rajan Vajad5dd8362018-01-30 04:16:31 -08001434 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301435static void pm_pinctrl_get_function_name(uint32_t fid, char *name)
Rajan Vajad5dd8362018-01-30 04:16:31 -08001436{
Rajan Vajacd825682020-11-23 21:33:39 -08001437 pm_api_pinctrl_get_function_name(fid, name);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001438}
1439
1440/**
1441 * pm_pinctrl_get_function_groups - PM call to request function groups
1442 * @fid: Id of function
1443 * @index: Index of next function groups
1444 * @groups: Function groups
1445 *
1446 * This function is used by master to get function groups specified
1447 * by given function Id. This API will return 6 function groups with
1448 * a single response. To get other function groups, master should call
1449 * same API in loop with new function groups index till error is returned.
1450 *
1451 * E.g First call should have index 0 which will return function groups
1452 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1453 * function groups 6, 7, 8, 9, 10 and 11 and so on.
1454 *
1455 * Return: Returns status, either success or error+reason.
1456 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301457static enum pm_ret_status pm_pinctrl_get_function_groups(uint32_t fid,
1458 uint32_t index,
Rajan Vajad5dd8362018-01-30 04:16:31 -08001459 uint16_t *groups)
1460{
1461 return pm_api_pinctrl_get_function_groups(fid, index, groups);
1462}
1463
1464/**
1465 * pm_pinctrl_get_pin_groups - PM call to request pin groups
1466 * @pin_id: Id of pin
1467 * @index: Index of next pin groups
1468 * @groups: pin groups
1469 *
1470 * This function is used by master to get pin groups specified
1471 * by given pin Id. This API will return 6 pin groups with
1472 * a single response. To get other pin groups, master should call
1473 * same API in loop with new pin groups index till error is returned.
1474 *
1475 * E.g First call should have index 0 which will return pin groups
1476 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1477 * pin groups 6, 7, 8, 9, 10 and 11 and so on.
1478 *
1479 * Return: Returns status, either success or error+reason.
1480 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301481static enum pm_ret_status pm_pinctrl_get_pin_groups(uint32_t pin_id,
1482 uint32_t index,
Rajan Vajad5dd8362018-01-30 04:16:31 -08001483 uint16_t *groups)
1484{
1485 return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
1486}
1487
1488/**
Rajan Vaja35116132018-01-17 02:39:25 -08001489 * pm_query_data() - PM API for querying firmware data
1490 * @arg1 Argument 1 to requested IOCTL call
1491 * @arg2 Argument 2 to requested IOCTL call
1492 * @arg3 Argument 3 to requested IOCTL call
1493 * @arg4 Argument 4 to requested IOCTL call
1494 * @data Returned output data
1495 *
1496 * This function returns requested data.
Rajan Vaja35116132018-01-17 02:39:25 -08001497 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301498void pm_query_data(enum pm_query_id qid, uint32_t arg1, uint32_t arg2,
1499 uint32_t arg3, uint32_t *data)
Rajan Vaja35116132018-01-17 02:39:25 -08001500{
Rajan Vaja35116132018-01-17 02:39:25 -08001501 switch (qid) {
1502 case PM_QID_CLOCK_GET_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001503 pm_clock_get_name(arg1, (char *)data);
Rajan Vaja35116132018-01-17 02:39:25 -08001504 break;
1505 case PM_QID_CLOCK_GET_TOPOLOGY:
Rajan Vajacd825682020-11-23 21:33:39 -08001506 data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001507 break;
1508 case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
Rajan Vajacd825682020-11-23 21:33:39 -08001509 data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
1510 &data[2]);
Rajan Vaja35116132018-01-17 02:39:25 -08001511 break;
1512 case PM_QID_CLOCK_GET_PARENTS:
Rajan Vajacd825682020-11-23 21:33:39 -08001513 data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001514 break;
1515 case PM_QID_CLOCK_GET_ATTRIBUTES:
Rajan Vajacd825682020-11-23 21:33:39 -08001516 data[0] = pm_clock_get_attributes(arg1, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001517 break;
Rajan Vajad5dd8362018-01-30 04:16:31 -08001518 case PM_QID_PINCTRL_GET_NUM_PINS:
Rajan Vajacd825682020-11-23 21:33:39 -08001519 data[0] = pm_pinctrl_get_num_pins(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001520 break;
1521 case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
Rajan Vajacd825682020-11-23 21:33:39 -08001522 data[0] = pm_pinctrl_get_num_functions(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001523 break;
1524 case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001525 data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001526 break;
1527 case PM_QID_PINCTRL_GET_FUNCTION_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001528 pm_pinctrl_get_function_name(arg1, (char *)data);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001529 break;
1530 case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001531 data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
1532 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001533 break;
1534 case PM_QID_PINCTRL_GET_PIN_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001535 data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
1536 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001537 break;
Rajan Vajada959402018-07-20 03:16:27 -07001538 case PM_QID_CLOCK_GET_NUM_CLOCKS:
Rajan Vajacd825682020-11-23 21:33:39 -08001539 data[0] = pm_clock_get_num_clocks(&data[1]);
Rajan Vajada959402018-07-20 03:16:27 -07001540 break;
Rajan Vajab34deca2019-03-20 01:13:21 +05301541
1542 case PM_QID_CLOCK_GET_MAX_DIVISOR:
Rajan Vajacd825682020-11-23 21:33:39 -08001543 data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
Rajan Vajab34deca2019-03-20 01:13:21 +05301544 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001545 default:
Rajan Vajacd825682020-11-23 21:33:39 -08001546 data[0] = PM_RET_ERROR_ARGS;
Rajan Vaja35116132018-01-17 02:39:25 -08001547 WARN("Unimplemented query service call: 0x%x\n", qid);
Venkatesh Yadav Abbarapu41886f72022-04-29 15:17:13 +05301548 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001549 }
Rajan Vaja35116132018-01-17 02:39:25 -08001550}
Siva Durga Prasad Paladuguf3994cc2018-05-01 11:12:55 +05301551
1552enum pm_ret_status pm_sha_hash(uint32_t address_high,
1553 uint32_t address_low,
1554 uint32_t size,
1555 uint32_t flags)
1556{
1557 uint32_t payload[PAYLOAD_ARG_CNT];
1558
1559 /* Send request to the PMU */
1560 PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
1561 size, flags);
1562 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1563}
1564
1565enum pm_ret_status pm_rsa_core(uint32_t address_high,
1566 uint32_t address_low,
1567 uint32_t size,
1568 uint32_t flags)
1569{
1570 uint32_t payload[PAYLOAD_ARG_CNT];
1571
1572 /* Send request to the PMU */
1573 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
1574 size, flags);
1575 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1576}
Siva Durga Prasad Paladugua4ed4b22018-04-30 20:06:58 +05301577
1578enum pm_ret_status pm_secure_image(uint32_t address_low,
1579 uint32_t address_high,
1580 uint32_t key_lo,
1581 uint32_t key_hi,
1582 uint32_t *value)
1583{
1584 uint32_t payload[PAYLOAD_ARG_CNT];
1585
1586 /* Send request to the PMU */
1587 PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
1588 key_hi, key_lo);
1589 return pm_ipi_send_sync(primary_proc, payload, value, 2);
1590}
Siva Durga Prasad Paladugu7c6516a2018-09-04 17:41:34 +05301591
1592/**
1593 * pm_fpga_read - Perform the fpga configuration readback
1594 *
1595 * @reg_numframes: Configuration register offset (or) Number of frames to read
1596 * @address_low: lower 32-bit Linear memory space address
1597 * @address_high: higher 32-bit Linear memory space address
1598 * @readback_type: Type of fpga readback operation
1599 * 0 -- Configuration Register readback
1600 * 1 -- Configuration Data readback
1601 * @value: Value to read
1602 *
1603 * This function provides access to the xilfpga library to read
1604 * the PL configuration.
1605 *
1606 * Return: Returns status, either success or error+reason.
1607 */
1608enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
1609 uint32_t address_low,
1610 uint32_t address_high,
1611 uint32_t readback_type,
1612 uint32_t *value)
1613{
1614 uint32_t payload[PAYLOAD_ARG_CNT];
1615
1616 /* Send request to the PMU */
1617 PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
1618 address_high, readback_type);
1619 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1620}
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001621
1622/*
1623 * pm_pll_set_parameter() - Set the PLL parameter value
1624 * @nid Node id of the target PLL
1625 * @param_id ID of the PLL parameter
1626 * @value Parameter value to be set
1627 *
1628 * Setting the parameter will have physical effect once the PLL mode is set to
1629 * integer or fractional.
1630 *
1631 * @return Error if an argument is not valid or status as returned by the
1632 * PM controller (PMU)
1633 */
1634enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
1635 enum pm_pll_param param_id,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301636 uint32_t value)
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001637{
1638 uint32_t payload[PAYLOAD_ARG_CNT];
1639
1640 /* Check if given node ID is a PLL node */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301641 if (nid < NODE_APLL || nid > NODE_IOPLL) {
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001642 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301643 }
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001644
1645 /* Check if parameter ID is valid and return an error if it's not */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301646 if (param_id >= PM_PLL_PARAM_MAX) {
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001647 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301648 }
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001649
1650 /* Send request to the PMU */
1651 PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
1652 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1653}
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001654
1655/**
1656 * pm_pll_get_parameter() - Get the PLL parameter value
1657 * @nid Node id of the target PLL
1658 * @param_id ID of the PLL parameter
1659 * @value Location to store the parameter value
1660 *
1661 * @return Error if an argument is not valid or status as returned by the
1662 * PM controller (PMU)
1663 */
1664enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
1665 enum pm_pll_param param_id,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301666 uint32_t *value)
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001667{
1668 uint32_t payload[PAYLOAD_ARG_CNT];
1669
1670 /* Check if given node ID is a PLL node */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301671 if (nid < NODE_APLL || nid > NODE_IOPLL) {
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001672 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301673 }
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001674
1675 /* Check if parameter ID is valid and return an error if it's not */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301676 if (param_id >= PM_PLL_PARAM_MAX) {
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001677 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301678 }
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001679
1680 /* Send request to the PMU */
1681 PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
1682 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1683}
Jolly Shah1f0d5852019-01-04 11:32:31 -08001684
1685/**
1686 * pm_pll_set_mode() - Set the PLL mode
1687 * @nid Node id of the target PLL
1688 * @mode PLL mode to be set
1689 *
1690 * If reset mode is set the PM controller will first bypass the PLL and then
1691 * assert the reset. If integer or fractional mode is set the PM controller will
1692 * ensure that the complete PLL programming sequence is satisfied. After this
1693 * function returns success the PLL is locked and its bypass is deasserted.
1694 *
1695 * @return Error if an argument is not valid or status as returned by the
1696 * PM controller (PMU)
1697 */
1698enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
1699{
1700 uint32_t payload[PAYLOAD_ARG_CNT];
1701
1702 /* Check if given node ID is a PLL node */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301703 if (nid < NODE_APLL || nid > NODE_IOPLL) {
Jolly Shah1f0d5852019-01-04 11:32:31 -08001704 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301705 }
Jolly Shah1f0d5852019-01-04 11:32:31 -08001706
1707 /* Check if PLL mode is valid */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301708 if (mode >= PM_PLL_MODE_MAX) {
Jolly Shah1f0d5852019-01-04 11:32:31 -08001709 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301710 }
Jolly Shah1f0d5852019-01-04 11:32:31 -08001711
1712 /* Send request to the PMU */
1713 PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
1714 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1715}
Jolly Shah141421e2019-01-04 11:35:48 -08001716
1717/**
1718 * pm_pll_get_mode() - Get the PLL mode
1719 * @nid Node id of the target PLL
1720 * @mode Location to store the mode of the PLL
1721 *
1722 * @return Error if an argument is not valid or status as returned by the
1723 * PM controller (PMU)
1724 */
1725enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
1726{
1727 uint32_t payload[PAYLOAD_ARG_CNT];
1728
1729 /* Check if given node ID is a PLL node */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301730 if (nid < NODE_APLL || nid > NODE_IOPLL) {
Jolly Shah141421e2019-01-04 11:35:48 -08001731 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301732 }
Jolly Shah141421e2019-01-04 11:35:48 -08001733
1734 /* Send request to the PMU */
1735 PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
1736 return pm_ipi_send_sync(primary_proc, payload, mode, 1);
1737}
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001738
1739/**
1740 * pm_register_access() - PM API for register read/write access data
1741 *
1742 * @register_access_id Register_access_id which says register read/write
1743 *
1744 * @address Address of the register to be accessed
1745 *
1746 * @mask Mask value to be used while writing value
1747 *
1748 * @value Value to be written to register
1749 *
1750 * @out Returned output data
1751 *
1752 * This function returns requested data.
1753 *
1754 * @return Returns status, either success or error+reason
1755 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301756enum pm_ret_status pm_register_access(uint32_t register_access_id,
1757 uint32_t address,
1758 uint32_t mask,
1759 uint32_t value,
1760 uint32_t *out)
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001761{
1762 enum pm_ret_status ret;
1763
1764 if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
1765 ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
1766 ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301767 ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) {
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001768 return PM_RET_ERROR_ACCESS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301769 }
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001770
1771 switch (register_access_id) {
1772 case CONFIG_REG_WRITE:
1773 ret = pm_mmio_write(address, mask, value);
1774 break;
1775 case CONFIG_REG_READ:
1776 ret = pm_mmio_read(address, out);
1777 break;
1778 default:
1779 ret = PM_RET_ERROR_ARGS;
1780 WARN("Unimplemented register_access call\n\r");
Venkatesh Yadav Abbarapu41886f72022-04-29 15:17:13 +05301781 break;
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001782 }
1783 return ret;
1784}
VNSL Durgadeb1a362020-11-23 04:46:04 -08001785
1786/**
1787 * pm_efuse_access() - To program or read efuse bits.
1788 *
1789 * This function provides access to the xilskey library to program/read
1790 * efuse bits.
1791 *
1792 * address_low: lower 32-bit Linear memory space address
1793 * address_high: higher 32-bit Linear memory space address
1794 *
1795 * value: Returned output value
1796 *
1797 * @return Returns status, either success or error+reason
1798 *
1799 */
1800enum pm_ret_status pm_efuse_access(uint32_t address_high,
1801 uint32_t address_low,
1802 uint32_t *value)
1803{
1804 uint32_t payload[PAYLOAD_ARG_CNT];
1805
1806 /* Send request to the PMU */
1807 PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
1808
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -08001809 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1810}
1811
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301812enum pm_ret_status em_set_action(uint32_t *value)
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -08001813{
1814 uint32_t payload[PAYLOAD_ARG_CNT];
1815
1816 /* Send request to the PMU */
1817 EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
1818 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1819}
1820
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301821enum pm_ret_status em_remove_action(uint32_t *value)
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -08001822{
1823 uint32_t payload[PAYLOAD_ARG_CNT];
1824
1825 /* Send request to the PMU */
1826 EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
1827 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1828}
1829
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301830enum pm_ret_status em_send_errors(uint32_t *value)
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -08001831{
1832 uint32_t payload[PAYLOAD_ARG_CNT];
1833
1834 /* Send request to the PMU */
1835 EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
VNSL Durgadeb1a362020-11-23 04:46:04 -08001836 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1837}