1 /* 2 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 /* 8 * Xilinx IPI agent registers access management 9 */ 10 11 #include <errno.h> 12 #include <string.h> 13 14 #include <common/debug.h> 15 #include <common/runtime_svc.h> 16 #include <drivers/delay_timer.h> 17 #include <lib/bakery_lock.h> 18 #include <lib/mmio.h> 19 20 #include <ipi.h> 21 #include <plat_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 Timeout */ 43 #define TIMEOUT_COUNT_US U(0x4000) 44 45 /* IPI configuration table */ 46 const static struct ipi_config *ipi_table; 47 48 /* Total number of IPI */ 49 static uint32_t ipi_total; 50 51 /** 52 * ipi_config_init() - Initialize IPI configuration data 53 * 54 * @ipi_config_table - IPI configuration table 55 * @ipi_total - Total number of IPI available 56 * 57 */ 58 void ipi_config_table_init(const struct ipi_config *ipi_config_table, 59 uint32_t total_ipi) 60 { 61 ipi_table = ipi_config_table; 62 ipi_total = total_ipi; 63 } 64 65 /* is_ipi_mb_within_range() - verify if IPI mailbox is within range 66 * 67 * @local - local IPI ID 68 * @remote - remote IPI ID 69 * 70 * return - 1 if within range, 0 if not 71 */ 72 static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote) 73 { 74 int ret = 1; 75 76 if (remote >= ipi_total || local >= ipi_total) 77 ret = 0; 78 79 return ret; 80 } 81 82 /** 83 * ipi_mb_validate() - validate IPI mailbox access 84 * 85 * @local - local IPI ID 86 * @remote - remote IPI ID 87 * @is_secure - indicate if the requester is from secure software 88 * 89 * return - 0 success, negative value for errors 90 */ 91 int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure) 92 { 93 int ret = 0; 94 95 if (!is_ipi_mb_within_range(local, remote)) 96 ret = -EINVAL; 97 else if (IPI_IS_SECURE(local) && !is_secure) 98 ret = -EPERM; 99 else if (IPI_IS_SECURE(remote) && !is_secure) 100 ret = -EPERM; 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 = 0; 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 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 return ret; 155 } 156 157 /* ipi_mb_notify() - Trigger IPI mailbox notification 158 * 159 * @local - local IPI ID 160 * @remote - remote IPI ID 161 * @is_blocking - if to trigger the notification in blocking mode or not. 162 * 163 * return - 0 - Success or Error incase of timeout 164 * It sets the remote bit in the IPI agent trigger register. 165 * 166 */ 167 int ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking) 168 { 169 uint32_t status; 170 const unsigned int timeout_count = TIMEOUT_COUNT_US; 171 uint64_t timeout; 172 173 mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET, 174 IPI_BIT_MASK(remote)); 175 if (is_blocking) { 176 timeout = timeout_init_us(timeout_count); 177 do { 178 status = mmio_read_32(IPI_REG_BASE(local) + 179 IPI_OBR_OFFSET); 180 if (timeout_elapsed(timeout)) { 181 return -ETIMEDOUT; 182 } 183 } while (status & IPI_BIT_MASK(remote)); 184 } 185 186 return 0; 187 } 188 189 /* ipi_mb_ack() - Ack IPI mailbox notification from the other end 190 * 191 * @local - local IPI ID 192 * @remote - remote IPI ID 193 * 194 * It will clear the remote bit in the isr register. 195 * 196 */ 197 void ipi_mb_ack(uint32_t local, uint32_t remote) 198 { 199 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, 200 IPI_BIT_MASK(remote)); 201 } 202 203 /* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt 204 * 205 * @local - local IPI ID 206 * @remote - remote IPI ID 207 * 208 * It will mask the remote bit in the idr register. 209 * 210 */ 211 void ipi_mb_disable_irq(uint32_t local, uint32_t remote) 212 { 213 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 214 IPI_BIT_MASK(remote)); 215 } 216 217 /* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt 218 * 219 * @local - local IPI ID 220 * @remote - remote IPI ID 221 * 222 * It will mask the remote bit in the idr register. 223 * 224 */ 225 void ipi_mb_enable_irq(uint32_t local, uint32_t remote) 226 { 227 mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET, 228 IPI_BIT_MASK(remote)); 229 } 230