1 /* 2 * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved. 3 * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 /* 9 * Top-level SMC handler for ZynqMP IPI Mailbox doorbell functions. 10 */ 11 12 #include <errno.h> 13 #include <string.h> 14 15 #include <common/debug.h> 16 #include <common/runtime_svc.h> 17 #include <lib/bakery_lock.h> 18 #include <lib/mmio.h> 19 20 #include <ipi.h> 21 #include "ipi_mailbox_svc.h" 22 #include <plat_ipi.h> 23 #include <plat_private.h> 24 25 /********************************************************************* 26 * Macros definitions 27 ********************************************************************/ 28 29 /* IPI SMC calls macros: */ 30 #define IPI_SMC_OPEN_IRQ_MASK 0x00000001U /* IRQ enable bit in IPI 31 * open SMC call 32 */ 33 #define IPI_SMC_NOTIFY_BLOCK_MASK 0x00000001U /* Flag to indicate if 34 * IPI notification needs 35 * to be blocking. 36 */ 37 #define IPI_SMC_ENQUIRY_DIRQ_MASK 0x00000001U /* Flag to indicate if 38 * notification interrupt 39 * to be disabled. 40 */ 41 #define IPI_SMC_ACK_EIRQ_MASK 0x00000001U /* Flag to indicate if 42 * notification interrupt 43 * to be enable. 44 */ 45 46 #define UNSIGNED32_MASK 0xFFFFFFFFU /* 32bit mask */ 47 48 /** 49 * ipi_smc_handler() - SMC handler for IPI SMC calls. 50 * @smc_fid: Function identifier. 51 * @x1: Arguments. 52 * @x2: Arguments. 53 * @x3: Arguments. 54 * @x4: Arguments. 55 * @cookie: Unused. 56 * @handle: Pointer to caller's context structure. 57 * @flags: SECURE_FLAG or NON_SECURE_FLAG. 58 * 59 * Return: Unused. 60 * 61 * Determines that smc_fid is valid and supported PM SMC Function ID from the 62 * list of pm_api_ids, otherwise completes the request with 63 * the unknown SMC Function ID. 64 * 65 * The SMC calls for PM service are forwarded from SIP Service SMC handler 66 * function with rt_svc_handle signature. 67 * 68 */ 69 uint64_t ipi_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, 70 uint64_t x3, uint64_t x4, const void *cookie, 71 void *handle, uint64_t flags) 72 { 73 int32_t ret; 74 uint32_t ipi_local_id; 75 uint32_t ipi_remote_id; 76 uint32_t is_secure; 77 78 ipi_local_id = x1 & UNSIGNED32_MASK; 79 ipi_remote_id = x2 & UNSIGNED32_MASK; 80 81 /* OEN Number 48 to 63 is for Trusted App and OS 82 * GET_SMC_OEN limits the return value of OEN number to 63 by bitwise 83 * AND operation with 0x3F. 84 * Upper limit check for OEN value is not required. 85 */ 86 if (GET_SMC_OEN(smc_fid) >= OEN_TAP_START) { 87 is_secure = 1; 88 } else { 89 is_secure = 0; 90 } 91 92 /* Validate IPI mailbox access */ 93 ret = ipi_mb_validate(ipi_local_id, ipi_remote_id, is_secure); 94 if (ret) 95 SMC_RET1(handle, ret); 96 97 switch (GET_SMC_NUM(smc_fid)) { 98 case IPI_MAILBOX_OPEN: 99 ipi_mb_open(ipi_local_id, ipi_remote_id); 100 SMC_RET1(handle, 0); 101 case IPI_MAILBOX_RELEASE: 102 ipi_mb_release(ipi_local_id, ipi_remote_id); 103 SMC_RET1(handle, 0); 104 case IPI_MAILBOX_STATUS_ENQUIRY: 105 { 106 int32_t disable_irq; 107 108 disable_irq = (x3 & IPI_SMC_ENQUIRY_DIRQ_MASK) ? 1 : 0; 109 ret = ipi_mb_enquire_status(ipi_local_id, ipi_remote_id); 110 if ((ret & IPI_MB_STATUS_RECV_PENDING) && disable_irq) 111 ipi_mb_disable_irq(ipi_local_id, ipi_remote_id); 112 SMC_RET1(handle, ret); 113 } 114 case IPI_MAILBOX_NOTIFY: 115 { 116 uint32_t is_blocking; 117 118 is_blocking = (x3 & IPI_SMC_NOTIFY_BLOCK_MASK) ? 1 : 0; 119 ipi_mb_notify(ipi_local_id, ipi_remote_id, is_blocking); 120 SMC_RET1(handle, 0); 121 } 122 case IPI_MAILBOX_ACK: 123 { 124 int32_t enable_irq; 125 126 enable_irq = (x3 & IPI_SMC_ACK_EIRQ_MASK) ? 1 : 0; 127 ipi_mb_ack(ipi_local_id, ipi_remote_id); 128 if (enable_irq) 129 ipi_mb_enable_irq(ipi_local_id, ipi_remote_id); 130 SMC_RET1(handle, 0); 131 } 132 case IPI_MAILBOX_ENABLE_IRQ: 133 ipi_mb_enable_irq(ipi_local_id, ipi_remote_id); 134 SMC_RET1(handle, 0); 135 case IPI_MAILBOX_DISABLE_IRQ: 136 ipi_mb_disable_irq(ipi_local_id, ipi_remote_id); 137 SMC_RET1(handle, 0); 138 default: 139 WARN("Unimplemented IPI service call: 0x%x\n", smc_fid); 140 SMC_RET1(handle, SMC_UNK); 141 } 142 } 143