blob: 96f2b9c3b18741410ca734b1dfa1d0f2de3e7468 [file] [log] [blame]
Wendy Liang3aebacf2017-09-13 11:02:42 -07001/*
Jolly Shah0bfd7002019-01-08 11:10:47 -08002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Wendy Liang3aebacf2017-09-13 11:02:42 -07003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7/*
8 * Zynq UltraScale+ MPSoC IPI agent registers access management
9 */
10
Wendy Liang3aebacf2017-09-13 11:02:42 -070011#include <errno.h>
Wendy Liang3aebacf2017-09-13 11:02:42 -070012#include <string.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000013
14#include <common/debug.h>
15#include <common/runtime_svc.h>
16#include <lib/bakery_lock.h>
17#include <lib/mmio.h>
Jolly Shah4c172372019-01-08 11:21:29 -080018#include <plat_ipi.h>
Jolly Shah0bfd7002019-01-08 11:10:47 -080019#include <plat_private.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000020
Wendy Liang3aebacf2017-09-13 11:02:42 -070021/*********************************************************************
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 */
52struct 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 */
59const 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,
Rajan Vajaba2b0562018-01-30 03:59:23 -080088 .secure_only = 0,
Wendy Liang3aebacf2017-09-13 11:02:42 -070089 },
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 */
135static 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 */
155int 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 */
176void 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 */
191void 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 */
206int 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 */
230void 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 */
252void 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 */
266void 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 */
280void 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}