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