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