xref: /optee_os/core/drivers/versal_mbox.c (revision bc679ca5079e11f0f5a3cf1788fb2e5e4d861d14)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2022 Foundries.io Ltd
4  * Jorge Ramirez-Ortiz <jorge@foundries.io>
5  *
6  * Copyright (C) 2023 ProvenRun S.A.S
7  */
8 
9 #include <assert.h>
10 #include <io.h>
11 #include <kernel/panic.h>
12 #include <mm/core_mmu.h>
13 #include <string.h>
14 #include <tee/cache.h>
15 #include "drivers/versal_mbox.h"
16 
17 
18 #if defined(PLATFORM_FLAVOR_net)
19 #define IPI_REG_BASEADDR		0xEB300000
20 #define IPI_BUFFER_BASEADDR		0xEB3F0000
21 #else
22 #define IPI_REG_BASEADDR		0xFF300000
23 #define IPI_BUFFER_BASEADDR		0xFF3F0000
24 #endif
25 
26 #define IPI_SIZE			0x10000
27 
28 #define IPI_TRIG_OFFSET			0x00
29 #define IPI_OBR_OFFSET			0x04
30 #define IPI_ISR_OFFSET			0x10
31 #define IPI_IMR_OFFSET			0x14
32 #define IPI_IER_OFFSET			0x18
33 #define IPI_IDR_OFFSET			0x1C
34 
35 #define IPI_PMC_TRIG_BIT		BIT(1)
36 #define IPI0_TRIG_BIT			BIT(2)
37 #define IPI1_TRIG_BIT			BIT(3)
38 #define IPI2_TRIG_BIT			BIT(4)
39 #define IPI3_TRIG_BIT			BIT(5)
40 #define IPI4_TRIG_BIT			BIT(6)
41 #define IPI5_TRIG_BIT			BIT(7)
42 
43 /* Interrupt Config Registers */
44 #define IPI_PMC_REG_BASE		(IPI_REG_BASEADDR + 0x20000)
45 #define IPI0_REG_BASE			(IPI_REG_BASEADDR + 0x30000)
46 #define IPI1_REG_BASE			(IPI_REG_BASEADDR + 0x40000)
47 #define IPI2_REG_BASE			(IPI_REG_BASEADDR + 0x50000)
48 #define IPI3_REG_BASE			(IPI_REG_BASEADDR + 0x60000)
49 #define IPI4_REG_BASE			(IPI_REG_BASEADDR + 0x70000)
50 #define IPI5_REG_BASE			(IPI_REG_BASEADDR + 0x80000)
51 
52 /* Buffers */
53 #define IPI_BUFFER_PMC_BASE		(IPI_BUFFER_BASEADDR + 0x200)
54 #define IPI_BUFFER_APU_ID_0_BASE	(IPI_BUFFER_BASEADDR + 0x400)
55 #define IPI_BUFFER_APU_ID_1_BASE	(IPI_BUFFER_BASEADDR + 0x600)
56 #define IPI_BUFFER_APU_ID_2_BASE	(IPI_BUFFER_BASEADDR + 0x800)
57 #define IPI_BUFFER_APU_ID_3_BASE	(IPI_BUFFER_BASEADDR + 0xA00)
58 #define IPI_BUFFER_APU_ID_4_BASE	(IPI_BUFFER_BASEADDR + 0xC00)
59 #define IPI_BUFFER_APU_ID_5_BASE	(IPI_BUFFER_BASEADDR + 0xE00)
60 #define IPI_BUFFER_TARGET_PMC_OFFSET	0x40
61 #define IPI_BUFFER_TARGET_ID_0_OFFSET	0x80
62 #define IPI_BUFFER_TARGET_ID_1_OFFSET	0xC0
63 #define IPI_BUFFER_TARGET_ID_2_OFFSET	0x100
64 #define IPI_BUFFER_TARGET_ID_3_OFFSET	0x140
65 #define IPI_BUFFER_TARGET_ID_4_OFFSET	0x180
66 #define IPI_BUFFER_TARGET_ID_5_OFFSET	0x1C0
67 
68 #define IPI_BUFFER_REQ_OFFSET		0x0
69 #define IPI_BUFFER_RESP_OFFSET		0x20
70 
71 static const struct versal_ipi_cfg {
72 	uint32_t ipi_bit_mask;
73 	uint32_t ipi_reg_base;
74 	uint32_t ipi_buf_base;
75 	uint32_t ipi_remote_offset;
76 } versal_ipi_cfgs[] = {
77 	/* PMC IPI */
78 	[VERSAL_IPI_ID_PMC] = {
79 		.ipi_bit_mask = IPI_PMC_TRIG_BIT,
80 		.ipi_reg_base = IPI_PMC_REG_BASE,
81 		.ipi_buf_base = IPI_BUFFER_PMC_BASE,
82 		.ipi_remote_offset = IPI_BUFFER_TARGET_PMC_OFFSET,
83 	},
84 
85 	/* IPI0 IPI */
86 	[VERSAL_IPI_ID_0] = {
87 		.ipi_bit_mask = IPI0_TRIG_BIT,
88 		.ipi_reg_base = IPI0_REG_BASE,
89 		.ipi_buf_base = IPI_BUFFER_APU_ID_0_BASE,
90 		.ipi_remote_offset = IPI_BUFFER_TARGET_ID_0_OFFSET,
91 	},
92 
93 	/* IPI1 IPI */
94 	[VERSAL_IPI_ID_1] = {
95 		.ipi_bit_mask = IPI1_TRIG_BIT,
96 		.ipi_reg_base = IPI1_REG_BASE,
97 		.ipi_buf_base = IPI_BUFFER_APU_ID_1_BASE,
98 		.ipi_remote_offset = IPI_BUFFER_TARGET_ID_1_OFFSET,
99 	},
100 
101 	/* IPI2 IPI */
102 	[VERSAL_IPI_ID_2] = {
103 		.ipi_bit_mask = IPI2_TRIG_BIT,
104 		.ipi_reg_base = IPI2_REG_BASE,
105 		.ipi_buf_base = IPI_BUFFER_APU_ID_2_BASE,
106 		.ipi_remote_offset = IPI_BUFFER_TARGET_ID_2_OFFSET,
107 	},
108 
109 	/* IPI3 IPI */
110 	[VERSAL_IPI_ID_3] = {
111 		.ipi_bit_mask = IPI3_TRIG_BIT,
112 		.ipi_reg_base = IPI3_REG_BASE,
113 		.ipi_buf_base = IPI_BUFFER_APU_ID_3_BASE,
114 		.ipi_remote_offset = IPI_BUFFER_TARGET_ID_3_OFFSET,
115 	},
116 
117 	/* IPI4 IPI */
118 	[VERSAL_IPI_ID_4] = {
119 		.ipi_bit_mask = IPI4_TRIG_BIT,
120 		.ipi_reg_base = IPI4_REG_BASE,
121 		.ipi_buf_base = IPI_BUFFER_APU_ID_4_BASE,
122 		.ipi_remote_offset = IPI_BUFFER_TARGET_ID_4_OFFSET,
123 	},
124 
125 	/* IPI5 IPI */
126 	[VERSAL_IPI_ID_5] = {
127 		.ipi_bit_mask = IPI5_TRIG_BIT,
128 		.ipi_reg_base = IPI5_REG_BASE,
129 		.ipi_buf_base = IPI_BUFFER_APU_ID_5_BASE,
130 		.ipi_remote_offset = IPI_BUFFER_TARGET_ID_5_OFFSET,
131 	},
132 };
133 
134 #define IPI_REG_BASE(idx) (versal_ipi_cfgs[idx].ipi_reg_base)
135 #define IPI_BIT_MASK(idx) (versal_ipi_cfgs[idx].ipi_bit_mask)
136 #define IPI_BUFFER_BASE(idx) (versal_ipi_cfgs[idx].ipi_buf_base)
137 #define IPI_REMOTE_OFFSET(idx) (versal_ipi_cfgs[idx].ipi_remote_offset)
138 
139 static TEE_Result versal_mbox_write_req(struct versal_ipi *ipi,
140 					struct versal_ipi_cmd *cmd)
141 {
142 	size_t i = 0;
143 
144 	assert(ipi);
145 	assert(cmd);
146 
147 	for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) {
148 		if (!cmd->ibuf[i].mem.buf)
149 			continue;
150 
151 		if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf,
152 				CACHELINE_LEN)) {
153 			EMSG("address not aligned: buffer %zu - %p", i,
154 			     cmd->ibuf[i].mem.buf);
155 			return TEE_ERROR_GENERIC;
156 		}
157 
158 		if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) {
159 			EMSG("length not aligned: buffer %zu - %zu",
160 			     i, cmd->ibuf[i].mem.alloc_len);
161 			return TEE_ERROR_GENERIC;
162 		}
163 
164 		cache_operation(TEE_CACHEFLUSH, cmd->ibuf[i].mem.buf,
165 				cmd->ibuf[i].mem.alloc_len);
166 	}
167 
168 	memcpy(ipi->req, cmd->data, sizeof(cmd->data));
169 
170 	/* Cache operation on the IPI buffer is safe */
171 	cache_operation(TEE_CACHEFLUSH, ipi->req, sizeof(cmd->data));
172 
173 	return TEE_SUCCESS;
174 }
175 
176 static TEE_Result versal_mbox_read_rsp(struct versal_ipi *ipi,
177 				       struct versal_ipi_cmd *cmd,
178 				       struct versal_ipi_cmd *rsp,
179 				       uint32_t *status)
180 {
181 	size_t i = 0;
182 
183 	assert(ipi);
184 	assert(cmd);
185 
186 	/* Cache operation on the IPI buffer is safe */
187 	cache_operation(TEE_CACHEINVALIDATE, ipi->rsp, sizeof(rsp->data));
188 
189 	*status = *(uint32_t *)ipi->rsp;
190 
191 	if (*status)
192 		return TEE_ERROR_GENERIC;
193 
194 	if (rsp)
195 		memcpy(rsp->data, ipi->rsp, sizeof(rsp->data));
196 
197 	for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) {
198 		if (!cmd->ibuf[i].mem.buf)
199 			continue;
200 
201 		if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf,
202 				CACHELINE_LEN)) {
203 			EMSG("address not aligned: buffer %zu - %p",
204 			     i, cmd->ibuf[i].mem.buf);
205 			return TEE_ERROR_GENERIC;
206 		}
207 
208 		if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) {
209 			EMSG("length not aligned: buffer %zu - %zu",
210 			     i, cmd->ibuf[i].mem.alloc_len);
211 			return TEE_ERROR_GENERIC;
212 		}
213 
214 		cache_operation(TEE_CACHEINVALIDATE,
215 				cmd->ibuf[i].mem.buf,
216 				cmd->ibuf[i].mem.alloc_len);
217 	}
218 
219 	return TEE_SUCCESS;
220 }
221 
222 TEE_Result versal_mbox_open(uint32_t local, uint32_t remote,
223 			    struct versal_ipi *ipi)
224 {
225 	assert(ipi);
226 
227 	ipi->regs = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC,
228 						  IPI_REG_BASE(local),
229 						  IPI_SIZE);
230 
231 	ipi->req = core_mmu_add_mapping(MEM_AREA_IO_SEC,
232 					IPI_BUFFER_BASE(local) +
233 					IPI_REMOTE_OFFSET(remote) +
234 					IPI_BUFFER_REQ_OFFSET,
235 					sizeof(struct versal_ipi_cmd));
236 
237 	ipi->rsp = core_mmu_add_mapping(MEM_AREA_IO_SEC,
238 					IPI_BUFFER_BASE(local) +
239 					IPI_REMOTE_OFFSET(remote) +
240 					IPI_BUFFER_RESP_OFFSET,
241 					sizeof(struct versal_ipi_cmd));
242 
243 	ipi->lcl = local;
244 	ipi->rmt = remote;
245 
246 	if (!ipi->regs || !ipi->req || !ipi->rsp)
247 		panic();
248 
249 	mutex_init(&ipi->lock);
250 
251 	io_write32(ipi->regs + IPI_IDR_OFFSET, IPI_BIT_MASK(remote));
252 	io_write32(ipi->regs + IPI_ISR_OFFSET, IPI_BIT_MASK(remote));
253 
254 	return TEE_SUCCESS;
255 }
256 
257 TEE_Result versal_mbox_close(struct versal_ipi *ipi)
258 {
259 	assert(ipi);
260 
261 	io_write32(ipi->regs + IPI_IDR_OFFSET,
262 		   IPI_BIT_MASK(ipi->rmt));
263 
264 	return TEE_SUCCESS;
265 }
266 
267 TEE_Result versal_mbox_alloc(size_t len, const void *init,
268 			     struct versal_mbox_mem *mem)
269 {
270 	mem->buf = memalign(CACHELINE_LEN, ROUNDUP(len, CACHELINE_LEN));
271 	if (!mem->buf)
272 		return TEE_ERROR_OUT_OF_MEMORY;
273 
274 	memset(mem->buf, 0, ROUNDUP(len, CACHELINE_LEN));
275 
276 	if (init)
277 		memcpy(mem->buf, init, len);
278 
279 	mem->alloc_len = ROUNDUP(len, CACHELINE_LEN);
280 	mem->len = len;
281 
282 	return TEE_SUCCESS;
283 }
284 
285 void versal_mbox_free(struct versal_mbox_mem *mem)
286 {
287 	assert(mem);
288 
289 	free(mem->buf);
290 	mem->buf = NULL;
291 }
292 
293 TEE_Result versal_mbox_notify(struct versal_ipi *ipi,
294 			      struct versal_ipi_cmd *cmd,
295 			      struct versal_ipi_cmd *rsp, uint32_t *err)
296 {
297 	TEE_Result ret = TEE_SUCCESS;
298 	uint32_t remote_status = 0;
299 
300 	mutex_lock(&ipi->lock);
301 
302 	ret = versal_mbox_write_req(ipi, cmd);
303 	if (ret) {
304 		EMSG("Can't write the request command");
305 		goto out;
306 	}
307 
308 	/* Trigger interrupt to remote */
309 	io_write32(ipi->regs + IPI_TRIG_OFFSET, IPI_BIT_MASK(ipi->rmt));
310 
311 	/* Wait for remote to acknowledge the interrupt */
312 	if (IO_READ32_POLL_TIMEOUT(ipi->regs + IPI_OBR_OFFSET, remote_status,
313 				   !(remote_status & IPI_BIT_MASK(ipi->rmt)), 1,
314 				   CFG_VERSAL_MBOX_TIMEOUT)) {
315 		EMSG("Timeout waiting for remote response");
316 		ret = TEE_ERROR_GENERIC;
317 		goto out;
318 	}
319 
320 	ret = versal_mbox_read_rsp(ipi, cmd, rsp, &remote_status);
321 	if (ret)
322 		EMSG("Can't read the remote response");
323 
324 	if (remote_status) {
325 		if (err)
326 			*err = remote_status;
327 
328 		ret = TEE_ERROR_GENERIC;
329 	}
330 out:
331 	mutex_unlock(&ipi->lock);
332 
333 	return ret;
334 }
335