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