xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/zynqmp_ipi.c (revision ff2743e544f0f82381ebb9dff8f14eacb837d2e0)
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