blob: 99594f756b73525aeec5c95ad6ef59481203827e [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
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800256/**
257 * pm_self_suspend() - PM call for processor to suspend itself
258 * @nid Node id of the processor or subsystem
259 * @latency Requested maximum wakeup latency (not supported)
Filip Drazic0bd9d0c2016-07-20 17:17:39 +0200260 * @state Requested state
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800261 * @address Resume address
262 *
263 * This is a blocking call, it will return only once PMU has responded.
264 * On a wakeup, resume address will be automatically set by PMU.
265 *
266 * @return Returns status, either success or error+reason
267 */
268enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530269 uint32_t latency,
270 uint32_t state,
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800271 uintptr_t address)
272{
273 uint32_t payload[PAYLOAD_ARG_CNT];
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530274 uint32_t cpuid = plat_my_core_pos();
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800275 const struct pm_proc *proc = pm_get_proc(cpuid);
276
277 /*
278 * Do client specific suspend operations
279 * (e.g. set powerdown request bit)
280 */
Filip Drazic4c0765a2016-07-26 12:11:33 +0200281 pm_client_suspend(proc, state);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800282 /* Send request to the PMU */
283 PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
284 state, address, (address >> 32));
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700285 return pm_ipi_send_sync(proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800286}
287
288/**
289 * pm_req_suspend() - PM call to request for another PU or subsystem to
290 * be suspended gracefully.
291 * @target Node id of the targeted PU or subsystem
292 * @ack Flag to specify whether acknowledge is requested
293 * @latency Requested wakeup latency (not supported)
294 * @state Requested state (not supported)
295 *
296 * @return Returns status, either success or error+reason
297 */
298enum pm_ret_status pm_req_suspend(enum pm_node_id target,
299 enum pm_request_ack ack,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530300 uint32_t latency, uint32_t state)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800301{
302 uint32_t payload[PAYLOAD_ARG_CNT];
303
304 /* Send request to the PMU */
305 PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530306 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700307 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530308 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800309 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530310 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800311}
312
313/**
314 * pm_req_wakeup() - PM call for processor to wake up selected processor
315 * or subsystem
316 * @target Node id of the processor or subsystem to wake up
317 * @ack Flag to specify whether acknowledge requested
318 * @set_address Resume address presence indicator
319 * 1 resume address specified, 0 otherwise
320 * @address Resume address
321 *
322 * This API function is either used to power up another APU core for SMP
323 * (by PSCI) or to power up an entirely different PU or subsystem, such
324 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
325 * automatically set by PMU.
326 *
327 * @return Returns status, either success or error+reason
328 */
329enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530330 uint32_t set_address,
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800331 uintptr_t address,
332 enum pm_request_ack ack)
333{
334 uint32_t payload[PAYLOAD_ARG_CNT];
335 uint64_t encoded_address;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800336
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800337
338 /* encode set Address into 1st bit of address */
339 encoded_address = address;
340 encoded_address |= !!set_address;
341
342 /* Send request to the PMU to perform the wake of the PU */
343 PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
344 encoded_address >> 32, ack);
345
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530346 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700347 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530348 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800349 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530350 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800351}
352
353/**
354 * pm_force_powerdown() - PM call to request for another PU or subsystem to
355 * be powered down forcefully
356 * @target Node id of the targeted PU or subsystem
357 * @ack Flag to specify whether acknowledge is requested
358 *
359 * @return Returns status, either success or error+reason
360 */
361enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
362 enum pm_request_ack ack)
363{
364 uint32_t payload[PAYLOAD_ARG_CNT];
365
366 /* Send request to the PMU */
367 PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
368
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530369 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700370 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530371 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800372 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530373 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800374}
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,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530412 uint32_t enable)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800413{
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 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530428enum pm_ret_status pm_system_shutdown(uint32_t type, uint32_t 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,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530454 uint32_t capabilities,
455 uint32_t qos,
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800456 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
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530462 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700463 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530464 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800465 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530466 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800467}
468
469/**
470 * pm_set_requirement() - PM call to set requirement for PM slaves
471 * @nid Node id of the slave
472 * @capabilities Requested capabilities of the slave
473 * @qos Quality of service (not supported)
474 * @ack Flag to specify whether acknowledge is requested
475 *
476 * This API function is to be used for slaves a PU already has requested
477 *
478 * @return Returns status, either success or error+reason
479 */
480enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530481 uint32_t capabilities,
482 uint32_t qos,
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800483 enum pm_request_ack ack)
484{
485 uint32_t payload[PAYLOAD_ARG_CNT];
486
487 PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
488 ack);
489
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530490 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700491 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530492 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800493 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530494 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800495}
496
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800497/* Miscellaneous API functions */
498
499/**
500 * pm_get_api_version() - Get version number of PMU PM firmware
501 * @version Returns 32-bit version number of PMU Power Management Firmware
502 *
503 * @return Returns status, either success or error+reason
504 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530505enum pm_ret_status pm_get_api_version(uint32_t *version)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800506{
507 uint32_t payload[PAYLOAD_ARG_CNT];
508
509 /* Send request to the PMU */
510 PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700511 return pm_ipi_send_sync(primary_proc, payload, version, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800512}
513
514/**
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100515 * pm_get_node_status() - PM call to request a node's current status
516 * @nid Node id
517 * @ret_buff Buffer for the return values:
518 * [0] - Current power state of the node
519 * [1] - Current requirements for the node (slave nodes only)
520 * [2] - Current usage status for the node (slave nodes only)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800521 *
522 * @return Returns status, either success or error+reason
523 */
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100524enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
525 uint32_t *ret_buff)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800526{
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800527 uint32_t payload[PAYLOAD_ARG_CNT];
528
529 PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100530 return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800531}
532
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800533/**
534 * pm_mmio_write() - Perform write to protected mmio
535 * @address Address to write to
536 * @mask Mask to apply
537 * @value Value to write
538 *
539 * This function provides access to PM-related control registers
540 * that may not be directly accessible by a particular PU.
541 *
542 * @return Returns status, either success or error+reason
543 */
544enum pm_ret_status pm_mmio_write(uintptr_t address,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530545 uint32_t mask,
546 uint32_t value)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800547{
548 uint32_t payload[PAYLOAD_ARG_CNT];
549
550 /* Send request to the PMU */
551 PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700552 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800553}
554
555/**
556 * pm_mmio_read() - Read value from protected mmio
557 * @address Address to write to
558 * @value Value to write
559 *
560 * This function provides access to PM-related control registers
561 * that may not be directly accessible by a particular PU.
562 *
563 * @return Returns status, either success or error+reason
564 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530565enum pm_ret_status pm_mmio_read(uintptr_t address, uint32_t *value)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800566{
567 uint32_t payload[PAYLOAD_ARG_CNT];
568
569 /* Send request to the PMU */
570 PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700571 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800572}
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530573
574/**
575 * pm_fpga_load() - Load the bitstream into the PL.
576 *
577 * This function provides access to the xilfpga library to load
578 * the Bit-stream into PL.
579 *
580 * address_low: lower 32-bit Linear memory space address
581 *
582 * address_high: higher 32-bit Linear memory space address
583 *
584 * size: Number of 32bit words
585 *
586 * @return Returns status, either success or error+reason
587 */
588enum pm_ret_status pm_fpga_load(uint32_t address_low,
589 uint32_t address_high,
590 uint32_t size,
591 uint32_t flags)
592{
593 uint32_t payload[PAYLOAD_ARG_CNT];
594
595 /* Send request to the PMU */
596 PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
597 size, flags);
Siva Durga Prasad Paladugubf83b9c2018-02-07 13:13:01 +0530598 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530599}
600
601/**
602 * pm_fpga_get_status() - Read value from fpga status register
603 * @value Value to read
604 *
605 * This function provides access to the xilfpga library to get
606 * the fpga status
607 * @return Returns status, either success or error+reason
608 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530609enum pm_ret_status pm_fpga_get_status(uint32_t *value)
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530610{
611 uint32_t payload[PAYLOAD_ARG_CNT];
612
613 /* Send request to the PMU */
614 PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700615 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530616}
Soren Brinkmanncb366812016-09-22 12:21:11 -0700617
618/**
619 * pm_get_chipid() - Read silicon ID registers
620 * @value Buffer for return values. Must be large enough
621 * to hold 8 bytes.
622 *
623 * @return Returns silicon ID registers
624 */
625enum pm_ret_status pm_get_chipid(uint32_t *value)
626{
627 uint32_t payload[PAYLOAD_ARG_CNT];
628
629 /* Send request to the PMU */
630 PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
631 return pm_ipi_send_sync(primary_proc, payload, value, 2);
632}
Soren Brinkmann84f0af42016-09-30 14:24:25 -0700633
634/**
Siva Durga Prasad Paladugude93d982018-04-30 15:49:27 +0530635 * pm_secure_rsaaes() - Load the secure images.
636 *
637 * This function provides access to the xilsecure library to load
638 * the authenticated, encrypted, and authenicated/encrypted images.
639 *
640 * address_low: lower 32-bit Linear memory space address
641 *
642 * address_high: higher 32-bit Linear memory space address
643 *
644 * size: Number of 32bit words
645 *
646 * @return Returns status, either success or error+reason
647 */
648enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
649 uint32_t address_high,
650 uint32_t size,
651 uint32_t flags)
652{
653 uint32_t payload[PAYLOAD_ARG_CNT];
654
655 /* Send request to the PMU */
656 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
657 size, flags);
658 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
659}
660
661/**
Siva Durga Prasad Paladugu8bd905b2018-09-04 18:05:50 +0530662 * pm_aes_engine() - Aes data blob encryption/decryption
663 * This function provides access to the xilsecure library to
664 * encrypt/decrypt data blobs.
665 *
666 * address_low: lower 32-bit address of the AesParams structure
667 *
668 * address_high: higher 32-bit address of the AesParams structure
669 *
670 * value: Returned output value
671 *
672 * @return Returns status, either success or error+reason
673 */
674enum pm_ret_status pm_aes_engine(uint32_t address_high,
675 uint32_t address_low,
676 uint32_t *value)
677{
678 uint32_t payload[PAYLOAD_ARG_CNT];
679
680 /* Send request to the PMU */
681 PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
682 return pm_ipi_send_sync(primary_proc, payload, value, 1);
683}
684
685/**
Rajan Vaja02d18422019-03-04 11:09:39 +0530686 * pm_get_callbackdata() - Read from IPI response buffer
687 * @data - array of PAYLOAD_ARG_CNT elements
688 *
689 * Read value from ipi buffer response buffer.
690 */
691void pm_get_callbackdata(uint32_t *data, size_t count)
692{
693 /* Return if interrupt is not from PMU */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530694 if (!pm_ipi_irq_status(primary_proc)) {
Rajan Vaja02d18422019-03-04 11:09:39 +0530695 return;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530696 }
Rajan Vaja02d18422019-03-04 11:09:39 +0530697
698 pm_ipi_buff_read_callb(data, count);
699 pm_ipi_irq_clear(primary_proc);
700}
701
702/**
Rajan Vaja5529a012018-01-17 02:39:23 -0800703 * pm_ioctl() - PM IOCTL API for device control and configs
704 * @node_id Node ID of the device
705 * @ioctl_id ID of the requested IOCTL
706 * @arg1 Argument 1 to requested IOCTL call
707 * @arg2 Argument 2 to requested IOCTL call
708 * @out Returned output value
709 *
710 * This function calls IOCTL to firmware for device control and configuration.
711 *
712 * @return Returns status, either success or error+reason
713 */
714enum pm_ret_status pm_ioctl(enum pm_node_id nid,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530715 uint32_t ioctl_id,
716 uint32_t arg1,
717 uint32_t arg2,
718 uint32_t *value)
Rajan Vaja5529a012018-01-17 02:39:23 -0800719{
720 return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
721}
Rajan Vaja35116132018-01-17 02:39:25 -0800722
723/**
Ronak Jain325bad12021-12-21 01:39:59 -0800724 * fw_api_version() - Returns API version implemented in firmware
725 * @api_id API ID to check
726 * @version Returned supported API version
727 * @len Number of words to be returned
728 *
729 * @return Returns status, either success or error+reason
730 */
731static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version,
732 uint32_t len)
733{
734 uint32_t payload[PAYLOAD_ARG_CNT];
735
736 PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id);
737 return pm_ipi_send_sync(primary_proc, payload, version, len);
738}
739
740/**
741 * check_api_dependency() - API to check dependent EEMI API version
742 * @id EEMI API ID to check
743 *
744 * @return Returns status, either success or error+reason
745 */
746enum pm_ret_status check_api_dependency(uint8_t id)
747{
748 uint8_t i;
749 uint32_t version;
750 int ret;
751
752 for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
753 if (api_dep_table[i].id == id) {
754 if (api_dep_table[i].api_id == 0U) {
755 break;
756 }
757
758 ret = fw_api_version(api_dep_table[i].api_id,
759 &version, 1);
760 if (ret != PM_RET_SUCCESS) {
761 return ret;
762 }
763
764 /* Check if fw version matches ATF expected version */
765 if (version != atf_expected_ver_id[api_dep_table[i].api_id]) {
766 return PM_RET_ERROR_NOTSUPPORTED;
767 }
768 }
769 }
770
771 return PM_RET_SUCCESS;
772}
773
774/**
775 * feature_check_atf() - These are API's completely implemented in ATF
776 * @api_id API ID to check
777 * @version Returned supported API version
778 *
779 * @return Returns status, either success or error+reason
780 */
781static enum pm_ret_status feature_check_atf(uint32_t api_id, uint32_t *version,
782 uint32_t *bit_mask)
783{
784 switch (api_id) {
785 case PM_QUERY_DATA:
Ronak Jain11b084a2023-02-13 04:48:06 -0800786 *version = TFA_API_QUERY_DATA_VERSION;
Ronak Jain325bad12021-12-21 01:39:59 -0800787 bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
788 bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
789 return PM_RET_SUCCESS;
790 case PM_GET_CALLBACK_DATA:
791 case PM_GET_TRUSTZONE_VERSION:
792 case PM_SET_SUSPEND_MODE:
793 *version = ATF_API_BASE_VERSION;
794 return PM_RET_SUCCESS;
795 default:
796 return PM_RET_ERROR_NO_FEATURE;
797 }
798}
799
800/**
801 * get_atf_version_for_partial_apis() - Return ATF version for partially
802 * implemented APIs
803 * @api_id API ID to check
804 * @version Returned supported API version
805 *
806 * @return Returns status, either success or error+reason
807 */
808static enum pm_ret_status get_atf_version_for_partial_apis(uint32_t api_id,
809 uint32_t *version)
810{
811 switch (api_id) {
812 case PM_SELF_SUSPEND:
813 case PM_REQ_WAKEUP:
814 case PM_ABORT_SUSPEND:
815 case PM_SET_WAKEUP_SOURCE:
816 case PM_SYSTEM_SHUTDOWN:
817 case PM_GET_API_VERSION:
818 case PM_CLOCK_ENABLE:
819 case PM_CLOCK_DISABLE:
820 case PM_CLOCK_GETSTATE:
821 case PM_CLOCK_SETDIVIDER:
822 case PM_CLOCK_GETDIVIDER:
823 case PM_CLOCK_SETPARENT:
824 case PM_CLOCK_GETPARENT:
825 case PM_PLL_SET_PARAMETER:
826 case PM_PLL_GET_PARAMETER:
827 case PM_PLL_SET_MODE:
828 case PM_PLL_GET_MODE:
829 case PM_REGISTER_ACCESS:
830 *version = ATF_API_BASE_VERSION;
831 return PM_RET_SUCCESS;
832 case PM_FEATURE_CHECK:
833 *version = FW_API_VERSION_2;
834 return PM_RET_SUCCESS;
835 default:
836 return PM_RET_ERROR_ARGS;
837 }
838}
839
840/**
841 * feature_check_partial() - These are API's partially implemented in
842 * ATF and firmware both
843 * @api_id API ID to check
844 * @version Returned supported API version
845 *
846 * @return Returns status, either success or error+reason
847 */
848static enum pm_ret_status feature_check_partial(uint32_t api_id,
849 uint32_t *version)
850{
851 uint32_t status;
852
853 switch (api_id) {
854 case PM_SELF_SUSPEND:
855 case PM_REQ_WAKEUP:
856 case PM_ABORT_SUSPEND:
857 case PM_SET_WAKEUP_SOURCE:
858 case PM_SYSTEM_SHUTDOWN:
859 case PM_GET_API_VERSION:
860 case PM_CLOCK_ENABLE:
861 case PM_CLOCK_DISABLE:
862 case PM_CLOCK_GETSTATE:
863 case PM_CLOCK_SETDIVIDER:
864 case PM_CLOCK_GETDIVIDER:
865 case PM_CLOCK_SETPARENT:
866 case PM_CLOCK_GETPARENT:
867 case PM_PLL_SET_PARAMETER:
868 case PM_PLL_GET_PARAMETER:
869 case PM_PLL_SET_MODE:
870 case PM_PLL_GET_MODE:
871 case PM_REGISTER_ACCESS:
872 case PM_FEATURE_CHECK:
873 status = check_api_dependency(api_id);
874 if (status != PM_RET_SUCCESS) {
875 return status;
876 }
877 return get_atf_version_for_partial_apis(api_id, version);
878 default:
879 return PM_RET_ERROR_NO_FEATURE;
880 }
881}
882
883/**
884 * pm_feature_check() - Returns the supported API version if supported
885 * @api_id API ID to check
886 * @version Returned supported API version
887 * @bit_mask Returned supported IOCTL id version
888 * @len Number of bytes to be returned in bit_mask variable
889 *
890 * @return Returns status, either success or error+reason
891 */
892enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
893 uint32_t *bit_mask, uint8_t len)
894{
895 uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
896 uint32_t status;
897
898 /* Get API version implemented in ATF */
899 status = feature_check_atf(api_id, version, bit_mask);
900 if (status != PM_RET_ERROR_NO_FEATURE) {
901 return status;
902 }
903
904 /* Get API version implemented by firmware and ATF both */
905 status = feature_check_partial(api_id, version);
906 if (status != PM_RET_ERROR_NO_FEATURE) {
907 return status;
908 }
909
910 /* Get API version implemented by firmware */
911 status = fw_api_version(api_id, ret_payload, 3);
912 /* IOCTL call may return failure whose ID is not implemented in
913 * firmware but implemented in ATF
914 */
915 if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) {
916 return status;
917 }
918
919 *version = ret_payload[0];
920
921 /* Update IOCTL bit mask which are implemented in ATF */
Ronak Jainc443e802023-02-22 04:28:02 -0800922 if ((api_id == PM_IOCTL) || (api_id == PM_GET_OP_CHARACTERISTIC)) {
Ronak Jain325bad12021-12-21 01:39:59 -0800923 if (len < 2) {
924 return PM_RET_ERROR_ARGS;
925 }
926 bit_mask[0] = ret_payload[1];
927 bit_mask[1] = ret_payload[2];
Ronak Jainc443e802023-02-22 04:28:02 -0800928 if (api_id == PM_IOCTL) {
929 /* Get IOCTL's implemented by ATF */
930 status = atf_ioctl_bitmask(bit_mask);
931 }
Ronak Jain325bad12021-12-21 01:39:59 -0800932 } else {
933 /* Requires for MISRA */
934 }
935
936 return status;
937}
938
939/**
Rajan Vajab34deca2019-03-20 01:13:21 +0530940 * pm_clock_get_max_divisor - PM call to get max divisor
941 * @clock_id Clock ID
942 * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2)
943 * @max_div Maximum supported divisor
944 *
945 * This function is used by master to get maximum supported value.
946 *
947 * Return: Returns status, either success or error+reason.
948 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530949static enum pm_ret_status pm_clock_get_max_divisor(uint32_t clock_id,
Rajan Vajab34deca2019-03-20 01:13:21 +0530950 uint8_t div_type,
951 uint32_t *max_div)
952{
953 return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
954}
955
956/**
Rajan Vajada959402018-07-20 03:16:27 -0700957 * pm_clock_get_num_clocks - PM call to request number of clocks
958 * @nclockss: Number of clocks
959 *
960 * This function is used by master to get number of clocks.
961 *
962 * Return: Returns status, either success or error+reason.
963 */
964static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
965{
966 return pm_api_clock_get_num_clocks(nclocks);
967}
968
969/**
Rajan Vaja35116132018-01-17 02:39:25 -0800970 * pm_clock_get_name() - PM call to request a clock's name
971 * @clock_id Clock ID
972 * @name Name of clock (max 16 bytes)
973 *
974 * This function is used by master to get nmae of clock specified
975 * by given clock ID.
Rajan Vaja35116132018-01-17 02:39:25 -0800976 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530977static void pm_clock_get_name(uint32_t clock_id, char *name)
Rajan Vaja35116132018-01-17 02:39:25 -0800978{
Rajan Vajacd825682020-11-23 21:33:39 -0800979 pm_api_clock_get_name(clock_id, name);
Rajan Vaja35116132018-01-17 02:39:25 -0800980}
981
982/**
983 * pm_clock_get_topology() - PM call to request a clock's topology
984 * @clock_id Clock ID
985 * @index Topology index for next toplogy node
986 * @topology Buffer to store nodes in topology and flags
987 *
988 * This function is used by master to get topology information for the
989 * clock specified by given clock ID. Each response would return 3
990 * topology nodes. To get next nodes, caller needs to call this API with
991 * index of next node. Index starts from 0.
992 *
993 * @return Returns status, either success or error+reason
994 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +0530995static enum pm_ret_status pm_clock_get_topology(uint32_t clock_id,
996 uint32_t index,
Rajan Vaja35116132018-01-17 02:39:25 -0800997 uint32_t *topology)
998{
999 return pm_api_clock_get_topology(clock_id, index, topology);
1000}
1001
1002/**
1003 * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
1004 * parameters for fixed clock
1005 * @clock_id Clock ID
1006 * @mul Multiplication value
1007 * @div Divisor value
1008 *
1009 * This function is used by master to get fixed factor parameers for the
1010 * fixed clock. This API is application only for the fixed clock.
1011 *
1012 * @return Returns status, either success or error+reason
1013 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301014static enum pm_ret_status pm_clock_get_fixedfactor_params(uint32_t clock_id,
Rajan Vaja35116132018-01-17 02:39:25 -08001015 uint32_t *mul,
1016 uint32_t *div)
1017{
1018 return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
1019}
1020
1021/**
1022 * pm_clock_get_parents() - PM call to request a clock's first 3 parents
1023 * @clock_id Clock ID
1024 * @index Index of next parent
1025 * @parents Parents of the given clock
1026 *
1027 * This function is used by master to get clock's parents information.
1028 * This API will return 3 parents with a single response. To get other
1029 * parents, master should call same API in loop with new parent index
1030 * till error is returned.
1031 *
1032 * E.g First call should have index 0 which will return parents 0, 1 and
1033 * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
1034 * so on.
1035 *
1036 * @return Returns status, either success or error+reason
1037 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301038static enum pm_ret_status pm_clock_get_parents(uint32_t clock_id,
1039 uint32_t index,
Rajan Vaja35116132018-01-17 02:39:25 -08001040 uint32_t *parents)
1041{
1042 return pm_api_clock_get_parents(clock_id, index, parents);
1043}
1044
1045/**
1046 * pm_clock_get_attributes() - PM call to request a clock's attributes
1047 * @clock_id Clock ID
1048 * @attr Clock attributes
1049 *
1050 * This function is used by master to get clock's attributes
1051 * (e.g. valid, clock type, etc).
1052 *
1053 * @return Returns status, either success or error+reason
1054 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301055static enum pm_ret_status pm_clock_get_attributes(uint32_t clock_id,
Rajan Vaja35116132018-01-17 02:39:25 -08001056 uint32_t *attr)
1057{
1058 return pm_api_clock_get_attributes(clock_id, attr);
1059}
1060
1061/**
Jolly Shaha5209802019-01-04 11:45:59 -08001062 * pm_clock_gate() - Configure clock gate
1063 * @clock_id Id of the clock to be configured
1064 * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
1065 *
1066 * @return Error if an argument is not valid or status as returned by the
1067 * PM controller (PMU)
1068 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301069static enum pm_ret_status pm_clock_gate(uint32_t clock_id,
1070 uint8_t enable)
Jolly Shaha5209802019-01-04 11:45:59 -08001071{
1072 uint32_t payload[PAYLOAD_ARG_CNT];
1073 enum pm_ret_status status;
1074 enum pm_api_id api_id;
1075
1076 /* Check if clock ID is valid and return an error if it is not */
1077 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301078 if (status != PM_RET_SUCCESS) {
Jolly Shaha5209802019-01-04 11:45:59 -08001079 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301080 }
Jolly Shaha5209802019-01-04 11:45:59 -08001081
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301082 if (enable) {
Jolly Shaha5209802019-01-04 11:45:59 -08001083 api_id = PM_CLOCK_ENABLE;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301084 } else {
Jolly Shaha5209802019-01-04 11:45:59 -08001085 api_id = PM_CLOCK_DISABLE;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301086 }
Jolly Shaha5209802019-01-04 11:45:59 -08001087
1088 /* Send request to the PMU */
1089 PM_PACK_PAYLOAD2(payload, api_id, clock_id);
Mirela Simonovic64514a72018-08-24 17:09:07 +02001090 status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1091
1092 /* If action fails due to the lack of permissions filter the error */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301093 if (status == PM_RET_ERROR_ACCESS) {
Mirela Simonovic64514a72018-08-24 17:09:07 +02001094 status = PM_RET_SUCCESS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301095 }
Mirela Simonovic64514a72018-08-24 17:09:07 +02001096
1097 return status;
Jolly Shaha5209802019-01-04 11:45:59 -08001098}
1099
1100/**
Rajan Vaja35116132018-01-17 02:39:25 -08001101 * pm_clock_enable() - Enable the clock for given id
1102 * @clock_id: Id of the clock to be enabled
1103 *
1104 * This function is used by master to enable the clock
1105 * including peripherals and PLL clocks.
1106 *
Jolly Shaha5209802019-01-04 11:45:59 -08001107 * @return: Error if an argument is not valid or status as returned by the
1108 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -08001109 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301110enum pm_ret_status pm_clock_enable(uint32_t clock_id)
Rajan Vaja35116132018-01-17 02:39:25 -08001111{
Jolly Shaha5209802019-01-04 11:45:59 -08001112 struct pm_pll *pll;
1113
1114 /* First try to handle it as a PLL */
1115 pll = pm_clock_get_pll(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301116 if (pll) {
Jolly Shaha5209802019-01-04 11:45:59 -08001117 return pm_clock_pll_enable(pll);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301118 }
Jolly Shaha5209802019-01-04 11:45:59 -08001119
1120 /* It's an on-chip clock, PMU should configure clock's gate */
1121 return pm_clock_gate(clock_id, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001122}
1123
1124/**
1125 * pm_clock_disable - Disable the clock for given id
1126 * @clock_id: Id of the clock to be disable
1127 *
1128 * This function is used by master to disable the clock
1129 * including peripherals and PLL clocks.
1130 *
Jolly Shaha9057a02019-01-02 12:54:40 -08001131 * @return: Error if an argument is not valid or status as returned by the
1132 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -08001133 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301134enum pm_ret_status pm_clock_disable(uint32_t clock_id)
Rajan Vaja35116132018-01-17 02:39:25 -08001135{
Jolly Shaha9057a02019-01-02 12:54:40 -08001136 struct pm_pll *pll;
1137
1138 /* First try to handle it as a PLL */
1139 pll = pm_clock_get_pll(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301140 if (pll) {
Jolly Shaha9057a02019-01-02 12:54:40 -08001141 return pm_clock_pll_disable(pll);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301142 }
Jolly Shaha9057a02019-01-02 12:54:40 -08001143
1144 /* It's an on-chip clock, PMU should configure clock's gate */
1145 return pm_clock_gate(clock_id, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001146}
1147
1148/**
1149 * pm_clock_getstate - Get the clock state for given id
1150 * @clock_id: Id of the clock to be queried
1151 * @state: 1/0 (Enabled/Disabled)
1152 *
1153 * This function is used by master to get the state of clock
1154 * including peripherals and PLL clocks.
1155 *
1156 * Return: Returns status, either success or error+reason.
1157 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301158enum pm_ret_status pm_clock_getstate(uint32_t clock_id,
1159 uint32_t *state)
Rajan Vaja35116132018-01-17 02:39:25 -08001160{
Jolly Shah99e8ac92019-01-02 12:55:41 -08001161 struct pm_pll *pll;
1162 uint32_t payload[PAYLOAD_ARG_CNT];
1163 enum pm_ret_status status;
1164
1165 /* First try to handle it as a PLL */
1166 pll = pm_clock_get_pll(clock_id);
1167 if (pll)
1168 return pm_clock_pll_get_state(pll, state);
1169
1170 /* Check if clock ID is a valid on-chip clock */
1171 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301172 if (status != PM_RET_SUCCESS) {
Jolly Shah99e8ac92019-01-02 12:55:41 -08001173 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301174 }
Jolly Shah99e8ac92019-01-02 12:55:41 -08001175
1176 /* Send request to the PMU */
1177 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
1178 return pm_ipi_send_sync(primary_proc, payload, state, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001179}
1180
1181/**
1182 * pm_clock_setdivider - Set the clock divider for given id
1183 * @clock_id: Id of the clock
1184 * @divider: divider value
1185 *
1186 * This function is used by master to set divider for any clock
1187 * to achieve desired rate.
1188 *
1189 * Return: Returns status, either success or error+reason.
1190 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301191enum pm_ret_status pm_clock_setdivider(uint32_t clock_id,
1192 uint32_t divider)
Rajan Vaja35116132018-01-17 02:39:25 -08001193{
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001194 enum pm_ret_status status;
1195 enum pm_node_id nid;
1196 enum pm_clock_div_id div_id;
1197 uint32_t payload[PAYLOAD_ARG_CNT];
1198 const uint32_t div0 = 0xFFFF0000;
1199 const uint32_t div1 = 0x0000FFFF;
1200 uint32_t val;
1201
1202 /* Get PLL node ID using PLL clock ID */
1203 status = pm_clock_get_pll_node_id(clock_id, &nid);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301204 if (status == PM_RET_SUCCESS) {
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001205 return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301206 }
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001207
1208 /* Check if clock ID is a valid on-chip clock */
1209 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301210 if (status != PM_RET_SUCCESS) {
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001211 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301212 }
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001213
1214 if (div0 == (divider & div0)) {
1215 div_id = PM_CLOCK_DIV0_ID;
1216 val = divider & ~div0;
1217 } else if (div1 == (divider & div1)) {
1218 div_id = PM_CLOCK_DIV1_ID;
1219 val = (divider & ~div1) >> 16;
1220 } else {
1221 return PM_RET_ERROR_ARGS;
1222 }
1223
1224 /* Send request to the PMU */
1225 PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
1226 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001227}
1228
1229/**
1230 * pm_clock_getdivider - Get the clock divider for given id
1231 * @clock_id: Id of the clock
1232 * @divider: divider value
1233 *
1234 * This function is used by master to get divider values
1235 * for any clock.
1236 *
1237 * Return: Returns status, either success or error+reason.
1238 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301239enum pm_ret_status pm_clock_getdivider(uint32_t clock_id,
1240 uint32_t *divider)
Rajan Vaja35116132018-01-17 02:39:25 -08001241{
Jolly Shah4dd11762019-01-04 11:53:37 -08001242 enum pm_ret_status status;
1243 enum pm_node_id nid;
1244 uint32_t payload[PAYLOAD_ARG_CNT];
1245 uint32_t val;
1246
1247 /* Get PLL node ID using PLL clock ID */
1248 status = pm_clock_get_pll_node_id(clock_id, &nid);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301249 if (status == PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001250 return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301251 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001252
1253 /* Check if clock ID is a valid on-chip clock */
1254 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301255 if (status != PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001256 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301257 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001258
1259 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
1260 /* Send request to the PMU to get div0 */
1261 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1262 PM_CLOCK_DIV0_ID);
1263 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301264 if (status != PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001265 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301266 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001267 *divider = val;
1268 }
1269
1270 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
1271 /* Send request to the PMU to get div1 */
1272 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1273 PM_CLOCK_DIV1_ID);
1274 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301275 if (status != PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001276 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301277 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001278 *divider |= val << 16;
1279 }
1280
1281 return status;
Rajan Vaja35116132018-01-17 02:39:25 -08001282}
1283
1284/**
1285 * pm_clock_setrate - Set the clock rate for given id
1286 * @clock_id: Id of the clock
1287 * @rate: rate value in hz
1288 *
1289 * This function is used by master to set rate for any clock.
1290 *
1291 * Return: Returns status, either success or error+reason.
1292 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301293enum pm_ret_status pm_clock_setrate(uint32_t clock_id,
Rajan Vaja35116132018-01-17 02:39:25 -08001294 uint64_t rate)
1295{
Jolly Shahc1391812019-01-02 13:39:30 -08001296 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001297}
1298
1299/**
1300 * pm_clock_getrate - Get the clock rate for given id
1301 * @clock_id: Id of the clock
1302 * @rate: rate value in hz
1303 *
1304 * This function is used by master to get rate
1305 * for any clock.
1306 *
1307 * Return: Returns status, either success or error+reason.
1308 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301309enum pm_ret_status pm_clock_getrate(uint32_t clock_id,
Rajan Vaja35116132018-01-17 02:39:25 -08001310 uint64_t *rate)
1311{
Jolly Shahc1391812019-01-02 13:39:30 -08001312 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001313}
1314
1315/**
1316 * pm_clock_setparent - Set the clock parent for given id
1317 * @clock_id: Id of the clock
Jolly Shah407fc0a2019-01-04 11:57:40 -08001318 * @parent_index: Index of the parent clock into clock's parents array
Rajan Vaja35116132018-01-17 02:39:25 -08001319 *
1320 * This function is used by master to set parent for any clock.
1321 *
1322 * Return: Returns status, either success or error+reason.
1323 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301324enum pm_ret_status pm_clock_setparent(uint32_t clock_id,
1325 uint32_t parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001326{
Jolly Shah407fc0a2019-01-04 11:57:40 -08001327 struct pm_pll *pll;
1328 uint32_t payload[PAYLOAD_ARG_CNT];
1329 enum pm_ret_status status;
1330
1331 /* First try to handle it as a PLL */
1332 pll = pm_clock_get_pll_by_related_clk(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301333 if (pll) {
Jolly Shah407fc0a2019-01-04 11:57:40 -08001334 return pm_clock_pll_set_parent(pll, clock_id, parent_index);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301335 }
Jolly Shah407fc0a2019-01-04 11:57:40 -08001336
1337 /* Check if clock ID is a valid on-chip clock */
1338 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301339 if (status != PM_RET_SUCCESS) {
Jolly Shah407fc0a2019-01-04 11:57:40 -08001340 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301341 }
Jolly Shah407fc0a2019-01-04 11:57:40 -08001342
1343 /* Send request to the PMU */
1344 PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
1345 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001346}
1347
1348/**
1349 * pm_clock_getparent - Get the clock parent for given id
1350 * @clock_id: Id of the clock
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001351 * @parent_index: parent index
Rajan Vaja35116132018-01-17 02:39:25 -08001352 *
1353 * This function is used by master to get parent index
1354 * for any clock.
1355 *
1356 * Return: Returns status, either success or error+reason.
1357 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301358enum pm_ret_status pm_clock_getparent(uint32_t clock_id,
1359 uint32_t *parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001360{
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001361 struct pm_pll *pll;
1362 uint32_t payload[PAYLOAD_ARG_CNT];
1363 enum pm_ret_status status;
1364
1365 /* First try to handle it as a PLL */
1366 pll = pm_clock_get_pll_by_related_clk(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301367 if (pll) {
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001368 return pm_clock_pll_get_parent(pll, clock_id, parent_index);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301369 }
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001370
1371 /* Check if clock ID is a valid on-chip clock */
1372 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301373 if (status != PM_RET_SUCCESS) {
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001374 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301375 }
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001376
1377 /* Send request to the PMU */
1378 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
1379 return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001380}
1381
1382/**
Rajan Vajad5dd8362018-01-30 04:16:31 -08001383 * pm_pinctrl_get_num_pins - PM call to request number of pins
1384 * @npins: Number of pins
1385 *
1386 * This function is used by master to get number of pins
1387 *
1388 * Return: Returns status, either success or error+reason.
1389 */
1390static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
1391{
1392 return pm_api_pinctrl_get_num_pins(npins);
1393}
1394
1395/**
1396 * pm_pinctrl_get_num_functions - PM call to request number of functions
1397 * @nfuncs: Number of functions
1398 *
1399 * This function is used by master to get number of functions
1400 *
1401 * Return: Returns status, either success or error+reason.
1402 */
1403static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
1404{
1405 return pm_api_pinctrl_get_num_functions(nfuncs);
1406}
1407
1408/**
1409 * pm_pinctrl_get_num_function_groups - PM call to request number of
1410 * function groups
1411 * @fid: Id of function
1412 * @ngroups: Number of function groups
1413 *
1414 * This function is used by master to get number of function groups specified
1415 * by given function Id
1416 *
1417 * Return: Returns status, either success or error+reason.
1418 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301419static enum pm_ret_status pm_pinctrl_get_num_function_groups(uint32_t fid,
Rajan Vajad5dd8362018-01-30 04:16:31 -08001420 uint32_t *ngroups)
1421{
1422 return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
1423}
1424
1425/**
1426 * pm_pinctrl_get_function_name - PM call to request function name
1427 * @fid: Id of function
1428 * @name: Name of function
1429 *
1430 * This function is used by master to get name of function specified
1431 * by given function Id
Rajan Vajad5dd8362018-01-30 04:16:31 -08001432 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301433static void pm_pinctrl_get_function_name(uint32_t fid, char *name)
Rajan Vajad5dd8362018-01-30 04:16:31 -08001434{
Rajan Vajacd825682020-11-23 21:33:39 -08001435 pm_api_pinctrl_get_function_name(fid, name);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001436}
1437
1438/**
1439 * pm_pinctrl_get_function_groups - PM call to request function groups
1440 * @fid: Id of function
1441 * @index: Index of next function groups
1442 * @groups: Function groups
1443 *
1444 * This function is used by master to get function groups specified
1445 * by given function Id. This API will return 6 function groups with
1446 * a single response. To get other function groups, master should call
1447 * same API in loop with new function groups index till error is returned.
1448 *
1449 * E.g First call should have index 0 which will return function groups
1450 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1451 * function groups 6, 7, 8, 9, 10 and 11 and so on.
1452 *
1453 * Return: Returns status, either success or error+reason.
1454 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301455static enum pm_ret_status pm_pinctrl_get_function_groups(uint32_t fid,
1456 uint32_t index,
Rajan Vajad5dd8362018-01-30 04:16:31 -08001457 uint16_t *groups)
1458{
1459 return pm_api_pinctrl_get_function_groups(fid, index, groups);
1460}
1461
1462/**
1463 * pm_pinctrl_get_pin_groups - PM call to request pin groups
1464 * @pin_id: Id of pin
1465 * @index: Index of next pin groups
1466 * @groups: pin groups
1467 *
1468 * This function is used by master to get pin groups specified
1469 * by given pin Id. This API will return 6 pin groups with
1470 * a single response. To get other pin groups, master should call
1471 * same API in loop with new pin groups index till error is returned.
1472 *
1473 * E.g First call should have index 0 which will return pin groups
1474 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1475 * pin groups 6, 7, 8, 9, 10 and 11 and so on.
1476 *
1477 * Return: Returns status, either success or error+reason.
1478 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301479static enum pm_ret_status pm_pinctrl_get_pin_groups(uint32_t pin_id,
1480 uint32_t index,
Rajan Vajad5dd8362018-01-30 04:16:31 -08001481 uint16_t *groups)
1482{
1483 return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
1484}
1485
1486/**
Rajan Vaja35116132018-01-17 02:39:25 -08001487 * pm_query_data() - PM API for querying firmware data
1488 * @arg1 Argument 1 to requested IOCTL call
1489 * @arg2 Argument 2 to requested IOCTL call
1490 * @arg3 Argument 3 to requested IOCTL call
1491 * @arg4 Argument 4 to requested IOCTL call
1492 * @data Returned output data
1493 *
1494 * This function returns requested data.
Rajan Vaja35116132018-01-17 02:39:25 -08001495 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301496void pm_query_data(enum pm_query_id qid, uint32_t arg1, uint32_t arg2,
1497 uint32_t arg3, uint32_t *data)
Rajan Vaja35116132018-01-17 02:39:25 -08001498{
Rajan Vaja35116132018-01-17 02:39:25 -08001499 switch (qid) {
1500 case PM_QID_CLOCK_GET_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001501 pm_clock_get_name(arg1, (char *)data);
Rajan Vaja35116132018-01-17 02:39:25 -08001502 break;
1503 case PM_QID_CLOCK_GET_TOPOLOGY:
Rajan Vajacd825682020-11-23 21:33:39 -08001504 data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001505 break;
1506 case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
Rajan Vajacd825682020-11-23 21:33:39 -08001507 data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
1508 &data[2]);
Rajan Vaja35116132018-01-17 02:39:25 -08001509 break;
1510 case PM_QID_CLOCK_GET_PARENTS:
Rajan Vajacd825682020-11-23 21:33:39 -08001511 data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001512 break;
1513 case PM_QID_CLOCK_GET_ATTRIBUTES:
Rajan Vajacd825682020-11-23 21:33:39 -08001514 data[0] = pm_clock_get_attributes(arg1, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001515 break;
Rajan Vajad5dd8362018-01-30 04:16:31 -08001516 case PM_QID_PINCTRL_GET_NUM_PINS:
Rajan Vajacd825682020-11-23 21:33:39 -08001517 data[0] = pm_pinctrl_get_num_pins(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001518 break;
1519 case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
Rajan Vajacd825682020-11-23 21:33:39 -08001520 data[0] = pm_pinctrl_get_num_functions(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001521 break;
1522 case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001523 data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001524 break;
1525 case PM_QID_PINCTRL_GET_FUNCTION_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001526 pm_pinctrl_get_function_name(arg1, (char *)data);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001527 break;
1528 case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001529 data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
1530 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001531 break;
1532 case PM_QID_PINCTRL_GET_PIN_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001533 data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
1534 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001535 break;
Rajan Vajada959402018-07-20 03:16:27 -07001536 case PM_QID_CLOCK_GET_NUM_CLOCKS:
Rajan Vajacd825682020-11-23 21:33:39 -08001537 data[0] = pm_clock_get_num_clocks(&data[1]);
Rajan Vajada959402018-07-20 03:16:27 -07001538 break;
Rajan Vajab34deca2019-03-20 01:13:21 +05301539
1540 case PM_QID_CLOCK_GET_MAX_DIVISOR:
Rajan Vajacd825682020-11-23 21:33:39 -08001541 data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
Rajan Vajab34deca2019-03-20 01:13:21 +05301542 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001543 default:
Rajan Vajacd825682020-11-23 21:33:39 -08001544 data[0] = PM_RET_ERROR_ARGS;
Rajan Vaja35116132018-01-17 02:39:25 -08001545 WARN("Unimplemented query service call: 0x%x\n", qid);
Venkatesh Yadav Abbarapu41886f72022-04-29 15:17:13 +05301546 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001547 }
Rajan Vaja35116132018-01-17 02:39:25 -08001548}
Siva Durga Prasad Paladuguf3994cc2018-05-01 11:12:55 +05301549
1550enum pm_ret_status pm_sha_hash(uint32_t address_high,
1551 uint32_t address_low,
1552 uint32_t size,
1553 uint32_t flags)
1554{
1555 uint32_t payload[PAYLOAD_ARG_CNT];
1556
1557 /* Send request to the PMU */
1558 PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
1559 size, flags);
1560 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1561}
1562
1563enum pm_ret_status pm_rsa_core(uint32_t address_high,
1564 uint32_t address_low,
1565 uint32_t size,
1566 uint32_t flags)
1567{
1568 uint32_t payload[PAYLOAD_ARG_CNT];
1569
1570 /* Send request to the PMU */
1571 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
1572 size, flags);
1573 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1574}
Siva Durga Prasad Paladugua4ed4b22018-04-30 20:06:58 +05301575
1576enum pm_ret_status pm_secure_image(uint32_t address_low,
1577 uint32_t address_high,
1578 uint32_t key_lo,
1579 uint32_t key_hi,
1580 uint32_t *value)
1581{
1582 uint32_t payload[PAYLOAD_ARG_CNT];
1583
1584 /* Send request to the PMU */
1585 PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
1586 key_hi, key_lo);
1587 return pm_ipi_send_sync(primary_proc, payload, value, 2);
1588}
Siva Durga Prasad Paladugu7c6516a2018-09-04 17:41:34 +05301589
1590/**
1591 * pm_fpga_read - Perform the fpga configuration readback
1592 *
1593 * @reg_numframes: Configuration register offset (or) Number of frames to read
1594 * @address_low: lower 32-bit Linear memory space address
1595 * @address_high: higher 32-bit Linear memory space address
1596 * @readback_type: Type of fpga readback operation
1597 * 0 -- Configuration Register readback
1598 * 1 -- Configuration Data readback
1599 * @value: Value to read
1600 *
1601 * This function provides access to the xilfpga library to read
1602 * the PL configuration.
1603 *
1604 * Return: Returns status, either success or error+reason.
1605 */
1606enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
1607 uint32_t address_low,
1608 uint32_t address_high,
1609 uint32_t readback_type,
1610 uint32_t *value)
1611{
1612 uint32_t payload[PAYLOAD_ARG_CNT];
1613
1614 /* Send request to the PMU */
1615 PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
1616 address_high, readback_type);
1617 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1618}
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001619
1620/*
1621 * pm_pll_set_parameter() - Set the PLL parameter value
1622 * @nid Node id of the target PLL
1623 * @param_id ID of the PLL parameter
1624 * @value Parameter value to be set
1625 *
1626 * Setting the parameter will have physical effect once the PLL mode is set to
1627 * integer or fractional.
1628 *
1629 * @return Error if an argument is not valid or status as returned by the
1630 * PM controller (PMU)
1631 */
1632enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
1633 enum pm_pll_param param_id,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301634 uint32_t value)
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001635{
1636 uint32_t payload[PAYLOAD_ARG_CNT];
1637
1638 /* Check if given node ID is a PLL node */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301639 if (nid < NODE_APLL || nid > NODE_IOPLL) {
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001640 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301641 }
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001642
1643 /* Check if parameter ID is valid and return an error if it's not */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301644 if (param_id >= PM_PLL_PARAM_MAX) {
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001645 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301646 }
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001647
1648 /* Send request to the PMU */
1649 PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
1650 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1651}
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001652
1653/**
1654 * pm_pll_get_parameter() - Get the PLL parameter value
1655 * @nid Node id of the target PLL
1656 * @param_id ID of the PLL parameter
1657 * @value Location to store the parameter value
1658 *
1659 * @return Error if an argument is not valid or status as returned by the
1660 * PM controller (PMU)
1661 */
1662enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
1663 enum pm_pll_param param_id,
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301664 uint32_t *value)
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001665{
1666 uint32_t payload[PAYLOAD_ARG_CNT];
1667
1668 /* Check if given node ID is a PLL node */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301669 if (nid < NODE_APLL || nid > NODE_IOPLL) {
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001670 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301671 }
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001672
1673 /* Check if parameter ID is valid and return an error if it's not */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301674 if (param_id >= PM_PLL_PARAM_MAX) {
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001675 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301676 }
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001677
1678 /* Send request to the PMU */
1679 PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
1680 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1681}
Jolly Shah1f0d5852019-01-04 11:32:31 -08001682
1683/**
1684 * pm_pll_set_mode() - Set the PLL mode
1685 * @nid Node id of the target PLL
1686 * @mode PLL mode to be set
1687 *
1688 * If reset mode is set the PM controller will first bypass the PLL and then
1689 * assert the reset. If integer or fractional mode is set the PM controller will
1690 * ensure that the complete PLL programming sequence is satisfied. After this
1691 * function returns success the PLL is locked and its bypass is deasserted.
1692 *
1693 * @return Error if an argument is not valid or status as returned by the
1694 * PM controller (PMU)
1695 */
1696enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
1697{
1698 uint32_t payload[PAYLOAD_ARG_CNT];
1699
1700 /* Check if given node ID is a PLL node */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301701 if (nid < NODE_APLL || nid > NODE_IOPLL) {
Jolly Shah1f0d5852019-01-04 11:32:31 -08001702 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301703 }
Jolly Shah1f0d5852019-01-04 11:32:31 -08001704
1705 /* Check if PLL mode is valid */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301706 if (mode >= PM_PLL_MODE_MAX) {
Jolly Shah1f0d5852019-01-04 11:32:31 -08001707 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301708 }
Jolly Shah1f0d5852019-01-04 11:32:31 -08001709
1710 /* Send request to the PMU */
1711 PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
1712 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1713}
Jolly Shah141421e2019-01-04 11:35:48 -08001714
1715/**
1716 * pm_pll_get_mode() - Get the PLL mode
1717 * @nid Node id of the target PLL
1718 * @mode Location to store the mode of the PLL
1719 *
1720 * @return Error if an argument is not valid or status as returned by the
1721 * PM controller (PMU)
1722 */
1723enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
1724{
1725 uint32_t payload[PAYLOAD_ARG_CNT];
1726
1727 /* Check if given node ID is a PLL node */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301728 if (nid < NODE_APLL || nid > NODE_IOPLL) {
Jolly Shah141421e2019-01-04 11:35:48 -08001729 return PM_RET_ERROR_ARGS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301730 }
Jolly Shah141421e2019-01-04 11:35:48 -08001731
1732 /* Send request to the PMU */
1733 PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
1734 return pm_ipi_send_sync(primary_proc, payload, mode, 1);
1735}
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001736
1737/**
1738 * pm_register_access() - PM API for register read/write access data
1739 *
1740 * @register_access_id Register_access_id which says register read/write
1741 *
1742 * @address Address of the register to be accessed
1743 *
1744 * @mask Mask value to be used while writing value
1745 *
1746 * @value Value to be written to register
1747 *
1748 * @out Returned output data
1749 *
1750 * This function returns requested data.
1751 *
1752 * @return Returns status, either success or error+reason
1753 */
Venkatesh Yadav Abbarapue7c45382022-05-19 14:49:49 +05301754enum pm_ret_status pm_register_access(uint32_t register_access_id,
1755 uint32_t address,
1756 uint32_t mask,
1757 uint32_t value,
1758 uint32_t *out)
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001759{
1760 enum pm_ret_status ret;
1761
1762 if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
1763 ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
1764 ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301765 ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE)) {
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001766 return PM_RET_ERROR_ACCESS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301767 }
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001768
1769 switch (register_access_id) {
1770 case CONFIG_REG_WRITE:
1771 ret = pm_mmio_write(address, mask, value);
1772 break;
1773 case CONFIG_REG_READ:
1774 ret = pm_mmio_read(address, out);
1775 break;
1776 default:
1777 ret = PM_RET_ERROR_ARGS;
1778 WARN("Unimplemented register_access call\n\r");
Venkatesh Yadav Abbarapu41886f72022-04-29 15:17:13 +05301779 break;
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001780 }
1781 return ret;
1782}
VNSL Durgadeb1a362020-11-23 04:46:04 -08001783
1784/**
1785 * pm_efuse_access() - To program or read efuse bits.
1786 *
1787 * This function provides access to the xilskey library to program/read
1788 * efuse bits.
1789 *
1790 * address_low: lower 32-bit Linear memory space address
1791 * address_high: higher 32-bit Linear memory space address
1792 *
1793 * value: Returned output value
1794 *
1795 * @return Returns status, either success or error+reason
1796 *
1797 */
1798enum pm_ret_status pm_efuse_access(uint32_t address_high,
1799 uint32_t address_low,
1800 uint32_t *value)
1801{
1802 uint32_t payload[PAYLOAD_ARG_CNT];
1803
1804 /* Send request to the PMU */
1805 PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
1806
1807 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1808}