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 * Zynq UltraScale+ MPSoC 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 <lib/bakery_lock.h> 17 #include <lib/mmio.h> 18 #include <plat_ipi.h> 19 #include <plat_private.h> 20 21 /********************************************************************* 22 * Macros definitions 23 ********************************************************************/ 24 25 /* IPI registers base address */ 26 #define IPI_REGS_BASE 0xFF300000U 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) (zynqmp_ipi_table[(I)].ipi_reg_base) 38 39 /* IPI register bit mask */ 40 #define IPI_BIT_MASK(I) (zynqmp_ipi_table[(I)].ipi_bit_mask) 41 42 /* IPI secure check */ 43 #define IPI_SECURE_MASK 0x1U 44 #define IPI_IS_SECURE(I) ((zynqmp_ipi_table[(I)].secure_only & \ 45 IPI_SECURE_MASK) ? 1 : 0) 46 47 /********************************************************************* 48 * Struct definitions 49 ********************************************************************/ 50 51 /* structure to maintain IPI configuration information */ 52 struct zynqmp_ipi_config { 53 unsigned int ipi_bit_mask; 54 unsigned int ipi_reg_base; 55 unsigned char secure_only; 56 }; 57 58 /* Zynqmp ipi configuration table */ 59 const static struct zynqmp_ipi_config zynqmp_ipi_table[] = { 60 /* APU IPI */ 61 { 62 .ipi_bit_mask = 0x1, 63 .ipi_reg_base = 0xFF300000, 64 .secure_only = 0, 65 }, 66 /* RPU0 IPI */ 67 { 68 .ipi_bit_mask = 0x100, 69 .ipi_reg_base = 0xFF310000, 70 .secure_only = 0, 71 }, 72 /* RPU1 IPI */ 73 { 74 .ipi_bit_mask = 0x200, 75 .ipi_reg_base = 0xFF320000, 76 .secure_only = 0, 77 }, 78 /* PMU0 IPI */ 79 { 80 .ipi_bit_mask = 0x10000, 81 .ipi_reg_base = 0xFF330000, 82 .secure_only = IPI_SECURE_MASK, 83 }, 84 /* PMU1 IPI */ 85 { 86 .ipi_bit_mask = 0x20000, 87 .ipi_reg_base = 0xFF331000, 88 .secure_only = 0, 89 }, 90 /* PMU2 IPI */ 91 { 92 .ipi_bit_mask = 0x40000, 93 .ipi_reg_base = 0xFF332000, 94 .secure_only = IPI_SECURE_MASK, 95 }, 96 /* PMU3 IPI */ 97 { 98 .ipi_bit_mask = 0x80000, 99 .ipi_reg_base = 0xFF333000, 100 .secure_only = IPI_SECURE_MASK, 101 }, 102 /* PL0 IPI */ 103 { 104 .ipi_bit_mask = 0x1000000, 105 .ipi_reg_base = 0xFF340000, 106 .secure_only = 0, 107 }, 108 /* PL1 IPI */ 109 { 110 .ipi_bit_mask = 0x2000000, 111 .ipi_reg_base = 0xFF350000, 112 .secure_only = 0, 113 }, 114 /* PL2 IPI */ 115 { 116 .ipi_bit_mask = 0x4000000, 117 .ipi_reg_base = 0xFF360000, 118 .secure_only = 0, 119 }, 120 /* PL3 IPI */ 121 { 122 .ipi_bit_mask = 0x8000000, 123 .ipi_reg_base = 0xFF370000, 124 .secure_only = 0, 125 }, 126 }; 127 128 /* is_ipi_mb_within_range() - verify if IPI mailbox is within range 129 * 130 * @local - local IPI ID 131 * @remote - remote IPI ID 132 * 133 * return - 1 if within range, 0 if not 134 */ 135 static inline int is_ipi_mb_within_range(uint32_t local, uint32_t remote) 136 { 137 int ret = 1; 138 uint32_t ipi_total = ARRAY_SIZE(zynqmp_ipi_table); 139 140 if (remote >= ipi_total || local >= ipi_total) 141 ret = 0; 142 143 return ret; 144 } 145 146 /** 147 * ipi_mb_validate() - validate IPI mailbox access 148 * 149 * @local - local IPI ID 150 * @remote - remote IPI ID 151 * @is_secure - indicate if the requester is from secure software 152 * 153 * return - 0 success, negative value for errors 154 */ 155 int ipi_mb_validate(uint32_t local, uint32_t remote, unsigned int is_secure) 156 { 157 int ret = 0; 158 159 if (!is_ipi_mb_within_range(local, remote)) 160 ret = -EINVAL; 161 else if (IPI_IS_SECURE(local) && !is_secure) 162 ret = -EPERM; 163 else if (IPI_IS_SECURE(remote) && !is_secure) 164 ret = -EPERM; 165 166 return ret; 167 } 168 169 /** 170 * ipi_mb_open() - Open IPI mailbox. 171 * 172 * @local - local IPI ID 173 * @remote - remote IPI ID 174 * 175 */ 176 void ipi_mb_open(uint32_t local, uint32_t remote) 177 { 178 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 179 IPI_BIT_MASK(remote)); 180 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, 181 IPI_BIT_MASK(remote)); 182 } 183 184 /** 185 * ipi_mb_release() - Open IPI mailbox. 186 * 187 * @local - local IPI ID 188 * @remote - remote IPI ID 189 * 190 */ 191 void ipi_mb_release(uint32_t local, uint32_t remote) 192 { 193 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 194 IPI_BIT_MASK(remote)); 195 } 196 197 /** 198 * ipi_mb_enquire_status() - Enquire IPI mailbox status 199 * 200 * @local - local IPI ID 201 * @remote - remote IPI ID 202 * 203 * return - 0 idle, positive value for pending sending or receiving, 204 * negative value for errors 205 */ 206 int ipi_mb_enquire_status(uint32_t local, uint32_t remote) 207 { 208 int ret = 0; 209 uint32_t status; 210 211 status = mmio_read_32(IPI_REG_BASE(local) + IPI_OBR_OFFSET); 212 if (status & IPI_BIT_MASK(remote)) 213 ret |= IPI_MB_STATUS_SEND_PENDING; 214 status = mmio_read_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET); 215 if (status & IPI_BIT_MASK(remote)) 216 ret |= IPI_MB_STATUS_RECV_PENDING; 217 218 return ret; 219 } 220 221 /* ipi_mb_notify() - Trigger IPI mailbox notification 222 * 223 * @local - local IPI ID 224 * @remote - remote IPI ID 225 * @is_blocking - if to trigger the notification in blocking mode or not. 226 * 227 * It sets the remote bit in the IPI agent trigger register. 228 * 229 */ 230 void ipi_mb_notify(uint32_t local, uint32_t remote, uint32_t is_blocking) 231 { 232 uint32_t status; 233 234 mmio_write_32(IPI_REG_BASE(local) + IPI_TRIG_OFFSET, 235 IPI_BIT_MASK(remote)); 236 if (is_blocking) { 237 do { 238 status = mmio_read_32(IPI_REG_BASE(local) + 239 IPI_OBR_OFFSET); 240 } while (status & IPI_BIT_MASK(remote)); 241 } 242 } 243 244 /* ipi_mb_ack() - Ack IPI mailbox notification from the other end 245 * 246 * @local - local IPI ID 247 * @remote - remote IPI ID 248 * 249 * It will clear the remote bit in the isr register. 250 * 251 */ 252 void ipi_mb_ack(uint32_t local, uint32_t remote) 253 { 254 mmio_write_32(IPI_REG_BASE(local) + IPI_ISR_OFFSET, 255 IPI_BIT_MASK(remote)); 256 } 257 258 /* ipi_mb_disable_irq() - Disable IPI mailbox notification interrupt 259 * 260 * @local - local IPI ID 261 * @remote - remote IPI ID 262 * 263 * It will mask the remote bit in the idr register. 264 * 265 */ 266 void ipi_mb_disable_irq(uint32_t local, uint32_t remote) 267 { 268 mmio_write_32(IPI_REG_BASE(local) + IPI_IDR_OFFSET, 269 IPI_BIT_MASK(remote)); 270 } 271 272 /* ipi_mb_enable_irq() - Enable IPI mailbox notification interrupt 273 * 274 * @local - local IPI ID 275 * @remote - remote IPI ID 276 * 277 * It will mask the remote bit in the idr register. 278 * 279 */ 280 void ipi_mb_enable_irq(uint32_t local, uint32_t remote) 281 { 282 mmio_write_32(IPI_REG_BASE(local) + IPI_IER_OFFSET, 283 IPI_BIT_MASK(remote)); 284 } 285