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