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