blob: 2aaebac8bb357830de9939f1fa6dd6ad68e7f538 [file] [log] [blame]
Soren Brinkmann76fcae32016-03-06 20:16:27 -08001/*
Rajan Vaja02d18422019-03-04 11:09:39 +05302 * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
Soren Brinkmann76fcae32016-03-06 20:16:27 -08003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Soren Brinkmann76fcae32016-03-06 20:16:27 -08005 */
6
7/*
8 * ZynqMP system level PM-API functions and communication with PMU via
9 * IPI interrupts
10 */
11
12#include <arch_helpers.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013#include <plat/common/platform.h>
14
Rajan Vaja35116132018-01-17 02:39:25 -080015#include "pm_api_clock.h"
Rajan Vaja5529a012018-01-17 02:39:23 -080016#include "pm_api_ioctl.h"
Rajan Vaja0ac2be12018-01-17 02:39:21 -080017#include "pm_api_pinctrl.h"
Isla Mitchelle3631462017-07-14 10:46:32 +010018#include "pm_api_sys.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080019#include "pm_client.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080020#include "pm_common.h"
Isla Mitchelle3631462017-07-14 10:46:32 +010021#include "pm_ipi.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080022
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +053023/* default shutdown/reboot scope is system(2) */
24static unsigned int pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM;
25
26/**
27 * pm_get_shutdown_scope() - Get the currently set shutdown scope
28 *
29 * @return Shutdown scope value
30 */
31unsigned int pm_get_shutdown_scope(void)
32{
33 return pm_shutdown_scope;
34}
35
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -080036#define EM_PACK_PAYLOAD1(pl, arg0) { \
37 pl[0] = (uint16_t)(0xE) << 16 | (uint16_t)arg0; \
38}
39
Soren Brinkmann76fcae32016-03-06 20:16:27 -080040/**
41 * pm_self_suspend() - PM call for processor to suspend itself
42 * @nid Node id of the processor or subsystem
43 * @latency Requested maximum wakeup latency (not supported)
Filip Drazic0bd9d0c2016-07-20 17:17:39 +020044 * @state Requested state
Soren Brinkmann76fcae32016-03-06 20:16:27 -080045 * @address Resume address
46 *
47 * This is a blocking call, it will return only once PMU has responded.
48 * On a wakeup, resume address will be automatically set by PMU.
49 *
50 * @return Returns status, either success or error+reason
51 */
52enum pm_ret_status pm_self_suspend(enum pm_node_id nid,
53 unsigned int latency,
54 unsigned int state,
55 uintptr_t address)
56{
57 uint32_t payload[PAYLOAD_ARG_CNT];
58 unsigned int cpuid = plat_my_core_pos();
59 const struct pm_proc *proc = pm_get_proc(cpuid);
60
61 /*
62 * Do client specific suspend operations
63 * (e.g. set powerdown request bit)
64 */
Filip Drazic4c0765a2016-07-26 12:11:33 +020065 pm_client_suspend(proc, state);
Soren Brinkmann76fcae32016-03-06 20:16:27 -080066 /* Send request to the PMU */
67 PM_PACK_PAYLOAD6(payload, PM_SELF_SUSPEND, proc->node_id, latency,
68 state, address, (address >> 32));
Soren Brinkmannd6c9e032016-09-22 11:35:47 -070069 return pm_ipi_send_sync(proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -080070}
71
72/**
73 * pm_req_suspend() - PM call to request for another PU or subsystem to
74 * be suspended gracefully.
75 * @target Node id of the targeted PU or subsystem
76 * @ack Flag to specify whether acknowledge is requested
77 * @latency Requested wakeup latency (not supported)
78 * @state Requested state (not supported)
79 *
80 * @return Returns status, either success or error+reason
81 */
82enum pm_ret_status pm_req_suspend(enum pm_node_id target,
83 enum pm_request_ack ack,
84 unsigned int latency, unsigned int state)
85{
86 uint32_t payload[PAYLOAD_ARG_CNT];
87
88 /* Send request to the PMU */
89 PM_PACK_PAYLOAD5(payload, PM_REQ_SUSPEND, target, ack, latency, state);
90 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -070091 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -080092 else
93 return pm_ipi_send(primary_proc, payload);
94}
95
96/**
97 * pm_req_wakeup() - PM call for processor to wake up selected processor
98 * or subsystem
99 * @target Node id of the processor or subsystem to wake up
100 * @ack Flag to specify whether acknowledge requested
101 * @set_address Resume address presence indicator
102 * 1 resume address specified, 0 otherwise
103 * @address Resume address
104 *
105 * This API function is either used to power up another APU core for SMP
106 * (by PSCI) or to power up an entirely different PU or subsystem, such
107 * as RPU0, RPU, or PL_CORE_xx. Resume address for the target PU will be
108 * automatically set by PMU.
109 *
110 * @return Returns status, either success or error+reason
111 */
112enum pm_ret_status pm_req_wakeup(enum pm_node_id target,
113 unsigned int set_address,
114 uintptr_t address,
115 enum pm_request_ack ack)
116{
117 uint32_t payload[PAYLOAD_ARG_CNT];
118 uint64_t encoded_address;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800119
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800120
121 /* encode set Address into 1st bit of address */
122 encoded_address = address;
123 encoded_address |= !!set_address;
124
125 /* Send request to the PMU to perform the wake of the PU */
126 PM_PACK_PAYLOAD5(payload, PM_REQ_WAKEUP, target, encoded_address,
127 encoded_address >> 32, ack);
128
129 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700130 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800131 else
132 return pm_ipi_send(primary_proc, payload);
133}
134
135/**
136 * pm_force_powerdown() - PM call to request for another PU or subsystem to
137 * be powered down forcefully
138 * @target Node id of the targeted PU or subsystem
139 * @ack Flag to specify whether acknowledge is requested
140 *
141 * @return Returns status, either success or error+reason
142 */
143enum pm_ret_status pm_force_powerdown(enum pm_node_id target,
144 enum pm_request_ack ack)
145{
146 uint32_t payload[PAYLOAD_ARG_CNT];
147
148 /* Send request to the PMU */
149 PM_PACK_PAYLOAD3(payload, PM_FORCE_POWERDOWN, target, ack);
150
151 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700152 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800153 else
154 return pm_ipi_send(primary_proc, payload);
155}
156
157/**
158 * pm_abort_suspend() - PM call to announce that a prior suspend request
159 * is to be aborted.
160 * @reason Reason for the abort
161 *
162 * Calling PU expects the PMU to abort the initiated suspend procedure.
163 * This is a non-blocking call without any acknowledge.
164 *
165 * @return Returns status, either success or error+reason
166 */
167enum pm_ret_status pm_abort_suspend(enum pm_abort_reason reason)
168{
169 uint32_t payload[PAYLOAD_ARG_CNT];
170
171 /*
172 * Do client specific abort suspend operations
173 * (e.g. enable interrupts and clear powerdown request bit)
174 */
175 pm_client_abort_suspend();
176 /* Send request to the PMU */
177 /* TODO: allow passing the node ID of the affected CPU */
178 PM_PACK_PAYLOAD3(payload, PM_ABORT_SUSPEND, reason,
179 primary_proc->node_id);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700180 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800181}
182
183/**
184 * pm_set_wakeup_source() - PM call to specify the wakeup source while suspended
185 * @target Node id of the targeted PU or subsystem
186 * @wkup_node Node id of the wakeup peripheral
187 * @enable Enable or disable the specified peripheral as wake source
188 *
189 * @return Returns status, either success or error+reason
190 */
191enum pm_ret_status pm_set_wakeup_source(enum pm_node_id target,
192 enum pm_node_id wkup_node,
193 unsigned int enable)
194{
195 uint32_t payload[PAYLOAD_ARG_CNT];
196
197 PM_PACK_PAYLOAD4(payload, PM_SET_WAKEUP_SOURCE, target, wkup_node,
198 enable);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700199 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800200}
201
202/**
203 * pm_system_shutdown() - PM call to request a system shutdown or restart
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530204 * @type Shutdown or restart? 0=shutdown, 1=restart, 2=setscope
205 * @subtype Scope: 0=APU-subsystem, 1=PS, 2=system
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800206 *
207 * @return Returns status, either success or error+reason
208 */
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700209enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800210{
211 uint32_t payload[PAYLOAD_ARG_CNT];
212
Siva Durga Prasad Paladugu1f80d3f2018-04-30 15:56:10 +0530213 if (type == PMF_SHUTDOWN_TYPE_SETSCOPE_ONLY) {
214 /* Setting scope for subsequent PSCI reboot or shutdown */
215 pm_shutdown_scope = subtype;
216 return PM_RET_SUCCESS;
217 }
218
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700219 PM_PACK_PAYLOAD3(payload, PM_SYSTEM_SHUTDOWN, type, subtype);
Tejas Patelaf4b10e2018-02-09 02:42:59 -0800220 return pm_ipi_send_non_blocking(primary_proc, payload);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800221}
222
223/* APIs for managing PM slaves: */
224
225/**
226 * pm_req_node() - PM call to request a node with specific capabilities
227 * @nid Node id of the slave
228 * @capabilities Requested capabilities of the slave
229 * @qos Quality of service (not supported)
230 * @ack Flag to specify whether acknowledge is requested
231 *
232 * @return Returns status, either success or error+reason
233 */
234enum pm_ret_status pm_req_node(enum pm_node_id nid,
235 unsigned int capabilities,
236 unsigned int qos,
237 enum pm_request_ack ack)
238{
239 uint32_t payload[PAYLOAD_ARG_CNT];
240
241 PM_PACK_PAYLOAD5(payload, PM_REQ_NODE, nid, capabilities, qos, ack);
242
243 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700244 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800245 else
246 return pm_ipi_send(primary_proc, payload);
247}
248
249/**
250 * pm_set_requirement() - PM call to set requirement for PM slaves
251 * @nid Node id of the slave
252 * @capabilities Requested capabilities of the slave
253 * @qos Quality of service (not supported)
254 * @ack Flag to specify whether acknowledge is requested
255 *
256 * This API function is to be used for slaves a PU already has requested
257 *
258 * @return Returns status, either success or error+reason
259 */
260enum pm_ret_status pm_set_requirement(enum pm_node_id nid,
261 unsigned int capabilities,
262 unsigned int qos,
263 enum pm_request_ack ack)
264{
265 uint32_t payload[PAYLOAD_ARG_CNT];
266
267 PM_PACK_PAYLOAD5(payload, PM_SET_REQUIREMENT, nid, capabilities, qos,
268 ack);
269
270 if (ack == REQ_ACK_BLOCKING)
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700271 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800272 else
273 return pm_ipi_send(primary_proc, payload);
274}
275
276/**
277 * pm_release_node() - PM call to release a node
278 * @nid Node id of the slave
279 *
280 * @return Returns status, either success or error+reason
281 */
282enum pm_ret_status pm_release_node(enum pm_node_id nid)
283{
284 uint32_t payload[PAYLOAD_ARG_CNT];
285
286 PM_PACK_PAYLOAD2(payload, PM_RELEASE_NODE, nid);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700287 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800288}
289
290/**
291 * pm_set_max_latency() - PM call to set wakeup latency requirements
292 * @nid Node id of the slave
293 * @latency Requested maximum wakeup latency
294 *
295 * @return Returns status, either success or error+reason
296 */
297enum pm_ret_status pm_set_max_latency(enum pm_node_id nid,
298 unsigned int latency)
299{
300 uint32_t payload[PAYLOAD_ARG_CNT];
301
302 PM_PACK_PAYLOAD3(payload, PM_SET_MAX_LATENCY, nid, latency);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700303 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800304}
305
306/* Miscellaneous API functions */
307
308/**
309 * pm_get_api_version() - Get version number of PMU PM firmware
310 * @version Returns 32-bit version number of PMU Power Management Firmware
311 *
312 * @return Returns status, either success or error+reason
313 */
314enum pm_ret_status pm_get_api_version(unsigned int *version)
315{
316 uint32_t payload[PAYLOAD_ARG_CNT];
317
318 /* Send request to the PMU */
319 PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700320 return pm_ipi_send_sync(primary_proc, payload, version, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800321}
322
323/**
324 * pm_set_configuration() - PM call to set system configuration
325 * @phys_addr Physical 32-bit address of data structure in memory
326 *
327 * @return Returns status, either success or error+reason
328 */
329enum pm_ret_status pm_set_configuration(unsigned int phys_addr)
330{
Luca Ceresolif00986c2019-02-28 22:15:35 +0100331 uint32_t payload[PAYLOAD_ARG_CNT];
332
333 PM_PACK_PAYLOAD2(payload, PM_SET_CONFIGURATION, phys_addr);
334 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800335}
336
337/**
Filip Drazicf2ddd912017-03-15 11:50:47 +0100338 * pm_init_finalize() - Call to notify PMU firmware that master has power
339 * management enabled and that it has finished its
340 * initialization
341 *
342 * @return Status returned by the PMU firmware
343 */
344enum pm_ret_status pm_init_finalize(void)
345{
346 uint32_t payload[PAYLOAD_ARG_CNT];
347
348 /* Send request to the PMU */
349 PM_PACK_PAYLOAD1(payload, PM_INIT_FINALIZE);
350 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
351}
352
353/**
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100354 * pm_get_node_status() - PM call to request a node's current status
355 * @nid Node id
356 * @ret_buff Buffer for the return values:
357 * [0] - Current power state of the node
358 * [1] - Current requirements for the node (slave nodes only)
359 * [2] - Current usage status for the node (slave nodes only)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800360 *
361 * @return Returns status, either success or error+reason
362 */
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100363enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
364 uint32_t *ret_buff)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800365{
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800366 uint32_t payload[PAYLOAD_ARG_CNT];
367
368 PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100369 return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800370}
371
372/**
373 * pm_register_notifier() - Register the PU to be notified of PM events
374 * @nid Node id of the slave
375 * @event The event to be notified about
376 * @wake Wake up on event
377 * @enable Enable or disable the notifier
378 *
379 * @return Returns status, either success or error+reason
380 */
381enum pm_ret_status pm_register_notifier(enum pm_node_id nid,
382 unsigned int event,
383 unsigned int wake,
384 unsigned int enable)
385{
Anes Hadziahmetagicc95ae092016-05-12 16:17:34 +0200386 uint32_t payload[PAYLOAD_ARG_CNT];
387
388 PM_PACK_PAYLOAD5(payload, PM_REGISTER_NOTIFIER,
389 nid, event, wake, enable);
390
Soren Brinkmanna1b0a902016-09-30 11:30:21 -0700391 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800392}
393
394/**
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200395 * pm_get_op_characteristic() - PM call to request operating characteristics
396 * of a node
397 * @nid Node id of the slave
398 * @type Type of the operating characteristic
399 * (power, temperature and latency)
400 * @result Returns the operating characteristic for the requested node,
401 * specified by the type
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800402 *
403 * @return Returns status, either success or error+reason
404 */
405enum pm_ret_status pm_get_op_characteristic(enum pm_node_id nid,
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200406 enum pm_opchar_type type,
407 uint32_t *result)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800408{
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200409 uint32_t payload[PAYLOAD_ARG_CNT];
410
411 /* Send request to the PMU */
412 PM_PACK_PAYLOAD3(payload, PM_GET_OP_CHARACTERISTIC, nid, type);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700413 return pm_ipi_send_sync(primary_proc, payload, result, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800414}
415
416/* Direct-Control API functions */
417
418/**
419 * pm_reset_assert() - Assert reset
420 * @reset Reset ID
421 * @assert Assert (1) or de-assert (0)
422 *
423 * @return Returns status, either success or error+reason
424 */
425enum pm_ret_status pm_reset_assert(unsigned int reset,
426 unsigned int assert)
427{
428 uint32_t payload[PAYLOAD_ARG_CNT];
429
430 /* Send request to the PMU */
431 PM_PACK_PAYLOAD3(payload, PM_RESET_ASSERT, reset, assert);
Abhyuday Godhasara0d9b7652021-06-24 05:49:04 -0700432 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800433}
434
435/**
436 * pm_reset_get_status() - Get current status of a reset line
437 * @reset Reset ID
438 * @reset_status Returns current status of selected reset line
439 *
440 * @return Returns status, either success or error+reason
441 */
442enum pm_ret_status pm_reset_get_status(unsigned int reset,
443 unsigned int *reset_status)
444{
445 uint32_t payload[PAYLOAD_ARG_CNT];
446
447 /* Send request to the PMU */
448 PM_PACK_PAYLOAD2(payload, PM_RESET_GET_STATUS, reset);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700449 return pm_ipi_send_sync(primary_proc, payload, reset_status, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800450}
451
452/**
453 * pm_mmio_write() - Perform write to protected mmio
454 * @address Address to write to
455 * @mask Mask to apply
456 * @value Value to write
457 *
458 * This function provides access to PM-related control registers
459 * that may not be directly accessible by a particular PU.
460 *
461 * @return Returns status, either success or error+reason
462 */
463enum pm_ret_status pm_mmio_write(uintptr_t address,
464 unsigned int mask,
465 unsigned int value)
466{
467 uint32_t payload[PAYLOAD_ARG_CNT];
468
469 /* Send request to the PMU */
470 PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700471 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800472}
473
474/**
475 * pm_mmio_read() - Read value from protected mmio
476 * @address Address to write to
477 * @value Value to write
478 *
479 * This function provides access to PM-related control registers
480 * that may not be directly accessible by a particular PU.
481 *
482 * @return Returns status, either success or error+reason
483 */
484enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
485{
486 uint32_t payload[PAYLOAD_ARG_CNT];
487
488 /* Send request to the PMU */
489 PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700490 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800491}
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530492
493/**
494 * pm_fpga_load() - Load the bitstream into the PL.
495 *
496 * This function provides access to the xilfpga library to load
497 * the Bit-stream into PL.
498 *
499 * address_low: lower 32-bit Linear memory space address
500 *
501 * address_high: higher 32-bit Linear memory space address
502 *
503 * size: Number of 32bit words
504 *
505 * @return Returns status, either success or error+reason
506 */
507enum pm_ret_status pm_fpga_load(uint32_t address_low,
508 uint32_t address_high,
509 uint32_t size,
510 uint32_t flags)
511{
512 uint32_t payload[PAYLOAD_ARG_CNT];
513
514 /* Send request to the PMU */
515 PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
516 size, flags);
Siva Durga Prasad Paladugubf83b9c2018-02-07 13:13:01 +0530517 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530518}
519
520/**
521 * pm_fpga_get_status() - Read value from fpga status register
522 * @value Value to read
523 *
524 * This function provides access to the xilfpga library to get
525 * the fpga status
526 * @return Returns status, either success or error+reason
527 */
528enum pm_ret_status pm_fpga_get_status(unsigned int *value)
529{
530 uint32_t payload[PAYLOAD_ARG_CNT];
531
532 /* Send request to the PMU */
533 PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700534 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530535}
Soren Brinkmanncb366812016-09-22 12:21:11 -0700536
537/**
538 * pm_get_chipid() - Read silicon ID registers
539 * @value Buffer for return values. Must be large enough
540 * to hold 8 bytes.
541 *
542 * @return Returns silicon ID registers
543 */
544enum pm_ret_status pm_get_chipid(uint32_t *value)
545{
546 uint32_t payload[PAYLOAD_ARG_CNT];
547
548 /* Send request to the PMU */
549 PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
550 return pm_ipi_send_sync(primary_proc, payload, value, 2);
551}
Soren Brinkmann84f0af42016-09-30 14:24:25 -0700552
553/**
Siva Durga Prasad Paladugude93d982018-04-30 15:49:27 +0530554 * pm_secure_rsaaes() - Load the secure images.
555 *
556 * This function provides access to the xilsecure library to load
557 * the authenticated, encrypted, and authenicated/encrypted images.
558 *
559 * address_low: lower 32-bit Linear memory space address
560 *
561 * address_high: higher 32-bit Linear memory space address
562 *
563 * size: Number of 32bit words
564 *
565 * @return Returns status, either success or error+reason
566 */
567enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
568 uint32_t address_high,
569 uint32_t size,
570 uint32_t flags)
571{
572 uint32_t payload[PAYLOAD_ARG_CNT];
573
574 /* Send request to the PMU */
575 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
576 size, flags);
577 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
578}
579
580/**
Siva Durga Prasad Paladugu8bd905b2018-09-04 18:05:50 +0530581 * pm_aes_engine() - Aes data blob encryption/decryption
582 * This function provides access to the xilsecure library to
583 * encrypt/decrypt data blobs.
584 *
585 * address_low: lower 32-bit address of the AesParams structure
586 *
587 * address_high: higher 32-bit address of the AesParams structure
588 *
589 * value: Returned output value
590 *
591 * @return Returns status, either success or error+reason
592 */
593enum pm_ret_status pm_aes_engine(uint32_t address_high,
594 uint32_t address_low,
595 uint32_t *value)
596{
597 uint32_t payload[PAYLOAD_ARG_CNT];
598
599 /* Send request to the PMU */
600 PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
601 return pm_ipi_send_sync(primary_proc, payload, value, 1);
602}
603
604/**
Rajan Vaja02d18422019-03-04 11:09:39 +0530605 * pm_get_callbackdata() - Read from IPI response buffer
606 * @data - array of PAYLOAD_ARG_CNT elements
607 *
608 * Read value from ipi buffer response buffer.
609 */
610void pm_get_callbackdata(uint32_t *data, size_t count)
611{
612 /* Return if interrupt is not from PMU */
613 if (!pm_ipi_irq_status(primary_proc))
614 return;
615
616 pm_ipi_buff_read_callb(data, count);
617 pm_ipi_irq_clear(primary_proc);
618}
619
620/**
Rajan Vaja83687612018-01-17 02:39:20 -0800621 * pm_pinctrl_request() - Request Pin from firmware
622 * @pin Pin number to request
623 *
624 * This function requests pin from firmware.
625 *
626 * @return Returns status, either success or error+reason.
627 */
628enum pm_ret_status pm_pinctrl_request(unsigned int pin)
629{
Mirela Simonovicedefb042018-09-13 12:49:45 +0200630 uint32_t payload[PAYLOAD_ARG_CNT];
631
632 /* Send request to the PMU */
633 PM_PACK_PAYLOAD2(payload, PM_PINCTRL_REQUEST, pin);
634 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800635}
636
637/**
638 * pm_pinctrl_release() - Release Pin from firmware
639 * @pin Pin number to release
640 *
641 * This function releases pin from firmware.
642 *
643 * @return Returns status, either success or error+reason.
644 */
645enum pm_ret_status pm_pinctrl_release(unsigned int pin)
646{
Mirela Simonovicedefb042018-09-13 12:49:45 +0200647 uint32_t payload[PAYLOAD_ARG_CNT];
648
649 /* Send request to the PMU */
650 PM_PACK_PAYLOAD2(payload, PM_PINCTRL_RELEASE, pin);
651 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800652}
653
654/**
655 * pm_pinctrl_get_function() - Read function id set for the given pin
656 * @pin Pin number
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200657 * @fid ID of function currently set for given pin
Rajan Vaja83687612018-01-17 02:39:20 -0800658 *
659 * This function provides the function currently set for the given pin.
660 *
661 * @return Returns status, either success or error+reason
662 */
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200663enum pm_ret_status pm_pinctrl_get_function(unsigned int pin, unsigned int *fid)
Rajan Vaja83687612018-01-17 02:39:20 -0800664{
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200665 uint32_t payload[PAYLOAD_ARG_CNT];
666
667 PM_PACK_PAYLOAD2(payload, PM_PINCTRL_GET_FUNCTION, pin);
668 return pm_ipi_send_sync(primary_proc, payload, fid, 1);
Rajan Vaja83687612018-01-17 02:39:20 -0800669}
670
671/**
672 * pm_pinctrl_set_function() - Set function id set for the given pin
673 * @pin Pin number
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200674 * @fid ID of function to set for given pin
Rajan Vaja83687612018-01-17 02:39:20 -0800675 *
676 * @return Returns status, either success or error+reason
677 */
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200678enum pm_ret_status pm_pinctrl_set_function(unsigned int pin, unsigned int fid)
Rajan Vaja83687612018-01-17 02:39:20 -0800679{
Mirela Simonovic0304fa52018-09-13 12:49:46 +0200680 uint32_t payload[PAYLOAD_ARG_CNT];
681
682 /* Send request to the PMU */
683 PM_PACK_PAYLOAD3(payload, PM_PINCTRL_SET_FUNCTION, pin, fid);
684 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800685}
686
687/**
688 * pm_pinctrl_get_config() - Read value of requested config param for given pin
689 * @pin Pin number
690 * @param Parameter values to be read
691 * @value Buffer for configuration Parameter value
692 *
693 * This function provides the configuration parameter value for the given pin.
694 *
695 * @return Returns status, either success or error+reason
696 */
697enum pm_ret_status pm_pinctrl_get_config(unsigned int pin,
698 unsigned int param,
699 unsigned int *value)
700{
Mirela Simonovic4dadd9c2020-11-22 23:31:14 -0800701 uint32_t payload[PAYLOAD_ARG_CNT];
702
703 PM_PACK_PAYLOAD3(payload, PM_PINCTRL_CONFIG_PARAM_GET, pin, param);
704 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Rajan Vaja83687612018-01-17 02:39:20 -0800705}
706
707/**
Mirela Simonovic4dadd9c2020-11-22 23:31:14 -0800708 * pm_pinctrl_set_config() - Set value of requested config param for given pin
Rajan Vaja83687612018-01-17 02:39:20 -0800709 * @pin Pin number
710 * @param Parameter to set
711 * @value Parameter value to set
712 *
Rajan Vaja83687612018-01-17 02:39:20 -0800713 * @return Returns status, either success or error+reason
714 */
715enum pm_ret_status pm_pinctrl_set_config(unsigned int pin,
716 unsigned int param,
717 unsigned int value)
718{
Mirela Simonovic4dadd9c2020-11-22 23:31:14 -0800719 uint32_t payload[PAYLOAD_ARG_CNT];
720
721 /* Send request to the PMU */
722 PM_PACK_PAYLOAD4(payload, PM_PINCTRL_CONFIG_PARAM_SET, pin, param,
723 value);
724 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja83687612018-01-17 02:39:20 -0800725}
Rajan Vaja5529a012018-01-17 02:39:23 -0800726
727/**
728 * pm_ioctl() - PM IOCTL API for device control and configs
729 * @node_id Node ID of the device
730 * @ioctl_id ID of the requested IOCTL
731 * @arg1 Argument 1 to requested IOCTL call
732 * @arg2 Argument 2 to requested IOCTL call
733 * @out Returned output value
734 *
735 * This function calls IOCTL to firmware for device control and configuration.
736 *
737 * @return Returns status, either success or error+reason
738 */
739enum pm_ret_status pm_ioctl(enum pm_node_id nid,
740 unsigned int ioctl_id,
741 unsigned int arg1,
742 unsigned int arg2,
743 unsigned int *value)
744{
745 return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
746}
Rajan Vaja35116132018-01-17 02:39:25 -0800747
748/**
Rajan Vajab34deca2019-03-20 01:13:21 +0530749 * pm_clock_get_max_divisor - PM call to get max divisor
750 * @clock_id Clock ID
751 * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2)
752 * @max_div Maximum supported divisor
753 *
754 * This function is used by master to get maximum supported value.
755 *
756 * Return: Returns status, either success or error+reason.
757 */
758static enum pm_ret_status pm_clock_get_max_divisor(unsigned int clock_id,
759 uint8_t div_type,
760 uint32_t *max_div)
761{
762 return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
763}
764
765/**
Rajan Vajada959402018-07-20 03:16:27 -0700766 * pm_clock_get_num_clocks - PM call to request number of clocks
767 * @nclockss: Number of clocks
768 *
769 * This function is used by master to get number of clocks.
770 *
771 * Return: Returns status, either success or error+reason.
772 */
773static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
774{
775 return pm_api_clock_get_num_clocks(nclocks);
776}
777
778/**
Rajan Vaja35116132018-01-17 02:39:25 -0800779 * pm_clock_get_name() - PM call to request a clock's name
780 * @clock_id Clock ID
781 * @name Name of clock (max 16 bytes)
782 *
783 * This function is used by master to get nmae of clock specified
784 * by given clock ID.
Rajan Vaja35116132018-01-17 02:39:25 -0800785 */
Rajan Vajacd825682020-11-23 21:33:39 -0800786static void pm_clock_get_name(unsigned int clock_id, char *name)
Rajan Vaja35116132018-01-17 02:39:25 -0800787{
Rajan Vajacd825682020-11-23 21:33:39 -0800788 pm_api_clock_get_name(clock_id, name);
Rajan Vaja35116132018-01-17 02:39:25 -0800789}
790
791/**
792 * pm_clock_get_topology() - PM call to request a clock's topology
793 * @clock_id Clock ID
794 * @index Topology index for next toplogy node
795 * @topology Buffer to store nodes in topology and flags
796 *
797 * This function is used by master to get topology information for the
798 * clock specified by given clock ID. Each response would return 3
799 * topology nodes. To get next nodes, caller needs to call this API with
800 * index of next node. Index starts from 0.
801 *
802 * @return Returns status, either success or error+reason
803 */
804static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id,
805 unsigned int index,
806 uint32_t *topology)
807{
808 return pm_api_clock_get_topology(clock_id, index, topology);
809}
810
811/**
812 * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
813 * parameters for fixed clock
814 * @clock_id Clock ID
815 * @mul Multiplication value
816 * @div Divisor value
817 *
818 * This function is used by master to get fixed factor parameers for the
819 * fixed clock. This API is application only for the fixed clock.
820 *
821 * @return Returns status, either success or error+reason
822 */
823static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id,
824 uint32_t *mul,
825 uint32_t *div)
826{
827 return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
828}
829
830/**
831 * pm_clock_get_parents() - PM call to request a clock's first 3 parents
832 * @clock_id Clock ID
833 * @index Index of next parent
834 * @parents Parents of the given clock
835 *
836 * This function is used by master to get clock's parents information.
837 * This API will return 3 parents with a single response. To get other
838 * parents, master should call same API in loop with new parent index
839 * till error is returned.
840 *
841 * E.g First call should have index 0 which will return parents 0, 1 and
842 * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
843 * so on.
844 *
845 * @return Returns status, either success or error+reason
846 */
847static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id,
848 unsigned int index,
849 uint32_t *parents)
850{
851 return pm_api_clock_get_parents(clock_id, index, parents);
852}
853
854/**
855 * pm_clock_get_attributes() - PM call to request a clock's attributes
856 * @clock_id Clock ID
857 * @attr Clock attributes
858 *
859 * This function is used by master to get clock's attributes
860 * (e.g. valid, clock type, etc).
861 *
862 * @return Returns status, either success or error+reason
863 */
864static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
865 uint32_t *attr)
866{
867 return pm_api_clock_get_attributes(clock_id, attr);
868}
869
870/**
Jolly Shaha5209802019-01-04 11:45:59 -0800871 * pm_clock_gate() - Configure clock gate
872 * @clock_id Id of the clock to be configured
873 * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
874 *
875 * @return Error if an argument is not valid or status as returned by the
876 * PM controller (PMU)
877 */
878static enum pm_ret_status pm_clock_gate(unsigned int clock_id,
879 unsigned char enable)
880{
881 uint32_t payload[PAYLOAD_ARG_CNT];
882 enum pm_ret_status status;
883 enum pm_api_id api_id;
884
885 /* Check if clock ID is valid and return an error if it is not */
886 status = pm_clock_id_is_valid(clock_id);
887 if (status != PM_RET_SUCCESS)
888 return status;
889
890 if (enable)
891 api_id = PM_CLOCK_ENABLE;
892 else
893 api_id = PM_CLOCK_DISABLE;
894
895 /* Send request to the PMU */
896 PM_PACK_PAYLOAD2(payload, api_id, clock_id);
Mirela Simonovic64514a72018-08-24 17:09:07 +0200897 status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
898
899 /* If action fails due to the lack of permissions filter the error */
900 if (status == PM_RET_ERROR_ACCESS)
901 status = PM_RET_SUCCESS;
902
903 return status;
Jolly Shaha5209802019-01-04 11:45:59 -0800904}
905
906/**
Rajan Vaja35116132018-01-17 02:39:25 -0800907 * pm_clock_enable() - Enable the clock for given id
908 * @clock_id: Id of the clock to be enabled
909 *
910 * This function is used by master to enable the clock
911 * including peripherals and PLL clocks.
912 *
Jolly Shaha5209802019-01-04 11:45:59 -0800913 * @return: Error if an argument is not valid or status as returned by the
914 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -0800915 */
Rajan Vaja35116132018-01-17 02:39:25 -0800916enum pm_ret_status pm_clock_enable(unsigned int clock_id)
917{
Jolly Shaha5209802019-01-04 11:45:59 -0800918 struct pm_pll *pll;
919
920 /* First try to handle it as a PLL */
921 pll = pm_clock_get_pll(clock_id);
922 if (pll)
923 return pm_clock_pll_enable(pll);
924
925 /* It's an on-chip clock, PMU should configure clock's gate */
926 return pm_clock_gate(clock_id, 1);
Rajan Vaja35116132018-01-17 02:39:25 -0800927}
928
929/**
930 * pm_clock_disable - Disable the clock for given id
931 * @clock_id: Id of the clock to be disable
932 *
933 * This function is used by master to disable the clock
934 * including peripherals and PLL clocks.
935 *
Jolly Shaha9057a02019-01-02 12:54:40 -0800936 * @return: Error if an argument is not valid or status as returned by the
937 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -0800938 */
Rajan Vaja35116132018-01-17 02:39:25 -0800939enum pm_ret_status pm_clock_disable(unsigned int clock_id)
940{
Jolly Shaha9057a02019-01-02 12:54:40 -0800941 struct pm_pll *pll;
942
943 /* First try to handle it as a PLL */
944 pll = pm_clock_get_pll(clock_id);
945 if (pll)
946 return pm_clock_pll_disable(pll);
947
948 /* It's an on-chip clock, PMU should configure clock's gate */
949 return pm_clock_gate(clock_id, 0);
Rajan Vaja35116132018-01-17 02:39:25 -0800950}
951
952/**
953 * pm_clock_getstate - Get the clock state for given id
954 * @clock_id: Id of the clock to be queried
955 * @state: 1/0 (Enabled/Disabled)
956 *
957 * This function is used by master to get the state of clock
958 * including peripherals and PLL clocks.
959 *
960 * Return: Returns status, either success or error+reason.
961 */
962enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
963 unsigned int *state)
964{
Jolly Shah99e8ac92019-01-02 12:55:41 -0800965 struct pm_pll *pll;
966 uint32_t payload[PAYLOAD_ARG_CNT];
967 enum pm_ret_status status;
968
969 /* First try to handle it as a PLL */
970 pll = pm_clock_get_pll(clock_id);
971 if (pll)
972 return pm_clock_pll_get_state(pll, state);
973
974 /* Check if clock ID is a valid on-chip clock */
975 status = pm_clock_id_is_valid(clock_id);
976 if (status != PM_RET_SUCCESS)
977 return status;
978
979 /* Send request to the PMU */
980 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
981 return pm_ipi_send_sync(primary_proc, payload, state, 1);
Rajan Vaja35116132018-01-17 02:39:25 -0800982}
983
984/**
985 * pm_clock_setdivider - Set the clock divider for given id
986 * @clock_id: Id of the clock
987 * @divider: divider value
988 *
989 * This function is used by master to set divider for any clock
990 * to achieve desired rate.
991 *
992 * Return: Returns status, either success or error+reason.
993 */
994enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
995 unsigned int divider)
996{
Jolly Shah8b4c4c72019-01-04 11:49:46 -0800997 enum pm_ret_status status;
998 enum pm_node_id nid;
999 enum pm_clock_div_id div_id;
1000 uint32_t payload[PAYLOAD_ARG_CNT];
1001 const uint32_t div0 = 0xFFFF0000;
1002 const uint32_t div1 = 0x0000FFFF;
1003 uint32_t val;
1004
1005 /* Get PLL node ID using PLL clock ID */
1006 status = pm_clock_get_pll_node_id(clock_id, &nid);
1007 if (status == PM_RET_SUCCESS)
1008 return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1009
1010 /* Check if clock ID is a valid on-chip clock */
1011 status = pm_clock_id_is_valid(clock_id);
1012 if (status != PM_RET_SUCCESS)
1013 return status;
1014
1015 if (div0 == (divider & div0)) {
1016 div_id = PM_CLOCK_DIV0_ID;
1017 val = divider & ~div0;
1018 } else if (div1 == (divider & div1)) {
1019 div_id = PM_CLOCK_DIV1_ID;
1020 val = (divider & ~div1) >> 16;
1021 } else {
1022 return PM_RET_ERROR_ARGS;
1023 }
1024
1025 /* Send request to the PMU */
1026 PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
1027 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001028}
1029
1030/**
1031 * pm_clock_getdivider - Get the clock divider for given id
1032 * @clock_id: Id of the clock
1033 * @divider: divider value
1034 *
1035 * This function is used by master to get divider values
1036 * for any clock.
1037 *
1038 * Return: Returns status, either success or error+reason.
1039 */
1040enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
1041 unsigned int *divider)
1042{
Jolly Shah4dd11762019-01-04 11:53:37 -08001043 enum pm_ret_status status;
1044 enum pm_node_id nid;
1045 uint32_t payload[PAYLOAD_ARG_CNT];
1046 uint32_t val;
1047
1048 /* Get PLL node ID using PLL clock ID */
1049 status = pm_clock_get_pll_node_id(clock_id, &nid);
1050 if (status == PM_RET_SUCCESS)
1051 return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
1052
1053 /* Check if clock ID is a valid on-chip clock */
1054 status = pm_clock_id_is_valid(clock_id);
1055 if (status != PM_RET_SUCCESS)
1056 return status;
1057
1058 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
1059 /* Send request to the PMU to get div0 */
1060 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1061 PM_CLOCK_DIV0_ID);
1062 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1063 if (status != PM_RET_SUCCESS)
1064 return status;
1065 *divider = val;
1066 }
1067
1068 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
1069 /* Send request to the PMU to get div1 */
1070 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
1071 PM_CLOCK_DIV1_ID);
1072 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
1073 if (status != PM_RET_SUCCESS)
1074 return status;
1075 *divider |= val << 16;
1076 }
1077
1078 return status;
Rajan Vaja35116132018-01-17 02:39:25 -08001079}
1080
1081/**
1082 * pm_clock_setrate - Set the clock rate for given id
1083 * @clock_id: Id of the clock
1084 * @rate: rate value in hz
1085 *
1086 * This function is used by master to set rate for any clock.
1087 *
1088 * Return: Returns status, either success or error+reason.
1089 */
1090enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
1091 uint64_t rate)
1092{
Jolly Shahc1391812019-01-02 13:39:30 -08001093 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001094}
1095
1096/**
1097 * pm_clock_getrate - Get the clock rate for given id
1098 * @clock_id: Id of the clock
1099 * @rate: rate value in hz
1100 *
1101 * This function is used by master to get rate
1102 * for any clock.
1103 *
1104 * Return: Returns status, either success or error+reason.
1105 */
1106enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
1107 uint64_t *rate)
1108{
Jolly Shahc1391812019-01-02 13:39:30 -08001109 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -08001110}
1111
1112/**
1113 * pm_clock_setparent - Set the clock parent for given id
1114 * @clock_id: Id of the clock
Jolly Shah407fc0a2019-01-04 11:57:40 -08001115 * @parent_index: Index of the parent clock into clock's parents array
Rajan Vaja35116132018-01-17 02:39:25 -08001116 *
1117 * This function is used by master to set parent for any clock.
1118 *
1119 * Return: Returns status, either success or error+reason.
1120 */
1121enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
Jolly Shah407fc0a2019-01-04 11:57:40 -08001122 unsigned int parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001123{
Jolly Shah407fc0a2019-01-04 11:57:40 -08001124 struct pm_pll *pll;
1125 uint32_t payload[PAYLOAD_ARG_CNT];
1126 enum pm_ret_status status;
1127
1128 /* First try to handle it as a PLL */
1129 pll = pm_clock_get_pll_by_related_clk(clock_id);
1130 if (pll)
1131 return pm_clock_pll_set_parent(pll, clock_id, parent_index);
1132
1133 /* Check if clock ID is a valid on-chip clock */
1134 status = pm_clock_id_is_valid(clock_id);
1135 if (status != PM_RET_SUCCESS)
1136 return status;
1137
1138 /* Send request to the PMU */
1139 PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
1140 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -08001141}
1142
1143/**
1144 * pm_clock_getparent - Get the clock parent for given id
1145 * @clock_id: Id of the clock
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001146 * @parent_index: parent index
Rajan Vaja35116132018-01-17 02:39:25 -08001147 *
1148 * This function is used by master to get parent index
1149 * for any clock.
1150 *
1151 * Return: Returns status, either success or error+reason.
1152 */
1153enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001154 unsigned int *parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -08001155{
Jolly Shah7c8e79c2019-01-02 13:44:25 -08001156 struct pm_pll *pll;
1157 uint32_t payload[PAYLOAD_ARG_CNT];
1158 enum pm_ret_status status;
1159
1160 /* First try to handle it as a PLL */
1161 pll = pm_clock_get_pll_by_related_clk(clock_id);
1162 if (pll)
1163 return pm_clock_pll_get_parent(pll, clock_id, parent_index);
1164
1165 /* Check if clock ID is a valid on-chip clock */
1166 status = pm_clock_id_is_valid(clock_id);
1167 if (status != PM_RET_SUCCESS)
1168 return status;
1169
1170 /* Send request to the PMU */
1171 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
1172 return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
Rajan Vaja35116132018-01-17 02:39:25 -08001173}
1174
1175/**
Rajan Vajad5dd8362018-01-30 04:16:31 -08001176 * pm_pinctrl_get_num_pins - PM call to request number of pins
1177 * @npins: Number of pins
1178 *
1179 * This function is used by master to get number of pins
1180 *
1181 * Return: Returns status, either success or error+reason.
1182 */
1183static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
1184{
1185 return pm_api_pinctrl_get_num_pins(npins);
1186}
1187
1188/**
1189 * pm_pinctrl_get_num_functions - PM call to request number of functions
1190 * @nfuncs: Number of functions
1191 *
1192 * This function is used by master to get number of functions
1193 *
1194 * Return: Returns status, either success or error+reason.
1195 */
1196static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
1197{
1198 return pm_api_pinctrl_get_num_functions(nfuncs);
1199}
1200
1201/**
1202 * pm_pinctrl_get_num_function_groups - PM call to request number of
1203 * function groups
1204 * @fid: Id of function
1205 * @ngroups: Number of function groups
1206 *
1207 * This function is used by master to get number of function groups specified
1208 * by given function Id
1209 *
1210 * Return: Returns status, either success or error+reason.
1211 */
1212static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid,
1213 uint32_t *ngroups)
1214{
1215 return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
1216}
1217
1218/**
1219 * pm_pinctrl_get_function_name - PM call to request function name
1220 * @fid: Id of function
1221 * @name: Name of function
1222 *
1223 * This function is used by master to get name of function specified
1224 * by given function Id
Rajan Vajad5dd8362018-01-30 04:16:31 -08001225 */
Rajan Vajacd825682020-11-23 21:33:39 -08001226static void pm_pinctrl_get_function_name(unsigned int fid, char *name)
Rajan Vajad5dd8362018-01-30 04:16:31 -08001227{
Rajan Vajacd825682020-11-23 21:33:39 -08001228 pm_api_pinctrl_get_function_name(fid, name);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001229}
1230
1231/**
1232 * pm_pinctrl_get_function_groups - PM call to request function groups
1233 * @fid: Id of function
1234 * @index: Index of next function groups
1235 * @groups: Function groups
1236 *
1237 * This function is used by master to get function groups specified
1238 * by given function Id. This API will return 6 function groups with
1239 * a single response. To get other function groups, master should call
1240 * same API in loop with new function groups index till error is returned.
1241 *
1242 * E.g First call should have index 0 which will return function groups
1243 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1244 * function groups 6, 7, 8, 9, 10 and 11 and so on.
1245 *
1246 * Return: Returns status, either success or error+reason.
1247 */
1248static enum pm_ret_status pm_pinctrl_get_function_groups(unsigned int fid,
1249 unsigned int index,
1250 uint16_t *groups)
1251{
1252 return pm_api_pinctrl_get_function_groups(fid, index, groups);
1253}
1254
1255/**
1256 * pm_pinctrl_get_pin_groups - PM call to request pin groups
1257 * @pin_id: Id of pin
1258 * @index: Index of next pin groups
1259 * @groups: pin groups
1260 *
1261 * This function is used by master to get pin groups specified
1262 * by given pin Id. This API will return 6 pin groups with
1263 * a single response. To get other pin groups, master should call
1264 * same API in loop with new pin groups index till error is returned.
1265 *
1266 * E.g First call should have index 0 which will return pin groups
1267 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1268 * pin groups 6, 7, 8, 9, 10 and 11 and so on.
1269 *
1270 * Return: Returns status, either success or error+reason.
1271 */
1272static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id,
1273 unsigned int index,
1274 uint16_t *groups)
1275{
1276 return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
1277}
1278
1279/**
Rajan Vaja35116132018-01-17 02:39:25 -08001280 * pm_query_data() - PM API for querying firmware data
1281 * @arg1 Argument 1 to requested IOCTL call
1282 * @arg2 Argument 2 to requested IOCTL call
1283 * @arg3 Argument 3 to requested IOCTL call
1284 * @arg4 Argument 4 to requested IOCTL call
1285 * @data Returned output data
1286 *
1287 * This function returns requested data.
Rajan Vaja35116132018-01-17 02:39:25 -08001288 */
Rajan Vajacd825682020-11-23 21:33:39 -08001289void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
1290 unsigned int arg3, unsigned int *data)
Rajan Vaja35116132018-01-17 02:39:25 -08001291{
Rajan Vaja35116132018-01-17 02:39:25 -08001292 switch (qid) {
1293 case PM_QID_CLOCK_GET_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001294 pm_clock_get_name(arg1, (char *)data);
Rajan Vaja35116132018-01-17 02:39:25 -08001295 break;
1296 case PM_QID_CLOCK_GET_TOPOLOGY:
Rajan Vajacd825682020-11-23 21:33:39 -08001297 data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001298 break;
1299 case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
Rajan Vajacd825682020-11-23 21:33:39 -08001300 data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
1301 &data[2]);
Rajan Vaja35116132018-01-17 02:39:25 -08001302 break;
1303 case PM_QID_CLOCK_GET_PARENTS:
Rajan Vajacd825682020-11-23 21:33:39 -08001304 data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001305 break;
1306 case PM_QID_CLOCK_GET_ATTRIBUTES:
Rajan Vajacd825682020-11-23 21:33:39 -08001307 data[0] = pm_clock_get_attributes(arg1, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001308 break;
Rajan Vajad5dd8362018-01-30 04:16:31 -08001309 case PM_QID_PINCTRL_GET_NUM_PINS:
Rajan Vajacd825682020-11-23 21:33:39 -08001310 data[0] = pm_pinctrl_get_num_pins(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001311 break;
1312 case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
Rajan Vajacd825682020-11-23 21:33:39 -08001313 data[0] = pm_pinctrl_get_num_functions(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001314 break;
1315 case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001316 data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001317 break;
1318 case PM_QID_PINCTRL_GET_FUNCTION_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001319 pm_pinctrl_get_function_name(arg1, (char *)data);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001320 break;
1321 case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001322 data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
1323 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001324 break;
1325 case PM_QID_PINCTRL_GET_PIN_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001326 data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
1327 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001328 break;
Rajan Vajada959402018-07-20 03:16:27 -07001329 case PM_QID_CLOCK_GET_NUM_CLOCKS:
Rajan Vajacd825682020-11-23 21:33:39 -08001330 data[0] = pm_clock_get_num_clocks(&data[1]);
Rajan Vajada959402018-07-20 03:16:27 -07001331 break;
Rajan Vajab34deca2019-03-20 01:13:21 +05301332
1333 case PM_QID_CLOCK_GET_MAX_DIVISOR:
Rajan Vajacd825682020-11-23 21:33:39 -08001334 data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
Rajan Vajab34deca2019-03-20 01:13:21 +05301335 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001336 default:
Rajan Vajacd825682020-11-23 21:33:39 -08001337 data[0] = PM_RET_ERROR_ARGS;
Rajan Vaja35116132018-01-17 02:39:25 -08001338 WARN("Unimplemented query service call: 0x%x\n", qid);
1339 }
Rajan Vaja35116132018-01-17 02:39:25 -08001340}
Siva Durga Prasad Paladuguf3994cc2018-05-01 11:12:55 +05301341
1342enum pm_ret_status pm_sha_hash(uint32_t address_high,
1343 uint32_t address_low,
1344 uint32_t size,
1345 uint32_t flags)
1346{
1347 uint32_t payload[PAYLOAD_ARG_CNT];
1348
1349 /* Send request to the PMU */
1350 PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
1351 size, flags);
1352 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1353}
1354
1355enum pm_ret_status pm_rsa_core(uint32_t address_high,
1356 uint32_t address_low,
1357 uint32_t size,
1358 uint32_t flags)
1359{
1360 uint32_t payload[PAYLOAD_ARG_CNT];
1361
1362 /* Send request to the PMU */
1363 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
1364 size, flags);
1365 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1366}
Siva Durga Prasad Paladugua4ed4b22018-04-30 20:06:58 +05301367
1368enum pm_ret_status pm_secure_image(uint32_t address_low,
1369 uint32_t address_high,
1370 uint32_t key_lo,
1371 uint32_t key_hi,
1372 uint32_t *value)
1373{
1374 uint32_t payload[PAYLOAD_ARG_CNT];
1375
1376 /* Send request to the PMU */
1377 PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
1378 key_hi, key_lo);
1379 return pm_ipi_send_sync(primary_proc, payload, value, 2);
1380}
Siva Durga Prasad Paladugu7c6516a2018-09-04 17:41:34 +05301381
1382/**
1383 * pm_fpga_read - Perform the fpga configuration readback
1384 *
1385 * @reg_numframes: Configuration register offset (or) Number of frames to read
1386 * @address_low: lower 32-bit Linear memory space address
1387 * @address_high: higher 32-bit Linear memory space address
1388 * @readback_type: Type of fpga readback operation
1389 * 0 -- Configuration Register readback
1390 * 1 -- Configuration Data readback
1391 * @value: Value to read
1392 *
1393 * This function provides access to the xilfpga library to read
1394 * the PL configuration.
1395 *
1396 * Return: Returns status, either success or error+reason.
1397 */
1398enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
1399 uint32_t address_low,
1400 uint32_t address_high,
1401 uint32_t readback_type,
1402 uint32_t *value)
1403{
1404 uint32_t payload[PAYLOAD_ARG_CNT];
1405
1406 /* Send request to the PMU */
1407 PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
1408 address_high, readback_type);
1409 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1410}
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001411
1412/*
1413 * pm_pll_set_parameter() - Set the PLL parameter value
1414 * @nid Node id of the target PLL
1415 * @param_id ID of the PLL parameter
1416 * @value Parameter value to be set
1417 *
1418 * Setting the parameter will have physical effect once the PLL mode is set to
1419 * integer or fractional.
1420 *
1421 * @return Error if an argument is not valid or status as returned by the
1422 * PM controller (PMU)
1423 */
1424enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
1425 enum pm_pll_param param_id,
1426 unsigned int value)
1427{
1428 uint32_t payload[PAYLOAD_ARG_CNT];
1429
1430 /* Check if given node ID is a PLL node */
1431 if (nid < NODE_APLL || nid > NODE_IOPLL)
1432 return PM_RET_ERROR_ARGS;
1433
1434 /* Check if parameter ID is valid and return an error if it's not */
1435 if (param_id >= PM_PLL_PARAM_MAX)
1436 return PM_RET_ERROR_ARGS;
1437
1438 /* Send request to the PMU */
1439 PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
1440 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1441}
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001442
1443/**
1444 * pm_pll_get_parameter() - Get the PLL parameter value
1445 * @nid Node id of the target PLL
1446 * @param_id ID of the PLL parameter
1447 * @value Location to store the parameter value
1448 *
1449 * @return Error if an argument is not valid or status as returned by the
1450 * PM controller (PMU)
1451 */
1452enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
1453 enum pm_pll_param param_id,
1454 unsigned int *value)
1455{
1456 uint32_t payload[PAYLOAD_ARG_CNT];
1457
1458 /* Check if given node ID is a PLL node */
1459 if (nid < NODE_APLL || nid > NODE_IOPLL)
1460 return PM_RET_ERROR_ARGS;
1461
1462 /* Check if parameter ID is valid and return an error if it's not */
1463 if (param_id >= PM_PLL_PARAM_MAX)
1464 return PM_RET_ERROR_ARGS;
1465
1466 /* Send request to the PMU */
1467 PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
1468 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1469}
Jolly Shah1f0d5852019-01-04 11:32:31 -08001470
1471/**
1472 * pm_pll_set_mode() - Set the PLL mode
1473 * @nid Node id of the target PLL
1474 * @mode PLL mode to be set
1475 *
1476 * If reset mode is set the PM controller will first bypass the PLL and then
1477 * assert the reset. If integer or fractional mode is set the PM controller will
1478 * ensure that the complete PLL programming sequence is satisfied. After this
1479 * function returns success the PLL is locked and its bypass is deasserted.
1480 *
1481 * @return Error if an argument is not valid or status as returned by the
1482 * PM controller (PMU)
1483 */
1484enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
1485{
1486 uint32_t payload[PAYLOAD_ARG_CNT];
1487
1488 /* Check if given node ID is a PLL node */
1489 if (nid < NODE_APLL || nid > NODE_IOPLL)
1490 return PM_RET_ERROR_ARGS;
1491
1492 /* Check if PLL mode is valid */
1493 if (mode >= PM_PLL_MODE_MAX)
1494 return PM_RET_ERROR_ARGS;
1495
1496 /* Send request to the PMU */
1497 PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
1498 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1499}
Jolly Shah141421e2019-01-04 11:35:48 -08001500
1501/**
1502 * pm_pll_get_mode() - Get the PLL mode
1503 * @nid Node id of the target PLL
1504 * @mode Location to store the mode of the PLL
1505 *
1506 * @return Error if an argument is not valid or status as returned by the
1507 * PM controller (PMU)
1508 */
1509enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
1510{
1511 uint32_t payload[PAYLOAD_ARG_CNT];
1512
1513 /* Check if given node ID is a PLL node */
1514 if (nid < NODE_APLL || nid > NODE_IOPLL)
1515 return PM_RET_ERROR_ARGS;
1516
1517 /* Send request to the PMU */
1518 PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
1519 return pm_ipi_send_sync(primary_proc, payload, mode, 1);
1520}
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001521
1522/**
1523 * pm_register_access() - PM API for register read/write access data
1524 *
1525 * @register_access_id Register_access_id which says register read/write
1526 *
1527 * @address Address of the register to be accessed
1528 *
1529 * @mask Mask value to be used while writing value
1530 *
1531 * @value Value to be written to register
1532 *
1533 * @out Returned output data
1534 *
1535 * This function returns requested data.
1536 *
1537 * @return Returns status, either success or error+reason
1538 */
1539enum pm_ret_status pm_register_access(unsigned int register_access_id,
1540 unsigned int address,
1541 unsigned int mask,
1542 unsigned int value,
1543 unsigned int *out)
1544{
1545 enum pm_ret_status ret;
1546
1547 if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
1548 ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
1549 ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
1550 ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE))
1551 return PM_RET_ERROR_ACCESS;
1552
1553 switch (register_access_id) {
1554 case CONFIG_REG_WRITE:
1555 ret = pm_mmio_write(address, mask, value);
1556 break;
1557 case CONFIG_REG_READ:
1558 ret = pm_mmio_read(address, out);
1559 break;
1560 default:
1561 ret = PM_RET_ERROR_ARGS;
1562 WARN("Unimplemented register_access call\n\r");
1563 }
1564 return ret;
1565}
VNSL Durgadeb1a362020-11-23 04:46:04 -08001566
1567/**
1568 * pm_efuse_access() - To program or read efuse bits.
1569 *
1570 * This function provides access to the xilskey library to program/read
1571 * efuse bits.
1572 *
1573 * address_low: lower 32-bit Linear memory space address
1574 * address_high: higher 32-bit Linear memory space address
1575 *
1576 * value: Returned output value
1577 *
1578 * @return Returns status, either success or error+reason
1579 *
1580 */
1581enum pm_ret_status pm_efuse_access(uint32_t address_high,
1582 uint32_t address_low,
1583 uint32_t *value)
1584{
1585 uint32_t payload[PAYLOAD_ARG_CNT];
1586
1587 /* Send request to the PMU */
1588 PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
1589
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -08001590 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1591}
1592
1593enum pm_ret_status em_set_action(unsigned int *value)
1594{
1595 uint32_t payload[PAYLOAD_ARG_CNT];
1596
1597 /* Send request to the PMU */
1598 EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
1599 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1600}
1601
1602enum pm_ret_status em_remove_action(unsigned int *value)
1603{
1604 uint32_t payload[PAYLOAD_ARG_CNT];
1605
1606 /* Send request to the PMU */
1607 EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
1608 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1609}
1610
1611enum pm_ret_status em_send_errors(unsigned int *value)
1612{
1613 uint32_t payload[PAYLOAD_ARG_CNT];
1614
1615 /* Send request to the PMU */
1616 EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
VNSL Durgadeb1a362020-11-23 04:46:04 -08001617 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1618}