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