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