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