1 /* 2 * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved. 3 * Copyright (c) 2022-2025, 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 or NON_SECURE. 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 (void) x4; 74 (void) flags; 75 (void) cookie; 76 int32_t ret; 77 uint32_t ipi_local_id; 78 uint32_t ipi_remote_id; 79 uint32_t is_secure; 80 81 ipi_local_id = (uint32_t)(x1 & UNSIGNED32_MASK); 82 ipi_remote_id = (uint32_t)(x2 & UNSIGNED32_MASK); 83 84 /* OEN Number 48 to 63 is for Trusted App and OS 85 * GET_SMC_OEN limits the return value of OEN number to 63 by bitwise 86 * AND operation with 0x3F. 87 * Upper limit check for OEN value is not required. 88 */ 89 if (GET_SMC_OEN(smc_fid) >= OEN_TAP_START) { 90 is_secure = 1; 91 } else { 92 is_secure = 0; 93 } 94 95 /* Validate IPI mailbox access */ 96 ret = ipi_mb_validate(ipi_local_id, ipi_remote_id, is_secure); 97 if (ret != 0) 98 SMC_RET1(handle, ret); 99 100 switch (GET_SMC_NUM(smc_fid)) { 101 case (uint32_t)IPI_MAILBOX_OPEN: 102 ipi_mb_open(ipi_local_id, ipi_remote_id); 103 SMC_RET1(handle, 0); 104 case (uint32_t)IPI_MAILBOX_RELEASE: 105 ipi_mb_release(ipi_local_id, ipi_remote_id); 106 SMC_RET1(handle, 0); 107 case (uint32_t)IPI_MAILBOX_STATUS_ENQUIRY: 108 { 109 bool disable_interrupt; 110 111 disable_interrupt = ((x3 & IPI_SMC_ENQUIRY_DIRQ_MASK) != 0U); 112 ret = (int32_t)ipi_mb_enquire_status(ipi_local_id, ipi_remote_id); 113 if ((((uint32_t)ret & IPI_MB_STATUS_RECV_PENDING) > 0U) && disable_interrupt) { 114 ipi_mb_disable_irq(ipi_local_id, ipi_remote_id); 115 } 116 SMC_RET1(handle, ret); 117 } 118 case (uint32_t)IPI_MAILBOX_NOTIFY: 119 { 120 uint32_t is_blocking; 121 122 is_blocking = (uint32_t)((x3 & IPI_SMC_NOTIFY_BLOCK_MASK) != 0U); 123 ipi_mb_notify(ipi_local_id, ipi_remote_id, is_blocking); 124 SMC_RET1(handle, 0); 125 } 126 case (uint32_t)IPI_MAILBOX_ACK: 127 { 128 bool enable_interrupt; 129 130 enable_interrupt = ((x3 & IPI_SMC_ACK_EIRQ_MASK) != 0U); 131 ipi_mb_ack(ipi_local_id, ipi_remote_id); 132 if (enable_interrupt != 0) { 133 ipi_mb_enable_irq(ipi_local_id, ipi_remote_id); 134 } 135 SMC_RET1(handle, 0); 136 } 137 case (uint32_t)IPI_MAILBOX_ENABLE_IRQ: 138 ipi_mb_enable_irq(ipi_local_id, ipi_remote_id); 139 SMC_RET1(handle, 0); 140 case (uint32_t)IPI_MAILBOX_DISABLE_IRQ: 141 ipi_mb_disable_irq(ipi_local_id, ipi_remote_id); 142 SMC_RET1(handle, 0); 143 default: 144 WARN("Unimplemented IPI service call: 0x%x\n", smc_fid); 145 SMC_RET1(handle, SMC_UNK); 146 } 147 } 148