blob: faa2827450bb44b2e3abd2b6fcfc6205dffc4e1f [file] [log] [blame]
Soren Brinkmann76fcae32016-03-06 20:16:27 -08001/*
Rajan Vaja83687612018-01-17 02:39:20 -08002 * Copyright (c) 2013-2018, 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 * Top-level SMC handler for ZynqMP power management calls and
9 * IPI setup functions for communication with PMU.
10 */
11
12#include <errno.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013
14#include <common/runtime_svc.h>
15#if ZYNQMP_WDT_RESTART
16#include <arch_helpers.h>
17#include <drivers/arm/gicv2.h>
18#include <lib/mmio.h>
19#include <lib/spinlock.h>
20#include <plat/common/platform.h>
21#endif
22
Jolly Shah0bfd7002019-01-08 11:10:47 -080023#include <plat_private.h>
Soren Brinkmann76fcae32016-03-06 20:16:27 -080024#include "pm_api_sys.h"
25#include "pm_client.h"
26#include "pm_ipi.h"
Soren Brinkmann76fcae32016-03-06 20:16:27 -080027
Siva Durga Prasad Paladugu43b23a32018-04-27 16:26:47 +053028#define PM_SET_SUSPEND_MODE 0xa02
Rajan Vajac7ee23d2018-02-14 23:10:54 -080029#define PM_GET_TRUSTZONE_VERSION 0xa03
Soren Brinkmann84f0af42016-09-30 14:24:25 -070030
Siva Durga Prasad Paladugu79f75952018-04-30 19:39:49 +053031/* !0 - UP, 0 - DOWN */
32static int32_t pm_up = 0;
Soren Brinkmann76fcae32016-03-06 20:16:27 -080033
Siva Durga Prasad Paladuguefd431b2018-04-30 20:12:12 +053034#if ZYNQMP_WDT_RESTART
35static spinlock_t inc_lock;
36static int active_cores = 0;
37#endif
38
39
Soren Brinkmann76fcae32016-03-06 20:16:27 -080040/**
41 * pm_context - Structure which contains data for power management
42 * @api_version version of PM API, must match with one on PMU side
43 * @payload payload array used to store received
44 * data from ipi buffer registers
45 */
46static struct {
47 uint32_t api_version;
48 uint32_t payload[PAYLOAD_ARG_CNT];
49} pm_ctx;
50
Siva Durga Prasad Paladuguefd431b2018-04-30 20:12:12 +053051#if ZYNQMP_WDT_RESTART
52/**
53 * trigger_wdt_restart() - Trigger warm restart event to APU cores
54 *
55 * This function triggers SGI for all active APU CPUs. SGI handler then
56 * power down CPU and call system reset.
57 */
58static void trigger_wdt_restart(void)
59{
60 uint32_t core_count = 0;
61 uint32_t core_status[3];
62 uint32_t target_cpu_list = 0;
63 int i;
64
65 for (i = 0; i < 4; i++) {
66 pm_get_node_status(NODE_APU_0 + i, core_status);
67 if (core_status[0] == 1) {
68 core_count++;
69 target_cpu_list |= (1 << i);
70 }
71 }
72
73 spin_lock(&inc_lock);
74 active_cores = core_count;
75 spin_unlock(&inc_lock);
76
77 INFO("Active Cores: %d\n", active_cores);
78
79 /* trigger SGI to active cores */
80 gicv2_raise_sgi(ARM_IRQ_SEC_SGI_7, target_cpu_list);
81}
82
83/**
84 * ttc_fiq_handler() - TTC Handler for timer event
85 * @id number of the highest priority pending interrupt of the type
86 * that this handler was registered for
87 * @flags security state, bit[0]
88 * @handler pointer to 'cpu_context' structure of the current CPU for the
89 * security state specified in the 'flags' parameter
90 * @cookie unused
91 *
92 * Function registered as INTR_TYPE_EL3 interrupt handler
93 *
94 * When WDT event is received in PMU, PMU needs to notify master to do cleanup
95 * if required. PMU sets up timer and starts timer to overflow in zero time upon
96 * WDT event. ATF handles this timer event and takes necessary action required
97 * for warm restart.
98 *
99 * In presence of non-secure software layers (EL1/2) sets the interrupt
100 * at registered entrance in GIC and informs that PMU responsed or demands
101 * action.
102 */
103static uint64_t ttc_fiq_handler(uint32_t id, uint32_t flags, void *handle,
104 void *cookie)
105{
106 INFO("BL31: Got TTC FIQ\n");
107
108 /* Clear TTC interrupt by reading interrupt register */
109 mmio_read_32(TTC3_INTR_REGISTER_1);
110
111 /* Disable the timer interrupts */
112 mmio_write_32(TTC3_INTR_ENABLE_1, 0);
113
114 trigger_wdt_restart();
115
116 return 0;
117}
118
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800119/**
Siva Durga Prasad Paladuguefd431b2018-04-30 20:12:12 +0530120 * zynqmp_sgi7_irq() - Handler for SGI7 IRQ
121 * @id number of the highest priority pending interrupt of the type
122 * that this handler was registered for
123 * @flags security state, bit[0]
124 * @handler pointer to 'cpu_context' structure of the current CPU for the
125 * security state specified in the 'flags' parameter
126 * @cookie unused
127 *
128 * Function registered as INTR_TYPE_EL3 interrupt handler
129 *
130 * On receiving WDT event from PMU, ATF generates SGI7 to all running CPUs.
131 * In response to SGI7 interrupt, each CPUs do clean up if required and last
132 * running CPU calls system restart.
133 */
134static uint64_t __unused __dead2 zynqmp_sgi7_irq(uint32_t id, uint32_t flags,
135 void *handle, void *cookie)
136{
137 int i;
138 /* enter wfi and stay there */
139 INFO("Entering wfi\n");
140
141 spin_lock(&inc_lock);
142 active_cores--;
143
144 for (i = 0; i < 4; i++) {
145 mmio_write_32(BASE_GICD_BASE + GICD_CPENDSGIR + 4 * i,
146 0xffffffff);
147 }
148
149 spin_unlock(&inc_lock);
150
151 if (active_cores == 0) {
152 pm_system_shutdown(PMF_SHUTDOWN_TYPE_RESET,
153 PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM);
154 }
155
156 /* enter wfi and stay there */
157 while (1)
158 wfi();
159}
160
161/**
162 * pm_wdt_restart_setup() - Setup warm restart interrupts
163 *
164 * This function sets up handler for SGI7 and TTC interrupts
165 * used for warm restart.
166 */
167static int pm_wdt_restart_setup(void)
168{
169 int ret;
170
171 /* register IRQ handler for SGI7 */
172 ret = request_intr_type_el3(ARM_IRQ_SEC_SGI_7, zynqmp_sgi7_irq);
173 if (ret) {
174 WARN("BL31: registering SGI7 interrupt failed\n");
175 goto err;
176 }
177
178 ret = request_intr_type_el3(IRQ_TTC3_1, ttc_fiq_handler);
179 if (ret)
180 WARN("BL31: registering TTC3 interrupt failed\n");
181
182err:
183 return ret;
184}
185#endif
186
187/**
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800188 * pm_setup() - PM service setup
189 *
190 * @return On success, the initialization function must return 0.
191 * Any other return value will cause the framework to ignore
192 * the service
193 *
194 * Initialization functions for ZynqMP power management for
195 * communicaton with PMU.
196 *
197 * Called from sip_svc_setup initialization function with the
198 * rt_svc_init signature.
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800199 */
200int pm_setup(void)
201{
Wendy Liang328105c2017-10-03 23:21:11 -0700202 int status, ret;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800203
Wendy Liang328105c2017-10-03 23:21:11 -0700204 status = pm_ipi_init(primary_proc);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800205
Siva Durga Prasad Paladuguefd431b2018-04-30 20:12:12 +0530206#if ZYNQMP_WDT_RESTART
207 status = pm_wdt_restart_setup();
208 if (status)
209 WARN("BL31: warm-restart setup failed\n");
210#endif
211
Wendy Liang328105c2017-10-03 23:21:11 -0700212 if (status >= 0) {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800213 INFO("BL31: PM Service Init Complete: API v%d.%d\n",
214 PM_VERSION_MAJOR, PM_VERSION_MINOR);
Wendy Liang328105c2017-10-03 23:21:11 -0700215 ret = 0;
216 } else {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800217 INFO("BL31: PM Service Init Failed, Error Code %d!\n", status);
Wendy Liang328105c2017-10-03 23:21:11 -0700218 ret = status;
219 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800220
Siva Durga Prasad Paladugu79f75952018-04-30 19:39:49 +0530221 pm_up = !status;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800222
Wendy Liang328105c2017-10-03 23:21:11 -0700223 return ret;
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800224}
225
226/**
227 * pm_smc_handler() - SMC handler for PM-API calls coming from EL1/EL2.
228 * @smc_fid - Function Identifier
229 * @x1 - x4 - Arguments
230 * @cookie - Unused
231 * @handler - Pointer to caller's context structure
232 *
233 * @return - Unused
234 *
235 * Determines that smc_fid is valid and supported PM SMC Function ID from the
236 * list of pm_api_ids, otherwise completes the request with
237 * the unknown SMC Function ID
238 *
239 * The SMC calls for PM service are forwarded from SIP Service SMC handler
240 * function with rt_svc_handle signature
241 */
242uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3,
243 uint64_t x4, void *cookie, void *handle, uint64_t flags)
244{
245 enum pm_ret_status ret;
246
247 uint32_t pm_arg[4];
248
249 /* Handle case where PM wasn't initialized properly */
Siva Durga Prasad Paladugu79f75952018-04-30 19:39:49 +0530250 if (!pm_up)
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800251 SMC_RET1(handle, SMC_UNK);
252
253 pm_arg[0] = (uint32_t)x1;
254 pm_arg[1] = (uint32_t)(x1 >> 32);
255 pm_arg[2] = (uint32_t)x2;
256 pm_arg[3] = (uint32_t)(x2 >> 32);
257
258 switch (smc_fid & FUNCID_NUM_MASK) {
259 /* PM API Functions */
260 case PM_SELF_SUSPEND:
261 ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
262 pm_arg[3]);
263 SMC_RET1(handle, (uint64_t)ret);
264
265 case PM_REQ_SUSPEND:
266 ret = pm_req_suspend(pm_arg[0], pm_arg[1], pm_arg[2],
267 pm_arg[3]);
268 SMC_RET1(handle, (uint64_t)ret);
269
270 case PM_REQ_WAKEUP:
Filip Drazic78ba1452017-02-07 12:03:57 +0100271 {
272 /* Use address flag is encoded in the 1st bit of the low-word */
273 unsigned int set_addr = pm_arg[1] & 0x1;
274 uint64_t address = (uint64_t)pm_arg[2] << 32;
275
276 address |= pm_arg[1] & (~0x1);
277 ret = pm_req_wakeup(pm_arg[0], set_addr, address,
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800278 pm_arg[3]);
279 SMC_RET1(handle, (uint64_t)ret);
Filip Drazic78ba1452017-02-07 12:03:57 +0100280 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800281
282 case PM_FORCE_POWERDOWN:
283 ret = pm_force_powerdown(pm_arg[0], pm_arg[1]);
284 SMC_RET1(handle, (uint64_t)ret);
285
286 case PM_ABORT_SUSPEND:
287 ret = pm_abort_suspend(pm_arg[0]);
288 SMC_RET1(handle, (uint64_t)ret);
289
290 case PM_SET_WAKEUP_SOURCE:
291 ret = pm_set_wakeup_source(pm_arg[0], pm_arg[1], pm_arg[2]);
292 SMC_RET1(handle, (uint64_t)ret);
293
294 case PM_SYSTEM_SHUTDOWN:
Soren Brinkmann58fbb9b2016-09-02 09:50:54 -0700295 ret = pm_system_shutdown(pm_arg[0], pm_arg[1]);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800296 SMC_RET1(handle, (uint64_t)ret);
297
298 case PM_REQ_NODE:
299 ret = pm_req_node(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
300 SMC_RET1(handle, (uint64_t)ret);
301
302 case PM_RELEASE_NODE:
303 ret = pm_release_node(pm_arg[0]);
304 SMC_RET1(handle, (uint64_t)ret);
305
306 case PM_SET_REQUIREMENT:
307 ret = pm_set_requirement(pm_arg[0], pm_arg[1], pm_arg[2],
308 pm_arg[3]);
309 SMC_RET1(handle, (uint64_t)ret);
310
311 case PM_SET_MAX_LATENCY:
312 ret = pm_set_max_latency(pm_arg[0], pm_arg[1]);
313 SMC_RET1(handle, (uint64_t)ret);
314
315 case PM_GET_API_VERSION:
316 /* Check is PM API version already verified */
Soren Brinkmanna1b0a902016-09-30 11:30:21 -0700317 if (pm_ctx.api_version == PM_VERSION) {
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800318 SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
319 ((uint64_t)PM_VERSION << 32));
Soren Brinkmanna1b0a902016-09-30 11:30:21 -0700320 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800321
322 ret = pm_get_api_version(&pm_ctx.api_version);
Soren Brinkmanna1b0a902016-09-30 11:30:21 -0700323 /*
324 * Enable IPI IRQ
325 * assume the rich OS is OK to handle callback IRQs now.
326 * Even if we were wrong, it would not enable the IRQ in
327 * the GIC.
328 */
Wendy Liang328105c2017-10-03 23:21:11 -0700329 pm_ipi_irq_enable(primary_proc);
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800330 SMC_RET1(handle, (uint64_t)ret |
331 ((uint64_t)pm_ctx.api_version << 32));
332
333 case PM_SET_CONFIGURATION:
334 ret = pm_set_configuration(pm_arg[0]);
335 SMC_RET1(handle, (uint64_t)ret);
336
Filip Drazicf2ddd912017-03-15 11:50:47 +0100337 case PM_INIT_FINALIZE:
338 ret = pm_init_finalize();
339 SMC_RET1(handle, (uint64_t)ret);
340
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800341 case PM_GET_NODE_STATUS:
Anes Hadziahmetagic1caf88e2017-01-27 18:42:44 +0100342 {
343 uint32_t buff[3];
344
345 ret = pm_get_node_status(pm_arg[0], buff);
346 SMC_RET2(handle, (uint64_t)ret | ((uint64_t)buff[0] << 32),
347 (uint64_t)buff[1] | ((uint64_t)buff[2] << 32));
348 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800349
350 case PM_GET_OP_CHARACTERISTIC:
Anes Hadziahmetagic92aee012016-05-12 16:17:30 +0200351 {
352 uint32_t result;
353
354 ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1], &result);
355 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)result << 32));
356 }
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800357
358 case PM_REGISTER_NOTIFIER:
359 ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2],
360 pm_arg[3]);
361 SMC_RET1(handle, (uint64_t)ret);
362
363 case PM_RESET_ASSERT:
364 ret = pm_reset_assert(pm_arg[0], pm_arg[1]);
365 SMC_RET1(handle, (uint64_t)ret);
366
367 case PM_RESET_GET_STATUS:
368 {
369 uint32_t reset_status;
370
371 ret = pm_reset_get_status(pm_arg[0], &reset_status);
372 SMC_RET1(handle, (uint64_t)ret |
373 ((uint64_t)reset_status << 32));
374 }
375
376 /* PM memory access functions */
377 case PM_MMIO_WRITE:
378 ret = pm_mmio_write(pm_arg[0], pm_arg[1], pm_arg[2]);
379 SMC_RET1(handle, (uint64_t)ret);
380
381 case PM_MMIO_READ:
382 {
383 uint32_t value;
384
385 ret = pm_mmio_read(pm_arg[0], &value);
386 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
387 }
Nava kishore Manne68d460c2016-08-20 23:18:09 +0530388
389 case PM_FPGA_LOAD:
390 ret = pm_fpga_load(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3]);
391 SMC_RET1(handle, (uint64_t)ret);
392
393 case PM_FPGA_GET_STATUS:
394 {
395 uint32_t value;
396
397 ret = pm_fpga_get_status(&value);
398 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
399 }
400
Siva Durga Prasad Paladugu16427d12016-08-24 11:45:47 +0530401 case PM_GET_CHIPID:
Soren Brinkmanncb366812016-09-22 12:21:11 -0700402 {
403 uint32_t result[2];
404
405 ret = pm_get_chipid(result);
406 SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32),
407 result[1]);
408 }
Siva Durga Prasad Paladugu16427d12016-08-24 11:45:47 +0530409
Siva Durga Prasad Paladugude93d982018-04-30 15:49:27 +0530410 case PM_SECURE_RSA_AES:
411 ret = pm_secure_rsaaes(pm_arg[0], pm_arg[1], pm_arg[2],
412 pm_arg[3]);
413 SMC_RET1(handle, (uint64_t)ret);
414
Rajan Vaja83687612018-01-17 02:39:20 -0800415 case PM_PINCTRL_REQUEST:
416 ret = pm_pinctrl_request(pm_arg[0]);
417 SMC_RET1(handle, (uint64_t)ret);
418
419 case PM_PINCTRL_RELEASE:
420 ret = pm_pinctrl_release(pm_arg[0]);
421 SMC_RET1(handle, (uint64_t)ret);
422
423 case PM_PINCTRL_GET_FUNCTION:
424 {
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800425 uint32_t value = 0;
Rajan Vaja83687612018-01-17 02:39:20 -0800426
427 ret = pm_pinctrl_get_function(pm_arg[0], &value);
428 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
429 }
430
431 case PM_PINCTRL_SET_FUNCTION:
432 ret = pm_pinctrl_set_function(pm_arg[0], pm_arg[1]);
433 SMC_RET1(handle, (uint64_t)ret);
434
435 case PM_PINCTRL_CONFIG_PARAM_GET:
436 {
437 uint32_t value;
438
439 ret = pm_pinctrl_get_config(pm_arg[0], pm_arg[1], &value);
440 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
441 }
442
443 case PM_PINCTRL_CONFIG_PARAM_SET:
444 ret = pm_pinctrl_set_config(pm_arg[0], pm_arg[1], pm_arg[2]);
445 SMC_RET1(handle, (uint64_t)ret);
446
Rajan Vaja5529a012018-01-17 02:39:23 -0800447 case PM_IOCTL:
448 {
449 uint32_t value;
450
451 ret = pm_ioctl(pm_arg[0], pm_arg[1], pm_arg[2],
452 pm_arg[3], &value);
453 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
454 }
455
Rajan Vaja35116132018-01-17 02:39:25 -0800456 case PM_QUERY_DATA:
457 {
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800458 uint32_t data[4] = { 0 };
Rajan Vaja35116132018-01-17 02:39:25 -0800459
460 ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2],
461 pm_arg[3], data);
462 SMC_RET2(handle, (uint64_t)data[0] | ((uint64_t)data[1] << 32),
463 (uint64_t)data[2] | ((uint64_t)data[3] << 32));
464 }
465
466 case PM_CLOCK_ENABLE:
467 ret = pm_clock_enable(pm_arg[0]);
468 SMC_RET1(handle, (uint64_t)ret);
469
470 case PM_CLOCK_DISABLE:
471 ret = pm_clock_disable(pm_arg[0]);
472 SMC_RET1(handle, (uint64_t)ret);
473
474 case PM_CLOCK_GETSTATE:
475 {
476 uint32_t value;
477
478 ret = pm_clock_getstate(pm_arg[0], &value);
479 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
480 }
481
482 case PM_CLOCK_SETDIVIDER:
483 ret = pm_clock_setdivider(pm_arg[0], pm_arg[1]);
484 SMC_RET1(handle, (uint64_t)ret);
485
486 case PM_CLOCK_GETDIVIDER:
487 {
488 uint32_t value;
489
490 ret = pm_clock_getdivider(pm_arg[0], &value);
491 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
492 }
493
494 case PM_CLOCK_SETRATE:
495 ret = pm_clock_setrate(pm_arg[0],
496 ((uint64_t)pm_arg[2]) << 32 | pm_arg[1]);
497
498 SMC_RET1(handle, (uint64_t)ret);
499
500 case PM_CLOCK_GETRATE:
501 {
502 uint64_t value;
503
504 ret = pm_clock_getrate(pm_arg[0], &value);
Jolly Shah69fb5bf2018-02-07 16:25:41 -0800505 SMC_RET2(handle, (uint64_t)ret |
506 (((uint64_t)value & 0xFFFFFFFFU) << 32U),
507 (value >> 32U) & 0xFFFFFFFFU);
Rajan Vaja35116132018-01-17 02:39:25 -0800508
509 }
510
511 case PM_CLOCK_SETPARENT:
512 ret = pm_clock_setparent(pm_arg[0], pm_arg[1]);
513 SMC_RET1(handle, (uint64_t)ret);
514
515 case PM_CLOCK_GETPARENT:
516 {
517 uint32_t value;
518
519 ret = pm_clock_getparent(pm_arg[0], &value);
520 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
521 }
522
Rajan Vajac7ee23d2018-02-14 23:10:54 -0800523 case PM_GET_TRUSTZONE_VERSION:
524 SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS |
525 ((uint64_t)ZYNQMP_TZ_VERSION << 32));
526
Siva Durga Prasad Paladugu43b23a32018-04-27 16:26:47 +0530527 case PM_SET_SUSPEND_MODE:
528 ret = pm_set_suspend_mode(pm_arg[0]);
529 SMC_RET1(handle, (uint64_t)ret);
530
Siva Durga Prasad Paladuguf3994cc2018-05-01 11:12:55 +0530531 case PM_SECURE_SHA:
532 ret = pm_sha_hash(pm_arg[0], pm_arg[1], pm_arg[2],
533 pm_arg[3]);
534 SMC_RET1(handle, (uint64_t)ret);
535
536 case PM_SECURE_RSA:
537 ret = pm_rsa_core(pm_arg[0], pm_arg[1], pm_arg[2],
538 pm_arg[3]);
539 SMC_RET1(handle, (uint64_t)ret);
540
Siva Durga Prasad Paladugua4ed4b22018-04-30 20:06:58 +0530541 case PM_SECURE_IMAGE:
542 {
543 uint32_t result[2];
544
545 ret = pm_secure_image(pm_arg[0], pm_arg[1], pm_arg[2],
546 pm_arg[3], &result[0]);
547 SMC_RET2(handle, (uint64_t)ret | ((uint64_t)result[0] << 32),
548 result[1]);
549 }
550
Siva Durga Prasad Paladugu7c6516a2018-09-04 17:41:34 +0530551 case PM_FPGA_READ:
552 {
553 uint32_t value;
554
555 ret = pm_fpga_read(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3],
556 &value);
557 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
558 }
559
Siva Durga Prasad Paladugu8bd905b2018-09-04 18:05:50 +0530560 case PM_SECURE_AES:
561 {
562 uint32_t value;
563
564 ret = pm_aes_engine(pm_arg[0], pm_arg[1], &value);
565 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32);
566 }
567
Jolly Shaha7cc5ee2019-01-02 12:27:00 -0800568 case PM_PLL_SET_PARAMETER:
569 ret = pm_pll_set_parameter(pm_arg[0], pm_arg[1], pm_arg[2]);
570 SMC_RET1(handle, (uint64_t)ret);
571
Jolly Shahcb2f45d2019-01-04 11:28:38 -0800572 case PM_PLL_GET_PARAMETER:
573 {
574 uint32_t value;
575
576 ret = pm_pll_get_parameter(pm_arg[0], pm_arg[1], &value);
577 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value << 32));
578 }
579
Jolly Shah1f0d5852019-01-04 11:32:31 -0800580 case PM_PLL_SET_MODE:
581 ret = pm_pll_set_mode(pm_arg[0], pm_arg[1]);
582 SMC_RET1(handle, (uint64_t)ret);
583
Jolly Shah141421e2019-01-04 11:35:48 -0800584 case PM_PLL_GET_MODE:
585 {
586 uint32_t mode;
587
588 ret = pm_pll_get_mode(pm_arg[0], &mode);
589 SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32));
590 }
591
Soren Brinkmann76fcae32016-03-06 20:16:27 -0800592 default:
593 WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
594 SMC_RET1(handle, SMC_UNK);
595 }
596}