xref: /optee_os/core/drivers/versal_mbox.c (revision 4b46e0e812911b918c64c5f80da1ebc2bd6214d4)
1*4b46e0e8SJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-2-Clause
2*4b46e0e8SJorge Ramirez-Ortiz /*
3*4b46e0e8SJorge Ramirez-Ortiz  * Copyright (C) 2022 Foundries.io Ltd
4*4b46e0e8SJorge Ramirez-Ortiz  * Jorge Ramirez-Ortiz <jorge@foundries.io>
5*4b46e0e8SJorge Ramirez-Ortiz  */
6*4b46e0e8SJorge Ramirez-Ortiz 
7*4b46e0e8SJorge Ramirez-Ortiz #include <initcall.h>
8*4b46e0e8SJorge Ramirez-Ortiz #include <kernel/delay.h>
9*4b46e0e8SJorge Ramirez-Ortiz #include <kernel/panic.h>
10*4b46e0e8SJorge Ramirez-Ortiz #include <mm/core_mmu.h>
11*4b46e0e8SJorge Ramirez-Ortiz #include <string.h>
12*4b46e0e8SJorge Ramirez-Ortiz #include <tee/cache.h>
13*4b46e0e8SJorge Ramirez-Ortiz #include "drivers/versal_mbox.h"
14*4b46e0e8SJorge Ramirez-Ortiz 
15*4b46e0e8SJorge Ramirez-Ortiz #define PM_SIP_SVC	0xc2000000
16*4b46e0e8SJorge Ramirez-Ortiz 
17*4b46e0e8SJorge Ramirez-Ortiz /* IPI targets */
18*4b46e0e8SJorge Ramirez-Ortiz #define IPI_ID_PMC	1
19*4b46e0e8SJorge Ramirez-Ortiz #define IPI_ID_0	2
20*4b46e0e8SJorge Ramirez-Ortiz #define IPI_ID_RPU0	3
21*4b46e0e8SJorge Ramirez-Ortiz #define IPI_ID_RPU1	4
22*4b46e0e8SJorge Ramirez-Ortiz #define IPI_ID_3	5
23*4b46e0e8SJorge Ramirez-Ortiz #define IPI_ID_4	6
24*4b46e0e8SJorge Ramirez-Ortiz #define IPI_ID_5	7
25*4b46e0e8SJorge Ramirez-Ortiz 
26*4b46e0e8SJorge Ramirez-Ortiz /* Buffers */
27*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_BASEADDR		0xFF3F0000
28*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_APU_ID_0_BASE	(IPI_BUFFER_BASEADDR + 0x400)
29*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_APU_ID_3_BASE	(IPI_BUFFER_BASEADDR + 0xA00)
30*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_APU_ID_4_BASE	(IPI_BUFFER_BASEADDR + 0xC00)
31*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_APU_ID_5_BASE	(IPI_BUFFER_BASEADDR + 0xE00)
32*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_PMC_BASE		(IPI_BUFFER_BASEADDR + 0x200)
33*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_TARGET_APU_OFFSET	0x80
34*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_TARGET_PMC_OFFSET	0x40
35*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_REQ_OFFSET		0x0
36*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_RESP_OFFSET		0x20
37*4b46e0e8SJorge Ramirez-Ortiz 
38*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_LOCAL_OFFSET		IPI_BUFFER_TARGET_APU_OFFSET
39*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BUFFER_REMOTE_OFFSET	IPI_BUFFER_TARGET_PMC_OFFSET
40*4b46e0e8SJorge Ramirez-Ortiz 
41*4b46e0e8SJorge Ramirez-Ortiz #define IPI_BLOCK		1
42*4b46e0e8SJorge Ramirez-Ortiz #define IPI_NON_BLOCK		0
43*4b46e0e8SJorge Ramirez-Ortiz 
44*4b46e0e8SJorge Ramirez-Ortiz /* Mailbox api */
45*4b46e0e8SJorge Ramirez-Ortiz enum versal_ipi_api_id {
46*4b46e0e8SJorge Ramirez-Ortiz 	IPI_MAILBOX_OPEN = 0x1000,
47*4b46e0e8SJorge Ramirez-Ortiz 	IPI_MAILBOX_RELEASE,
48*4b46e0e8SJorge Ramirez-Ortiz 	IPI_MAILBOX_STATUS_ENQUIRY,
49*4b46e0e8SJorge Ramirez-Ortiz 	IPI_MAILBOX_NOTIFY,
50*4b46e0e8SJorge Ramirez-Ortiz 	IPI_MAILBOX_ACK,
51*4b46e0e8SJorge Ramirez-Ortiz 	IPI_MAILBOX_ENABLE_IRQ,
52*4b46e0e8SJorge Ramirez-Ortiz 	IPI_MAILBOX_DISABLE_IRQ
53*4b46e0e8SJorge Ramirez-Ortiz };
54*4b46e0e8SJorge Ramirez-Ortiz 
55*4b46e0e8SJorge Ramirez-Ortiz static struct versal_ipi {
56*4b46e0e8SJorge Ramirez-Ortiz 	uint32_t lcl;
57*4b46e0e8SJorge Ramirez-Ortiz 	const uint32_t rmt;
58*4b46e0e8SJorge Ramirez-Ortiz 	paddr_t buf;
59*4b46e0e8SJorge Ramirez-Ortiz 	/* Exclusive access to the IPI shared buffer */
60*4b46e0e8SJorge Ramirez-Ortiz 	struct mutex lock;
61*4b46e0e8SJorge Ramirez-Ortiz 	void *rsp;
62*4b46e0e8SJorge Ramirez-Ortiz 	void *req;
63*4b46e0e8SJorge Ramirez-Ortiz } ipi = {
64*4b46e0e8SJorge Ramirez-Ortiz 	.buf = IPI_BUFFER_APU_ID_3_BASE,
65*4b46e0e8SJorge Ramirez-Ortiz 	.rmt = IPI_ID_PMC,
66*4b46e0e8SJorge Ramirez-Ortiz 	.lcl = IPI_ID_3,
67*4b46e0e8SJorge Ramirez-Ortiz };
68*4b46e0e8SJorge Ramirez-Ortiz 
69*4b46e0e8SJorge Ramirez-Ortiz static const char *const nvm_id[] = {
70*4b46e0e8SJorge Ramirez-Ortiz 	[0] = "API_FEATURES",
71*4b46e0e8SJorge Ramirez-Ortiz 	[1] = "BBRAM_WRITE_AES_KEY",
72*4b46e0e8SJorge Ramirez-Ortiz 	[2] = "BBRAM_ZEROIZE",
73*4b46e0e8SJorge Ramirez-Ortiz 	[3] = "BBRAM_WRITE_USER_DATA",
74*4b46e0e8SJorge Ramirez-Ortiz 	[4] = "BBRAM_READ_USER_DATA",
75*4b46e0e8SJorge Ramirez-Ortiz 	[5] = "BBRAM_LOCK_WRITE_USER_DATA",
76*4b46e0e8SJorge Ramirez-Ortiz 	[6] = "EFUSE_WRITE",
77*4b46e0e8SJorge Ramirez-Ortiz 	[7] = "EFUSE_WRITE_PUF",
78*4b46e0e8SJorge Ramirez-Ortiz 	[8] = "EFUSE_PUF_USER_FUSE_WRITE",
79*4b46e0e8SJorge Ramirez-Ortiz 	[9] = "EFUSE_READ_IV",
80*4b46e0e8SJorge Ramirez-Ortiz 	[10] = "EFUSE_READ_REVOCATION_ID",
81*4b46e0e8SJorge Ramirez-Ortiz 	[11] = "EFUSE_READ_OFFCHIP_REVOCATION_ID",
82*4b46e0e8SJorge Ramirez-Ortiz 	[12] = "EFUSE_READ_USER_FUSES",
83*4b46e0e8SJorge Ramirez-Ortiz 	[13] = "EFUSE_READ_MISC_CTRL",
84*4b46e0e8SJorge Ramirez-Ortiz 	[14] = "EFUSE_READ_SEC_CTRL",
85*4b46e0e8SJorge Ramirez-Ortiz 	[15] = "EFUSE_READ_SEC_MISC1",
86*4b46e0e8SJorge Ramirez-Ortiz 	[16] = "EFUSE_READ_BOOT_ENV_CTRL",
87*4b46e0e8SJorge Ramirez-Ortiz 	[17] = "EFUSE_READ_PUF_SEC_CTRL",
88*4b46e0e8SJorge Ramirez-Ortiz 	[18] = "EFUSE_READ_PPK_HASH",
89*4b46e0e8SJorge Ramirez-Ortiz 	[19] = "EFUSE_READ_DEC_EFUSE_ONLY",
90*4b46e0e8SJorge Ramirez-Ortiz 	[20] = "EFUSE_READ_DNA",
91*4b46e0e8SJorge Ramirez-Ortiz 	[21] = "EFUSE_READ_PUF_USER_FUSES",
92*4b46e0e8SJorge Ramirez-Ortiz 	[22] = "EFUSE_READ_PUF",
93*4b46e0e8SJorge Ramirez-Ortiz 	[23] = "EFUSE_INVALID",
94*4b46e0e8SJorge Ramirez-Ortiz };
95*4b46e0e8SJorge Ramirez-Ortiz 
96*4b46e0e8SJorge Ramirez-Ortiz static const char *const crypto_id[] = {
97*4b46e0e8SJorge Ramirez-Ortiz 	[0] = "FEATURES",
98*4b46e0e8SJorge Ramirez-Ortiz 	[1] = "RSA_SIGN_VERIFY",
99*4b46e0e8SJorge Ramirez-Ortiz 	[2] = "RSA_PUBLIC_ENCRYPT",
100*4b46e0e8SJorge Ramirez-Ortiz 	[3] = "RSA_PRIVATE_DECRYPT",
101*4b46e0e8SJorge Ramirez-Ortiz 	[4] = "RSA_KAT",
102*4b46e0e8SJorge Ramirez-Ortiz 	[32] = "SHA3_UPDATE",
103*4b46e0e8SJorge Ramirez-Ortiz 	[33] = "SHA3_KAT",
104*4b46e0e8SJorge Ramirez-Ortiz 	[64] = "ELLIPTIC_GENERATE_PUBLIC_KEY",
105*4b46e0e8SJorge Ramirez-Ortiz 	[65] = "ELLIPTIC_GENERATE_SIGN",
106*4b46e0e8SJorge Ramirez-Ortiz 	[66] = "ELLIPTIC_VALIDATE_PUBLIC_KEY",
107*4b46e0e8SJorge Ramirez-Ortiz 	[67] = "ELLIPTIC_VERIFY_SIGN",
108*4b46e0e8SJorge Ramirez-Ortiz 	[68] = "ELLIPTIC_KAT",
109*4b46e0e8SJorge Ramirez-Ortiz 	[96] = "AES_INIT",
110*4b46e0e8SJorge Ramirez-Ortiz 	[97] = "AES_OP_INIT",
111*4b46e0e8SJorge Ramirez-Ortiz 	[98] = "AES_UPDATE_AAD",
112*4b46e0e8SJorge Ramirez-Ortiz 	[99] = "AES_ENCRYPT_UPDATE",
113*4b46e0e8SJorge Ramirez-Ortiz 	[100] = "AES_ENCRYPT_FINAL",
114*4b46e0e8SJorge Ramirez-Ortiz 	[101] = "AES_DECRYPT_UPDATE",
115*4b46e0e8SJorge Ramirez-Ortiz 	[102] = "AES_DECRYPT_FINAL",
116*4b46e0e8SJorge Ramirez-Ortiz 	[103] = "AES_KEY_ZERO",
117*4b46e0e8SJorge Ramirez-Ortiz 	[104] = "AES_WRITE_KEY",
118*4b46e0e8SJorge Ramirez-Ortiz 	[105] = "AES_LOCK_USER_KEY",
119*4b46e0e8SJorge Ramirez-Ortiz 	[106] = "AES_KEK_DECRYPT",
120*4b46e0e8SJorge Ramirez-Ortiz 	[107] = "AES_SET_DPA_CM",
121*4b46e0e8SJorge Ramirez-Ortiz 	[108] = "AES_DECRYPT_KAT",
122*4b46e0e8SJorge Ramirez-Ortiz 	[109] = "AES_DECRYPT_CM_KAT",
123*4b46e0e8SJorge Ramirez-Ortiz 	[110] = "MAX",
124*4b46e0e8SJorge Ramirez-Ortiz };
125*4b46e0e8SJorge Ramirez-Ortiz 
126*4b46e0e8SJorge Ramirez-Ortiz static const char *const puf_id[] = {
127*4b46e0e8SJorge Ramirez-Ortiz 	[0] = "PUF_API_FEATURES",
128*4b46e0e8SJorge Ramirez-Ortiz 	[1] = "PUF_REGISTRATION",
129*4b46e0e8SJorge Ramirez-Ortiz 	[2] = "PUF_REGENERATION",
130*4b46e0e8SJorge Ramirez-Ortiz 	[3] = "PUF_CLEAR_PUF_ID",
131*4b46e0e8SJorge Ramirez-Ortiz };
132*4b46e0e8SJorge Ramirez-Ortiz 
133*4b46e0e8SJorge Ramirez-Ortiz static const char *const module[] = {
134*4b46e0e8SJorge Ramirez-Ortiz 	[5] = "CRYPTO",
135*4b46e0e8SJorge Ramirez-Ortiz 	[7] = "FPGA",
136*4b46e0e8SJorge Ramirez-Ortiz 	[11] = "NVM",
137*4b46e0e8SJorge Ramirez-Ortiz 	[12] = "PUF",
138*4b46e0e8SJorge Ramirez-Ortiz };
139*4b46e0e8SJorge Ramirez-Ortiz 
140*4b46e0e8SJorge Ramirez-Ortiz static const char *const fpga_id[] = {
141*4b46e0e8SJorge Ramirez-Ortiz 	[1] = "LOAD",
142*4b46e0e8SJorge Ramirez-Ortiz };
143*4b46e0e8SJorge Ramirez-Ortiz 
versal_mbox_call_trace(uint32_t call)144*4b46e0e8SJorge Ramirez-Ortiz static void versal_mbox_call_trace(uint32_t call)
145*4b46e0e8SJorge Ramirez-Ortiz {
146*4b46e0e8SJorge Ramirez-Ortiz 	uint32_t mid = call >>  8 & 0xff;
147*4b46e0e8SJorge Ramirez-Ortiz 	uint32_t api = call & 0xff;
148*4b46e0e8SJorge Ramirez-Ortiz 	const char *val = NULL;
149*4b46e0e8SJorge Ramirez-Ortiz 
150*4b46e0e8SJorge Ramirez-Ortiz 	switch (mid) {
151*4b46e0e8SJorge Ramirez-Ortiz 	case 5:
152*4b46e0e8SJorge Ramirez-Ortiz 		if (api < ARRAY_SIZE(crypto_id))
153*4b46e0e8SJorge Ramirez-Ortiz 			val = crypto_id[api];
154*4b46e0e8SJorge Ramirez-Ortiz 
155*4b46e0e8SJorge Ramirez-Ortiz 		break;
156*4b46e0e8SJorge Ramirez-Ortiz 	case 7:
157*4b46e0e8SJorge Ramirez-Ortiz 		if (api < ARRAY_SIZE(fpga_id))
158*4b46e0e8SJorge Ramirez-Ortiz 			val = fpga_id[api];
159*4b46e0e8SJorge Ramirez-Ortiz 
160*4b46e0e8SJorge Ramirez-Ortiz 		break;
161*4b46e0e8SJorge Ramirez-Ortiz 	case 11:
162*4b46e0e8SJorge Ramirez-Ortiz 		if (api < ARRAY_SIZE(nvm_id))
163*4b46e0e8SJorge Ramirez-Ortiz 			val = nvm_id[api];
164*4b46e0e8SJorge Ramirez-Ortiz 
165*4b46e0e8SJorge Ramirez-Ortiz 		break;
166*4b46e0e8SJorge Ramirez-Ortiz 	case 12:
167*4b46e0e8SJorge Ramirez-Ortiz 		if (api < ARRAY_SIZE(puf_id))
168*4b46e0e8SJorge Ramirez-Ortiz 			val = puf_id[api];
169*4b46e0e8SJorge Ramirez-Ortiz 
170*4b46e0e8SJorge Ramirez-Ortiz 		break;
171*4b46e0e8SJorge Ramirez-Ortiz 	default:
172*4b46e0e8SJorge Ramirez-Ortiz 		break;
173*4b46e0e8SJorge Ramirez-Ortiz 	}
174*4b46e0e8SJorge Ramirez-Ortiz 
175*4b46e0e8SJorge Ramirez-Ortiz 	IMSG("--- mbox: service: %s\t call: %s", module[mid],
176*4b46e0e8SJorge Ramirez-Ortiz 	     val ? val : "Invalid");
177*4b46e0e8SJorge Ramirez-Ortiz };
178*4b46e0e8SJorge Ramirez-Ortiz 
mbox_call(enum versal_ipi_api_id id,uint32_t blocking_call)179*4b46e0e8SJorge Ramirez-Ortiz static TEE_Result mbox_call(enum versal_ipi_api_id id, uint32_t blocking_call)
180*4b46e0e8SJorge Ramirez-Ortiz {
181*4b46e0e8SJorge Ramirez-Ortiz 	struct thread_smc_args args = {
182*4b46e0e8SJorge Ramirez-Ortiz 		.a0 = PM_SIP_SVC | id,
183*4b46e0e8SJorge Ramirez-Ortiz 		.a1 = reg_pair_to_64(0, ipi.lcl),
184*4b46e0e8SJorge Ramirez-Ortiz 		.a2 = reg_pair_to_64(0, ipi.rmt),
185*4b46e0e8SJorge Ramirez-Ortiz 		.a3 = reg_pair_to_64(0, blocking_call),
186*4b46e0e8SJorge Ramirez-Ortiz 	};
187*4b46e0e8SJorge Ramirez-Ortiz 
188*4b46e0e8SJorge Ramirez-Ortiz 	thread_smccc(&args);
189*4b46e0e8SJorge Ramirez-Ortiz 
190*4b46e0e8SJorge Ramirez-Ortiz 	/* Give the PLM time to access the console */
191*4b46e0e8SJorge Ramirez-Ortiz 	if (IS_ENABLED(CFG_VERSAL_TRACE_PLM))
192*4b46e0e8SJorge Ramirez-Ortiz 		mdelay(500);
193*4b46e0e8SJorge Ramirez-Ortiz 
194*4b46e0e8SJorge Ramirez-Ortiz 	if (args.a0)
195*4b46e0e8SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
196*4b46e0e8SJorge Ramirez-Ortiz 
197*4b46e0e8SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
198*4b46e0e8SJorge Ramirez-Ortiz }
199*4b46e0e8SJorge Ramirez-Ortiz 
versal_mbox_write_req(struct versal_ipi_cmd * cmd)200*4b46e0e8SJorge Ramirez-Ortiz static TEE_Result versal_mbox_write_req(struct versal_ipi_cmd *cmd)
201*4b46e0e8SJorge Ramirez-Ortiz {
202*4b46e0e8SJorge Ramirez-Ortiz 	size_t i = 0;
203*4b46e0e8SJorge Ramirez-Ortiz 
204*4b46e0e8SJorge Ramirez-Ortiz 	for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) {
205*4b46e0e8SJorge Ramirez-Ortiz 		if (!cmd->ibuf[i].mem.buf)
206*4b46e0e8SJorge Ramirez-Ortiz 			continue;
207*4b46e0e8SJorge Ramirez-Ortiz 
208*4b46e0e8SJorge Ramirez-Ortiz 		if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf,
209*4b46e0e8SJorge Ramirez-Ortiz 				CACHELINE_LEN)) {
210*4b46e0e8SJorge Ramirez-Ortiz 			EMSG("address not aligned: buffer %zu - %p", i,
211*4b46e0e8SJorge Ramirez-Ortiz 			     cmd->ibuf[i].mem.buf);
212*4b46e0e8SJorge Ramirez-Ortiz 			return TEE_ERROR_GENERIC;
213*4b46e0e8SJorge Ramirez-Ortiz 		}
214*4b46e0e8SJorge Ramirez-Ortiz 
215*4b46e0e8SJorge Ramirez-Ortiz 		if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) {
216*4b46e0e8SJorge Ramirez-Ortiz 			EMSG("length not aligned: buffer %zu - %zu",
217*4b46e0e8SJorge Ramirez-Ortiz 			     i, cmd->ibuf[i].mem.alloc_len);
218*4b46e0e8SJorge Ramirez-Ortiz 			return TEE_ERROR_GENERIC;
219*4b46e0e8SJorge Ramirez-Ortiz 		}
220*4b46e0e8SJorge Ramirez-Ortiz 
221*4b46e0e8SJorge Ramirez-Ortiz 		cache_operation(TEE_CACHEFLUSH, cmd->ibuf[i].mem.buf,
222*4b46e0e8SJorge Ramirez-Ortiz 				cmd->ibuf[i].mem.alloc_len);
223*4b46e0e8SJorge Ramirez-Ortiz 	}
224*4b46e0e8SJorge Ramirez-Ortiz 
225*4b46e0e8SJorge Ramirez-Ortiz 	memcpy(ipi.req, cmd->data, sizeof(cmd->data));
226*4b46e0e8SJorge Ramirez-Ortiz 
227*4b46e0e8SJorge Ramirez-Ortiz 	/* Cache operation on the IPI buffer is safe */
228*4b46e0e8SJorge Ramirez-Ortiz 	cache_operation(TEE_CACHEFLUSH, ipi.req, sizeof(cmd->data));
229*4b46e0e8SJorge Ramirez-Ortiz 
230*4b46e0e8SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
231*4b46e0e8SJorge Ramirez-Ortiz }
232*4b46e0e8SJorge Ramirez-Ortiz 
versal_mbox_read_rsp(struct versal_ipi_cmd * cmd,struct versal_ipi_cmd * rsp,uint32_t * status)233*4b46e0e8SJorge Ramirez-Ortiz static TEE_Result versal_mbox_read_rsp(struct versal_ipi_cmd *cmd,
234*4b46e0e8SJorge Ramirez-Ortiz 				       struct versal_ipi_cmd *rsp,
235*4b46e0e8SJorge Ramirez-Ortiz 				       uint32_t *status)
236*4b46e0e8SJorge Ramirez-Ortiz {
237*4b46e0e8SJorge Ramirez-Ortiz 	size_t i = 0;
238*4b46e0e8SJorge Ramirez-Ortiz 
239*4b46e0e8SJorge Ramirez-Ortiz 	/* Cache operation on the IPI buffer is safe */
240*4b46e0e8SJorge Ramirez-Ortiz 	cache_operation(TEE_CACHEINVALIDATE, ipi.rsp, sizeof(rsp->data));
241*4b46e0e8SJorge Ramirez-Ortiz 
242*4b46e0e8SJorge Ramirez-Ortiz 	*status = *(uint32_t *)ipi.rsp;
243*4b46e0e8SJorge Ramirez-Ortiz 
244*4b46e0e8SJorge Ramirez-Ortiz 	if (*status)
245*4b46e0e8SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
246*4b46e0e8SJorge Ramirez-Ortiz 
247*4b46e0e8SJorge Ramirez-Ortiz 	if (rsp)
248*4b46e0e8SJorge Ramirez-Ortiz 		memcpy(rsp->data, ipi.rsp, sizeof(rsp->data));
249*4b46e0e8SJorge Ramirez-Ortiz 
250*4b46e0e8SJorge Ramirez-Ortiz 	for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) {
251*4b46e0e8SJorge Ramirez-Ortiz 		if (!cmd->ibuf[i].mem.buf)
252*4b46e0e8SJorge Ramirez-Ortiz 			continue;
253*4b46e0e8SJorge Ramirez-Ortiz 
254*4b46e0e8SJorge Ramirez-Ortiz 		if (!IS_ALIGNED((uintptr_t)cmd->ibuf[i].mem.buf,
255*4b46e0e8SJorge Ramirez-Ortiz 				CACHELINE_LEN)) {
256*4b46e0e8SJorge Ramirez-Ortiz 			EMSG("address not aligned: buffer %zu - %p",
257*4b46e0e8SJorge Ramirez-Ortiz 			     i, cmd->ibuf[i].mem.buf);
258*4b46e0e8SJorge Ramirez-Ortiz 			return TEE_ERROR_GENERIC;
259*4b46e0e8SJorge Ramirez-Ortiz 		}
260*4b46e0e8SJorge Ramirez-Ortiz 
261*4b46e0e8SJorge Ramirez-Ortiz 		if (!IS_ALIGNED(cmd->ibuf[i].mem.alloc_len, CACHELINE_LEN)) {
262*4b46e0e8SJorge Ramirez-Ortiz 			EMSG("length not aligned: buffer %zu - %zu",
263*4b46e0e8SJorge Ramirez-Ortiz 			     i, cmd->ibuf[i].mem.alloc_len);
264*4b46e0e8SJorge Ramirez-Ortiz 			return TEE_ERROR_GENERIC;
265*4b46e0e8SJorge Ramirez-Ortiz 		}
266*4b46e0e8SJorge Ramirez-Ortiz 
267*4b46e0e8SJorge Ramirez-Ortiz 		cache_operation(TEE_CACHEINVALIDATE,
268*4b46e0e8SJorge Ramirez-Ortiz 				cmd->ibuf[i].mem.buf,
269*4b46e0e8SJorge Ramirez-Ortiz 				cmd->ibuf[i].mem.alloc_len);
270*4b46e0e8SJorge Ramirez-Ortiz 	}
271*4b46e0e8SJorge Ramirez-Ortiz 
272*4b46e0e8SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
273*4b46e0e8SJorge Ramirez-Ortiz }
274*4b46e0e8SJorge Ramirez-Ortiz 
versal_mbox_alloc(size_t len,const void * init,struct versal_mbox_mem * mem)275*4b46e0e8SJorge Ramirez-Ortiz TEE_Result versal_mbox_alloc(size_t len, const void *init,
276*4b46e0e8SJorge Ramirez-Ortiz 			     struct versal_mbox_mem *mem)
277*4b46e0e8SJorge Ramirez-Ortiz {
278*4b46e0e8SJorge Ramirez-Ortiz 	mem->buf = memalign(CACHELINE_LEN, ROUNDUP(len, CACHELINE_LEN));
279*4b46e0e8SJorge Ramirez-Ortiz 	if (!mem->buf)
280*4b46e0e8SJorge Ramirez-Ortiz 		panic();
281*4b46e0e8SJorge Ramirez-Ortiz 
282*4b46e0e8SJorge Ramirez-Ortiz 	memset(mem->buf, 0, ROUNDUP(len, CACHELINE_LEN));
283*4b46e0e8SJorge Ramirez-Ortiz 
284*4b46e0e8SJorge Ramirez-Ortiz 	if (init)
285*4b46e0e8SJorge Ramirez-Ortiz 		memcpy(mem->buf, init, len);
286*4b46e0e8SJorge Ramirez-Ortiz 
287*4b46e0e8SJorge Ramirez-Ortiz 	mem->alloc_len = ROUNDUP(len, CACHELINE_LEN);
288*4b46e0e8SJorge Ramirez-Ortiz 	mem->len = len;
289*4b46e0e8SJorge Ramirez-Ortiz 
290*4b46e0e8SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
291*4b46e0e8SJorge Ramirez-Ortiz }
292*4b46e0e8SJorge Ramirez-Ortiz 
versal_mbox_notify(struct versal_ipi_cmd * cmd,struct versal_ipi_cmd * rsp,uint32_t * err)293*4b46e0e8SJorge Ramirez-Ortiz TEE_Result versal_mbox_notify(struct versal_ipi_cmd *cmd,
294*4b46e0e8SJorge Ramirez-Ortiz 			      struct versal_ipi_cmd *rsp, uint32_t *err)
295*4b46e0e8SJorge Ramirez-Ortiz {
296*4b46e0e8SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
297*4b46e0e8SJorge Ramirez-Ortiz 	uint32_t remote_status = 0;
298*4b46e0e8SJorge Ramirez-Ortiz 
299*4b46e0e8SJorge Ramirez-Ortiz 	mutex_lock(&ipi.lock);
300*4b46e0e8SJorge Ramirez-Ortiz 
301*4b46e0e8SJorge Ramirez-Ortiz 	ret = versal_mbox_write_req(cmd);
302*4b46e0e8SJorge Ramirez-Ortiz 	if (ret) {
303*4b46e0e8SJorge Ramirez-Ortiz 		EMSG("Can't write the request command");
304*4b46e0e8SJorge Ramirez-Ortiz 		goto out;
305*4b46e0e8SJorge Ramirez-Ortiz 	}
306*4b46e0e8SJorge Ramirez-Ortiz 
307*4b46e0e8SJorge Ramirez-Ortiz 	if (IS_ENABLED(CFG_VERSAL_TRACE_MBOX))
308*4b46e0e8SJorge Ramirez-Ortiz 		versal_mbox_call_trace(cmd->data[0]);
309*4b46e0e8SJorge Ramirez-Ortiz 
310*4b46e0e8SJorge Ramirez-Ortiz 	ret = mbox_call(IPI_MAILBOX_NOTIFY, IPI_BLOCK);
311*4b46e0e8SJorge Ramirez-Ortiz 	if (ret) {
312*4b46e0e8SJorge Ramirez-Ortiz 		EMSG("IPI error");
313*4b46e0e8SJorge Ramirez-Ortiz 		goto out;
314*4b46e0e8SJorge Ramirez-Ortiz 	}
315*4b46e0e8SJorge Ramirez-Ortiz 
316*4b46e0e8SJorge Ramirez-Ortiz 	ret = versal_mbox_read_rsp(cmd, rsp, &remote_status);
317*4b46e0e8SJorge Ramirez-Ortiz 	if (ret)
318*4b46e0e8SJorge Ramirez-Ortiz 		EMSG("Can't read the remote response");
319*4b46e0e8SJorge Ramirez-Ortiz 
320*4b46e0e8SJorge Ramirez-Ortiz 	if (remote_status) {
321*4b46e0e8SJorge Ramirez-Ortiz 		if (err)
322*4b46e0e8SJorge Ramirez-Ortiz 			*err = remote_status;
323*4b46e0e8SJorge Ramirez-Ortiz 		/*
324*4b46e0e8SJorge Ramirez-Ortiz 		 * Check the remote code (FSBL repository) in xplmi_status.h
325*4b46e0e8SJorge Ramirez-Ortiz 		 * and the relevant service error (ie, xsecure_error.h) for
326*4b46e0e8SJorge Ramirez-Ortiz 		 * detailed information.
327*4b46e0e8SJorge Ramirez-Ortiz 		 */
328*4b46e0e8SJorge Ramirez-Ortiz 		DMSG("PLM: plm status = 0x%" PRIx32 ", lib_status = 0x%" PRIx32,
329*4b46e0e8SJorge Ramirez-Ortiz 		     (remote_status & 0xFFFF0000) >> 16,
330*4b46e0e8SJorge Ramirez-Ortiz 		     (remote_status & 0x0000FFFF));
331*4b46e0e8SJorge Ramirez-Ortiz 
332*4b46e0e8SJorge Ramirez-Ortiz 		ret = TEE_ERROR_GENERIC;
333*4b46e0e8SJorge Ramirez-Ortiz 	}
334*4b46e0e8SJorge Ramirez-Ortiz out:
335*4b46e0e8SJorge Ramirez-Ortiz 	mutex_unlock(&ipi.lock);
336*4b46e0e8SJorge Ramirez-Ortiz 
337*4b46e0e8SJorge Ramirez-Ortiz 	return ret;
338*4b46e0e8SJorge Ramirez-Ortiz }
339*4b46e0e8SJorge Ramirez-Ortiz 
versal_mbox_init(void)340*4b46e0e8SJorge Ramirez-Ortiz static TEE_Result versal_mbox_init(void)
341*4b46e0e8SJorge Ramirez-Ortiz {
342*4b46e0e8SJorge Ramirez-Ortiz 	switch (CFG_VERSAL_MBOX_IPI_ID) {
343*4b46e0e8SJorge Ramirez-Ortiz 	case 0:
344*4b46e0e8SJorge Ramirez-Ortiz 		ipi.buf = IPI_BUFFER_APU_ID_0_BASE;
345*4b46e0e8SJorge Ramirez-Ortiz 		ipi.lcl = IPI_ID_0;
346*4b46e0e8SJorge Ramirez-Ortiz 		break;
347*4b46e0e8SJorge Ramirez-Ortiz 	case 3:
348*4b46e0e8SJorge Ramirez-Ortiz 		break;
349*4b46e0e8SJorge Ramirez-Ortiz 	case 4:
350*4b46e0e8SJorge Ramirez-Ortiz 		ipi.buf = IPI_BUFFER_APU_ID_4_BASE;
351*4b46e0e8SJorge Ramirez-Ortiz 		ipi.lcl = IPI_ID_4;
352*4b46e0e8SJorge Ramirez-Ortiz 		break;
353*4b46e0e8SJorge Ramirez-Ortiz 	case 5:
354*4b46e0e8SJorge Ramirez-Ortiz 		ipi.buf = IPI_BUFFER_APU_ID_5_BASE;
355*4b46e0e8SJorge Ramirez-Ortiz 		ipi.lcl = IPI_ID_5;
356*4b46e0e8SJorge Ramirez-Ortiz 		break;
357*4b46e0e8SJorge Ramirez-Ortiz 	default:
358*4b46e0e8SJorge Ramirez-Ortiz 		EMSG("Invalid IPI requested");
359*4b46e0e8SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
360*4b46e0e8SJorge Ramirez-Ortiz 	}
361*4b46e0e8SJorge Ramirez-Ortiz 
362*4b46e0e8SJorge Ramirez-Ortiz 	ipi.req = core_mmu_add_mapping(MEM_AREA_RAM_SEC,
363*4b46e0e8SJorge Ramirez-Ortiz 				       ipi.buf + IPI_BUFFER_REMOTE_OFFSET +
364*4b46e0e8SJorge Ramirez-Ortiz 				       IPI_BUFFER_REQ_OFFSET,
365*4b46e0e8SJorge Ramirez-Ortiz 				       sizeof(struct versal_ipi_cmd));
366*4b46e0e8SJorge Ramirez-Ortiz 
367*4b46e0e8SJorge Ramirez-Ortiz 	ipi.rsp = core_mmu_add_mapping(MEM_AREA_RAM_SEC,
368*4b46e0e8SJorge Ramirez-Ortiz 				       ipi.buf + IPI_BUFFER_REMOTE_OFFSET +
369*4b46e0e8SJorge Ramirez-Ortiz 				       IPI_BUFFER_RESP_OFFSET,
370*4b46e0e8SJorge Ramirez-Ortiz 				       sizeof(struct versal_ipi_cmd));
371*4b46e0e8SJorge Ramirez-Ortiz 	if (!ipi.req || !ipi.rsp)
372*4b46e0e8SJorge Ramirez-Ortiz 		panic();
373*4b46e0e8SJorge Ramirez-Ortiz 
374*4b46e0e8SJorge Ramirez-Ortiz 	mutex_init(&ipi.lock);
375*4b46e0e8SJorge Ramirez-Ortiz 
376*4b46e0e8SJorge Ramirez-Ortiz 	return mbox_call(IPI_MAILBOX_OPEN, IPI_BLOCK);
377*4b46e0e8SJorge Ramirez-Ortiz }
378*4b46e0e8SJorge Ramirez-Ortiz early_init(versal_mbox_init);
379