xref: /rk3399_ARM-atf/plat/xilinx/zynqmp/zynqmp_ipi.c (revision 1611ef2b0f6bf94fb80ba718d90eee5da871d563)
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 #include <plat_ipi.h>
19 #include <plat_private.h>
20 
21 /*********************************************************************
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 */
52 struct 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 */
59 const 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,
88 		.secure_only = 0,
89 	},
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  */
135 static 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  */
155 int 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  */
176 void 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  */
191 void 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  */
206 int 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  */
230 void 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  */
252 void 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  */
266 void 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  */
280 void 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 }
285