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