blob: 5c4fd4042392018e24d0ac9cc2e7bfb569861a44 [file] [log] [blame]
Soren Brinkmann76fcae32016-03-06 20:16:27 -08001/*
Ronak Jain52de5942022-01-20 23:11:18 -08002 * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved.
Soren Brinkmann76fcae32016-03-06 20:16:27 -08003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soren Brinkmann76fcae32016-03-06 20:16:27 -08005 */
6
7/*
8 * ZynqMP system level PM-API functions and communication with PMU via
9 * IPI interrupts
10 */
11
12#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013#include <plat/common/platform.h>
14
Rajan Vaja35116132018-01-17 02:39:25 -080015#include "pm_api_clock.h"
Rajan Vaja5529a012018-01-17 02:39:23 -080016#include "pm_api_ioctl.h"
Rajan Vaja0ac2be12018-01-17 02:39:21 -080017#include "pm_api_pinctrl.h"
Isla Mitchelle3631462017-07-14 10:46:32 +010018#include "pm_api_sys.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080019#include "pm_client.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080020#include "pm_common.h"
Isla Mitchelle3631462017-07-14 10:46:32 +010021#include "pm_ipi.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080022
Ronak Jain325bad12021-12-21 01:39:59 -080023#define PM_QUERY_FEATURE_BITMASK ( \
24 (1ULL << (uint64_t)PM_QID_CLOCK_GET_NAME) | \
25 (1ULL << (uint64_t)PM_QID_CLOCK_GET_TOPOLOGY) | \
26 (1ULL << (uint64_t)PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS) | \
27 (1ULL << (uint64_t)PM_QID_CLOCK_GET_PARENTS) | \
28 (1ULL << (uint64_t)PM_QID_CLOCK_GET_ATTRIBUTES) | \
29 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_PINS) | \
30 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTIONS) | \
31 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS) | \
32 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_NAME) | \
33 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_FUNCTION_GROUPS) | \
34 (1ULL << (uint64_t)PM_QID_PINCTRL_GET_PIN_GROUPS) | \
35 (1ULL << (uint64_t)PM_QID_CLOCK_GET_NUM_CLOCKS) | \
36 (1ULL << (uint64_t)PM_QID_CLOCK_GET_MAX_DIVISOR))
37
38/**
39 * struct eemi_api_dependency - Dependent EEMI APIs which are implemented
40 * on both the ATF and firmware
41 *
42 * @id: EEMI API id or IOCTL id to be checked
43 * @api_id: Dependent EEMI API
44 */
45typedef struct __attribute__((packed)) {
46 uint8_t id;
47 uint8_t api_id;
48} eemi_api_dependency;
49
50/* Dependent APIs for ATF to check their version from firmware */
51static const eemi_api_dependency api_dep_table[] = {
52 {
53 .id = PM_SELF_SUSPEND,
54 .api_id = PM_SELF_SUSPEND,
55 },
56 {
57 .id = PM_REQ_WAKEUP,
58 .api_id = PM_REQ_WAKEUP,
59 },
60 {
61 .id = PM_ABORT_SUSPEND,
62 .api_id = PM_ABORT_SUSPEND,
63 },
64 {
65 .id = PM_SET_WAKEUP_SOURCE,
66 .api_id = PM_SET_WAKEUP_SOURCE,
67 },
68 {
69 .id = PM_SYSTEM_SHUTDOWN,
70 .api_id = PM_SYSTEM_SHUTDOWN,
71 },
72 {
73 .id = PM_GET_API_VERSION,
74 .api_id = PM_GET_API_VERSION,
75 },
76 {
77 .id = PM_CLOCK_ENABLE,
78 .api_id = PM_PLL_SET_MODE,
79 },
80 {
81 .id = PM_CLOCK_ENABLE,
82 .api_id = PM_CLOCK_ENABLE,
83 },
84 {
85 .id = PM_CLOCK_DISABLE,
86 .api_id = PM_PLL_SET_MODE,
87 },
88 {
89 .id = PM_CLOCK_DISABLE,
90 .api_id = PM_CLOCK_DISABLE,
91 },
92 {
93 .id = PM_CLOCK_GETSTATE,
94 .api_id = PM_PLL_GET_MODE,
95 },
96 {
97 .id = PM_CLOCK_GETSTATE,
98 .api_id = PM_CLOCK_GETSTATE,
99 },
100 {
101 .id = PM_CLOCK_SETDIVIDER,
102 .api_id = PM_PLL_SET_PARAMETER,
103 },
104 {
105 .id = PM_CLOCK_SETDIVIDER,
106 .api_id = PM_CLOCK_SETDIVIDER,
107 },
108 {
109 .id = PM_CLOCK_GETDIVIDER,
110 .api_id = PM_PLL_GET_PARAMETER,
111 },
112 {
113 .id = PM_CLOCK_GETDIVIDER,
114 .api_id = PM_CLOCK_GETDIVIDER,
115 },
116 {
117 .id = PM_CLOCK_SETPARENT,
118 .api_id = PM_PLL_SET_PARAMETER,
119 },
120 {
121 .id = PM_CLOCK_SETPARENT,
122 .api_id = PM_CLOCK_SETPARENT,
123 },
124 {
125 .id = PM_CLOCK_GETPARENT,
126 .api_id = PM_PLL_GET_PARAMETER,
127 },
128 {
129 .id = PM_CLOCK_GETPARENT,
130 .api_id = PM_CLOCK_GETPARENT,
131 },
132 {
133 .id = PM_PLL_SET_PARAMETER,
134 .api_id = PM_PLL_SET_PARAMETER,
135 },
136 {
137 .id = PM_PLL_GET_PARAMETER,
138 .api_id = PM_PLL_GET_PARAMETER,
139 },
140 {
141 .id = PM_PLL_SET_MODE,
142 .api_id = PM_PLL_SET_MODE,
143 },
144 {
145 .id = PM_PLL_GET_MODE,
146 .api_id = PM_PLL_GET_MODE,
147 },
148 {
149 .id = PM_REGISTER_ACCESS,
150 .api_id = PM_MMIO_WRITE,
151 },
152 {
153 .id = PM_REGISTER_ACCESS,
154 .api_id = PM_MMIO_READ,
155 },
156 {
157 .id = PM_FEATURE_CHECK,
158 .api_id = PM_FEATURE_CHECK,
159 },
160 {
161 .id = IOCTL_SET_TAPDELAY_BYPASS,
162 .api_id = PM_MMIO_WRITE,
163 },
164 {
165 .id = IOCTL_SET_SGMII_MODE,
166 .api_id = PM_MMIO_WRITE,
167 },
168 {
169 .id = IOCTL_SD_DLL_RESET,
170 .api_id = PM_MMIO_WRITE,
171 },
172 {
173 .id = IOCTL_SET_SD_TAPDELAY,
174 .api_id = PM_MMIO_WRITE,
175 },
176 {
177 .id = IOCTL_SET_SD_TAPDELAY,
178 .api_id = PM_MMIO_READ,
179 },
180 {
181 .id = IOCTL_SET_PLL_FRAC_DATA,
182 .api_id = PM_PLL_SET_PARAMETER,
183 },
184 {
185 .id = IOCTL_GET_PLL_FRAC_DATA,
186 .api_id = PM_PLL_GET_PARAMETER,
187 },
188 {
189 .id = IOCTL_WRITE_GGS,
190 .api_id = PM_MMIO_WRITE,
191 },
192 {
193 .id = IOCTL_READ_GGS,
194 .api_id = PM_MMIO_READ,
195 },
196 {
197 .id = IOCTL_WRITE_PGGS,
198 .api_id = PM_MMIO_WRITE,
199 },
200 {
201 .id = IOCTL_READ_PGGS,
202 .api_id = PM_MMIO_READ,
203 },
204 {
205 .id = IOCTL_ULPI_RESET,
206 .api_id = PM_MMIO_WRITE,
207 },
208 {
209 .id = IOCTL_SET_BOOT_HEALTH_STATUS,
210 .api_id = PM_MMIO_WRITE,
211 },
212 {
213 .id = IOCTL_AFI,
214 .api_id = PM_MMIO_WRITE,
215 },
216};
217
218/* Expected firmware API version to ATF */
219static const uint8_t atf_expected_ver_id[] = {
220 [PM_SELF_SUSPEND] = FW_API_BASE_VERSION,
221 [PM_REQ_WAKEUP] = FW_API_BASE_VERSION,
222 [PM_ABORT_SUSPEND] = FW_API_BASE_VERSION,
223 [PM_SET_WAKEUP_SOURCE] = FW_API_BASE_VERSION,
224 [PM_SYSTEM_SHUTDOWN] = FW_API_BASE_VERSION,
225 [PM_GET_API_VERSION] = FW_API_BASE_VERSION,
226 [PM_PLL_SET_MODE] = FW_API_BASE_VERSION,
227 [PM_PLL_GET_MODE] = FW_API_BASE_VERSION,
228 [PM_CLOCK_ENABLE] = FW_API_BASE_VERSION,
229 [PM_CLOCK_DISABLE] = FW_API_BASE_VERSION,
230 [PM_CLOCK_GETSTATE] = FW_API_BASE_VERSION,
231 [PM_PLL_SET_PARAMETER] = FW_API_BASE_VERSION,
232 [PM_PLL_GET_PARAMETER] = FW_API_BASE_VERSION,
233 [PM_CLOCK_SETDIVIDER] = FW_API_BASE_VERSION,
234 [PM_CLOCK_GETDIVIDER] = FW_API_BASE_VERSION,
235 [PM_CLOCK_SETPARENT] = FW_API_BASE_VERSION,
236 [PM_CLOCK_GETPARENT] = FW_API_BASE_VERSION,
237 [PM_MMIO_WRITE] = FW_API_BASE_VERSION,
238 [PM_MMIO_READ] = FW_API_BASE_VERSION,
239 [PM_FEATURE_CHECK] = FW_API_VERSION_2,
240};
241
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530242/* default shutdown/reboot scope is system(2) */
243static unsigned int pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
244
245/**
246 * pm_get_shutdown_scope() - Get the currently set shutdown scope
247 *
248 * @return Shutdown scope value
249 */
250unsigned int pm_get_shutdown_scope(void)
251{
252 return pm_shutdown_scope;
253}
254
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -0800255#define EM_PACK_PAYLOAD1(pl, arg0) { \
256 pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \
257}
258
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800259/**
260 * pm_self_suspend() - PM call for processor to suspend itself
261 * @nid Node id of the processor or subsystem
262 * @latency Requested maximum wakeup latency (not supported)
Filip Drazic0bd9d0c2016-07-20 17:17:39 +0200263 * @state Requested state
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800264 * @address Resume address
265 *
266 * This is a blocking call, it will return only once PMU has responded.
267 * On a wakeup, resume address will be automatically set by PMU.
268 *
269 * @return Returns status, either success or error+reason
270 */
271enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
272 unsigned int latency,
273 unsigned int state,
274 uintptr_t address)
275{
276 uint32_t payload[PAYLOAD_ARG_CNT];
277 unsigned int cpuid = plat_my_core_pos();
278 const struct pm_proc *proc = pm_get_proc(cpuid);
279
280 /*
281 * Do client specific suspend operations
282 * (e.g. set powerdown request bit)
283 */
Filip Drazic4c0765a2016-07-26 12:11:33 +0200284 pm_client_suspend(proc, state);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800285 /* Send request to the PMU */
286 PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
287 state, address, (address >> 32));
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700288 return pm_ipi_send_sync(proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800289}
290
291/**
292 * pm_req_suspend() - PM call to request for another PU or subsystem to
293 * be suspended gracefully.
294 * @target Node id of the targeted PU or subsystem
295 * @ack Flag to specify whether acknowledge is requested
296 * @latency Requested wakeup latency (not supported)
297 * @state Requested state (not supported)
298 *
299 * @return Returns status, either success or error+reason
300 */
301enum pm_ret_status pm_req_suspend(enum pm_node_id target,
302 enum pm_request_ack ack,
303 unsigned int latency, unsigned int state)
304{
305 uint32_t payload[PAYLOAD_ARG_CNT];
306
307 /* Send request to the PMU */
308 PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530309 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700310 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530311 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800312 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530313 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800314}
315
316/**
317 * pm_req_wakeup() - PM call for processor to wake up selected processor
318 * or subsystem
319 * @target Node id of the processor or subsystem to wake up
320 * @ack Flag to specify whether acknowledge requested
321 * @set_address Resume address presence indicator
322 * 1 resume address specified, 0 otherwise
323 * @address Resume address
324 *
325 * This API function is either used to power up another APU core for SMP
326 * (by PSCI) or to power up an entirely different PU or subsystem, such
327 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
328 * automatically set by PMU.
329 *
330 * @return Returns status, either success or error+reason
331 */
332enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
333 unsigned int set_address,
334 uintptr_t address,
335 enum pm_request_ack ack)
336{
337 uint32_t payload[PAYLOAD_ARG_CNT];
338 uint64_t encoded_address;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800339
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800340
341 /* encode set Address into 1st bit of address */
342 encoded_address = address;
343 encoded_address |= !!set_address;
344
345 /* Send request to the PMU to perform the wake of the PU */
346 PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
347 encoded_address >> 32, ack);
348
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530349 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700350 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530351 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800352 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530353 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800354}
355
356/**
357 * pm_force_powerdown() - PM call to request for another PU or subsystem to
358 * be powered down forcefully
359 * @target Node id of the targeted PU or subsystem
360 * @ack Flag to specify whether acknowledge is requested
361 *
362 * @return Returns status, either success or error+reason
363 */
364enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
365 enum pm_request_ack ack)
366{
367 uint32_t payload[PAYLOAD_ARG_CNT];
368
369 /* Send request to the PMU */
370 PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
371
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530372 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700373 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530374 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800375 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530376 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800377}
378
379/**
380 * pm_abort_suspend() - PM call to announce that a prior suspend request
381 * is to be aborted.
382 * @reason Reason for the abort
383 *
384 * Calling PU expects the PMU to abort the initiated suspend procedure.
385 * This is a non-blocking call without any acknowledge.
386 *
387 * @return Returns status, either success or error+reason
388 */
389enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
390{
391 uint32_t payload[PAYLOAD_ARG_CNT];
392
393 /*
394 * Do client specific abort suspend operations
395 * (e.g. enable interrupts and clear powerdown request bit)
396 */
397 pm_client_abort_suspend();
398 /* Send request to the PMU */
399 /* TODO: allow passing the node ID of the affected CPU */
400 PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
401 primary_proc->node_id);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700402 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800403}
404
405/**
406 * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
407 * @target Node id of the targeted PU or subsystem
408 * @wkup_node Node id of the wakeup peripheral
409 * @enable Enable or disable the specified peripheral as wake source
410 *
411 * @return Returns status, either success or error+reason
412 */
413enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
414 enum pm_node_id wkup_node,
415 unsigned int enable)
416{
417 uint32_t payload[PAYLOAD_ARG_CNT];
418
419 PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
420 enable);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700421 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800422}
423
424/**
425 * pm_system_shutdown() - PM call to request a system shutdown or restart
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530426 * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
427 * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800428 *
429 * @return Returns status, either success or error+reason
430 */
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700431enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800432{
433 uint32_t payload[PAYLOAD_ARG_CNT];
434
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530435 if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
436 /* Setting scope for subsequent PSCI reboot or shutdown */
437 pm_shutdown_scope = subtype;
438 return PM_RET_SUCCESS;
439 }
440
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700441 PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
Tejas Patelaf4b10e2018-02-09 02:42:59 -0800442 return pm_ipi_send_non_blocking(primary_proc, payload);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800443}
444
445/* APIs for managing PM slaves: */
446
447/**
448 * pm_req_node() - PM call to request a node with specific capabilities
449 * @nid Node id of the slave
450 * @capabilities Requested capabilities of the slave
451 * @qos Quality of service (not supported)
452 * @ack Flag to specify whether acknowledge is requested
453 *
454 * @return Returns status, either success or error+reason
455 */
456enum pm_ret_status pm_req_node(enum pm_node_id nid,
457 unsigned int capabilities,
458 unsigned int qos,
459 enum pm_request_ack ack)
460{
461 uint32_t payload[PAYLOAD_ARG_CNT];
462
463 PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
464
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530465 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700466 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530467 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800468 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530469 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800470}
471
472/**
473 * pm_set_requirement() - PM call to set requirement for PM slaves
474 * @nid Node id of the slave
475 * @capabilities Requested capabilities of the slave
476 * @qos Quality of service (not supported)
477 * @ack Flag to specify whether acknowledge is requested
478 *
479 * This API function is to be used for slaves a PU already has requested
480 *
481 * @return Returns status, either success or error+reason
482 */
483enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
484 unsigned int capabilities,
485 unsigned int qos,
486 enum pm_request_ack ack)
487{
488 uint32_t payload[PAYLOAD_ARG_CNT];
489
490 PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
491 ack);
492
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530493 if (ack == REQ_ACK_BLOCKING) {
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700494 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530495 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800496 return pm_ipi_send(primary_proc, payload);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530497 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800498}
499
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800500/* Miscellaneous API functions */
501
502/**
503 * pm_get_api_version() - Get version number of PMU PM firmware
504 * @version Returns 32-bit version number of PMU Power Management Firmware
505 *
506 * @return Returns status, either success or error+reason
507 */
508enum pm_ret_status pm_get_api_version(unsigned int *version)
509{
510 uint32_t payload[PAYLOAD_ARG_CNT];
511
512 /* Send request to the PMU */
513 PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700514 return pm_ipi_send_sync(primary_proc, payload, version, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800515}
516
517/**
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100518 * pm_get_node_status() - PM call to request a node's current status
519 * @nid Node id
520 * @ret_buff Buffer for the return values:
521 * [0] - Current power state of the node
522 * [1] - Current requirements for the node (slave nodes only)
523 * [2] - Current usage status for the node (slave nodes only)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800524 *
525 * @return Returns status, either success or error+reason
526 */
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100527enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
528 uint32_t *ret_buff)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800529{
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800530 uint32_t payload[PAYLOAD_ARG_CNT];
531
532 PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100533 return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800534}
535
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800536/**
537 * pm_mmio_write() - Perform write to protected mmio
538 * @address Address to write to
539 * @mask Mask to apply
540 * @value Value to write
541 *
542 * This function provides access to PM-related control registers
543 * that may not be directly accessible by a particular PU.
544 *
545 * @return Returns status, either success or error+reason
546 */
547enum pm_ret_status pm_mmio_write(uintptr_t address,
548 unsigned int mask,
549 unsigned int value)
550{
551 uint32_t payload[PAYLOAD_ARG_CNT];
552
553 /* Send request to the PMU */
554 PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700555 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800556}
557
558/**
559 * pm_mmio_read() - Read value from protected mmio
560 * @address Address to write to
561 * @value Value to write
562 *
563 * This function provides access to PM-related control registers
564 * that may not be directly accessible by a particular PU.
565 *
566 * @return Returns status, either success or error+reason
567 */
568enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
569{
570 uint32_t payload[PAYLOAD_ARG_CNT];
571
572 /* Send request to the PMU */
573 PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700574 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800575}
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530576
577/**
578 * pm_fpga_load() - Load the bitstream into the PL.
579 *
580 * This function provides access to the xilfpga library to load
581 * the Bit-stream into PL.
582 *
583 * address_low: lower 32-bit Linear memory space address
584 *
585 * address_high: higher 32-bit Linear memory space address
586 *
587 * size: Number of 32bit words
588 *
589 * @return Returns status, either success or error+reason
590 */
591enum pm_ret_status pm_fpga_load(uint32_t address_low,
592 uint32_t address_high,
593 uint32_t size,
594 uint32_t flags)
595{
596 uint32_t payload[PAYLOAD_ARG_CNT];
597
598 /* Send request to the PMU */
599 PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
600 size, flags);
Siva Durga Prasad Paladugubf83b9c2018-02-07 13:13:01 +0530601 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530602}
603
604/**
605 * pm_fpga_get_status() - Read value from fpga status register
606 * @value Value to read
607 *
608 * This function provides access to the xilfpga library to get
609 * the fpga status
610 * @return Returns status, either success or error+reason
611 */
612enum pm_ret_status pm_fpga_get_status(unsigned int *value)
613{
614 uint32_t payload[PAYLOAD_ARG_CNT];
615
616 /* Send request to the PMU */
617 PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700618 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530619}
Soren Brinkmanncb366812016-09-22 12:21:11 -0700620
621/**
622 * pm_get_chipid() - Read silicon ID registers
623 * @value Buffer for return values. Must be large enough
624 * to hold 8 bytes.
625 *
626 * @return Returns silicon ID registers
627 */
628enum pm_ret_status pm_get_chipid(uint32_t *value)
629{
630 uint32_t payload[PAYLOAD_ARG_CNT];
631
632 /* Send request to the PMU */
633 PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
634 return pm_ipi_send_sync(primary_proc, payload, value, 2);
635}
Soren Brinkmann84f0af42016-09-30 14:24:25 -0700636
637/**
Siva Durga Prasad Paladugude93d982018-04-30 15:49:27 +0530638 * pm_secure_rsaaes() - Load the secure images.
639 *
640 * This function provides access to the xilsecure library to load
641 * the authenticated, encrypted, and authenicated/encrypted images.
642 *
643 * address_low: lower 32-bit Linear memory space address
644 *
645 * address_high: higher 32-bit Linear memory space address
646 *
647 * size: Number of 32bit words
648 *
649 * @return Returns status, either success or error+reason
650 */
651enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
652 uint32_t address_high,
653 uint32_t size,
654 uint32_t flags)
655{
656 uint32_t payload[PAYLOAD_ARG_CNT];
657
658 /* Send request to the PMU */
659 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
660 size, flags);
661 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
662}
663
664/**
Siva Durga Prasad Paladugu8bd905b2018-09-04 18:05:50 +0530665 * pm_aes_engine() - Aes data blob encryption/decryption
666 * This function provides access to the xilsecure library to
667 * encrypt/decrypt data blobs.
668 *
669 * address_low: lower 32-bit address of the AesParams structure
670 *
671 * address_high: higher 32-bit address of the AesParams structure
672 *
673 * value: Returned output value
674 *
675 * @return Returns status, either success or error+reason
676 */
677enum pm_ret_status pm_aes_engine(uint32_t address_high,
678 uint32_t address_low,
679 uint32_t *value)
680{
681 uint32_t payload[PAYLOAD_ARG_CNT];
682
683 /* Send request to the PMU */
684 PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
685 return pm_ipi_send_sync(primary_proc, payload, value, 1);
686}
687
688/**
Rajan Vaja02d18422019-03-04 11:09:39 +0530689 * pm_get_callbackdata() - Read from IPI response buffer
690 * @data - array of PAYLOAD_ARG_CNT elements
691 *
692 * Read value from ipi buffer response buffer.
693 */
694void pm_get_callbackdata(uint32_t *data, size_t count)
695{
696 /* Return if interrupt is not from PMU */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530697 if (!pm_ipi_irq_status(primary_proc)) {
Rajan Vaja02d18422019-03-04 11:09:39 +0530698 return;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +0530699 }
Rajan Vaja02d18422019-03-04 11:09:39 +0530700
701 pm_ipi_buff_read_callb(data, count);
702 pm_ipi_irq_clear(primary_proc);
703}
704
705/**
Rajan Vaja5529a012018-01-17 02:39:23 -0800706 * pm_ioctl() - PM IOCTL API for device control and configs
707 * @node_id Node ID of the device
708 * @ioctl_id ID of the requested IOCTL
709 * @arg1 Argument 1 to requested IOCTL call
710 * @arg2 Argument 2 to requested IOCTL call
711 * @out Returned output value
712 *
713 * This function calls IOCTL to firmware for device control and configuration.
714 *
715 * @return Returns status, either success or error+reason
716 */
717enum pm_ret_status pm_ioctl(enum pm_node_id nid,
718 unsigned int ioctl_id,
719 unsigned int arg1,
720 unsigned int arg2,
721 unsigned int *value)
722{
723 return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
724}
Rajan Vaja35116132018-01-17 02:39:25 -0800725
726/**
Ronak Jain325bad12021-12-21 01:39:59 -0800727 * fw_api_version() - Returns API version implemented in firmware
728 * @api_id API ID to check
729 * @version Returned supported API version
730 * @len Number of words to be returned
731 *
732 * @return Returns status, either success or error+reason
733 */
734static enum pm_ret_status fw_api_version(uint32_t id, uint32_t *version,
735 uint32_t len)
736{
737 uint32_t payload[PAYLOAD_ARG_CNT];
738
739 PM_PACK_PAYLOAD2(payload, PM_FEATURE_CHECK, id);
740 return pm_ipi_send_sync(primary_proc, payload, version, len);
741}
742
743/**
744 * check_api_dependency() - API to check dependent EEMI API version
745 * @id EEMI API ID to check
746 *
747 * @return Returns status, either success or error+reason
748 */
749enum pm_ret_status check_api_dependency(uint8_t id)
750{
751 uint8_t i;
752 uint32_t version;
753 int ret;
754
755 for (i = 0U; i < ARRAY_SIZE(api_dep_table); i++) {
756 if (api_dep_table[i].id == id) {
757 if (api_dep_table[i].api_id == 0U) {
758 break;
759 }
760
761 ret = fw_api_version(api_dep_table[i].api_id,
762 &version, 1);
763 if (ret != PM_RET_SUCCESS) {
764 return ret;
765 }
766
767 /* Check if fw version matches ATF expected version */
768 if (version != atf_expected_ver_id[api_dep_table[i].api_id]) {
769 return PM_RET_ERROR_NOTSUPPORTED;
770 }
771 }
772 }
773
774 return PM_RET_SUCCESS;
775}
776
777/**
778 * feature_check_atf() - These are API's completely implemented in ATF
779 * @api_id API ID to check
780 * @version Returned supported API version
781 *
782 * @return Returns status, either success or error+reason
783 */
784static enum pm_ret_status feature_check_atf(uint32_t api_id, uint32_t *version,
785 uint32_t *bit_mask)
786{
787 switch (api_id) {
788 case PM_QUERY_DATA:
789 *version = ATF_API_BASE_VERSION;
790 bit_mask[0] = (uint32_t)(PM_QUERY_FEATURE_BITMASK);
791 bit_mask[1] = (uint32_t)(PM_QUERY_FEATURE_BITMASK >> 32);
792 return PM_RET_SUCCESS;
793 case PM_GET_CALLBACK_DATA:
794 case PM_GET_TRUSTZONE_VERSION:
795 case PM_SET_SUSPEND_MODE:
796 *version = ATF_API_BASE_VERSION;
797 return PM_RET_SUCCESS;
798 default:
799 return PM_RET_ERROR_NO_FEATURE;
800 }
801}
802
803/**
804 * get_atf_version_for_partial_apis() - Return ATF version for partially
805 * implemented APIs
806 * @api_id API ID to check
807 * @version Returned supported API version
808 *
809 * @return Returns status, either success or error+reason
810 */
811static enum pm_ret_status get_atf_version_for_partial_apis(uint32_t api_id,
812 uint32_t *version)
813{
814 switch (api_id) {
815 case PM_SELF_SUSPEND:
816 case PM_REQ_WAKEUP:
817 case PM_ABORT_SUSPEND:
818 case PM_SET_WAKEUP_SOURCE:
819 case PM_SYSTEM_SHUTDOWN:
820 case PM_GET_API_VERSION:
821 case PM_CLOCK_ENABLE:
822 case PM_CLOCK_DISABLE:
823 case PM_CLOCK_GETSTATE:
824 case PM_CLOCK_SETDIVIDER:
825 case PM_CLOCK_GETDIVIDER:
826 case PM_CLOCK_SETPARENT:
827 case PM_CLOCK_GETPARENT:
828 case PM_PLL_SET_PARAMETER:
829 case PM_PLL_GET_PARAMETER:
830 case PM_PLL_SET_MODE:
831 case PM_PLL_GET_MODE:
832 case PM_REGISTER_ACCESS:
833 *version = ATF_API_BASE_VERSION;
834 return PM_RET_SUCCESS;
835 case PM_FEATURE_CHECK:
836 *version = FW_API_VERSION_2;
837 return PM_RET_SUCCESS;
838 default:
839 return PM_RET_ERROR_ARGS;
840 }
841}
842
843/**
844 * feature_check_partial() - These are API's partially implemented in
845 * ATF and firmware both
846 * @api_id API ID to check
847 * @version Returned supported API version
848 *
849 * @return Returns status, either success or error+reason
850 */
851static enum pm_ret_status feature_check_partial(uint32_t api_id,
852 uint32_t *version)
853{
854 uint32_t status;
855
856 switch (api_id) {
857 case PM_SELF_SUSPEND:
858 case PM_REQ_WAKEUP:
859 case PM_ABORT_SUSPEND:
860 case PM_SET_WAKEUP_SOURCE:
861 case PM_SYSTEM_SHUTDOWN:
862 case PM_GET_API_VERSION:
863 case PM_CLOCK_ENABLE:
864 case PM_CLOCK_DISABLE:
865 case PM_CLOCK_GETSTATE:
866 case PM_CLOCK_SETDIVIDER:
867 case PM_CLOCK_GETDIVIDER:
868 case PM_CLOCK_SETPARENT:
869 case PM_CLOCK_GETPARENT:
870 case PM_PLL_SET_PARAMETER:
871 case PM_PLL_GET_PARAMETER:
872 case PM_PLL_SET_MODE:
873 case PM_PLL_GET_MODE:
874 case PM_REGISTER_ACCESS:
875 case PM_FEATURE_CHECK:
876 status = check_api_dependency(api_id);
877 if (status != PM_RET_SUCCESS) {
878 return status;
879 }
880 return get_atf_version_for_partial_apis(api_id, version);
881 default:
882 return PM_RET_ERROR_NO_FEATURE;
883 }
884}
885
886/**
887 * pm_feature_check() - Returns the supported API version if supported
888 * @api_id API ID to check
889 * @version Returned supported API version
890 * @bit_mask Returned supported IOCTL id version
891 * @len Number of bytes to be returned in bit_mask variable
892 *
893 * @return Returns status, either success or error+reason
894 */
895enum pm_ret_status pm_feature_check(uint32_t api_id, uint32_t *version,
896 uint32_t *bit_mask, uint8_t len)
897{
898 uint32_t ret_payload[PAYLOAD_ARG_CNT] = {0U};
899 uint32_t status;
900
901 /* Get API version implemented in ATF */
902 status = feature_check_atf(api_id, version, bit_mask);
903 if (status != PM_RET_ERROR_NO_FEATURE) {
904 return status;
905 }
906
907 /* Get API version implemented by firmware and ATF both */
908 status = feature_check_partial(api_id, version);
909 if (status != PM_RET_ERROR_NO_FEATURE) {
910 return status;
911 }
912
913 /* Get API version implemented by firmware */
914 status = fw_api_version(api_id, ret_payload, 3);
915 /* IOCTL call may return failure whose ID is not implemented in
916 * firmware but implemented in ATF
917 */
918 if ((api_id != PM_IOCTL) && (status != PM_RET_SUCCESS)) {
919 return status;
920 }
921
922 *version = ret_payload[0];
923
924 /* Update IOCTL bit mask which are implemented in ATF */
925 if (api_id == PM_IOCTL) {
926 if (len < 2) {
927 return PM_RET_ERROR_ARGS;
928 }
929 bit_mask[0] = ret_payload[1];
930 bit_mask[1] = ret_payload[2];
931 /* Get IOCTL's implemented by ATF */
932 status = atf_ioctl_bitmask(bit_mask);
933 } else {
934 /* Requires for MISRA */
935 }
936
937 return status;
938}
939
940/**
Rajan Vajab34deca2019-03-20 01:13:21 +0530941 * pm_clock_get_max_divisor - PM call to get max divisor
942 * @clock_id Clock ID
943 * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2)
944 * @max_div Maximum supported divisor
945 *
946 * This function is used by master to get maximum supported value.
947 *
948 * Return: Returns status, either success or error+reason.
949 */
950static enum pm_ret_status pm_clock_get_max_divisor(unsigned int clock_id,
951 uint8_t div_type,
952 uint32_t *max_div)
953{
954 return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
955}
956
957/**
Rajan Vajada959402018-07-20 03:16:27 -0700958 * pm_clock_get_num_clocks - PM call to request number of clocks
959 * @nclockss: Number of clocks
960 *
961 * This function is used by master to get number of clocks.
962 *
963 * Return: Returns status, either success or error+reason.
964 */
965static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
966{
967 return pm_api_clock_get_num_clocks(nclocks);
968}
969
970/**
Rajan Vaja35116132018-01-17 02:39:25 -0800971 * pm_clock_get_name() - PM call to request a clock's name
972 * @clock_id Clock ID
973 * @name Name of clock (max 16 bytes)
974 *
975 * This function is used by master to get nmae of clock specified
976 * by given clock ID.
Rajan Vaja35116132018-01-17 02:39:25 -0800977 */
Rajan Vajacd825682020-11-23 21:33:39 -0800978static void pm_clock_get_name(unsigned int clock_id, char *name)
Rajan Vaja35116132018-01-17 02:39:25 -0800979{
Rajan Vajacd825682020-11-23 21:33:39 -0800980 pm_api_clock_get_name(clock_id, name);
Rajan Vaja35116132018-01-17 02:39:25 -0800981}
982
983/**
984 * pm_clock_get_topology() - PM call to request a clock's topology
985 * @clock_id Clock ID
986 * @index Topology index for next toplogy node
987 * @topology Buffer to store nodes in topology and flags
988 *
989 * This function is used by master to get topology information for the
990 * clock specified by given clock ID. Each response would return 3
991 * topology nodes. To get next nodes, caller needs to call this API with
992 * index of next node. Index starts from 0.
993 *
994 * @return Returns status, either success or error+reason
995 */
996static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id,
997 unsigned int index,
998 uint32_t *topology)
999{
1000 return pm_api_clock_get_topology(clock_id, index, topology);
1001}
1002
1003/**
1004 * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
1005 * parameters for fixed clock
1006 * @clock_id Clock ID
1007 * @mul Multiplication value
1008 * @div Divisor value
1009 *
1010 * This function is used by master to get fixed factor parameers for the
1011 * fixed clock. This API is application only for the fixed clock.
1012 *
1013 * @return Returns status, either success or error+reason
1014 */
1015static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id,
1016 uint32_t *mul,
1017 uint32_t *div)
1018{
1019 return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
1020}
1021
1022/**
1023 * pm_clock_get_parents() - PM call to request a clock's first 3 parents
1024 * @clock_id Clock ID
1025 * @index Index of next parent
1026 * @parents Parents of the given clock
1027 *
1028 * This function is used by master to get clock's parents information.
1029 * This API will return 3 parents with a single response. To get other
1030 * parents, master should call same API in loop with new parent index
1031 * till error is returned.
1032 *
1033 * E.g First call should have index 0 which will return parents 0, 1 and
1034 * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
1035 * so on.
1036 *
1037 * @return Returns status, either success or error+reason
1038 */
1039static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id,
1040 unsigned int index,
1041 uint32_t *parents)
1042{
1043 return pm_api_clock_get_parents(clock_id, index, parents);
1044}
1045
1046/**
1047 * pm_clock_get_attributes() - PM call to request a clock's attributes
1048 * @clock_id Clock ID
1049 * @attr Clock attributes
1050 *
1051 * This function is used by master to get clock's attributes
1052 * (e.g. valid, clock type, etc).
1053 *
1054 * @return Returns status, either success or error+reason
1055 */
1056static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
1057 uint32_t *attr)
1058{
1059 return pm_api_clock_get_attributes(clock_id, attr);
1060}
1061
1062/**
Jolly Shaha5209802019-01-04 11:45:59 -08001063 * pm_clock_gate() - Configure clock gate
1064 * @clock_id Id of the clock to be configured
1065 * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
1066 *
1067 * @return Error if an argument is not valid or status as returned by the
1068 * PM controller (PMU)
1069 */
1070static enum pm_ret_status pm_clock_gate(unsigned int clock_id,
1071 unsigned char enable)
1072{
1073 uint32_t payload[PAYLOAD_ARG_CNT];
1074 enum pm_ret_status status;
1075 enum pm_api_id api_id;
1076
1077 /* Check if clock ID is valid and return an error if it is not */
1078 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301079 if (status != PM_RET_SUCCESS) {
Jolly Shaha5209802019-01-04 11:45:59 -08001080 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301081 }
Jolly Shaha5209802019-01-04 11:45:59 -08001082
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301083 if (enable) {
Jolly Shaha5209802019-01-04 11:45:59 -08001084 api_id = PM_CLOCK_ENABLE;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301085 } else {
Jolly Shaha5209802019-01-04 11:45:59 -08001086 api_id = PM_CLOCK_DISABLE;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301087 }
Jolly Shaha5209802019-01-04 11:45:59 -08001088
1089 /* Send request to the PMU */
1090 PM_PACK_PAYLOAD2(payload, api_id, clock_id);
Mirela Simonovic64514a72018-08-24 17:09:07 +02001091 status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1092
1093 /* If action fails due to the lack of permissions filter the error */
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301094 if (status == PM_RET_ERROR_ACCESS) {
Mirela Simonovic64514a72018-08-24 17:09:07 +02001095 status = PM_RET_SUCCESS;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301096 }
Mirela Simonovic64514a72018-08-24 17:09:07 +02001097
1098 return status;
Jolly Shaha5209802019-01-04 11:45:59 -08001099}
1100
1101/**
Rajan Vaja35116132018-01-17 02:39:25 -08001102 * pm_clock_enable() - Enable the clock for given id
1103 * @clock_id: Id of the clock to be enabled
1104 *
1105 * This function is used by master to enable the clock
1106 * including peripherals and PLL clocks.
1107 *
Jolly Shaha5209802019-01-04 11:45:59 -08001108 * @return: Error if an argument is not valid or status as returned by the
1109 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -08001110 */
Rajan Vaja35116132018-01-17 02:39:25 -08001111enum pm_ret_status pm_clock_enable(unsigned int clock_id)
1112{
Jolly Shaha5209802019-01-04 11:45:59 -08001113 struct pm_pll *pll;
1114
1115 /* First try to handle it as a PLL */
1116 pll = pm_clock_get_pll(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301117 if (pll) {
Jolly Shaha5209802019-01-04 11:45:59 -08001118 return pm_clock_pll_enable(pll);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301119 }
Jolly Shaha5209802019-01-04 11:45:59 -08001120
1121 /* It's an on-chip clock, PMU should configure clock's gate */
1122 return pm_clock_gate(clock_id, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001123}
1124
1125/**
1126 * pm_clock_disable - Disable the clock for given id
1127 * @clock_id: Id of the clock to be disable
1128 *
1129 * This function is used by master to disable the clock
1130 * including peripherals and PLL clocks.
1131 *
Jolly Shaha9057a02019-01-02 12:54:40 -08001132 * @return: Error if an argument is not valid or status as returned by the
1133 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -08001134 */
Rajan Vaja35116132018-01-17 02:39:25 -08001135enum pm_ret_status pm_clock_disable(unsigned int clock_id)
1136{
Jolly Shaha9057a02019-01-02 12:54:40 -08001137 struct pm_pll *pll;
1138
1139 /* First try to handle it as a PLL */
1140 pll = pm_clock_get_pll(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301141 if (pll) {
Jolly Shaha9057a02019-01-02 12:54:40 -08001142 return pm_clock_pll_disable(pll);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301143 }
Jolly Shaha9057a02019-01-02 12:54:40 -08001144
1145 /* It's an on-chip clock, PMU should configure clock's gate */
1146 return pm_clock_gate(clock_id, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001147}
1148
1149/**
1150 * pm_clock_getstate - Get the clock state for given id
1151 * @clock_id: Id of the clock to be queried
1152 * @state: 1/0 (Enabled/Disabled)
1153 *
1154 * This function is used by master to get the state of clock
1155 * including peripherals and PLL clocks.
1156 *
1157 * Return: Returns status, either success or error+reason.
1158 */
1159enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
1160 unsigned int *state)
1161{
Jolly Shah99e8ac92019-01-02 12:55:41 -08001162 struct pm_pll *pll;
1163 uint32_t payload[PAYLOAD_ARG_CNT];
1164 enum pm_ret_status status;
1165
1166 /* First try to handle it as a PLL */
1167 pll = pm_clock_get_pll(clock_id);
1168 if (pll)
1169 return pm_clock_pll_get_state(pll, state);
1170
1171 /* Check if clock ID is a valid on-chip clock */
1172 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301173 if (status != PM_RET_SUCCESS) {
Jolly Shah99e8ac92019-01-02 12:55:41 -08001174 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301175 }
Jolly Shah99e8ac92019-01-02 12:55:41 -08001176
1177 /* Send request to the PMU */
1178 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
1179 return pm_ipi_send_sync(primary_proc, payload, state, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001180}
1181
1182/**
1183 * pm_clock_setdivider - Set the clock divider for given id
1184 * @clock_id: Id of the clock
1185 * @divider: divider value
1186 *
1187 * This function is used by master to set divider for any clock
1188 * to achieve desired rate.
1189 *
1190 * Return: Returns status, either success or error+reason.
1191 */
1192enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
1193 unsigned int divider)
1194{
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001195 enum pm_ret_status status;
1196 enum pm_node_id nid;
1197 enum pm_clock_div_id div_id;
1198 uint32_t payload[PAYLOAD_ARG_CNT];
1199 const uint32_t div0 = 0xFFFF0000;
1200 const uint32_t div1 = 0x0000FFFF;
1201 uint32_t val;
1202
1203 /* Get PLL node ID using PLL clock ID */
1204 status = pm_clock_get_pll_node_id(clock_id, &nid);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301205 if (status == PM_RET_SUCCESS) {
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001206 return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301207 }
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001208
1209 /* Check if clock ID is a valid on-chip clock */
1210 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301211 if (status != PM_RET_SUCCESS) {
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001212 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301213 }
Jolly Shah8b4c4c72019-01-04 11:49:46 -08001214
1215 if (div0 == (divider & div0)) {
1216 div_id = PM_CLOCK_DIV0_ID;
1217 val = divider & ~div0;
1218 } else if (div1 == (divider & div1)) {
1219 div_id = PM_CLOCK_DIV1_ID;
1220 val = (divider & ~div1) >> 16;
1221 } else {
1222 return PM_RET_ERROR_ARGS;
1223 }
1224
1225 /* Send request to the PMU */
1226 PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
1227 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001228}
1229
1230/**
1231 * pm_clock_getdivider - Get the clock divider for given id
1232 * @clock_id: Id of the clock
1233 * @divider: divider value
1234 *
1235 * This function is used by master to get divider values
1236 * for any clock.
1237 *
1238 * Return: Returns status, either success or error+reason.
1239 */
1240enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
1241 unsigned int *divider)
1242{
Jolly Shah4dd11762019-01-04 11:53:37 -08001243 enum pm_ret_status status;
1244 enum pm_node_id nid;
1245 uint32_t payload[PAYLOAD_ARG_CNT];
1246 uint32_t val;
1247
1248 /* Get PLL node ID using PLL clock ID */
1249 status = pm_clock_get_pll_node_id(clock_id, &nid);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301250 if (status == PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001251 return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301252 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001253
1254 /* Check if clock ID is a valid on-chip clock */
1255 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301256 if (status != PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001257 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301258 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001259
1260 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
1261 /* Send request to the PMU to get div0 */
1262 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1263 PM_CLOCK_DIV0_ID);
1264 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301265 if (status != PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001266 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301267 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001268 *divider = val;
1269 }
1270
1271 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
1272 /* Send request to the PMU to get div1 */
1273 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1274 PM_CLOCK_DIV1_ID);
1275 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301276 if (status != PM_RET_SUCCESS) {
Jolly Shah4dd11762019-01-04 11:53:37 -08001277 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301278 }
Jolly Shah4dd11762019-01-04 11:53:37 -08001279 *divider |= val << 16;
1280 }
1281
1282 return status;
Rajan Vaja35116132018-01-17 02:39:25 -08001283}
1284
1285/**
1286 * pm_clock_setrate - Set the clock rate for given id
1287 * @clock_id: Id of the clock
1288 * @rate: rate value in hz
1289 *
1290 * This function is used by master to set rate for any clock.
1291 *
1292 * Return: Returns status, either success or error+reason.
1293 */
1294enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
1295 uint64_t rate)
1296{
Jolly Shahc1391812019-01-02 13:39:30 -08001297 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001298}
1299
1300/**
1301 * pm_clock_getrate - Get the clock rate for given id
1302 * @clock_id: Id of the clock
1303 * @rate: rate value in hz
1304 *
1305 * This function is used by master to get rate
1306 * for any clock.
1307 *
1308 * Return: Returns status, either success or error+reason.
1309 */
1310enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
1311 uint64_t *rate)
1312{
Jolly Shahc1391812019-01-02 13:39:30 -08001313 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001314}
1315
1316/**
1317 * pm_clock_setparent - Set the clock parent for given id
1318 * @clock_id: Id of the clock
Jolly Shah407fc0a2019-01-04 11:57:40 -08001319 * @parent_index: Index of the parent clock into clock's parents array
Rajan Vaja35116132018-01-17 02:39:25 -08001320 *
1321 * This function is used by master to set parent for any clock.
1322 *
1323 * Return: Returns status, either success or error+reason.
1324 */
1325enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
Jolly Shah407fc0a2019-01-04 11:57:40 -08001326 unsigned int parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001327{
Jolly Shah407fc0a2019-01-04 11:57:40 -08001328 struct pm_pll *pll;
1329 uint32_t payload[PAYLOAD_ARG_CNT];
1330 enum pm_ret_status status;
1331
1332 /* First try to handle it as a PLL */
1333 pll = pm_clock_get_pll_by_related_clk(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301334 if (pll) {
Jolly Shah407fc0a2019-01-04 11:57:40 -08001335 return pm_clock_pll_set_parent(pll, clock_id, parent_index);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301336 }
Jolly Shah407fc0a2019-01-04 11:57:40 -08001337
1338 /* Check if clock ID is a valid on-chip clock */
1339 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301340 if (status != PM_RET_SUCCESS) {
Jolly Shah407fc0a2019-01-04 11:57:40 -08001341 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301342 }
Jolly Shah407fc0a2019-01-04 11:57:40 -08001343
1344 /* Send request to the PMU */
1345 PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
1346 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001347}
1348
1349/**
1350 * pm_clock_getparent - Get the clock parent for given id
1351 * @clock_id: Id of the clock
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001352 * @parent_index: parent index
Rajan Vaja35116132018-01-17 02:39:25 -08001353 *
1354 * This function is used by master to get parent index
1355 * for any clock.
1356 *
1357 * Return: Returns status, either success or error+reason.
1358 */
1359enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001360 unsigned int *parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001361{
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001362 struct pm_pll *pll;
1363 uint32_t payload[PAYLOAD_ARG_CNT];
1364 enum pm_ret_status status;
1365
1366 /* First try to handle it as a PLL */
1367 pll = pm_clock_get_pll_by_related_clk(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301368 if (pll) {
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001369 return pm_clock_pll_get_parent(pll, clock_id, parent_index);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301370 }
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001371
1372 /* Check if clock ID is a valid on-chip clock */
1373 status = pm_clock_id_is_valid(clock_id);
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301374 if (status != PM_RET_SUCCESS) {
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001375 return status;
Venkatesh Yadav Abbarapu987fad32022-04-29 13:52:00 +05301376 }
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001377
1378 /* Send request to the PMU */
1379 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
1380 return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001381}
1382
1383/**
Rajan Vajad5dd8362018-01-30 04:16:31 -08001384 * pm_pinctrl_get_num_pins - PM call to request number of pins
1385 * @npins: Number of pins
1386 *
1387 * This function is used by master to get number of pins
1388 *
1389 * Return: Returns status, either success or error+reason.
1390 */
1391static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
1392{
1393 return pm_api_pinctrl_get_num_pins(npins);
1394}
1395
1396/**
1397 * pm_pinctrl_get_num_functions - PM call to request number of functions
1398 * @nfuncs: Number of functions
1399 *
1400 * This function is used by master to get number of functions
1401 *
1402 * Return: Returns status, either success or error+reason.
1403 */
1404static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
1405{
1406 return pm_api_pinctrl_get_num_functions(nfuncs);
1407}
1408
1409/**
1410 * pm_pinctrl_get_num_function_groups - PM call to request number of
1411 * function groups
1412 * @fid: Id of function
1413 * @ngroups: Number of function groups
1414 *
1415 * This function is used by master to get number of function groups specified
1416 * by given function Id
1417 *
1418 * Return: Returns status, either success or error+reason.
1419 */
1420static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid,
1421 uint32_t *ngroups)
1422{
1423 return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
1424}
1425
1426/**
1427 * pm_pinctrl_get_function_name - PM call to request function name
1428 * @fid: Id of function
1429 * @name: Name of function
1430 *
1431 * This function is used by master to get name of function specified
1432 * by given function Id
Rajan Vajad5dd8362018-01-30 04:16:31 -08001433 */
Rajan Vajacd825682020-11-23 21:33:39 -08001434static void pm_pinctrl_get_function_name(unsigned int fid, char *name)
Rajan Vajad5dd8362018-01-30 04:16:31 -08001435{
Rajan Vajacd825682020-11-23 21:33:39 -08001436 pm_api_pinctrl_get_function_name(fid, name);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001437}
1438
1439/**
1440 * pm_pinctrl_get_function_groups - PM call to request function groups
1441 * @fid: Id of function
1442 * @index: Index of next function groups
1443 * @groups: Function groups
1444 *
1445 * This function is used by master to get function groups specified
1446 * by given function Id. This API will return 6 function groups with
1447 * a single response. To get other function groups, master should call
1448 * same API in loop with new function groups index till error is returned.
1449 *
1450 * E.g First call should have index 0 which will return function groups
1451 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1452 * function groups 6, 7, 8, 9, 10 and 11 and so on.
1453 *
1454 * Return: Returns status, either success or error+reason.
1455 */
1456static enum pm_ret_status pm_pinctrl_get_function_groups(unsigned int fid,
1457 unsigned int index,
1458 uint16_t *groups)
1459{
1460 return pm_api_pinctrl_get_function_groups(fid, index, groups);
1461}
1462
1463/**
1464 * pm_pinctrl_get_pin_groups - PM call to request pin groups
1465 * @pin_id: Id of pin
1466 * @index: Index of next pin groups
1467 * @groups: pin groups
1468 *
1469 * This function is used by master to get pin groups specified
1470 * by given pin Id. This API will return 6 pin groups with
1471 * a single response. To get other pin groups, master should call
1472 * same API in loop with new pin groups index till error is returned.
1473 *
1474 * E.g First call should have index 0 which will return pin groups
1475 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1476 * pin groups 6, 7, 8, 9, 10 and 11 and so on.
1477 *
1478 * Return: Returns status, either success or error+reason.
1479 */
1480static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id,
1481 unsigned int index,
1482 uint16_t *groups)
1483{
1484 return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
1485}
1486
1487/**
Rajan Vaja35116132018-01-17 02:39:25 -08001488 * pm_query_data() - PM API for querying firmware data
1489 * @arg1 Argument 1 to requested IOCTL call
1490 * @arg2 Argument 2 to requested IOCTL call
1491 * @arg3 Argument 3 to requested IOCTL call
1492 * @arg4 Argument 4 to requested IOCTL call
1493 * @data Returned output data
1494 *
1495 * This function returns requested data.
Rajan Vaja35116132018-01-17 02:39:25 -08001496 */
Rajan Vajacd825682020-11-23 21:33:39 -08001497void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
1498 unsigned int arg3, unsigned int *data)
Rajan Vaja35116132018-01-17 02:39:25 -08001499{
Rajan Vaja35116132018-01-17 02:39:25 -08001500 switch (qid) {
1501 case PM_QID_CLOCK_GET_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001502 pm_clock_get_name(arg1, (char *)data);
Rajan Vaja35116132018-01-17 02:39:25 -08001503 break;
1504 case PM_QID_CLOCK_GET_TOPOLOGY:
Rajan Vajacd825682020-11-23 21:33:39 -08001505 data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001506 break;
1507 case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
Rajan Vajacd825682020-11-23 21:33:39 -08001508 data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
1509 &data[2]);
Rajan Vaja35116132018-01-17 02:39:25 -08001510 break;
1511 case PM_QID_CLOCK_GET_PARENTS:
Rajan Vajacd825682020-11-23 21:33:39 -08001512 data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001513 break;
1514 case PM_QID_CLOCK_GET_ATTRIBUTES:
Rajan Vajacd825682020-11-23 21:33:39 -08001515 data[0] = pm_clock_get_attributes(arg1, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001516 break;
Rajan Vajad5dd8362018-01-30 04:16:31 -08001517 case PM_QID_PINCTRL_GET_NUM_PINS:
Rajan Vajacd825682020-11-23 21:33:39 -08001518 data[0] = pm_pinctrl_get_num_pins(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001519 break;
1520 case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
Rajan Vajacd825682020-11-23 21:33:39 -08001521 data[0] = pm_pinctrl_get_num_functions(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001522 break;
1523 case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001524 data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001525 break;
1526 case PM_QID_PINCTRL_GET_FUNCTION_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001527 pm_pinctrl_get_function_name(arg1, (char *)data);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001528 break;
1529 case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001530 data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
1531 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001532 break;
1533 case PM_QID_PINCTRL_GET_PIN_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001534 data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
1535 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001536 break;
Rajan Vajada959402018-07-20 03:16:27 -07001537 case PM_QID_CLOCK_GET_NUM_CLOCKS:
Rajan Vajacd825682020-11-23 21:33:39 -08001538 data[0] = pm_clock_get_num_clocks(&data[1]);
Rajan Vajada959402018-07-20 03:16:27 -07001539 break;
Rajan Vajab34deca2019-03-20 01:13:21 +05301540
1541 case PM_QID_CLOCK_GET_MAX_DIVISOR:
Rajan Vajacd825682020-11-23 21:33:39 -08001542 data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
Rajan Vajab34deca2019-03-20 01:13:21 +05301543 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001544 default:
Rajan Vajacd825682020-11-23 21:33:39 -08001545 data[0] = PM_RET_ERROR_ARGS;
Rajan Vaja35116132018-01-17 02:39:25 -08001546 WARN("Unimplemented query service call: 0x%x\n", qid);
1547 }
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,
1634 unsigned int value)
1635{
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,
1664 unsigned int *value)
1665{
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 */
1754enum pm_ret_status pm_register_access(unsigned int register_access_id,
1755 unsigned int address,
1756 unsigned int mask,
1757 unsigned int value,
1758 unsigned int *out)
1759{
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");
1779 }
1780 return ret;
1781}
VNSL Durgadeb1a362020-11-23 04:46:04 -08001782
1783/**
1784 * pm_efuse_access() - To program or read efuse bits.
1785 *
1786 * This function provides access to the xilskey library to program/read
1787 * efuse bits.
1788 *
1789 * address_low: lower 32-bit Linear memory space address
1790 * address_high: higher 32-bit Linear memory space address
1791 *
1792 * value: Returned output value
1793 *
1794 * @return Returns status, either success or error+reason
1795 *
1796 */
1797enum pm_ret_status pm_efuse_access(uint32_t address_high,
1798 uint32_t address_low,
1799 uint32_t *value)
1800{
1801 uint32_t payload[PAYLOAD_ARG_CNT];
1802
1803 /* Send request to the PMU */
1804 PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
1805
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -08001806 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1807}
1808
1809enum pm_ret_status em_set_action(unsigned int *value)
1810{
1811 uint32_t payload[PAYLOAD_ARG_CNT];
1812
1813 /* Send request to the PMU */
1814 EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
1815 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1816}
1817
1818enum pm_ret_status em_remove_action(unsigned int *value)
1819{
1820 uint32_t payload[PAYLOAD_ARG_CNT];
1821
1822 /* Send request to the PMU */
1823 EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
1824 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1825}
1826
1827enum pm_ret_status em_send_errors(unsigned int *value)
1828{
1829 uint32_t payload[PAYLOAD_ARG_CNT];
1830
1831 /* Send request to the PMU */
1832 EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
VNSL Durgadeb1a362020-11-23 04:46:04 -08001833 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1834}