blob: faaff1b08641a672ed5d1cc9b1fea15db201db81 [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
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
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800276/* Miscellaneous API functions */
277
278/**
279 * pm_get_api_version() - Get version number of PMU PM firmware
280 * @version Returns 32-bit version number of PMU Power Management Firmware
281 *
282 * @return Returns status, either success or error+reason
283 */
284enum pm_ret_status pm_get_api_version(unsigned int *version)
285{
286 uint32_t payload[PAYLOAD_ARG_CNT];
287
288 /* Send request to the PMU */
289 PM_PACK_PAYLOAD1(payload, PM_GET_API_VERSION);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700290 return pm_ipi_send_sync(primary_proc, payload, version, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800291}
292
293/**
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100294 * pm_get_node_status() - PM call to request a node's current status
295 * @nid Node id
296 * @ret_buff Buffer for the return values:
297 * [0] - Current power state of the node
298 * [1] - Current requirements for the node (slave nodes only)
299 * [2] - Current usage status for the node (slave nodes only)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800300 *
301 * @return Returns status, either success or error+reason
302 */
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100303enum pm_ret_status pm_get_node_status(enum pm_node_id nid,
304 uint32_t *ret_buff)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800305{
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800306 uint32_t payload[PAYLOAD_ARG_CNT];
307
308 PM_PACK_PAYLOAD2(payload, PM_GET_NODE_STATUS, nid);
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100309 return pm_ipi_send_sync(primary_proc, payload, ret_buff, 3);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800310}
311
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800312/**
313 * pm_mmio_write() - Perform write to protected mmio
314 * @address Address to write to
315 * @mask Mask to apply
316 * @value Value to write
317 *
318 * This function provides access to PM-related control registers
319 * that may not be directly accessible by a particular PU.
320 *
321 * @return Returns status, either success or error+reason
322 */
323enum pm_ret_status pm_mmio_write(uintptr_t address,
324 unsigned int mask,
325 unsigned int value)
326{
327 uint32_t payload[PAYLOAD_ARG_CNT];
328
329 /* Send request to the PMU */
330 PM_PACK_PAYLOAD4(payload, PM_MMIO_WRITE, address, mask, value);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700331 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800332}
333
334/**
335 * pm_mmio_read() - Read value from protected mmio
336 * @address Address to write to
337 * @value Value to write
338 *
339 * This function provides access to PM-related control registers
340 * that may not be directly accessible by a particular PU.
341 *
342 * @return Returns status, either success or error+reason
343 */
344enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *value)
345{
346 uint32_t payload[PAYLOAD_ARG_CNT];
347
348 /* Send request to the PMU */
349 PM_PACK_PAYLOAD2(payload, PM_MMIO_READ, address);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700350 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800351}
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530352
353/**
354 * pm_fpga_load() - Load the bitstream into the PL.
355 *
356 * This function provides access to the xilfpga library to load
357 * the Bit-stream into PL.
358 *
359 * address_low: lower 32-bit Linear memory space address
360 *
361 * address_high: higher 32-bit Linear memory space address
362 *
363 * size: Number of 32bit words
364 *
365 * @return Returns status, either success or error+reason
366 */
367enum pm_ret_status pm_fpga_load(uint32_t address_low,
368 uint32_t address_high,
369 uint32_t size,
370 uint32_t flags)
371{
372 uint32_t payload[PAYLOAD_ARG_CNT];
373
374 /* Send request to the PMU */
375 PM_PACK_PAYLOAD5(payload, PM_FPGA_LOAD, address_high, address_low,
376 size, flags);
Siva Durga Prasad Paladugubf83b9c2018-02-07 13:13:01 +0530377 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530378}
379
380/**
381 * pm_fpga_get_status() - Read value from fpga status register
382 * @value Value to read
383 *
384 * This function provides access to the xilfpga library to get
385 * the fpga status
386 * @return Returns status, either success or error+reason
387 */
388enum pm_ret_status pm_fpga_get_status(unsigned int *value)
389{
390 uint32_t payload[PAYLOAD_ARG_CNT];
391
392 /* Send request to the PMU */
393 PM_PACK_PAYLOAD1(payload, PM_FPGA_GET_STATUS);
Soren Brinkmannd6c9e032016-09-22 11:35:47 -0700394 return pm_ipi_send_sync(primary_proc, payload, value, 1);
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530395}
Soren Brinkmanncb366812016-09-22 12:21:11 -0700396
397/**
398 * pm_get_chipid() - Read silicon ID registers
399 * @value Buffer for return values. Must be large enough
400 * to hold 8 bytes.
401 *
402 * @return Returns silicon ID registers
403 */
404enum pm_ret_status pm_get_chipid(uint32_t *value)
405{
406 uint32_t payload[PAYLOAD_ARG_CNT];
407
408 /* Send request to the PMU */
409 PM_PACK_PAYLOAD1(payload, PM_GET_CHIPID);
410 return pm_ipi_send_sync(primary_proc, payload, value, 2);
411}
Soren Brinkmann84f0af42016-09-30 14:24:25 -0700412
413/**
Siva Durga Prasad Paladugude93d982018-04-30 15:49:27 +0530414 * pm_secure_rsaaes() - Load the secure images.
415 *
416 * This function provides access to the xilsecure library to load
417 * the authenticated, encrypted, and authenicated/encrypted images.
418 *
419 * address_low: lower 32-bit Linear memory space address
420 *
421 * address_high: higher 32-bit Linear memory space address
422 *
423 * size: Number of 32bit words
424 *
425 * @return Returns status, either success or error+reason
426 */
427enum pm_ret_status pm_secure_rsaaes(uint32_t address_low,
428 uint32_t address_high,
429 uint32_t size,
430 uint32_t flags)
431{
432 uint32_t payload[PAYLOAD_ARG_CNT];
433
434 /* Send request to the PMU */
435 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA_AES, address_high, address_low,
436 size, flags);
437 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
438}
439
440/**
Siva Durga Prasad Paladugu8bd905b2018-09-04 18:05:50 +0530441 * pm_aes_engine() - Aes data blob encryption/decryption
442 * This function provides access to the xilsecure library to
443 * encrypt/decrypt data blobs.
444 *
445 * address_low: lower 32-bit address of the AesParams structure
446 *
447 * address_high: higher 32-bit address of the AesParams structure
448 *
449 * value: Returned output value
450 *
451 * @return Returns status, either success or error+reason
452 */
453enum pm_ret_status pm_aes_engine(uint32_t address_high,
454 uint32_t address_low,
455 uint32_t *value)
456{
457 uint32_t payload[PAYLOAD_ARG_CNT];
458
459 /* Send request to the PMU */
460 PM_PACK_PAYLOAD3(payload, PM_SECURE_AES, address_high, address_low);
461 return pm_ipi_send_sync(primary_proc, payload, value, 1);
462}
463
464/**
Rajan Vaja02d18422019-03-04 11:09:39 +0530465 * pm_get_callbackdata() - Read from IPI response buffer
466 * @data - array of PAYLOAD_ARG_CNT elements
467 *
468 * Read value from ipi buffer response buffer.
469 */
470void pm_get_callbackdata(uint32_t *data, size_t count)
471{
472 /* Return if interrupt is not from PMU */
473 if (!pm_ipi_irq_status(primary_proc))
474 return;
475
476 pm_ipi_buff_read_callb(data, count);
477 pm_ipi_irq_clear(primary_proc);
478}
479
480/**
Rajan Vaja5529a012018-01-17 02:39:23 -0800481 * pm_ioctl() - PM IOCTL API for device control and configs
482 * @node_id Node ID of the device
483 * @ioctl_id ID of the requested IOCTL
484 * @arg1 Argument 1 to requested IOCTL call
485 * @arg2 Argument 2 to requested IOCTL call
486 * @out Returned output value
487 *
488 * This function calls IOCTL to firmware for device control and configuration.
489 *
490 * @return Returns status, either success or error+reason
491 */
492enum pm_ret_status pm_ioctl(enum pm_node_id nid,
493 unsigned int ioctl_id,
494 unsigned int arg1,
495 unsigned int arg2,
496 unsigned int *value)
497{
498 return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value);
499}
Rajan Vaja35116132018-01-17 02:39:25 -0800500
501/**
Rajan Vajab34deca2019-03-20 01:13:21 +0530502 * pm_clock_get_max_divisor - PM call to get max divisor
503 * @clock_id Clock ID
504 * @div_type Divisor ID (TYPE_DIV1 or TYPE_DIV2)
505 * @max_div Maximum supported divisor
506 *
507 * This function is used by master to get maximum supported value.
508 *
509 * Return: Returns status, either success or error+reason.
510 */
511static enum pm_ret_status pm_clock_get_max_divisor(unsigned int clock_id,
512 uint8_t div_type,
513 uint32_t *max_div)
514{
515 return pm_api_clock_get_max_divisor(clock_id, div_type, max_div);
516}
517
518/**
Rajan Vajada959402018-07-20 03:16:27 -0700519 * pm_clock_get_num_clocks - PM call to request number of clocks
520 * @nclockss: Number of clocks
521 *
522 * This function is used by master to get number of clocks.
523 *
524 * Return: Returns status, either success or error+reason.
525 */
526static enum pm_ret_status pm_clock_get_num_clocks(uint32_t *nclocks)
527{
528 return pm_api_clock_get_num_clocks(nclocks);
529}
530
531/**
Rajan Vaja35116132018-01-17 02:39:25 -0800532 * pm_clock_get_name() - PM call to request a clock's name
533 * @clock_id Clock ID
534 * @name Name of clock (max 16 bytes)
535 *
536 * This function is used by master to get nmae of clock specified
537 * by given clock ID.
Rajan Vaja35116132018-01-17 02:39:25 -0800538 */
Rajan Vajacd825682020-11-23 21:33:39 -0800539static void pm_clock_get_name(unsigned int clock_id, char *name)
Rajan Vaja35116132018-01-17 02:39:25 -0800540{
Rajan Vajacd825682020-11-23 21:33:39 -0800541 pm_api_clock_get_name(clock_id, name);
Rajan Vaja35116132018-01-17 02:39:25 -0800542}
543
544/**
545 * pm_clock_get_topology() - PM call to request a clock's topology
546 * @clock_id Clock ID
547 * @index Topology index for next toplogy node
548 * @topology Buffer to store nodes in topology and flags
549 *
550 * This function is used by master to get topology information for the
551 * clock specified by given clock ID. Each response would return 3
552 * topology nodes. To get next nodes, caller needs to call this API with
553 * index of next node. Index starts from 0.
554 *
555 * @return Returns status, either success or error+reason
556 */
557static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id,
558 unsigned int index,
559 uint32_t *topology)
560{
561 return pm_api_clock_get_topology(clock_id, index, topology);
562}
563
564/**
565 * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor
566 * parameters for fixed clock
567 * @clock_id Clock ID
568 * @mul Multiplication value
569 * @div Divisor value
570 *
571 * This function is used by master to get fixed factor parameers for the
572 * fixed clock. This API is application only for the fixed clock.
573 *
574 * @return Returns status, either success or error+reason
575 */
576static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id,
577 uint32_t *mul,
578 uint32_t *div)
579{
580 return pm_api_clock_get_fixedfactor_params(clock_id, mul, div);
581}
582
583/**
584 * pm_clock_get_parents() - PM call to request a clock's first 3 parents
585 * @clock_id Clock ID
586 * @index Index of next parent
587 * @parents Parents of the given clock
588 *
589 * This function is used by master to get clock's parents information.
590 * This API will return 3 parents with a single response. To get other
591 * parents, master should call same API in loop with new parent index
592 * till error is returned.
593 *
594 * E.g First call should have index 0 which will return parents 0, 1 and
595 * 2. Next call, index should be 3 which will return parent 3,4 and 5 and
596 * so on.
597 *
598 * @return Returns status, either success or error+reason
599 */
600static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id,
601 unsigned int index,
602 uint32_t *parents)
603{
604 return pm_api_clock_get_parents(clock_id, index, parents);
605}
606
607/**
608 * pm_clock_get_attributes() - PM call to request a clock's attributes
609 * @clock_id Clock ID
610 * @attr Clock attributes
611 *
612 * This function is used by master to get clock's attributes
613 * (e.g. valid, clock type, etc).
614 *
615 * @return Returns status, either success or error+reason
616 */
617static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id,
618 uint32_t *attr)
619{
620 return pm_api_clock_get_attributes(clock_id, attr);
621}
622
623/**
Jolly Shaha5209802019-01-04 11:45:59 -0800624 * pm_clock_gate() - Configure clock gate
625 * @clock_id Id of the clock to be configured
626 * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
627 *
628 * @return Error if an argument is not valid or status as returned by the
629 * PM controller (PMU)
630 */
631static enum pm_ret_status pm_clock_gate(unsigned int clock_id,
632 unsigned char enable)
633{
634 uint32_t payload[PAYLOAD_ARG_CNT];
635 enum pm_ret_status status;
636 enum pm_api_id api_id;
637
638 /* Check if clock ID is valid and return an error if it is not */
639 status = pm_clock_id_is_valid(clock_id);
640 if (status != PM_RET_SUCCESS)
641 return status;
642
643 if (enable)
644 api_id = PM_CLOCK_ENABLE;
645 else
646 api_id = PM_CLOCK_DISABLE;
647
648 /* Send request to the PMU */
649 PM_PACK_PAYLOAD2(payload, api_id, clock_id);
Mirela Simonovic64514a72018-08-24 17:09:07 +0200650 status = pm_ipi_send_sync(primary_proc, payload, NULL, 0);
651
652 /* If action fails due to the lack of permissions filter the error */
653 if (status == PM_RET_ERROR_ACCESS)
654 status = PM_RET_SUCCESS;
655
656 return status;
Jolly Shaha5209802019-01-04 11:45:59 -0800657}
658
659/**
Rajan Vaja35116132018-01-17 02:39:25 -0800660 * pm_clock_enable() - Enable the clock for given id
661 * @clock_id: Id of the clock to be enabled
662 *
663 * This function is used by master to enable the clock
664 * including peripherals and PLL clocks.
665 *
Jolly Shaha5209802019-01-04 11:45:59 -0800666 * @return: Error if an argument is not valid or status as returned by the
667 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -0800668 */
Rajan Vaja35116132018-01-17 02:39:25 -0800669enum pm_ret_status pm_clock_enable(unsigned int clock_id)
670{
Jolly Shaha5209802019-01-04 11:45:59 -0800671 struct pm_pll *pll;
672
673 /* First try to handle it as a PLL */
674 pll = pm_clock_get_pll(clock_id);
675 if (pll)
676 return pm_clock_pll_enable(pll);
677
678 /* It's an on-chip clock, PMU should configure clock's gate */
679 return pm_clock_gate(clock_id, 1);
Rajan Vaja35116132018-01-17 02:39:25 -0800680}
681
682/**
683 * pm_clock_disable - Disable the clock for given id
684 * @clock_id: Id of the clock to be disable
685 *
686 * This function is used by master to disable the clock
687 * including peripherals and PLL clocks.
688 *
Jolly Shaha9057a02019-01-02 12:54:40 -0800689 * @return: Error if an argument is not valid or status as returned by the
690 * pm_clock_gate
Rajan Vaja35116132018-01-17 02:39:25 -0800691 */
Rajan Vaja35116132018-01-17 02:39:25 -0800692enum pm_ret_status pm_clock_disable(unsigned int clock_id)
693{
Jolly Shaha9057a02019-01-02 12:54:40 -0800694 struct pm_pll *pll;
695
696 /* First try to handle it as a PLL */
697 pll = pm_clock_get_pll(clock_id);
698 if (pll)
699 return pm_clock_pll_disable(pll);
700
701 /* It's an on-chip clock, PMU should configure clock's gate */
702 return pm_clock_gate(clock_id, 0);
Rajan Vaja35116132018-01-17 02:39:25 -0800703}
704
705/**
706 * pm_clock_getstate - Get the clock state for given id
707 * @clock_id: Id of the clock to be queried
708 * @state: 1/0 (Enabled/Disabled)
709 *
710 * This function is used by master to get the state of clock
711 * including peripherals and PLL clocks.
712 *
713 * Return: Returns status, either success or error+reason.
714 */
715enum pm_ret_status pm_clock_getstate(unsigned int clock_id,
716 unsigned int *state)
717{
Jolly Shah99e8ac92019-01-02 12:55:41 -0800718 struct pm_pll *pll;
719 uint32_t payload[PAYLOAD_ARG_CNT];
720 enum pm_ret_status status;
721
722 /* First try to handle it as a PLL */
723 pll = pm_clock_get_pll(clock_id);
724 if (pll)
725 return pm_clock_pll_get_state(pll, state);
726
727 /* Check if clock ID is a valid on-chip clock */
728 status = pm_clock_id_is_valid(clock_id);
729 if (status != PM_RET_SUCCESS)
730 return status;
731
732 /* Send request to the PMU */
733 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETSTATE, clock_id);
734 return pm_ipi_send_sync(primary_proc, payload, state, 1);
Rajan Vaja35116132018-01-17 02:39:25 -0800735}
736
737/**
738 * pm_clock_setdivider - Set the clock divider for given id
739 * @clock_id: Id of the clock
740 * @divider: divider value
741 *
742 * This function is used by master to set divider for any clock
743 * to achieve desired rate.
744 *
745 * Return: Returns status, either success or error+reason.
746 */
747enum pm_ret_status pm_clock_setdivider(unsigned int clock_id,
748 unsigned int divider)
749{
Jolly Shah8b4c4c72019-01-04 11:49:46 -0800750 enum pm_ret_status status;
751 enum pm_node_id nid;
752 enum pm_clock_div_id div_id;
753 uint32_t payload[PAYLOAD_ARG_CNT];
754 const uint32_t div0 = 0xFFFF0000;
755 const uint32_t div1 = 0x0000FFFF;
756 uint32_t val;
757
758 /* Get PLL node ID using PLL clock ID */
759 status = pm_clock_get_pll_node_id(clock_id, &nid);
760 if (status == PM_RET_SUCCESS)
761 return pm_pll_set_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
762
763 /* Check if clock ID is a valid on-chip clock */
764 status = pm_clock_id_is_valid(clock_id);
765 if (status != PM_RET_SUCCESS)
766 return status;
767
768 if (div0 == (divider & div0)) {
769 div_id = PM_CLOCK_DIV0_ID;
770 val = divider & ~div0;
771 } else if (div1 == (divider & div1)) {
772 div_id = PM_CLOCK_DIV1_ID;
773 val = (divider & ~div1) >> 16;
774 } else {
775 return PM_RET_ERROR_ARGS;
776 }
777
778 /* Send request to the PMU */
779 PM_PACK_PAYLOAD4(payload, PM_CLOCK_SETDIVIDER, clock_id, div_id, val);
780 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -0800781}
782
783/**
784 * pm_clock_getdivider - Get the clock divider for given id
785 * @clock_id: Id of the clock
786 * @divider: divider value
787 *
788 * This function is used by master to get divider values
789 * for any clock.
790 *
791 * Return: Returns status, either success or error+reason.
792 */
793enum pm_ret_status pm_clock_getdivider(unsigned int clock_id,
794 unsigned int *divider)
795{
Jolly Shah4dd11762019-01-04 11:53:37 -0800796 enum pm_ret_status status;
797 enum pm_node_id nid;
798 uint32_t payload[PAYLOAD_ARG_CNT];
799 uint32_t val;
800
801 /* Get PLL node ID using PLL clock ID */
802 status = pm_clock_get_pll_node_id(clock_id, &nid);
803 if (status == PM_RET_SUCCESS)
804 return pm_pll_get_parameter(nid, PM_PLL_PARAM_FBDIV, divider);
805
806 /* Check if clock ID is a valid on-chip clock */
807 status = pm_clock_id_is_valid(clock_id);
808 if (status != PM_RET_SUCCESS)
809 return status;
810
811 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV0_ID)) {
812 /* Send request to the PMU to get div0 */
813 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
814 PM_CLOCK_DIV0_ID);
815 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
816 if (status != PM_RET_SUCCESS)
817 return status;
818 *divider = val;
819 }
820
821 if (pm_clock_has_div(clock_id, PM_CLOCK_DIV1_ID)) {
822 /* Send request to the PMU to get div1 */
823 PM_PACK_PAYLOAD3(payload, PM_CLOCK_GETDIVIDER, clock_id,
824 PM_CLOCK_DIV1_ID);
825 status = pm_ipi_send_sync(primary_proc, payload, &val, 1);
826 if (status != PM_RET_SUCCESS)
827 return status;
828 *divider |= val << 16;
829 }
830
831 return status;
Rajan Vaja35116132018-01-17 02:39:25 -0800832}
833
834/**
835 * pm_clock_setrate - Set the clock rate for given id
836 * @clock_id: Id of the clock
837 * @rate: rate value in hz
838 *
839 * This function is used by master to set rate for any clock.
840 *
841 * Return: Returns status, either success or error+reason.
842 */
843enum pm_ret_status pm_clock_setrate(unsigned int clock_id,
844 uint64_t rate)
845{
Jolly Shahc1391812019-01-02 13:39:30 -0800846 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -0800847}
848
849/**
850 * pm_clock_getrate - Get the clock rate for given id
851 * @clock_id: Id of the clock
852 * @rate: rate value in hz
853 *
854 * This function is used by master to get rate
855 * for any clock.
856 *
857 * Return: Returns status, either success or error+reason.
858 */
859enum pm_ret_status pm_clock_getrate(unsigned int clock_id,
860 uint64_t *rate)
861{
Jolly Shahc1391812019-01-02 13:39:30 -0800862 return PM_RET_ERROR_NOTSUPPORTED;
Rajan Vaja35116132018-01-17 02:39:25 -0800863}
864
865/**
866 * pm_clock_setparent - Set the clock parent for given id
867 * @clock_id: Id of the clock
Jolly Shah407fc0a2019-01-04 11:57:40 -0800868 * @parent_index: Index of the parent clock into clock's parents array
Rajan Vaja35116132018-01-17 02:39:25 -0800869 *
870 * This function is used by master to set parent for any clock.
871 *
872 * Return: Returns status, either success or error+reason.
873 */
874enum pm_ret_status pm_clock_setparent(unsigned int clock_id,
Jolly Shah407fc0a2019-01-04 11:57:40 -0800875 unsigned int parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -0800876{
Jolly Shah407fc0a2019-01-04 11:57:40 -0800877 struct pm_pll *pll;
878 uint32_t payload[PAYLOAD_ARG_CNT];
879 enum pm_ret_status status;
880
881 /* First try to handle it as a PLL */
882 pll = pm_clock_get_pll_by_related_clk(clock_id);
883 if (pll)
884 return pm_clock_pll_set_parent(pll, clock_id, parent_index);
885
886 /* Check if clock ID is a valid on-chip clock */
887 status = pm_clock_id_is_valid(clock_id);
888 if (status != PM_RET_SUCCESS)
889 return status;
890
891 /* Send request to the PMU */
892 PM_PACK_PAYLOAD3(payload, PM_CLOCK_SETPARENT, clock_id, parent_index);
893 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
Rajan Vaja35116132018-01-17 02:39:25 -0800894}
895
896/**
897 * pm_clock_getparent - Get the clock parent for given id
898 * @clock_id: Id of the clock
Jolly Shah7c8e79c2019-01-02 13:44:25 -0800899 * @parent_index: parent index
Rajan Vaja35116132018-01-17 02:39:25 -0800900 *
901 * This function is used by master to get parent index
902 * for any clock.
903 *
904 * Return: Returns status, either success or error+reason.
905 */
906enum pm_ret_status pm_clock_getparent(unsigned int clock_id,
Jolly Shah7c8e79c2019-01-02 13:44:25 -0800907 unsigned int *parent_index)
Rajan Vaja35116132018-01-17 02:39:25 -0800908{
Jolly Shah7c8e79c2019-01-02 13:44:25 -0800909 struct pm_pll *pll;
910 uint32_t payload[PAYLOAD_ARG_CNT];
911 enum pm_ret_status status;
912
913 /* First try to handle it as a PLL */
914 pll = pm_clock_get_pll_by_related_clk(clock_id);
915 if (pll)
916 return pm_clock_pll_get_parent(pll, clock_id, parent_index);
917
918 /* Check if clock ID is a valid on-chip clock */
919 status = pm_clock_id_is_valid(clock_id);
920 if (status != PM_RET_SUCCESS)
921 return status;
922
923 /* Send request to the PMU */
924 PM_PACK_PAYLOAD2(payload, PM_CLOCK_GETPARENT, clock_id);
925 return pm_ipi_send_sync(primary_proc, payload, parent_index, 1);
Rajan Vaja35116132018-01-17 02:39:25 -0800926}
927
928/**
Rajan Vajad5dd8362018-01-30 04:16:31 -0800929 * pm_pinctrl_get_num_pins - PM call to request number of pins
930 * @npins: Number of pins
931 *
932 * This function is used by master to get number of pins
933 *
934 * Return: Returns status, either success or error+reason.
935 */
936static enum pm_ret_status pm_pinctrl_get_num_pins(uint32_t *npins)
937{
938 return pm_api_pinctrl_get_num_pins(npins);
939}
940
941/**
942 * pm_pinctrl_get_num_functions - PM call to request number of functions
943 * @nfuncs: Number of functions
944 *
945 * This function is used by master to get number of functions
946 *
947 * Return: Returns status, either success or error+reason.
948 */
949static enum pm_ret_status pm_pinctrl_get_num_functions(uint32_t *nfuncs)
950{
951 return pm_api_pinctrl_get_num_functions(nfuncs);
952}
953
954/**
955 * pm_pinctrl_get_num_function_groups - PM call to request number of
956 * function groups
957 * @fid: Id of function
958 * @ngroups: Number of function groups
959 *
960 * This function is used by master to get number of function groups specified
961 * by given function Id
962 *
963 * Return: Returns status, either success or error+reason.
964 */
965static enum pm_ret_status pm_pinctrl_get_num_function_groups(unsigned int fid,
966 uint32_t *ngroups)
967{
968 return pm_api_pinctrl_get_num_func_groups(fid, ngroups);
969}
970
971/**
972 * pm_pinctrl_get_function_name - PM call to request function name
973 * @fid: Id of function
974 * @name: Name of function
975 *
976 * This function is used by master to get name of function specified
977 * by given function Id
Rajan Vajad5dd8362018-01-30 04:16:31 -0800978 */
Rajan Vajacd825682020-11-23 21:33:39 -0800979static void pm_pinctrl_get_function_name(unsigned int fid, char *name)
Rajan Vajad5dd8362018-01-30 04:16:31 -0800980{
Rajan Vajacd825682020-11-23 21:33:39 -0800981 pm_api_pinctrl_get_function_name(fid, name);
Rajan Vajad5dd8362018-01-30 04:16:31 -0800982}
983
984/**
985 * pm_pinctrl_get_function_groups - PM call to request function groups
986 * @fid: Id of function
987 * @index: Index of next function groups
988 * @groups: Function groups
989 *
990 * This function is used by master to get function groups specified
991 * by given function Id. This API will return 6 function groups with
992 * a single response. To get other function groups, master should call
993 * same API in loop with new function groups index till error is returned.
994 *
995 * E.g First call should have index 0 which will return function groups
996 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
997 * function groups 6, 7, 8, 9, 10 and 11 and so on.
998 *
999 * Return: Returns status, either success or error+reason.
1000 */
1001static enum pm_ret_status pm_pinctrl_get_function_groups(unsigned int fid,
1002 unsigned int index,
1003 uint16_t *groups)
1004{
1005 return pm_api_pinctrl_get_function_groups(fid, index, groups);
1006}
1007
1008/**
1009 * pm_pinctrl_get_pin_groups - PM call to request pin groups
1010 * @pin_id: Id of pin
1011 * @index: Index of next pin groups
1012 * @groups: pin groups
1013 *
1014 * This function is used by master to get pin groups specified
1015 * by given pin Id. This API will return 6 pin groups with
1016 * a single response. To get other pin groups, master should call
1017 * same API in loop with new pin groups index till error is returned.
1018 *
1019 * E.g First call should have index 0 which will return pin groups
1020 * 0, 1, 2, 3, 4 and 5. Next call, index should be 6 which will return
1021 * pin groups 6, 7, 8, 9, 10 and 11 and so on.
1022 *
1023 * Return: Returns status, either success or error+reason.
1024 */
1025static enum pm_ret_status pm_pinctrl_get_pin_groups(unsigned int pin_id,
1026 unsigned int index,
1027 uint16_t *groups)
1028{
1029 return pm_api_pinctrl_get_pin_groups(pin_id, index, groups);
1030}
1031
1032/**
Rajan Vaja35116132018-01-17 02:39:25 -08001033 * pm_query_data() - PM API for querying firmware data
1034 * @arg1 Argument 1 to requested IOCTL call
1035 * @arg2 Argument 2 to requested IOCTL call
1036 * @arg3 Argument 3 to requested IOCTL call
1037 * @arg4 Argument 4 to requested IOCTL call
1038 * @data Returned output data
1039 *
1040 * This function returns requested data.
Rajan Vaja35116132018-01-17 02:39:25 -08001041 */
Rajan Vajacd825682020-11-23 21:33:39 -08001042void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2,
1043 unsigned int arg3, unsigned int *data)
Rajan Vaja35116132018-01-17 02:39:25 -08001044{
Rajan Vaja35116132018-01-17 02:39:25 -08001045 switch (qid) {
1046 case PM_QID_CLOCK_GET_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001047 pm_clock_get_name(arg1, (char *)data);
Rajan Vaja35116132018-01-17 02:39:25 -08001048 break;
1049 case PM_QID_CLOCK_GET_TOPOLOGY:
Rajan Vajacd825682020-11-23 21:33:39 -08001050 data[0] = pm_clock_get_topology(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001051 break;
1052 case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS:
Rajan Vajacd825682020-11-23 21:33:39 -08001053 data[0] = pm_clock_get_fixedfactor_params(arg1, &data[1],
1054 &data[2]);
Rajan Vaja35116132018-01-17 02:39:25 -08001055 break;
1056 case PM_QID_CLOCK_GET_PARENTS:
Rajan Vajacd825682020-11-23 21:33:39 -08001057 data[0] = pm_clock_get_parents(arg1, arg2, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001058 break;
1059 case PM_QID_CLOCK_GET_ATTRIBUTES:
Rajan Vajacd825682020-11-23 21:33:39 -08001060 data[0] = pm_clock_get_attributes(arg1, &data[1]);
Rajan Vaja35116132018-01-17 02:39:25 -08001061 break;
Rajan Vajad5dd8362018-01-30 04:16:31 -08001062 case PM_QID_PINCTRL_GET_NUM_PINS:
Rajan Vajacd825682020-11-23 21:33:39 -08001063 data[0] = pm_pinctrl_get_num_pins(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001064 break;
1065 case PM_QID_PINCTRL_GET_NUM_FUNCTIONS:
Rajan Vajacd825682020-11-23 21:33:39 -08001066 data[0] = pm_pinctrl_get_num_functions(&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001067 break;
1068 case PM_QID_PINCTRL_GET_NUM_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001069 data[0] = pm_pinctrl_get_num_function_groups(arg1, &data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001070 break;
1071 case PM_QID_PINCTRL_GET_FUNCTION_NAME:
Rajan Vajacd825682020-11-23 21:33:39 -08001072 pm_pinctrl_get_function_name(arg1, (char *)data);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001073 break;
1074 case PM_QID_PINCTRL_GET_FUNCTION_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001075 data[0] = pm_pinctrl_get_function_groups(arg1, arg2,
1076 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001077 break;
1078 case PM_QID_PINCTRL_GET_PIN_GROUPS:
Rajan Vajacd825682020-11-23 21:33:39 -08001079 data[0] = pm_pinctrl_get_pin_groups(arg1, arg2,
1080 (uint16_t *)&data[1]);
Rajan Vajad5dd8362018-01-30 04:16:31 -08001081 break;
Rajan Vajada959402018-07-20 03:16:27 -07001082 case PM_QID_CLOCK_GET_NUM_CLOCKS:
Rajan Vajacd825682020-11-23 21:33:39 -08001083 data[0] = pm_clock_get_num_clocks(&data[1]);
Rajan Vajada959402018-07-20 03:16:27 -07001084 break;
Rajan Vajab34deca2019-03-20 01:13:21 +05301085
1086 case PM_QID_CLOCK_GET_MAX_DIVISOR:
Rajan Vajacd825682020-11-23 21:33:39 -08001087 data[0] = pm_clock_get_max_divisor(arg1, arg2, &data[1]);
Rajan Vajab34deca2019-03-20 01:13:21 +05301088 break;
Rajan Vaja35116132018-01-17 02:39:25 -08001089 default:
Rajan Vajacd825682020-11-23 21:33:39 -08001090 data[0] = PM_RET_ERROR_ARGS;
Rajan Vaja35116132018-01-17 02:39:25 -08001091 WARN("Unimplemented query service call: 0x%x\n", qid);
1092 }
Rajan Vaja35116132018-01-17 02:39:25 -08001093}
Siva Durga Prasad Paladuguf3994cc2018-05-01 11:12:55 +05301094
1095enum pm_ret_status pm_sha_hash(uint32_t address_high,
1096 uint32_t address_low,
1097 uint32_t size,
1098 uint32_t flags)
1099{
1100 uint32_t payload[PAYLOAD_ARG_CNT];
1101
1102 /* Send request to the PMU */
1103 PM_PACK_PAYLOAD5(payload, PM_SECURE_SHA, address_high, address_low,
1104 size, flags);
1105 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1106}
1107
1108enum pm_ret_status pm_rsa_core(uint32_t address_high,
1109 uint32_t address_low,
1110 uint32_t size,
1111 uint32_t flags)
1112{
1113 uint32_t payload[PAYLOAD_ARG_CNT];
1114
1115 /* Send request to the PMU */
1116 PM_PACK_PAYLOAD5(payload, PM_SECURE_RSA, address_high, address_low,
1117 size, flags);
1118 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1119}
Siva Durga Prasad Paladugua4ed4b22018-04-30 20:06:58 +05301120
1121enum pm_ret_status pm_secure_image(uint32_t address_low,
1122 uint32_t address_high,
1123 uint32_t key_lo,
1124 uint32_t key_hi,
1125 uint32_t *value)
1126{
1127 uint32_t payload[PAYLOAD_ARG_CNT];
1128
1129 /* Send request to the PMU */
1130 PM_PACK_PAYLOAD5(payload, PM_SECURE_IMAGE, address_high, address_low,
1131 key_hi, key_lo);
1132 return pm_ipi_send_sync(primary_proc, payload, value, 2);
1133}
Siva Durga Prasad Paladugu7c6516a2018-09-04 17:41:34 +05301134
1135/**
1136 * pm_fpga_read - Perform the fpga configuration readback
1137 *
1138 * @reg_numframes: Configuration register offset (or) Number of frames to read
1139 * @address_low: lower 32-bit Linear memory space address
1140 * @address_high: higher 32-bit Linear memory space address
1141 * @readback_type: Type of fpga readback operation
1142 * 0 -- Configuration Register readback
1143 * 1 -- Configuration Data readback
1144 * @value: Value to read
1145 *
1146 * This function provides access to the xilfpga library to read
1147 * the PL configuration.
1148 *
1149 * Return: Returns status, either success or error+reason.
1150 */
1151enum pm_ret_status pm_fpga_read(uint32_t reg_numframes,
1152 uint32_t address_low,
1153 uint32_t address_high,
1154 uint32_t readback_type,
1155 uint32_t *value)
1156{
1157 uint32_t payload[PAYLOAD_ARG_CNT];
1158
1159 /* Send request to the PMU */
1160 PM_PACK_PAYLOAD5(payload, PM_FPGA_READ, reg_numframes, address_low,
1161 address_high, readback_type);
1162 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1163}
Jolly Shaha7cc5ee2019-01-02 12:27:00 -08001164
1165/*
1166 * pm_pll_set_parameter() - Set the PLL parameter value
1167 * @nid Node id of the target PLL
1168 * @param_id ID of the PLL parameter
1169 * @value Parameter value to be set
1170 *
1171 * Setting the parameter will have physical effect once the PLL mode is set to
1172 * integer or fractional.
1173 *
1174 * @return Error if an argument is not valid or status as returned by the
1175 * PM controller (PMU)
1176 */
1177enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid,
1178 enum pm_pll_param param_id,
1179 unsigned int value)
1180{
1181 uint32_t payload[PAYLOAD_ARG_CNT];
1182
1183 /* Check if given node ID is a PLL node */
1184 if (nid < NODE_APLL || nid > NODE_IOPLL)
1185 return PM_RET_ERROR_ARGS;
1186
1187 /* Check if parameter ID is valid and return an error if it's not */
1188 if (param_id >= PM_PLL_PARAM_MAX)
1189 return PM_RET_ERROR_ARGS;
1190
1191 /* Send request to the PMU */
1192 PM_PACK_PAYLOAD4(payload, PM_PLL_SET_PARAMETER, nid, param_id, value);
1193 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1194}
Jolly Shahcb2f45d2019-01-04 11:28:38 -08001195
1196/**
1197 * pm_pll_get_parameter() - Get the PLL parameter value
1198 * @nid Node id of the target PLL
1199 * @param_id ID of the PLL parameter
1200 * @value Location to store the parameter value
1201 *
1202 * @return Error if an argument is not valid or status as returned by the
1203 * PM controller (PMU)
1204 */
1205enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
1206 enum pm_pll_param param_id,
1207 unsigned int *value)
1208{
1209 uint32_t payload[PAYLOAD_ARG_CNT];
1210
1211 /* Check if given node ID is a PLL node */
1212 if (nid < NODE_APLL || nid > NODE_IOPLL)
1213 return PM_RET_ERROR_ARGS;
1214
1215 /* Check if parameter ID is valid and return an error if it's not */
1216 if (param_id >= PM_PLL_PARAM_MAX)
1217 return PM_RET_ERROR_ARGS;
1218
1219 /* Send request to the PMU */
1220 PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
1221 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1222}
Jolly Shah1f0d5852019-01-04 11:32:31 -08001223
1224/**
1225 * pm_pll_set_mode() - Set the PLL mode
1226 * @nid Node id of the target PLL
1227 * @mode PLL mode to be set
1228 *
1229 * If reset mode is set the PM controller will first bypass the PLL and then
1230 * assert the reset. If integer or fractional mode is set the PM controller will
1231 * ensure that the complete PLL programming sequence is satisfied. After this
1232 * function returns success the PLL is locked and its bypass is deasserted.
1233 *
1234 * @return Error if an argument is not valid or status as returned by the
1235 * PM controller (PMU)
1236 */
1237enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
1238{
1239 uint32_t payload[PAYLOAD_ARG_CNT];
1240
1241 /* Check if given node ID is a PLL node */
1242 if (nid < NODE_APLL || nid > NODE_IOPLL)
1243 return PM_RET_ERROR_ARGS;
1244
1245 /* Check if PLL mode is valid */
1246 if (mode >= PM_PLL_MODE_MAX)
1247 return PM_RET_ERROR_ARGS;
1248
1249 /* Send request to the PMU */
1250 PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
1251 return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
1252}
Jolly Shah141421e2019-01-04 11:35:48 -08001253
1254/**
1255 * pm_pll_get_mode() - Get the PLL mode
1256 * @nid Node id of the target PLL
1257 * @mode Location to store the mode of the PLL
1258 *
1259 * @return Error if an argument is not valid or status as returned by the
1260 * PM controller (PMU)
1261 */
1262enum pm_ret_status pm_pll_get_mode(enum pm_node_id nid, enum pm_pll_mode *mode)
1263{
1264 uint32_t payload[PAYLOAD_ARG_CNT];
1265
1266 /* Check if given node ID is a PLL node */
1267 if (nid < NODE_APLL || nid > NODE_IOPLL)
1268 return PM_RET_ERROR_ARGS;
1269
1270 /* Send request to the PMU */
1271 PM_PACK_PAYLOAD2(payload, PM_PLL_GET_MODE, nid);
1272 return pm_ipi_send_sync(primary_proc, payload, mode, 1);
1273}
Kalyani Akula6ebe4832020-11-22 22:42:10 -08001274
1275/**
1276 * pm_register_access() - PM API for register read/write access data
1277 *
1278 * @register_access_id Register_access_id which says register read/write
1279 *
1280 * @address Address of the register to be accessed
1281 *
1282 * @mask Mask value to be used while writing value
1283 *
1284 * @value Value to be written to register
1285 *
1286 * @out Returned output data
1287 *
1288 * This function returns requested data.
1289 *
1290 * @return Returns status, either success or error+reason
1291 */
1292enum pm_ret_status pm_register_access(unsigned int register_access_id,
1293 unsigned int address,
1294 unsigned int mask,
1295 unsigned int value,
1296 unsigned int *out)
1297{
1298 enum pm_ret_status ret;
1299
1300 if (((ZYNQMP_CSU_BASEADDR & address) != ZYNQMP_CSU_BASEADDR) &&
1301 ((CSUDMA_BASE & address) != CSUDMA_BASE) &&
1302 ((RSA_CORE_BASE & address) != RSA_CORE_BASE) &&
1303 ((PMU_GLOBAL_BASE & address) != PMU_GLOBAL_BASE))
1304 return PM_RET_ERROR_ACCESS;
1305
1306 switch (register_access_id) {
1307 case CONFIG_REG_WRITE:
1308 ret = pm_mmio_write(address, mask, value);
1309 break;
1310 case CONFIG_REG_READ:
1311 ret = pm_mmio_read(address, out);
1312 break;
1313 default:
1314 ret = PM_RET_ERROR_ARGS;
1315 WARN("Unimplemented register_access call\n\r");
1316 }
1317 return ret;
1318}
VNSL Durgadeb1a362020-11-23 04:46:04 -08001319
1320/**
1321 * pm_efuse_access() - To program or read efuse bits.
1322 *
1323 * This function provides access to the xilskey library to program/read
1324 * efuse bits.
1325 *
1326 * address_low: lower 32-bit Linear memory space address
1327 * address_high: higher 32-bit Linear memory space address
1328 *
1329 * value: Returned output value
1330 *
1331 * @return Returns status, either success or error+reason
1332 *
1333 */
1334enum pm_ret_status pm_efuse_access(uint32_t address_high,
1335 uint32_t address_low,
1336 uint32_t *value)
1337{
1338 uint32_t payload[PAYLOAD_ARG_CNT];
1339
1340 /* Send request to the PMU */
1341 PM_PACK_PAYLOAD3(payload, PM_EFUSE_ACCESS, address_high, address_low);
1342
Venkatesh Yadav Abbarapu7ace4af2020-11-23 04:26:54 -08001343 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1344}
1345
1346enum pm_ret_status em_set_action(unsigned int *value)
1347{
1348 uint32_t payload[PAYLOAD_ARG_CNT];
1349
1350 /* Send request to the PMU */
1351 EM_PACK_PAYLOAD1(payload, EM_SET_ACTION);
1352 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1353}
1354
1355enum pm_ret_status em_remove_action(unsigned int *value)
1356{
1357 uint32_t payload[PAYLOAD_ARG_CNT];
1358
1359 /* Send request to the PMU */
1360 EM_PACK_PAYLOAD1(payload, EM_REMOVE_ACTION);
1361 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1362}
1363
1364enum pm_ret_status em_send_errors(unsigned int *value)
1365{
1366 uint32_t payload[PAYLOAD_ARG_CNT];
1367
1368 /* Send request to the PMU */
1369 EM_PACK_PAYLOAD1(payload, EM_SEND_ERRORS);
VNSL Durgadeb1a362020-11-23 04:46:04 -08001370 return pm_ipi_send_sync(primary_proc, payload, value, 1);
1371}