1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * Copyright (c) 2020-2022, Xilinx, Inc. All rights reserved. 4*91f16700Schasinglulu * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. 5*91f16700Schasinglulu * 6*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 7*91f16700Schasinglulu */ 8*91f16700Schasinglulu 9*91f16700Schasinglulu /* 10*91f16700Schasinglulu * Xilinx IPI agent registers access management 11*91f16700Schasinglulu */ 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <errno.h> 14*91f16700Schasinglulu #include <string.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #include <common/debug.h> 17*91f16700Schasinglulu #include <common/runtime_svc.h> 18*91f16700Schasinglulu #include <lib/bakery_lock.h> 19*91f16700Schasinglulu #include <lib/mmio.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu #include <ipi.h> 22*91f16700Schasinglulu #include <plat_private.h> 23*91f16700Schasinglulu 24*91f16700Schasinglulu /********************************************************************* 25*91f16700Schasinglulu * Macros definitions 26*91f16700Schasinglulu ********************************************************************/ 27*91f16700Schasinglulu 28*91f16700Schasinglulu /* IPI registers offsets macros */ 29*91f16700Schasinglulu #define IPI_TRIG_OFFSET 0x00U 30*91f16700Schasinglulu #define IPI_OBR_OFFSET 0x04U 31*91f16700Schasinglulu #define IPI_ISR_OFFSET 0x10U 32*91f16700Schasinglulu #define IPI_IMR_OFFSET 0x14U 33*91f16700Schasinglulu #define IPI_IER_OFFSET 0x18U 34*91f16700Schasinglulu #define IPI_IDR_OFFSET 0x1CU 35*91f16700Schasinglulu 36*91f16700Schasinglulu /* IPI register start offset */ 37*91f16700Schasinglulu #define IPI_REG_BASE(I) (ipi_table[(I)].ipi_reg_base) 38*91f16700Schasinglulu 39*91f16700Schasinglulu /* IPI register bit mask */ 40*91f16700Schasinglulu #define IPI_BIT_MASK(I) (ipi_table[(I)].ipi_bit_mask) 41*91f16700Schasinglulu 42*91f16700Schasinglulu /* IPI configuration table */ 43*91f16700Schasinglulu static const struct ipi_config *ipi_table; 44*91f16700Schasinglulu 45*91f16700Schasinglulu /* Total number of IPI */ 46*91f16700Schasinglulu static uint32_t ipi_total; 47*91f16700Schasinglulu 48*91f16700Schasinglulu /** 49*91f16700Schasinglulu * ipi_config_table_init() - Initialize IPI configuration data. 50*91f16700Schasinglulu * @ipi_config_table: IPI configuration table. 51*91f16700Schasinglulu * @total_ipi: Total number of IPI available. 52*91f16700Schasinglulu * 53*91f16700Schasinglulu */ 54*91f16700Schasinglulu void ipi_config_table_init(const struct ipi_config *ipi_config_table, 55*91f16700Schasinglulu uint32_t total_ipi) 56*91f16700Schasinglulu { 57*91f16700Schasinglulu ipi_table = ipi_config_table; 58*91f16700Schasinglulu ipi_total = total_ipi; 59*91f16700Schasinglulu } 60*91f16700Schasinglulu 61*91f16700Schasinglulu /** 62*91f16700Schasinglulu * is_ipi_mb_within_range() - verify if IPI mailbox is within range. 63*91f16700Schasinglulu * @local: local IPI ID. 64*91f16700Schasinglulu * @remote: remote IPI ID. 65*91f16700Schasinglulu * 66*91f16700Schasinglulu * Return: - 1 if within range, 0 if not. 67*91f16700Schasinglulu * 68*91f16700Schasinglulu */ 69*91f16700Schasinglulu static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote) 70*91f16700Schasinglulu { 71*91f16700Schasinglulu int ret = 1; 72*91f16700Schasinglulu 73*91f16700Schasinglulu if (remote >= ipi_total || local >= ipi_total) { 74*91f16700Schasinglulu ret = 0; 75*91f16700Schasinglulu } 76*91f16700Schasinglulu 77*91f16700Schasinglulu return ret; 78*91f16700Schasinglulu } 79*91f16700Schasinglulu 80*91f16700Schasinglulu /** 81*91f16700Schasinglulu * ipi_mb_validate() - validate IPI mailbox access. 82*91f16700Schasinglulu * @local: local IPI ID. 83*91f16700Schasinglulu * @remote: remote IPI ID. 84*91f16700Schasinglulu * @is_secure: indicate if the requester is from secure software. 85*91f16700Schasinglulu * 86*91f16700Schasinglulu * Return: 0 success, negative value for errors. 87*91f16700Schasinglulu * 88*91f16700Schasinglulu */ 89*91f16700Schasinglulu int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure) 90*91f16700Schasinglulu { 91*91f16700Schasinglulu int ret = 0; 92*91f16700Schasinglulu 93*91f16700Schasinglulu if (!is_ipi_mb_within_range(local, remote)) { 94*91f16700Schasinglulu ret = -EINVAL; 95*91f16700Schasinglulu } else if (IPI_IS_SECURE(local) && !is_secure) { 96*91f16700Schasinglulu ret = -EPERM; 97*91f16700Schasinglulu } else if (IPI_IS_SECURE(remote) && !is_secure) { 98*91f16700Schasinglulu ret = -EPERM; 99*91f16700Schasinglulu } else { 100*91f16700Schasinglulu /* To fix the misra 15.7 warning */ 101*91f16700Schasinglulu } 102*91f16700Schasinglulu 103*91f16700Schasinglulu return ret; 104*91f16700Schasinglulu } 105*91f16700Schasinglulu 106*91f16700Schasinglulu /** 107*91f16700Schasinglulu * ipi_mb_open() - Open IPI mailbox. 108*91f16700Schasinglulu * @local: local IPI ID. 109*91f16700Schasinglulu * @remote: remote IPI ID. 110*91f16700Schasinglulu * 111*91f16700Schasinglulu */ 112*91f16700Schasinglulu void ipi_mb_open(uint32_t local, uint32_t remote) 113*91f16700Schasinglulu { 114*91f16700Schasinglulu mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 115*91f16700Schasinglulu IPI_BIT_MASK(remote)); 116*91f16700Schasinglulu mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, 117*91f16700Schasinglulu IPI_BIT_MASK(remote)); 118*91f16700Schasinglulu } 119*91f16700Schasinglulu 120*91f16700Schasinglulu /** 121*91f16700Schasinglulu * ipi_mb_release() - Open IPI mailbox. 122*91f16700Schasinglulu * @local: local IPI ID. 123*91f16700Schasinglulu * @remote: remote IPI ID. 124*91f16700Schasinglulu * 125*91f16700Schasinglulu */ 126*91f16700Schasinglulu void ipi_mb_release(uint32_t local, uint32_t remote) 127*91f16700Schasinglulu { 128*91f16700Schasinglulu mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 129*91f16700Schasinglulu IPI_BIT_MASK(remote)); 130*91f16700Schasinglulu } 131*91f16700Schasinglulu 132*91f16700Schasinglulu /** 133*91f16700Schasinglulu * ipi_mb_enquire_status() - Enquire IPI mailbox status. 134*91f16700Schasinglulu * @local: local IPI ID. 135*91f16700Schasinglulu * @remote: remote IPI ID. 136*91f16700Schasinglulu * 137*91f16700Schasinglulu * Return: 0 idle, positive value for pending sending or receiving, 138*91f16700Schasinglulu * negative value for errors. 139*91f16700Schasinglulu * 140*91f16700Schasinglulu */ 141*91f16700Schasinglulu int ipi_mb_enquire_status(uint32_t local, uint32_t remote) 142*91f16700Schasinglulu { 143*91f16700Schasinglulu int ret = 0U; 144*91f16700Schasinglulu uint32_t status; 145*91f16700Schasinglulu 146*91f16700Schasinglulu status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET); 147*91f16700Schasinglulu if (status & IPI_BIT_MASK(remote)) { 148*91f16700Schasinglulu ret |= IPI_MB_STATUS_SEND_PENDING; 149*91f16700Schasinglulu } 150*91f16700Schasinglulu status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET); 151*91f16700Schasinglulu if (status & IPI_BIT_MASK(remote)) { 152*91f16700Schasinglulu ret |= IPI_MB_STATUS_RECV_PENDING; 153*91f16700Schasinglulu } 154*91f16700Schasinglulu 155*91f16700Schasinglulu return ret; 156*91f16700Schasinglulu } 157*91f16700Schasinglulu 158*91f16700Schasinglulu /** 159*91f16700Schasinglulu * ipi_mb_notify() - Trigger IPI mailbox notification. 160*91f16700Schasinglulu * @local: local IPI ID. 161*91f16700Schasinglulu * @remote: remote IPI ID. 162*91f16700Schasinglulu * @is_blocking: if to trigger the notification in blocking mode or not. 163*91f16700Schasinglulu * 164*91f16700Schasinglulu * It sets the remote bit in the IPI agent trigger register. 165*91f16700Schasinglulu * 166*91f16700Schasinglulu */ 167*91f16700Schasinglulu void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking) 168*91f16700Schasinglulu { 169*91f16700Schasinglulu uint32_t status; 170*91f16700Schasinglulu 171*91f16700Schasinglulu mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET, 172*91f16700Schasinglulu IPI_BIT_MASK(remote)); 173*91f16700Schasinglulu if (is_blocking) { 174*91f16700Schasinglulu do { 175*91f16700Schasinglulu status = mmio_read_32(IPI_REG_BASE(local) + 176*91f16700Schasinglulu IPI_OBR_OFFSET); 177*91f16700Schasinglulu } while (status & IPI_BIT_MASK(remote)); 178*91f16700Schasinglulu } 179*91f16700Schasinglulu } 180*91f16700Schasinglulu 181*91f16700Schasinglulu /** 182*91f16700Schasinglulu * ipi_mb_ack() - Ack IPI mailbox notification from the other end. 183*91f16700Schasinglulu * @local: local IPI ID. 184*91f16700Schasinglulu * @remote: remote IPI ID. 185*91f16700Schasinglulu * 186*91f16700Schasinglulu * It will clear the remote bit in the isr register. 187*91f16700Schasinglulu * 188*91f16700Schasinglulu */ 189*91f16700Schasinglulu void ipi_mb_ack(uint32_t local, uint32_t remote) 190*91f16700Schasinglulu { 191*91f16700Schasinglulu mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, 192*91f16700Schasinglulu IPI_BIT_MASK(remote)); 193*91f16700Schasinglulu } 194*91f16700Schasinglulu 195*91f16700Schasinglulu /** 196*91f16700Schasinglulu * ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt. 197*91f16700Schasinglulu * @local: local IPI ID. 198*91f16700Schasinglulu * @remote: remote IPI ID. 199*91f16700Schasinglulu * 200*91f16700Schasinglulu * It will mask the remote bit in the idr register. 201*91f16700Schasinglulu * 202*91f16700Schasinglulu */ 203*91f16700Schasinglulu void ipi_mb_disable_irq(uint32_t local, uint32_t remote) 204*91f16700Schasinglulu { 205*91f16700Schasinglulu mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 206*91f16700Schasinglulu IPI_BIT_MASK(remote)); 207*91f16700Schasinglulu } 208*91f16700Schasinglulu 209*91f16700Schasinglulu /** 210*91f16700Schasinglulu * ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt. 211*91f16700Schasinglulu * @local: local IPI ID. 212*91f16700Schasinglulu * @remote: remote IPI ID. 213*91f16700Schasinglulu * 214*91f16700Schasinglulu * It will mask the remote bit in the idr register. 215*91f16700Schasinglulu * 216*91f16700Schasinglulu */ 217*91f16700Schasinglulu void ipi_mb_enable_irq(uint32_t local, uint32_t remote) 218*91f16700Schasinglulu { 219*91f16700Schasinglulu mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET, 220*91f16700Schasinglulu IPI_BIT_MASK(remote)); 221*91f16700Schasinglulu } 222