xref: /optee_os/core/drivers/versal_nvm.c (revision 55667e70aa4b73dc43bd1a2c1decb40fb8ef65e7)
1*55667e70SJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-2-Clause
2*55667e70SJorge Ramirez-Ortiz /*
3*55667e70SJorge Ramirez-Ortiz  * Copyright (C) 2022 Foundries.io Ltd
4*55667e70SJorge Ramirez-Ortiz  * Jorge Ramirez-Ortiz <jorge@foundries.io>
5*55667e70SJorge Ramirez-Ortiz  */
6*55667e70SJorge Ramirez-Ortiz 
7*55667e70SJorge Ramirez-Ortiz #include <arm.h>
8*55667e70SJorge Ramirez-Ortiz #include <drivers/versal_nvm.h>
9*55667e70SJorge Ramirez-Ortiz #include <drivers/versal_mbox.h>
10*55667e70SJorge Ramirez-Ortiz #include <initcall.h>
11*55667e70SJorge Ramirez-Ortiz #include <kernel/panic.h>
12*55667e70SJorge Ramirez-Ortiz #include <kernel/tee_misc.h>
13*55667e70SJorge Ramirez-Ortiz #include <mm/core_memprot.h>
14*55667e70SJorge Ramirez-Ortiz #include <string.h>
15*55667e70SJorge Ramirez-Ortiz #include <tee/cache.h>
16*55667e70SJorge Ramirez-Ortiz 
17*55667e70SJorge Ramirez-Ortiz #include "drivers/versal_nvm.h"
18*55667e70SJorge Ramirez-Ortiz 
19*55667e70SJorge Ramirez-Ortiz #define NVM_WORD_LEN 4
20*55667e70SJorge Ramirez-Ortiz 
21*55667e70SJorge Ramirez-Ortiz /* Protocol API with the remote processor */
22*55667e70SJorge Ramirez-Ortiz #define NVM_MODULE_SHIFT		8
23*55667e70SJorge Ramirez-Ortiz #define NVM_MODULE			11
24*55667e70SJorge Ramirez-Ortiz #define NVM_API_ID(_id) ((NVM_MODULE << NVM_MODULE_SHIFT) | (_id))
25*55667e70SJorge Ramirez-Ortiz 
26*55667e70SJorge Ramirez-Ortiz #define __aligned_efuse			__aligned(CACHELINE_LEN)
27*55667e70SJorge Ramirez-Ortiz 
28*55667e70SJorge Ramirez-Ortiz /* Internal */
29*55667e70SJorge Ramirez-Ortiz struct versal_efuse_puf_fuse_addr {
30*55667e70SJorge Ramirez-Ortiz 	uint64_t data_addr;
31*55667e70SJorge Ramirez-Ortiz 	uint32_t start_row;
32*55667e70SJorge Ramirez-Ortiz 	uint32_t num_rows;
33*55667e70SJorge Ramirez-Ortiz 	uint8_t env_monitor_dis;
34*55667e70SJorge Ramirez-Ortiz 	uint8_t prgm_puf_fuse;
35*55667e70SJorge Ramirez-Ortiz 	uint8_t pad[46];
36*55667e70SJorge Ramirez-Ortiz };
37*55667e70SJorge Ramirez-Ortiz 
38*55667e70SJorge Ramirez-Ortiz /*
39*55667e70SJorge Ramirez-Ortiz  * Max size of the buffer needed for the remote processor to DMA efuse _data_
40*55667e70SJorge Ramirez-Ortiz  * to/from
41*55667e70SJorge Ramirez-Ortiz  */
42*55667e70SJorge Ramirez-Ortiz #define EFUSE_MAX_LEN (EFUSE_MAX_USER_FUSES * sizeof(uint32_t))
43*55667e70SJorge Ramirez-Ortiz 
44*55667e70SJorge Ramirez-Ortiz enum versal_nvm_api_id {
45*55667e70SJorge Ramirez-Ortiz 	API_FEATURES				= 0,
46*55667e70SJorge Ramirez-Ortiz 	BBRAM_WRITE_AES_KEY			= 1,
47*55667e70SJorge Ramirez-Ortiz 	BBRAM_ZEROIZE				= 2,
48*55667e70SJorge Ramirez-Ortiz 	BBRAM_WRITE_USER_DATA			= 3,
49*55667e70SJorge Ramirez-Ortiz 	BBRAM_READ_USER_DATA			= 4,
50*55667e70SJorge Ramirez-Ortiz 	BBRAM_LOCK_WRITE_USER_DATA		= 5,
51*55667e70SJorge Ramirez-Ortiz 	EFUSE_WRITE				= 6,
52*55667e70SJorge Ramirez-Ortiz 	EFUSE_WRITE_PUF				= 7,
53*55667e70SJorge Ramirez-Ortiz 	EFUSE_PUF_USER_FUSE_WRITE		= 8,
54*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_IV				= 9,
55*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_REVOCATION_ID		= 10,
56*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_OFFCHIP_REVOCATION_ID	= 11,
57*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_USER_FUSES			= 12,
58*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_MISC_CTRL			= 13,
59*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_SEC_CTRL			= 14,
60*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_SEC_MISC1			= 15,
61*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_BOOT_ENV_CTRL		= 16,
62*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_PUF_SEC_CTRL			= 17,
63*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_PPK_HASH			= 18,
64*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_DEC_EFUSE_ONLY		= 19,
65*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_DNA				= 20,
66*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_PUF_USER_FUSES		= 21,
67*55667e70SJorge Ramirez-Ortiz 	EFUSE_READ_PUF				= 22,
68*55667e70SJorge Ramirez-Ortiz 	EFUSE_INVALID				= 23,
69*55667e70SJorge Ramirez-Ortiz };
70*55667e70SJorge Ramirez-Ortiz 
71*55667e70SJorge Ramirez-Ortiz /* uint64_t are memory addresses */
72*55667e70SJorge Ramirez-Ortiz struct versal_efuse_data {
73*55667e70SJorge Ramirez-Ortiz 	uint64_t env_mon_dis_flag;
74*55667e70SJorge Ramirez-Ortiz 	uint64_t aes_key_addr;
75*55667e70SJorge Ramirez-Ortiz 	uint64_t ppk_hash_addr;
76*55667e70SJorge Ramirez-Ortiz 	uint64_t dec_only_addr;
77*55667e70SJorge Ramirez-Ortiz 	uint64_t sec_ctrl_addr;
78*55667e70SJorge Ramirez-Ortiz 	uint64_t misc_ctrl_addr;
79*55667e70SJorge Ramirez-Ortiz 	uint64_t revoke_id_addr;
80*55667e70SJorge Ramirez-Ortiz 	uint64_t iv_addr;
81*55667e70SJorge Ramirez-Ortiz 	uint64_t user_fuse_addr;
82*55667e70SJorge Ramirez-Ortiz 	uint64_t glitch_cfg_addr;
83*55667e70SJorge Ramirez-Ortiz 	uint64_t boot_env_ctrl_addr;
84*55667e70SJorge Ramirez-Ortiz 	uint64_t misc1_ctrl_addr;
85*55667e70SJorge Ramirez-Ortiz 	uint64_t offchip_id_addr;
86*55667e70SJorge Ramirez-Ortiz 	uint8_t pad[24];
87*55667e70SJorge Ramirez-Ortiz };
88*55667e70SJorge Ramirez-Ortiz 
89*55667e70SJorge Ramirez-Ortiz /* Helper read and write requests (not part of the protocol) */
90*55667e70SJorge Ramirez-Ortiz struct versal_nvm_buf {
91*55667e70SJorge Ramirez-Ortiz 	size_t len;
92*55667e70SJorge Ramirez-Ortiz 	void *buf;
93*55667e70SJorge Ramirez-Ortiz };
94*55667e70SJorge Ramirez-Ortiz 
95*55667e70SJorge Ramirez-Ortiz struct versal_nvm_read_req {
96*55667e70SJorge Ramirez-Ortiz 	enum versal_nvm_api_id efuse_id;
97*55667e70SJorge Ramirez-Ortiz 	enum versal_nvm_revocation_id revocation_id;
98*55667e70SJorge Ramirez-Ortiz 	enum versal_nvm_offchip_id offchip_id;
99*55667e70SJorge Ramirez-Ortiz 	enum versal_nvm_ppk_type ppk_type;
100*55667e70SJorge Ramirez-Ortiz 	enum versal_nvm_iv_type iv_type;
101*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF];
102*55667e70SJorge Ramirez-Ortiz };
103*55667e70SJorge Ramirez-Ortiz 
104*55667e70SJorge Ramirez-Ortiz struct versal_bbram_data {
105*55667e70SJorge Ramirez-Ortiz 	size_t aes_key_len;
106*55667e70SJorge Ramirez-Ortiz 	uint32_t user_data;
107*55667e70SJorge Ramirez-Ortiz };
108*55667e70SJorge Ramirez-Ortiz 
109*55667e70SJorge Ramirez-Ortiz struct versal_nvm_write_req {
110*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_data data;
111*55667e70SJorge Ramirez-Ortiz 	struct versal_bbram_data bbram;
112*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF];
113*55667e70SJorge Ramirez-Ortiz 	enum versal_nvm_api_id efuse_id;
114*55667e70SJorge Ramirez-Ortiz };
115*55667e70SJorge Ramirez-Ortiz 
116*55667e70SJorge Ramirez-Ortiz static TEE_Result
prepare_cmd(struct versal_ipi_cmd * cmd,enum versal_nvm_api_id efuse,struct versal_nvm_buf * ibufs,uint32_t * arg)117*55667e70SJorge Ramirez-Ortiz prepare_cmd(struct versal_ipi_cmd *cmd, enum versal_nvm_api_id efuse,
118*55667e70SJorge Ramirez-Ortiz 	    struct versal_nvm_buf *ibufs, uint32_t *arg)
119*55667e70SJorge Ramirez-Ortiz {
120*55667e70SJorge Ramirez-Ortiz 	uint32_t a = 0;
121*55667e70SJorge Ramirez-Ortiz 	uint32_t b = 0;
122*55667e70SJorge Ramirez-Ortiz 	size_t i = 0;
123*55667e70SJorge Ramirez-Ortiz 
124*55667e70SJorge Ramirez-Ortiz 	cmd->data[i++] = NVM_API_ID(efuse);
125*55667e70SJorge Ramirez-Ortiz 	if (arg)
126*55667e70SJorge Ramirez-Ortiz 		cmd->data[i++] = *arg;
127*55667e70SJorge Ramirez-Ortiz 
128*55667e70SJorge Ramirez-Ortiz 	if (!ibufs[0].buf)
129*55667e70SJorge Ramirez-Ortiz 		return TEE_SUCCESS;
130*55667e70SJorge Ramirez-Ortiz 
131*55667e70SJorge Ramirez-Ortiz 	reg_pair_from_64(virt_to_phys(ibufs[0].buf), &b, &a);
132*55667e70SJorge Ramirez-Ortiz 
133*55667e70SJorge Ramirez-Ortiz 	cmd->data[i++] = a;
134*55667e70SJorge Ramirez-Ortiz 	cmd->data[i++] = b;
135*55667e70SJorge Ramirez-Ortiz 
136*55667e70SJorge Ramirez-Ortiz 	for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) {
137*55667e70SJorge Ramirez-Ortiz 		cmd->ibuf[i].mem.alloc_len = ibufs[i].len;
138*55667e70SJorge Ramirez-Ortiz 		cmd->ibuf[i].mem.buf = ibufs[i].buf;
139*55667e70SJorge Ramirez-Ortiz 	}
140*55667e70SJorge Ramirez-Ortiz 
141*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
142*55667e70SJorge Ramirez-Ortiz }
143*55667e70SJorge Ramirez-Ortiz 
efuse_req(enum versal_nvm_api_id efuse,struct versal_nvm_buf * ibufs,uint32_t * arg)144*55667e70SJorge Ramirez-Ortiz static TEE_Result efuse_req(enum versal_nvm_api_id efuse,
145*55667e70SJorge Ramirez-Ortiz 			    struct versal_nvm_buf *ibufs, uint32_t *arg)
146*55667e70SJorge Ramirez-Ortiz {
147*55667e70SJorge Ramirez-Ortiz 	struct versal_ipi_cmd cmd = { };
148*55667e70SJorge Ramirez-Ortiz 	TEE_Result ret = TEE_SUCCESS;
149*55667e70SJorge Ramirez-Ortiz 
150*55667e70SJorge Ramirez-Ortiz 	ret = prepare_cmd(&cmd, efuse, ibufs, arg);
151*55667e70SJorge Ramirez-Ortiz 	if (ret)
152*55667e70SJorge Ramirez-Ortiz 		return ret;
153*55667e70SJorge Ramirez-Ortiz 
154*55667e70SJorge Ramirez-Ortiz 	ret = versal_mbox_notify(&cmd, NULL, NULL);
155*55667e70SJorge Ramirez-Ortiz 	if (ret)
156*55667e70SJorge Ramirez-Ortiz 		EMSG("Mailbox error");
157*55667e70SJorge Ramirez-Ortiz 
158*55667e70SJorge Ramirez-Ortiz 	return ret;
159*55667e70SJorge Ramirez-Ortiz }
160*55667e70SJorge Ramirez-Ortiz 
versal_alloc_read_buffer(struct versal_nvm_read_req * req)161*55667e70SJorge Ramirez-Ortiz static TEE_Result versal_alloc_read_buffer(struct versal_nvm_read_req *req)
162*55667e70SJorge Ramirez-Ortiz {
163*55667e70SJorge Ramirez-Ortiz 	assert(req);
164*55667e70SJorge Ramirez-Ortiz 	req->ibuf[0].len = 1024;
165*55667e70SJorge Ramirez-Ortiz 	req->ibuf[0].buf = alloc_cache_aligned(req->ibuf[0].len);
166*55667e70SJorge Ramirez-Ortiz 	if (!req->ibuf[0].buf)
167*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
168*55667e70SJorge Ramirez-Ortiz 
169*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
170*55667e70SJorge Ramirez-Ortiz }
171*55667e70SJorge Ramirez-Ortiz 
versal_free_read_buffer(struct versal_nvm_read_req * req)172*55667e70SJorge Ramirez-Ortiz static void versal_free_read_buffer(struct versal_nvm_read_req *req)
173*55667e70SJorge Ramirez-Ortiz {
174*55667e70SJorge Ramirez-Ortiz 	assert(req);
175*55667e70SJorge Ramirez-Ortiz 	free(req->ibuf[0].buf);
176*55667e70SJorge Ramirez-Ortiz }
177*55667e70SJorge Ramirez-Ortiz 
versal_get_read_buffer(struct versal_nvm_read_req * req)178*55667e70SJorge Ramirez-Ortiz static void *versal_get_read_buffer(struct versal_nvm_read_req *req)
179*55667e70SJorge Ramirez-Ortiz {
180*55667e70SJorge Ramirez-Ortiz 	assert(req);
181*55667e70SJorge Ramirez-Ortiz 	return req->ibuf[0].buf;
182*55667e70SJorge Ramirez-Ortiz }
183*55667e70SJorge Ramirez-Ortiz 
versal_nvm_read(struct versal_nvm_read_req * req)184*55667e70SJorge Ramirez-Ortiz static TEE_Result versal_nvm_read(struct versal_nvm_read_req *req)
185*55667e70SJorge Ramirez-Ortiz {
186*55667e70SJorge Ramirez-Ortiz 	uint32_t *arg = NULL;
187*55667e70SJorge Ramirez-Ortiz 	uint32_t val = 0;
188*55667e70SJorge Ramirez-Ortiz 
189*55667e70SJorge Ramirez-Ortiz 	if (!req)
190*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
191*55667e70SJorge Ramirez-Ortiz 
192*55667e70SJorge Ramirez-Ortiz 	switch (req->efuse_id) {
193*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_DNA:
194*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_DEC_EFUSE_ONLY:
195*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_PUF_SEC_CTRL:
196*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_BOOT_ENV_CTRL:
197*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_SEC_CTRL:
198*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_MISC_CTRL:
199*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_SEC_MISC1:
200*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_USER_FUSES:
201*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_PUF_USER_FUSES:
202*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_PUF:
203*55667e70SJorge Ramirez-Ortiz 		break;
204*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_OFFCHIP_REVOCATION_ID:
205*55667e70SJorge Ramirez-Ortiz 		val = req->offchip_id;
206*55667e70SJorge Ramirez-Ortiz 		arg = &val;
207*55667e70SJorge Ramirez-Ortiz 		break;
208*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_REVOCATION_ID:
209*55667e70SJorge Ramirez-Ortiz 		val = req->revocation_id;
210*55667e70SJorge Ramirez-Ortiz 		arg = &val;
211*55667e70SJorge Ramirez-Ortiz 		break;
212*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_IV:
213*55667e70SJorge Ramirez-Ortiz 		val = req->iv_type;
214*55667e70SJorge Ramirez-Ortiz 		arg = &val;
215*55667e70SJorge Ramirez-Ortiz 		break;
216*55667e70SJorge Ramirez-Ortiz 	case EFUSE_READ_PPK_HASH:
217*55667e70SJorge Ramirez-Ortiz 		val = req->ppk_type;
218*55667e70SJorge Ramirez-Ortiz 		arg = &val;
219*55667e70SJorge Ramirez-Ortiz 		break;
220*55667e70SJorge Ramirez-Ortiz 	case BBRAM_READ_USER_DATA:
221*55667e70SJorge Ramirez-Ortiz 		break;
222*55667e70SJorge Ramirez-Ortiz 	default:
223*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
224*55667e70SJorge Ramirez-Ortiz 	}
225*55667e70SJorge Ramirez-Ortiz 
226*55667e70SJorge Ramirez-Ortiz 	return efuse_req(req->efuse_id, req->ibuf, arg);
227*55667e70SJorge Ramirez-Ortiz }
228*55667e70SJorge Ramirez-Ortiz 
versal_nvm_write(struct versal_nvm_write_req * req)229*55667e70SJorge Ramirez-Ortiz static TEE_Result versal_nvm_write(struct versal_nvm_write_req *req)
230*55667e70SJorge Ramirez-Ortiz {
231*55667e70SJorge Ramirez-Ortiz 	uint32_t *arg = NULL;
232*55667e70SJorge Ramirez-Ortiz 	uint32_t val = 0;
233*55667e70SJorge Ramirez-Ortiz 
234*55667e70SJorge Ramirez-Ortiz 	switch (req->efuse_id) {
235*55667e70SJorge Ramirez-Ortiz 	case BBRAM_WRITE_AES_KEY:
236*55667e70SJorge Ramirez-Ortiz 		val = req->bbram.aes_key_len;
237*55667e70SJorge Ramirez-Ortiz 		arg = &val;
238*55667e70SJorge Ramirez-Ortiz 		break;
239*55667e70SJorge Ramirez-Ortiz 	case BBRAM_WRITE_USER_DATA:
240*55667e70SJorge Ramirez-Ortiz 		val = req->bbram.user_data;
241*55667e70SJorge Ramirez-Ortiz 		arg = &val;
242*55667e70SJorge Ramirez-Ortiz 		break;
243*55667e70SJorge Ramirez-Ortiz 	case EFUSE_PUF_USER_FUSE_WRITE:
244*55667e70SJorge Ramirez-Ortiz 	case EFUSE_WRITE_PUF:
245*55667e70SJorge Ramirez-Ortiz 	case EFUSE_WRITE:
246*55667e70SJorge Ramirez-Ortiz 		break;
247*55667e70SJorge Ramirez-Ortiz 	default:
248*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
249*55667e70SJorge Ramirez-Ortiz 	}
250*55667e70SJorge Ramirez-Ortiz 
251*55667e70SJorge Ramirez-Ortiz 	return efuse_req(req->efuse_id, req->ibuf, arg);
252*55667e70SJorge Ramirez-Ortiz }
253*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_user_data(uint32_t * buf,size_t len,uint32_t first,size_t num)254*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_user_data(uint32_t *buf, size_t len,
255*55667e70SJorge Ramirez-Ortiz 				       uint32_t first, size_t num)
256*55667e70SJorge Ramirez-Ortiz {
257*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_user_data cfg __aligned_efuse = {
258*55667e70SJorge Ramirez-Ortiz 		.start = first,
259*55667e70SJorge Ramirez-Ortiz 		.num = num,
260*55667e70SJorge Ramirez-Ortiz 	};
261*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
262*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_USER_FUSES,
263*55667e70SJorge Ramirez-Ortiz 	};
264*55667e70SJorge Ramirez-Ortiz 	void *rsp = NULL;
265*55667e70SJorge Ramirez-Ortiz 
266*55667e70SJorge Ramirez-Ortiz 	if (first + num > EFUSE_MAX_USER_FUSES || len < num * sizeof(uint32_t))
267*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
268*55667e70SJorge Ramirez-Ortiz 
269*55667e70SJorge Ramirez-Ortiz 	rsp = alloc_cache_aligned(1024);
270*55667e70SJorge Ramirez-Ortiz 	if (!rsp)
271*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
272*55667e70SJorge Ramirez-Ortiz 
273*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &cfg;
274*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(cfg);
275*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = rsp;
276*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = 1024;
277*55667e70SJorge Ramirez-Ortiz 
278*55667e70SJorge Ramirez-Ortiz 	cfg.addr = virt_to_phys((void *)rsp);
279*55667e70SJorge Ramirez-Ortiz 
280*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
281*55667e70SJorge Ramirez-Ortiz 		free(rsp);
282*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
283*55667e70SJorge Ramirez-Ortiz 	}
284*55667e70SJorge Ramirez-Ortiz 
285*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, rsp, num * sizeof(uint32_t));
286*55667e70SJorge Ramirez-Ortiz 	free(rsp);
287*55667e70SJorge Ramirez-Ortiz 
288*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
289*55667e70SJorge Ramirez-Ortiz }
290*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_dna(uint32_t * buf,size_t len)291*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_dna(uint32_t *buf, size_t len)
292*55667e70SJorge Ramirez-Ortiz {
293*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
294*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_DNA,
295*55667e70SJorge Ramirez-Ortiz 	};
296*55667e70SJorge Ramirez-Ortiz 
297*55667e70SJorge Ramirez-Ortiz 	if (len < EFUSE_DNA_LEN)
298*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
299*55667e70SJorge Ramirez-Ortiz 
300*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
301*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
302*55667e70SJorge Ramirez-Ortiz 
303*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
304*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
305*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
306*55667e70SJorge Ramirez-Ortiz 	}
307*55667e70SJorge Ramirez-Ortiz 
308*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), EFUSE_DNA_LEN);
309*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
310*55667e70SJorge Ramirez-Ortiz 
311*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
312*55667e70SJorge Ramirez-Ortiz }
313*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_iv(uint32_t * buf,size_t len,enum versal_nvm_iv_type type)314*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_iv(uint32_t *buf, size_t len,
315*55667e70SJorge Ramirez-Ortiz 				enum versal_nvm_iv_type type)
316*55667e70SJorge Ramirez-Ortiz {
317*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
318*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_IV,
319*55667e70SJorge Ramirez-Ortiz 		.iv_type = type,
320*55667e70SJorge Ramirez-Ortiz 	};
321*55667e70SJorge Ramirez-Ortiz 
322*55667e70SJorge Ramirez-Ortiz 	if (len < EFUSE_IV_LEN)
323*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
324*55667e70SJorge Ramirez-Ortiz 
325*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
326*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
327*55667e70SJorge Ramirez-Ortiz 
328*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
329*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
330*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
331*55667e70SJorge Ramirez-Ortiz 	}
332*55667e70SJorge Ramirez-Ortiz 
333*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), EFUSE_IV_LEN);
334*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
335*55667e70SJorge Ramirez-Ortiz 
336*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
337*55667e70SJorge Ramirez-Ortiz }
338*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_ppk(uint32_t * buf,size_t len,enum versal_nvm_ppk_type type)339*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_ppk(uint32_t *buf, size_t len,
340*55667e70SJorge Ramirez-Ortiz 				 enum versal_nvm_ppk_type type)
341*55667e70SJorge Ramirez-Ortiz {
342*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
343*55667e70SJorge Ramirez-Ortiz 		req.efuse_id = EFUSE_READ_PPK_HASH,
344*55667e70SJorge Ramirez-Ortiz 		.ppk_type = type,
345*55667e70SJorge Ramirez-Ortiz 	};
346*55667e70SJorge Ramirez-Ortiz 
347*55667e70SJorge Ramirez-Ortiz 	if (len < EFUSE_PPK_LEN)
348*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
349*55667e70SJorge Ramirez-Ortiz 
350*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
351*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
352*55667e70SJorge Ramirez-Ortiz 
353*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req))
354*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
355*55667e70SJorge Ramirez-Ortiz 
356*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), EFUSE_PPK_LEN);
357*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
358*55667e70SJorge Ramirez-Ortiz 
359*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
360*55667e70SJorge Ramirez-Ortiz }
361*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_user_data(uint32_t * buf,size_t len,uint32_t first,size_t num)362*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_user_data(uint32_t *buf, size_t len,
363*55667e70SJorge Ramirez-Ortiz 					uint32_t first, size_t num)
364*55667e70SJorge Ramirez-Ortiz {
365*55667e70SJorge Ramirez-Ortiz 	uint32_t lbuf[EFUSE_MAX_USER_FUSES] __aligned_efuse = { 0 };
366*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_user_data cfg __aligned_efuse = {
367*55667e70SJorge Ramirez-Ortiz 		.addr = (uintptr_t)lbuf,
368*55667e70SJorge Ramirez-Ortiz 		.start = first,
369*55667e70SJorge Ramirez-Ortiz 		.num = num,
370*55667e70SJorge Ramirez-Ortiz 	};
371*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req __aligned_efuse req = {
372*55667e70SJorge Ramirez-Ortiz 		.data.user_fuse_addr = virt_to_phys(&cfg),
373*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
374*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
375*55667e70SJorge Ramirez-Ortiz 	};
376*55667e70SJorge Ramirez-Ortiz 	size_t i = 0;
377*55667e70SJorge Ramirez-Ortiz 
378*55667e70SJorge Ramirez-Ortiz 	if (first + num > EFUSE_MAX_USER_FUSES || len  < num * sizeof(uint32_t))
379*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
380*55667e70SJorge Ramirez-Ortiz 
381*55667e70SJorge Ramirez-Ortiz 	req.data.user_fuse_addr = virt_to_phys((void *)req.data.user_fuse_addr);
382*55667e70SJorge Ramirez-Ortiz 	cfg.addr = virt_to_phys(lbuf);
383*55667e70SJorge Ramirez-Ortiz 
384*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
385*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
386*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
387*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
388*55667e70SJorge Ramirez-Ortiz 	req.ibuf[2].buf = lbuf;
389*55667e70SJorge Ramirez-Ortiz 	req.ibuf[2].len = sizeof(lbuf);
390*55667e70SJorge Ramirez-Ortiz 
391*55667e70SJorge Ramirez-Ortiz 	for (i = 0; i < cfg.num; i++)
392*55667e70SJorge Ramirez-Ortiz 		lbuf[i] = buf[i];
393*55667e70SJorge Ramirez-Ortiz 
394*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
395*55667e70SJorge Ramirez-Ortiz }
396*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_aes_keys(struct versal_efuse_aes_keys * keys)397*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_aes_keys(struct versal_efuse_aes_keys *keys)
398*55667e70SJorge Ramirez-Ortiz {
399*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_aes_keys cfg __aligned_efuse = { };
400*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
401*55667e70SJorge Ramirez-Ortiz 		.data.aes_key_addr = virt_to_phys(&cfg),
402*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
403*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
404*55667e70SJorge Ramirez-Ortiz 	};
405*55667e70SJorge Ramirez-Ortiz 
406*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, keys, sizeof(cfg));
407*55667e70SJorge Ramirez-Ortiz 
408*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
409*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
410*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
411*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
412*55667e70SJorge Ramirez-Ortiz 
413*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
414*55667e70SJorge Ramirez-Ortiz }
415*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_ppk_hash(struct versal_efuse_ppk_hash * hash)416*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_ppk_hash(struct versal_efuse_ppk_hash *hash)
417*55667e70SJorge Ramirez-Ortiz {
418*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_ppk_hash cfg __aligned_efuse = { };
419*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
420*55667e70SJorge Ramirez-Ortiz 		.data.ppk_hash_addr = virt_to_phys(&cfg),
421*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
422*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
423*55667e70SJorge Ramirez-Ortiz 	};
424*55667e70SJorge Ramirez-Ortiz 
425*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, hash, sizeof(cfg));
426*55667e70SJorge Ramirez-Ortiz 
427*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
428*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
429*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
430*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
431*55667e70SJorge Ramirez-Ortiz 
432*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
433*55667e70SJorge Ramirez-Ortiz }
434*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_iv(struct versal_efuse_ivs * p)435*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_iv(struct versal_efuse_ivs *p)
436*55667e70SJorge Ramirez-Ortiz {
437*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_ivs cfg __aligned_efuse = { };
438*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
439*55667e70SJorge Ramirez-Ortiz 		.data.iv_addr = virt_to_phys(&cfg),
440*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
441*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
442*55667e70SJorge Ramirez-Ortiz 	};
443*55667e70SJorge Ramirez-Ortiz 
444*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, p, sizeof(cfg));
445*55667e70SJorge Ramirez-Ortiz 
446*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
447*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
448*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
449*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
450*55667e70SJorge Ramirez-Ortiz 
451*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
452*55667e70SJorge Ramirez-Ortiz }
453*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_dec_only(struct versal_efuse_dec_only * p)454*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_dec_only(struct versal_efuse_dec_only *p)
455*55667e70SJorge Ramirez-Ortiz {
456*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_dec_only cfg __aligned_efuse = { };
457*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
458*55667e70SJorge Ramirez-Ortiz 		.data.dec_only_addr = virt_to_phys(&cfg),
459*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
460*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
461*55667e70SJorge Ramirez-Ortiz 	};
462*55667e70SJorge Ramirez-Ortiz 
463*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, p, sizeof(cfg));
464*55667e70SJorge Ramirez-Ortiz 
465*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
466*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
467*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
468*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
469*55667e70SJorge Ramirez-Ortiz 
470*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
471*55667e70SJorge Ramirez-Ortiz }
472*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_sec(struct versal_efuse_sec_ctrl_bits * p)473*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_sec(struct versal_efuse_sec_ctrl_bits *p)
474*55667e70SJorge Ramirez-Ortiz {
475*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_sec_ctrl_bits cfg __aligned_efuse = { };
476*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
477*55667e70SJorge Ramirez-Ortiz 		.data.sec_ctrl_addr = virt_to_phys(&cfg),
478*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
479*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
480*55667e70SJorge Ramirez-Ortiz 	};
481*55667e70SJorge Ramirez-Ortiz 
482*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, p, sizeof(cfg));
483*55667e70SJorge Ramirez-Ortiz 
484*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
485*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
486*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
487*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
488*55667e70SJorge Ramirez-Ortiz 
489*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
490*55667e70SJorge Ramirez-Ortiz }
491*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_misc(struct versal_efuse_misc_ctrl_bits * p)492*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_misc(struct versal_efuse_misc_ctrl_bits *p)
493*55667e70SJorge Ramirez-Ortiz {
494*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_misc_ctrl_bits cfg __aligned_efuse = { };
495*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
496*55667e70SJorge Ramirez-Ortiz 		.data.misc_ctrl_addr = virt_to_phys(&cfg),
497*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
498*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
499*55667e70SJorge Ramirez-Ortiz 	};
500*55667e70SJorge Ramirez-Ortiz 
501*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, p, sizeof(cfg));
502*55667e70SJorge Ramirez-Ortiz 
503*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
504*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
505*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
506*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
507*55667e70SJorge Ramirez-Ortiz 
508*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
509*55667e70SJorge Ramirez-Ortiz }
510*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits * p)511*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits *p)
512*55667e70SJorge Ramirez-Ortiz {
513*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_glitch_cfg_bits cfg __aligned_efuse = { };
514*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
515*55667e70SJorge Ramirez-Ortiz 		.data.glitch_cfg_addr = virt_to_phys(&cfg),
516*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
517*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
518*55667e70SJorge Ramirez-Ortiz 	};
519*55667e70SJorge Ramirez-Ortiz 
520*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, p, sizeof(cfg));
521*55667e70SJorge Ramirez-Ortiz 
522*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
523*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
524*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
525*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
526*55667e70SJorge Ramirez-Ortiz 
527*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
528*55667e70SJorge Ramirez-Ortiz }
529*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits * p)530*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits
531*55667e70SJorge Ramirez-Ortiz 				       *p)
532*55667e70SJorge Ramirez-Ortiz {
533*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_boot_env_ctrl_bits cfg __aligned_efuse = { };
534*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
535*55667e70SJorge Ramirez-Ortiz 		.data.boot_env_ctrl_addr = virt_to_phys(&cfg),
536*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
537*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
538*55667e70SJorge Ramirez-Ortiz 	};
539*55667e70SJorge Ramirez-Ortiz 
540*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, p, sizeof(cfg));
541*55667e70SJorge Ramirez-Ortiz 
542*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
543*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
544*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
545*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
546*55667e70SJorge Ramirez-Ortiz 
547*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
548*55667e70SJorge Ramirez-Ortiz }
549*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits * p)550*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits *p)
551*55667e70SJorge Ramirez-Ortiz {
552*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_sec_misc1_bits cfg __aligned_efuse = { };
553*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
554*55667e70SJorge Ramirez-Ortiz 		.data.misc1_ctrl_addr = virt_to_phys(&cfg),
555*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
556*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
557*55667e70SJorge Ramirez-Ortiz 	};
558*55667e70SJorge Ramirez-Ortiz 
559*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, p, sizeof(cfg));
560*55667e70SJorge Ramirez-Ortiz 
561*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
562*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
563*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
564*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
565*55667e70SJorge Ramirez-Ortiz 
566*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
567*55667e70SJorge Ramirez-Ortiz }
568*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_offchip_ids(struct versal_efuse_offchip_ids * p)569*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_offchip_ids(struct versal_efuse_offchip_ids *p)
570*55667e70SJorge Ramirez-Ortiz {
571*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_offchip_ids cfg __aligned_efuse = { };
572*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
573*55667e70SJorge Ramirez-Ortiz 		.data.offchip_id_addr = virt_to_phys(&cfg),
574*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
575*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
576*55667e70SJorge Ramirez-Ortiz 	};
577*55667e70SJorge Ramirez-Ortiz 
578*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, p, sizeof(cfg));
579*55667e70SJorge Ramirez-Ortiz 
580*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
581*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
582*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
583*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
584*55667e70SJorge Ramirez-Ortiz 
585*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
586*55667e70SJorge Ramirez-Ortiz }
587*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type)588*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type)
589*55667e70SJorge Ramirez-Ortiz {
590*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_misc_ctrl_bits cfg __aligned_efuse = { };
591*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
592*55667e70SJorge Ramirez-Ortiz 		.data.misc_ctrl_addr = virt_to_phys(&cfg),
593*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
594*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
595*55667e70SJorge Ramirez-Ortiz 	};
596*55667e70SJorge Ramirez-Ortiz 
597*55667e70SJorge Ramirez-Ortiz 	req.data.misc_ctrl_addr = virt_to_phys((void *)req.data.misc_ctrl_addr);
598*55667e70SJorge Ramirez-Ortiz 	if (type == EFUSE_PPK0)
599*55667e70SJorge Ramirez-Ortiz 		cfg.ppk0_invalid = 1;
600*55667e70SJorge Ramirez-Ortiz 	else if (type == EFUSE_PPK1)
601*55667e70SJorge Ramirez-Ortiz 		cfg.ppk1_invalid = 1;
602*55667e70SJorge Ramirez-Ortiz 	else if (type == EFUSE_PPK2)
603*55667e70SJorge Ramirez-Ortiz 		cfg.ppk2_invalid = 1;
604*55667e70SJorge Ramirez-Ortiz 	else
605*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
606*55667e70SJorge Ramirez-Ortiz 
607*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
608*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
609*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
610*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
611*55667e70SJorge Ramirez-Ortiz 
612*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
613*55667e70SJorge Ramirez-Ortiz }
614*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_revoke_id(uint32_t id)615*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_revoke_id(uint32_t id)
616*55667e70SJorge Ramirez-Ortiz {
617*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_revoke_ids cfg __aligned_efuse = { };
618*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
619*55667e70SJorge Ramirez-Ortiz 		.data.revoke_id_addr = virt_to_phys(&cfg),
620*55667e70SJorge Ramirez-Ortiz 		.data.env_mon_dis_flag = 1,
621*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE,
622*55667e70SJorge Ramirez-Ortiz 	};
623*55667e70SJorge Ramirez-Ortiz 	uint32_t row = 0;
624*55667e70SJorge Ramirez-Ortiz 	uint32_t bit = 0;
625*55667e70SJorge Ramirez-Ortiz 
626*55667e70SJorge Ramirez-Ortiz 	row = id >> (NVM_WORD_LEN + 1);
627*55667e70SJorge Ramirez-Ortiz 	bit = id & (NVM_WORD_LEN - 1);
628*55667e70SJorge Ramirez-Ortiz 
629*55667e70SJorge Ramirez-Ortiz 	cfg.revoke_id[row] = BIT(bit);
630*55667e70SJorge Ramirez-Ortiz 	cfg.prgm_revoke_id = 1;
631*55667e70SJorge Ramirez-Ortiz 
632*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &req.data;
633*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(req.data);
634*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = &cfg;
635*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(cfg);
636*55667e70SJorge Ramirez-Ortiz 
637*55667e70SJorge Ramirez-Ortiz 	return versal_nvm_write(&req);
638*55667e70SJorge Ramirez-Ortiz }
639*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_revoke_id(uint32_t * buf,size_t len,enum versal_nvm_revocation_id id)640*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_revoke_id(uint32_t *buf, size_t len,
641*55667e70SJorge Ramirez-Ortiz 				       enum versal_nvm_revocation_id id)
642*55667e70SJorge Ramirez-Ortiz {
643*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
644*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_REVOCATION_ID,
645*55667e70SJorge Ramirez-Ortiz 		.revocation_id = id,
646*55667e70SJorge Ramirez-Ortiz 	};
647*55667e70SJorge Ramirez-Ortiz 
648*55667e70SJorge Ramirez-Ortiz 	if (len < EFUSE_REVOCATION_ID_LEN)
649*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
650*55667e70SJorge Ramirez-Ortiz 
651*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
652*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
653*55667e70SJorge Ramirez-Ortiz 
654*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
655*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
656*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
657*55667e70SJorge Ramirez-Ortiz 	}
658*55667e70SJorge Ramirez-Ortiz 
659*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), EFUSE_REVOCATION_ID_LEN);
660*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
661*55667e70SJorge Ramirez-Ortiz 
662*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
663*55667e70SJorge Ramirez-Ortiz }
664*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits * buf)665*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits *buf)
666*55667e70SJorge Ramirez-Ortiz {
667*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
668*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_MISC_CTRL,
669*55667e70SJorge Ramirez-Ortiz 	};
670*55667e70SJorge Ramirez-Ortiz 
671*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
672*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
673*55667e70SJorge Ramirez-Ortiz 
674*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
675*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
676*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
677*55667e70SJorge Ramirez-Ortiz 	}
678*55667e70SJorge Ramirez-Ortiz 
679*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf));
680*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
681*55667e70SJorge Ramirez-Ortiz 
682*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
683*55667e70SJorge Ramirez-Ortiz }
684*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits * buf)685*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits *buf)
686*55667e70SJorge Ramirez-Ortiz {
687*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
688*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_SEC_CTRL,
689*55667e70SJorge Ramirez-Ortiz 	};
690*55667e70SJorge Ramirez-Ortiz 
691*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
692*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
693*55667e70SJorge Ramirez-Ortiz 
694*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
695*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
696*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
697*55667e70SJorge Ramirez-Ortiz 	}
698*55667e70SJorge Ramirez-Ortiz 
699*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf));
700*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
701*55667e70SJorge Ramirez-Ortiz 
702*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
703*55667e70SJorge Ramirez-Ortiz }
704*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits * buf)705*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits *buf)
706*55667e70SJorge Ramirez-Ortiz {
707*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
708*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_SEC_MISC1,
709*55667e70SJorge Ramirez-Ortiz 	};
710*55667e70SJorge Ramirez-Ortiz 
711*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
712*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
713*55667e70SJorge Ramirez-Ortiz 
714*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
715*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
716*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
717*55667e70SJorge Ramirez-Ortiz 	}
718*55667e70SJorge Ramirez-Ortiz 
719*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf));
720*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
721*55667e70SJorge Ramirez-Ortiz 
722*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
723*55667e70SJorge Ramirez-Ortiz }
724*55667e70SJorge Ramirez-Ortiz 
725*55667e70SJorge Ramirez-Ortiz TEE_Result
versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits * buf)726*55667e70SJorge Ramirez-Ortiz versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits *buf)
727*55667e70SJorge Ramirez-Ortiz {
728*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
729*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_BOOT_ENV_CTRL,
730*55667e70SJorge Ramirez-Ortiz 	};
731*55667e70SJorge Ramirez-Ortiz 
732*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
733*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
734*55667e70SJorge Ramirez-Ortiz 
735*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
736*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
737*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
738*55667e70SJorge Ramirez-Ortiz 	}
739*55667e70SJorge Ramirez-Ortiz 
740*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf));
741*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
742*55667e70SJorge Ramirez-Ortiz 
743*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
744*55667e70SJorge Ramirez-Ortiz }
745*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_offchip_revoke_id(uint32_t * buf,size_t len,enum versal_nvm_offchip_id id)746*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len,
747*55667e70SJorge Ramirez-Ortiz 					       enum versal_nvm_offchip_id id)
748*55667e70SJorge Ramirez-Ortiz {
749*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
750*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_OFFCHIP_REVOCATION_ID,
751*55667e70SJorge Ramirez-Ortiz 		.offchip_id = id,
752*55667e70SJorge Ramirez-Ortiz 	};
753*55667e70SJorge Ramirez-Ortiz 
754*55667e70SJorge Ramirez-Ortiz 	if (len < EFUSE_OFFCHIP_REVOCATION_ID_LEN)
755*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
756*55667e70SJorge Ramirez-Ortiz 
757*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
758*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
759*55667e70SJorge Ramirez-Ortiz 
760*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
761*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
762*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
763*55667e70SJorge Ramirez-Ortiz 	}
764*55667e70SJorge Ramirez-Ortiz 
765*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), EFUSE_REVOCATION_ID_LEN);
766*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
767*55667e70SJorge Ramirez-Ortiz 
768*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
769*55667e70SJorge Ramirez-Ortiz }
770*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_dec_only(uint32_t * buf,size_t len)771*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_dec_only(uint32_t *buf, size_t len)
772*55667e70SJorge Ramirez-Ortiz {
773*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
774*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_DEC_EFUSE_ONLY,
775*55667e70SJorge Ramirez-Ortiz 	};
776*55667e70SJorge Ramirez-Ortiz 
777*55667e70SJorge Ramirez-Ortiz 	if (len < EFUSE_DEC_ONLY_LEN)
778*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
779*55667e70SJorge Ramirez-Ortiz 
780*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
781*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
782*55667e70SJorge Ramirez-Ortiz 
783*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
784*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
785*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
786*55667e70SJorge Ramirez-Ortiz 	}
787*55667e70SJorge Ramirez-Ortiz 
788*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), EFUSE_DEC_ONLY_LEN);
789*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
790*55667e70SJorge Ramirez-Ortiz 
791*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
792*55667e70SJorge Ramirez-Ortiz }
793*55667e70SJorge Ramirez-Ortiz 
794*55667e70SJorge Ramirez-Ortiz TEE_Result
versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits * buf)795*55667e70SJorge Ramirez-Ortiz versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits *buf)
796*55667e70SJorge Ramirez-Ortiz {
797*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
798*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_PUF_SEC_CTRL,
799*55667e70SJorge Ramirez-Ortiz 	};
800*55667e70SJorge Ramirez-Ortiz 
801*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
802*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
803*55667e70SJorge Ramirez-Ortiz 
804*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
805*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
806*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
807*55667e70SJorge Ramirez-Ortiz 	}
808*55667e70SJorge Ramirez-Ortiz 
809*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf));
810*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
811*55667e70SJorge Ramirez-Ortiz 
812*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
813*55667e70SJorge Ramirez-Ortiz }
814*55667e70SJorge Ramirez-Ortiz 
versal_efuse_read_puf(struct versal_efuse_puf_header * buf)815*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_read_puf(struct versal_efuse_puf_header *buf)
816*55667e70SJorge Ramirez-Ortiz {
817*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
818*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_PUF,
819*55667e70SJorge Ramirez-Ortiz 	};
820*55667e70SJorge Ramirez-Ortiz 
821*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
822*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
823*55667e70SJorge Ramirez-Ortiz 
824*55667e70SJorge Ramirez-Ortiz 	memcpy(versal_get_read_buffer(&req), buf, sizeof(*buf));
825*55667e70SJorge Ramirez-Ortiz 
826*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
827*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
828*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
829*55667e70SJorge Ramirez-Ortiz 	}
830*55667e70SJorge Ramirez-Ortiz 
831*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, versal_get_read_buffer(&req), sizeof(*buf));
832*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
833*55667e70SJorge Ramirez-Ortiz 
834*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
835*55667e70SJorge Ramirez-Ortiz }
836*55667e70SJorge Ramirez-Ortiz 
837*55667e70SJorge Ramirez-Ortiz /*
838*55667e70SJorge Ramirez-Ortiz  *  This functionality requires building the PLM with XNVM_ACCESS_PUF_USER_DATA
839*55667e70SJorge Ramirez-Ortiz  *  Calls will fail otherwise.
840*55667e70SJorge Ramirez-Ortiz  *  When available, efuse_read_puf becomes unavailable.
841*55667e70SJorge Ramirez-Ortiz  */
842*55667e70SJorge Ramirez-Ortiz TEE_Result
versal_efuse_read_puf_as_user_fuse(struct versal_efuse_puf_user_fuse * p)843*55667e70SJorge Ramirez-Ortiz versal_efuse_read_puf_as_user_fuse(struct versal_efuse_puf_user_fuse *p)
844*55667e70SJorge Ramirez-Ortiz {
845*55667e70SJorge Ramirez-Ortiz 	uint32_t fuses[PUF_EFUSES_WORDS]__aligned_efuse = { 0 };
846*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_puf_fuse_addr lbuf __aligned_efuse = {
847*55667e70SJorge Ramirez-Ortiz 		.env_monitor_dis = p->env_monitor_dis,
848*55667e70SJorge Ramirez-Ortiz 		.prgm_puf_fuse = p->prgm_puf_fuse,
849*55667e70SJorge Ramirez-Ortiz 		.start_row = p->start_row,
850*55667e70SJorge Ramirez-Ortiz 		.num_rows = p->num_rows,
851*55667e70SJorge Ramirez-Ortiz 		.data_addr = virt_to_phys(fuses),
852*55667e70SJorge Ramirez-Ortiz 	};
853*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
854*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_READ_PUF_USER_FUSES,
855*55667e70SJorge Ramirez-Ortiz 	};
856*55667e70SJorge Ramirez-Ortiz 
857*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &lbuf;
858*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(lbuf);
859*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = fuses;
860*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(fuses);
861*55667e70SJorge Ramirez-Ortiz 
862*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req))
863*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
864*55667e70SJorge Ramirez-Ortiz 
865*55667e70SJorge Ramirez-Ortiz 	memcpy(p->data_addr, fuses, sizeof(fuses));
866*55667e70SJorge Ramirez-Ortiz 
867*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
868*55667e70SJorge Ramirez-Ortiz }
869*55667e70SJorge Ramirez-Ortiz 
870*55667e70SJorge Ramirez-Ortiz /*
871*55667e70SJorge Ramirez-Ortiz  *  This functionality requires building the PLM with XNVM_ACCESS_PUF_USER_DATA.
872*55667e70SJorge Ramirez-Ortiz  *  Calls will fail otherwise.
873*55667e70SJorge Ramirez-Ortiz  *  When available, efuse_write_puf becomes unavailable.
874*55667e70SJorge Ramirez-Ortiz  */
875*55667e70SJorge Ramirez-Ortiz TEE_Result
versal_efuse_write_puf_as_user_fuse(struct versal_efuse_puf_user_fuse * p)876*55667e70SJorge Ramirez-Ortiz versal_efuse_write_puf_as_user_fuse(struct versal_efuse_puf_user_fuse *p)
877*55667e70SJorge Ramirez-Ortiz {
878*55667e70SJorge Ramirez-Ortiz 	uint32_t fuses[PUF_EFUSES_WORDS]__aligned_efuse = { 0 };
879*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_puf_fuse_addr lbuf __aligned_efuse  = {
880*55667e70SJorge Ramirez-Ortiz 		.env_monitor_dis = p->env_monitor_dis,
881*55667e70SJorge Ramirez-Ortiz 		.prgm_puf_fuse = p->prgm_puf_fuse,
882*55667e70SJorge Ramirez-Ortiz 		.start_row = p->start_row,
883*55667e70SJorge Ramirez-Ortiz 		.num_rows = p->num_rows,
884*55667e70SJorge Ramirez-Ortiz 		.data_addr = virt_to_phys(fuses),
885*55667e70SJorge Ramirez-Ortiz 	};
886*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req = {
887*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_PUF_USER_FUSE_WRITE,
888*55667e70SJorge Ramirez-Ortiz 	};
889*55667e70SJorge Ramirez-Ortiz 
890*55667e70SJorge Ramirez-Ortiz 	memcpy(fuses, p->data_addr, sizeof(p->data_addr));
891*55667e70SJorge Ramirez-Ortiz 
892*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &lbuf;
893*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(lbuf);
894*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].buf = fuses;
895*55667e70SJorge Ramirez-Ortiz 	req.ibuf[1].len = sizeof(fuses);
896*55667e70SJorge Ramirez-Ortiz 
897*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_write(&req))
898*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
899*55667e70SJorge Ramirez-Ortiz 
900*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
901*55667e70SJorge Ramirez-Ortiz }
902*55667e70SJorge Ramirez-Ortiz 
versal_efuse_write_puf(struct versal_efuse_puf_header * buf)903*55667e70SJorge Ramirez-Ortiz TEE_Result versal_efuse_write_puf(struct versal_efuse_puf_header *buf)
904*55667e70SJorge Ramirez-Ortiz {
905*55667e70SJorge Ramirez-Ortiz 	struct versal_efuse_puf_header cfg __aligned_efuse = { };
906*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
907*55667e70SJorge Ramirez-Ortiz 		.efuse_id = EFUSE_WRITE_PUF,
908*55667e70SJorge Ramirez-Ortiz 	};
909*55667e70SJorge Ramirez-Ortiz 
910*55667e70SJorge Ramirez-Ortiz 	memcpy(&cfg, buf, sizeof(*buf));
911*55667e70SJorge Ramirez-Ortiz 
912*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = &cfg;
913*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = sizeof(cfg);
914*55667e70SJorge Ramirez-Ortiz 
915*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_write(&req))
916*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
917*55667e70SJorge Ramirez-Ortiz 
918*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
919*55667e70SJorge Ramirez-Ortiz }
920*55667e70SJorge Ramirez-Ortiz 
versal_bbram_write_aes_key(uint8_t * key,size_t len)921*55667e70SJorge Ramirez-Ortiz TEE_Result versal_bbram_write_aes_key(uint8_t *key, size_t len)
922*55667e70SJorge Ramirez-Ortiz {
923*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
924*55667e70SJorge Ramirez-Ortiz 		.efuse_id = BBRAM_WRITE_AES_KEY,
925*55667e70SJorge Ramirez-Ortiz 		.bbram.aes_key_len = len,
926*55667e70SJorge Ramirez-Ortiz 	};
927*55667e70SJorge Ramirez-Ortiz 	void *buf = NULL;
928*55667e70SJorge Ramirez-Ortiz 
929*55667e70SJorge Ramirez-Ortiz 	if (len != 32)
930*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
931*55667e70SJorge Ramirez-Ortiz 
932*55667e70SJorge Ramirez-Ortiz 	buf = alloc_cache_aligned(1024);
933*55667e70SJorge Ramirez-Ortiz 	if (!buf)
934*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
935*55667e70SJorge Ramirez-Ortiz 
936*55667e70SJorge Ramirez-Ortiz 	memcpy(buf, key, len);
937*55667e70SJorge Ramirez-Ortiz 
938*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].buf = buf;
939*55667e70SJorge Ramirez-Ortiz 	req.ibuf[0].len = 1024;
940*55667e70SJorge Ramirez-Ortiz 
941*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_write(&req)) {
942*55667e70SJorge Ramirez-Ortiz 		free(buf);
943*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
944*55667e70SJorge Ramirez-Ortiz 	}
945*55667e70SJorge Ramirez-Ortiz 	free(buf);
946*55667e70SJorge Ramirez-Ortiz 
947*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
948*55667e70SJorge Ramirez-Ortiz }
949*55667e70SJorge Ramirez-Ortiz 
versal_bbram_zeroize(void)950*55667e70SJorge Ramirez-Ortiz TEE_Result versal_bbram_zeroize(void)
951*55667e70SJorge Ramirez-Ortiz {
952*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse  = {
953*55667e70SJorge Ramirez-Ortiz 		.efuse_id = BBRAM_ZEROIZE,
954*55667e70SJorge Ramirez-Ortiz 	};
955*55667e70SJorge Ramirez-Ortiz 
956*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_write(&req))
957*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
958*55667e70SJorge Ramirez-Ortiz 
959*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
960*55667e70SJorge Ramirez-Ortiz }
961*55667e70SJorge Ramirez-Ortiz 
versal_bbram_write_user_data(uint32_t data)962*55667e70SJorge Ramirez-Ortiz TEE_Result versal_bbram_write_user_data(uint32_t data)
963*55667e70SJorge Ramirez-Ortiz {
964*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse = {
965*55667e70SJorge Ramirez-Ortiz 		.efuse_id = BBRAM_WRITE_USER_DATA,
966*55667e70SJorge Ramirez-Ortiz 		.bbram.user_data = data,
967*55667e70SJorge Ramirez-Ortiz 	};
968*55667e70SJorge Ramirez-Ortiz 
969*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_write(&req))
970*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
971*55667e70SJorge Ramirez-Ortiz 
972*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
973*55667e70SJorge Ramirez-Ortiz }
974*55667e70SJorge Ramirez-Ortiz 
versal_bbram_read_user_data(uint32_t * data)975*55667e70SJorge Ramirez-Ortiz TEE_Result versal_bbram_read_user_data(uint32_t *data)
976*55667e70SJorge Ramirez-Ortiz {
977*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_read_req req = {
978*55667e70SJorge Ramirez-Ortiz 		.efuse_id = BBRAM_READ_USER_DATA,
979*55667e70SJorge Ramirez-Ortiz 	};
980*55667e70SJorge Ramirez-Ortiz 
981*55667e70SJorge Ramirez-Ortiz 	if (versal_alloc_read_buffer(&req))
982*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_OUT_OF_MEMORY;
983*55667e70SJorge Ramirez-Ortiz 
984*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_read(&req)) {
985*55667e70SJorge Ramirez-Ortiz 		versal_free_read_buffer(&req);
986*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
987*55667e70SJorge Ramirez-Ortiz 	}
988*55667e70SJorge Ramirez-Ortiz 
989*55667e70SJorge Ramirez-Ortiz 	memcpy(data, versal_get_read_buffer(&req), sizeof(*data));
990*55667e70SJorge Ramirez-Ortiz 	versal_free_read_buffer(&req);
991*55667e70SJorge Ramirez-Ortiz 
992*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
993*55667e70SJorge Ramirez-Ortiz }
994*55667e70SJorge Ramirez-Ortiz 
versal_bbram_lock_write_user_data(void)995*55667e70SJorge Ramirez-Ortiz TEE_Result versal_bbram_lock_write_user_data(void)
996*55667e70SJorge Ramirez-Ortiz {
997*55667e70SJorge Ramirez-Ortiz 	struct versal_nvm_write_req req __aligned_efuse  = {
998*55667e70SJorge Ramirez-Ortiz 		.efuse_id = BBRAM_LOCK_WRITE_USER_DATA,
999*55667e70SJorge Ramirez-Ortiz 	};
1000*55667e70SJorge Ramirez-Ortiz 
1001*55667e70SJorge Ramirez-Ortiz 	if (versal_nvm_write(&req))
1002*55667e70SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
1003*55667e70SJorge Ramirez-Ortiz 
1004*55667e70SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
1005*55667e70SJorge Ramirez-Ortiz }
1006