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