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
versal_mbox_write_req(struct versal_ipi * ipi,struct versal_ipi_cmd * cmd)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
versal_mbox_read_rsp(struct versal_ipi * ipi,struct versal_ipi_cmd * cmd,struct versal_ipi_cmd * rsp,uint32_t * status)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
versal_mbox_open(uint32_t local,uint32_t remote,struct versal_ipi * ipi)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
versal_mbox_close(struct versal_ipi * ipi)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
versal_mbox_alloc(size_t len,const void * init,struct versal_mbox_mem * mem)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
versal_mbox_free(struct versal_mbox_mem * mem)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
versal_mbox_notify(struct versal_ipi * ipi,struct versal_ipi_cmd * cmd,struct versal_ipi_cmd * rsp,uint32_t * err)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