113dee78bSJoachim Foerster // SPDX-License-Identifier: BSD-2-Clause
213dee78bSJoachim Foerster /*
313dee78bSJoachim Foerster * Copyright (C) 2022 Foundries.io Ltd
413dee78bSJoachim Foerster * Jorge Ramirez-Ortiz <jorge@foundries.io>
5*b1fc8c0dSJoachim Foerster *
6*b1fc8c0dSJoachim Foerster * Copyright (C) ProvenRun SAS 2023
713dee78bSJoachim Foerster */
813dee78bSJoachim Foerster
913dee78bSJoachim Foerster #include <arm.h>
1013dee78bSJoachim Foerster #include <drivers/versal_nvm.h>
1113dee78bSJoachim Foerster #include <drivers/versal_pmc.h>
1213dee78bSJoachim Foerster #include <initcall.h>
1313dee78bSJoachim Foerster #include <kernel/panic.h>
1413dee78bSJoachim Foerster #include <kernel/tee_misc.h>
1513dee78bSJoachim Foerster #include <mm/core_memprot.h>
1613dee78bSJoachim Foerster #include <string.h>
1713dee78bSJoachim Foerster #include <tee/cache.h>
1813dee78bSJoachim Foerster
1913dee78bSJoachim Foerster #define NVM_WORD_LEN 4
2013dee78bSJoachim Foerster
2113dee78bSJoachim Foerster /* Protocol API with the remote processor */
2213dee78bSJoachim Foerster #define NVM_MODULE_SHIFT 8
2313dee78bSJoachim Foerster #define NVM_MODULE 11
2413dee78bSJoachim Foerster #define NVM_API_ID(_id) (SHIFT_U32(NVM_MODULE, NVM_MODULE_SHIFT) | (_id))
2513dee78bSJoachim Foerster
2613dee78bSJoachim Foerster #define __aligned_efuse __aligned(CACHELINE_LEN)
2713dee78bSJoachim Foerster
28*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_DNA_OFFSET 0x20
29*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_BOOT_ENV_CTRL_OFFSET 0x94
30*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_MISC_CTRL_OFFSET 0xA0
31*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_PUF_ECC_CTRL_OFFSET 0xA4
32*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_PUF_CHASH_OFFSET 0xA8
33*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_SEC_CTRL_OFFSET 0xAC
34*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_REVOCATION_ID0_OFFSET 0xB0
35*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_SEC_MISC0_OFFSET 0xE4
36*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_SEC_MISC1_OFFSET 0xE8
37*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_PPK0_OFFSET 0x100
38*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_PPK1_OFFSET 0x120
39*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_PPK2_OFFSET 0x140
40*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_OFFCHIP_REVOKE_ID0_OFFSET 0x160
41*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_METAHEADER_IV_RANGE0_OFFSET 0x180
42*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_BLACK_IV0_OFFSET 0x1D0
43*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_PLM_IV_RANGE0_OFFSET 0x1DC
44*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_DATA_PARTITION_IV_RANGE0_OFFSET 0x1E8
45*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_USER0_OFFSET 0x240
46*b1fc8c0dSJoachim Foerster #define EFUSE_CACHE_PUF_SYN0_OFFSET 0x300
47*b1fc8c0dSJoachim Foerster
48*b1fc8c0dSJoachim Foerster #define EFUSE_ENV_DIS_FLAG 0
49*b1fc8c0dSJoachim Foerster
50*b1fc8c0dSJoachim Foerster #define EFUSE_AES_KEY_ID 0
51*b1fc8c0dSJoachim Foerster #define EFUSE_USER_KEY0_ID 1
52*b1fc8c0dSJoachim Foerster #define EFUSE_USER_KEY1_ID 2
53*b1fc8c0dSJoachim Foerster
54*b1fc8c0dSJoachim Foerster #define EFUSE_WRITE_PUF_DATA_WORDS (PUF_SYN_DATA_WORDS + 6)
55*b1fc8c0dSJoachim Foerster
5613dee78bSJoachim Foerster /* Internal */
57*b1fc8c0dSJoachim Foerster struct versal_efuse_write_puf_data {
58*b1fc8c0dSJoachim Foerster uint32_t sec_ctrl;
59*b1fc8c0dSJoachim Foerster uint32_t prgm_puf_helper_data;
60*b1fc8c0dSJoachim Foerster uint32_t env_monitor_dis;
61*b1fc8c0dSJoachim Foerster uint32_t syn[PUF_SYN_DATA_WORDS];
62*b1fc8c0dSJoachim Foerster uint32_t chash;
63*b1fc8c0dSJoachim Foerster uint32_t aux;
64*b1fc8c0dSJoachim Foerster uint32_t ro_swap;
6513dee78bSJoachim Foerster };
6613dee78bSJoachim Foerster
6713dee78bSJoachim Foerster /*
6813dee78bSJoachim Foerster * Max size of the buffer needed for the remote processor to DMA efuse _data_
6913dee78bSJoachim Foerster * to/from
7013dee78bSJoachim Foerster */
7113dee78bSJoachim Foerster #define EFUSE_MAX_LEN (EFUSE_MAX_USER_FUSES * sizeof(uint32_t))
7213dee78bSJoachim Foerster
7313dee78bSJoachim Foerster enum versal_nvm_api_id {
7413dee78bSJoachim Foerster API_FEATURES = 0,
7513dee78bSJoachim Foerster BBRAM_WRITE_AES_KEY = 1,
7613dee78bSJoachim Foerster BBRAM_ZEROIZE = 2,
7713dee78bSJoachim Foerster BBRAM_WRITE_USER_DATA = 3,
7813dee78bSJoachim Foerster BBRAM_READ_USER_DATA = 4,
7913dee78bSJoachim Foerster BBRAM_LOCK_WRITE_USER_DATA = 5,
80*b1fc8c0dSJoachim Foerster BBRAM_WRITE_AES_KEY_FROM_PLOAD = 6,
81*b1fc8c0dSJoachim Foerster EFUSE_WRITE_AES_KEY = 7,
82*b1fc8c0dSJoachim Foerster EFUSE_WRITE_AES_KEY_FROM_PLOAD = 8,
83*b1fc8c0dSJoachim Foerster EFUSE_WRITE_PPK_HASH = 9,
84*b1fc8c0dSJoachim Foerster EFUSE_WRITE_PPK_HASH_FROM_PLOAD = 10,
85*b1fc8c0dSJoachim Foerster EFUSE_WRITE_IV = 11,
86*b1fc8c0dSJoachim Foerster EFUSE_WRITE_IV_FROM_PLOAD = 12,
87*b1fc8c0dSJoachim Foerster EFUSE_WRITE_GLITCH_CONFIG = 13,
88*b1fc8c0dSJoachim Foerster EFUSE_WRITE_DEC_ONLY = 14,
89*b1fc8c0dSJoachim Foerster EFUSE_WRITE_REVOCATION_ID = 15,
90*b1fc8c0dSJoachim Foerster EFUSE_WRITE_OFFCHIP_REVOKE_ID = 16,
91*b1fc8c0dSJoachim Foerster EFUSE_WRITE_MISC_CTRL_BITS = 17,
92*b1fc8c0dSJoachim Foerster EFUSE_WRITE_SEC_CTRL_BITS = 18,
93*b1fc8c0dSJoachim Foerster EFUSE_WRITE_MISC1_CTRL_BITS = 19,
94*b1fc8c0dSJoachim Foerster EFUSE_WRITE_BOOT_ENV_CTRL_BITS = 20,
95*b1fc8c0dSJoachim Foerster EFUSE_WRITE_FIPS_INFO = 21,
96*b1fc8c0dSJoachim Foerster EFUSE_WRITE_UDS_FROM_PLOAD = 22,
97*b1fc8c0dSJoachim Foerster EFUSE_WRITE_DME_KEY_FROM_PLOAD = 23,
98*b1fc8c0dSJoachim Foerster EFUSE_WRITE_DME_REVOKE = 24,
99*b1fc8c0dSJoachim Foerster EFUSE_WRITE_PLM_UPDATE = 25,
100*b1fc8c0dSJoachim Foerster EFUSE_WRITE_BOOT_MODE_DISABLE = 26,
101*b1fc8c0dSJoachim Foerster EFUSE_WRITE_CRC = 27,
102*b1fc8c0dSJoachim Foerster EFUSE_WRITE_DME_MODE = 28,
103*b1fc8c0dSJoachim Foerster EFUSE_WRITE_PUF_HD_FROM_PLOAD = 29,
104*b1fc8c0dSJoachim Foerster EFUSE_WRITE_PUF = 30,
105*b1fc8c0dSJoachim Foerster EFUSE_WRITE_ROM_RSVD = 31,
106*b1fc8c0dSJoachim Foerster EFUSE_WRITE_PUF_CTRL_BITS = 32,
107*b1fc8c0dSJoachim Foerster EFUSE_READ_CACHE = 33,
108*b1fc8c0dSJoachim Foerster EFUSE_RELOAD_N_PRGM_PROT_BITS = 34,
109*b1fc8c0dSJoachim Foerster EFUSE_INVALID = 35,
11013dee78bSJoachim Foerster };
11113dee78bSJoachim Foerster
11213dee78bSJoachim Foerster /* uint64_t are memory addresses */
11313dee78bSJoachim Foerster struct versal_efuse_data {
11413dee78bSJoachim Foerster uint64_t env_mon_dis_flag;
11513dee78bSJoachim Foerster uint64_t aes_key_addr;
11613dee78bSJoachim Foerster uint64_t ppk_hash_addr;
11713dee78bSJoachim Foerster uint64_t dec_only_addr;
11813dee78bSJoachim Foerster uint64_t sec_ctrl_addr;
11913dee78bSJoachim Foerster uint64_t misc_ctrl_addr;
12013dee78bSJoachim Foerster uint64_t revoke_id_addr;
12113dee78bSJoachim Foerster uint64_t iv_addr;
12213dee78bSJoachim Foerster uint64_t user_fuse_addr;
12313dee78bSJoachim Foerster uint64_t glitch_cfg_addr;
12413dee78bSJoachim Foerster uint64_t boot_env_ctrl_addr;
12513dee78bSJoachim Foerster uint64_t misc1_ctrl_addr;
12613dee78bSJoachim Foerster uint64_t offchip_id_addr;
12713dee78bSJoachim Foerster uint8_t pad[24];
12813dee78bSJoachim Foerster };
12913dee78bSJoachim Foerster
13013dee78bSJoachim Foerster /* Helper read and write requests (not part of the protocol) */
13113dee78bSJoachim Foerster struct versal_nvm_buf {
13213dee78bSJoachim Foerster size_t len;
13313dee78bSJoachim Foerster void *buf;
13413dee78bSJoachim Foerster };
13513dee78bSJoachim Foerster
13613dee78bSJoachim Foerster struct versal_nvm_read_req {
13713dee78bSJoachim Foerster enum versal_nvm_api_id efuse_id;
13813dee78bSJoachim Foerster struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF];
13913dee78bSJoachim Foerster };
14013dee78bSJoachim Foerster
14113dee78bSJoachim Foerster struct versal_bbram_data {
14213dee78bSJoachim Foerster size_t aes_key_len;
14313dee78bSJoachim Foerster uint32_t user_data;
14413dee78bSJoachim Foerster };
14513dee78bSJoachim Foerster
14613dee78bSJoachim Foerster struct versal_nvm_write_req {
14713dee78bSJoachim Foerster struct versal_efuse_data data;
14813dee78bSJoachim Foerster struct versal_bbram_data bbram;
14913dee78bSJoachim Foerster struct versal_nvm_buf ibuf[VERSAL_MAX_IPI_BUF];
15013dee78bSJoachim Foerster enum versal_nvm_api_id efuse_id;
15113dee78bSJoachim Foerster };
15213dee78bSJoachim Foerster
15313dee78bSJoachim Foerster static TEE_Result
prepare_cmd(struct versal_ipi_cmd * cmd,enum versal_nvm_api_id efuse,struct versal_nvm_buf * ibufs,uint32_t * arg)15413dee78bSJoachim Foerster prepare_cmd(struct versal_ipi_cmd *cmd, enum versal_nvm_api_id efuse,
15513dee78bSJoachim Foerster struct versal_nvm_buf *ibufs, uint32_t *arg)
15613dee78bSJoachim Foerster {
157*b1fc8c0dSJoachim Foerster uint32_t low = 0;
158*b1fc8c0dSJoachim Foerster uint32_t hi = 0;
15913dee78bSJoachim Foerster size_t i = 0;
16013dee78bSJoachim Foerster
16113dee78bSJoachim Foerster cmd->data[i++] = NVM_API_ID(efuse);
16213dee78bSJoachim Foerster if (arg)
16313dee78bSJoachim Foerster cmd->data[i++] = *arg;
16413dee78bSJoachim Foerster
16513dee78bSJoachim Foerster if (!ibufs[0].buf)
16613dee78bSJoachim Foerster return TEE_SUCCESS;
16713dee78bSJoachim Foerster
168*b1fc8c0dSJoachim Foerster reg_pair_from_64(virt_to_phys(ibufs[0].buf), &hi, &low);
16913dee78bSJoachim Foerster
170*b1fc8c0dSJoachim Foerster cmd->data[i++] = low;
171*b1fc8c0dSJoachim Foerster cmd->data[i++] = hi;
17213dee78bSJoachim Foerster
17313dee78bSJoachim Foerster for (i = 0; i < VERSAL_MAX_IPI_BUF; i++) {
17413dee78bSJoachim Foerster cmd->ibuf[i].mem.alloc_len = ibufs[i].len;
17513dee78bSJoachim Foerster cmd->ibuf[i].mem.buf = ibufs[i].buf;
17613dee78bSJoachim Foerster }
17713dee78bSJoachim Foerster
17813dee78bSJoachim Foerster return TEE_SUCCESS;
17913dee78bSJoachim Foerster }
18013dee78bSJoachim Foerster
efuse_req(enum versal_nvm_api_id efuse,struct versal_nvm_buf * ibufs,uint32_t * arg)18113dee78bSJoachim Foerster static TEE_Result efuse_req(enum versal_nvm_api_id efuse,
18213dee78bSJoachim Foerster struct versal_nvm_buf *ibufs, uint32_t *arg)
18313dee78bSJoachim Foerster {
18413dee78bSJoachim Foerster struct versal_ipi_cmd cmd = { };
18513dee78bSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
18613dee78bSJoachim Foerster
18713dee78bSJoachim Foerster ret = prepare_cmd(&cmd, efuse, ibufs, arg);
18813dee78bSJoachim Foerster if (ret)
18913dee78bSJoachim Foerster return ret;
19013dee78bSJoachim Foerster
19113dee78bSJoachim Foerster ret = versal_pmc_notify(&cmd, NULL, NULL);
19213dee78bSJoachim Foerster if (ret)
19313dee78bSJoachim Foerster EMSG("Mailbox error");
19413dee78bSJoachim Foerster
19513dee78bSJoachim Foerster return ret;
19613dee78bSJoachim Foerster }
19713dee78bSJoachim Foerster
versal_alloc_read_buffer(struct versal_nvm_read_req * req)19813dee78bSJoachim Foerster static TEE_Result versal_alloc_read_buffer(struct versal_nvm_read_req *req)
19913dee78bSJoachim Foerster {
20013dee78bSJoachim Foerster assert(req);
20113dee78bSJoachim Foerster req->ibuf[0].len = 1024;
20213dee78bSJoachim Foerster req->ibuf[0].buf = alloc_cache_aligned(req->ibuf[0].len);
20313dee78bSJoachim Foerster if (!req->ibuf[0].buf)
20413dee78bSJoachim Foerster return TEE_ERROR_OUT_OF_MEMORY;
20513dee78bSJoachim Foerster
20613dee78bSJoachim Foerster return TEE_SUCCESS;
20713dee78bSJoachim Foerster }
20813dee78bSJoachim Foerster
versal_free_read_buffer(struct versal_nvm_read_req * req)20913dee78bSJoachim Foerster static void versal_free_read_buffer(struct versal_nvm_read_req *req)
21013dee78bSJoachim Foerster {
21113dee78bSJoachim Foerster assert(req);
21213dee78bSJoachim Foerster free(req->ibuf[0].buf);
21313dee78bSJoachim Foerster }
21413dee78bSJoachim Foerster
versal_get_read_buffer(struct versal_nvm_read_req * req)21513dee78bSJoachim Foerster static void *versal_get_read_buffer(struct versal_nvm_read_req *req)
21613dee78bSJoachim Foerster {
21713dee78bSJoachim Foerster assert(req);
21813dee78bSJoachim Foerster return req->ibuf[0].buf;
21913dee78bSJoachim Foerster }
22013dee78bSJoachim Foerster
versal_nvm_read(struct versal_nvm_read_req * req)22113dee78bSJoachim Foerster static TEE_Result versal_nvm_read(struct versal_nvm_read_req *req)
22213dee78bSJoachim Foerster {
22313dee78bSJoachim Foerster if (!req)
22413dee78bSJoachim Foerster return TEE_ERROR_GENERIC;
22513dee78bSJoachim Foerster
22613dee78bSJoachim Foerster switch (req->efuse_id) {
227*b1fc8c0dSJoachim Foerster case EFUSE_READ_CACHE:
22813dee78bSJoachim Foerster case BBRAM_READ_USER_DATA:
22913dee78bSJoachim Foerster break;
23013dee78bSJoachim Foerster default:
23113dee78bSJoachim Foerster return TEE_ERROR_GENERIC;
23213dee78bSJoachim Foerster }
23313dee78bSJoachim Foerster
234*b1fc8c0dSJoachim Foerster return efuse_req(req->efuse_id, req->ibuf, NULL);
23513dee78bSJoachim Foerster }
23613dee78bSJoachim Foerster
versal_nvm_write(struct versal_nvm_write_req * req)23713dee78bSJoachim Foerster static TEE_Result versal_nvm_write(struct versal_nvm_write_req *req)
23813dee78bSJoachim Foerster {
23913dee78bSJoachim Foerster uint32_t *arg = NULL;
24013dee78bSJoachim Foerster uint32_t val = 0;
24113dee78bSJoachim Foerster
24213dee78bSJoachim Foerster switch (req->efuse_id) {
24313dee78bSJoachim Foerster case BBRAM_WRITE_AES_KEY:
24413dee78bSJoachim Foerster val = req->bbram.aes_key_len;
24513dee78bSJoachim Foerster arg = &val;
24613dee78bSJoachim Foerster break;
24713dee78bSJoachim Foerster case BBRAM_ZEROIZE:
24813dee78bSJoachim Foerster break;
24913dee78bSJoachim Foerster case BBRAM_WRITE_USER_DATA:
25013dee78bSJoachim Foerster val = req->bbram.user_data;
25113dee78bSJoachim Foerster arg = &val;
25213dee78bSJoachim Foerster break;
25313dee78bSJoachim Foerster default:
25413dee78bSJoachim Foerster return TEE_ERROR_GENERIC;
25513dee78bSJoachim Foerster }
25613dee78bSJoachim Foerster
25713dee78bSJoachim Foerster return efuse_req(req->efuse_id, req->ibuf, arg);
25813dee78bSJoachim Foerster }
25913dee78bSJoachim Foerster
versal_efuse_read_cache(uint16_t off,uint16_t num,uint32_t * buf,size_t len)260*b1fc8c0dSJoachim Foerster static TEE_Result versal_efuse_read_cache(uint16_t off, uint16_t num,
261*b1fc8c0dSJoachim Foerster uint32_t *buf, size_t len)
262*b1fc8c0dSJoachim Foerster {
263*b1fc8c0dSJoachim Foerster struct versal_ipi_cmd cmd = { };
264*b1fc8c0dSJoachim Foerster struct versal_mbox_mem p = { };
265*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
266*b1fc8c0dSJoachim Foerster uint32_t low = 0;
267*b1fc8c0dSJoachim Foerster uint32_t hi = 0;
268*b1fc8c0dSJoachim Foerster
269*b1fc8c0dSJoachim Foerster if (!buf)
270*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
271*b1fc8c0dSJoachim Foerster
272*b1fc8c0dSJoachim Foerster if (len < num * NVM_WORD_LEN)
273*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
274*b1fc8c0dSJoachim Foerster
275*b1fc8c0dSJoachim Foerster ret = versal_mbox_alloc(num * NVM_WORD_LEN, NULL, &p);
276*b1fc8c0dSJoachim Foerster if (ret)
277*b1fc8c0dSJoachim Foerster return ret;
278*b1fc8c0dSJoachim Foerster
279*b1fc8c0dSJoachim Foerster reg_pair_from_64(virt_to_phys(p.buf), &hi, &low);
280*b1fc8c0dSJoachim Foerster
281*b1fc8c0dSJoachim Foerster cmd.data[0] = NVM_API_ID(EFUSE_READ_CACHE);
282*b1fc8c0dSJoachim Foerster cmd.data[1] = SHIFT_U32(num, 16) | off;
283*b1fc8c0dSJoachim Foerster cmd.data[2] = low;
284*b1fc8c0dSJoachim Foerster cmd.data[3] = hi;
285*b1fc8c0dSJoachim Foerster
286*b1fc8c0dSJoachim Foerster cmd.ibuf[0].mem = p;
287*b1fc8c0dSJoachim Foerster
288*b1fc8c0dSJoachim Foerster ret = versal_pmc_notify(&cmd, NULL, NULL);
289*b1fc8c0dSJoachim Foerster if (ret)
290*b1fc8c0dSJoachim Foerster EMSG("Mailbox error");
291*b1fc8c0dSJoachim Foerster else
292*b1fc8c0dSJoachim Foerster memcpy(buf, p.buf, num * NVM_WORD_LEN);
293*b1fc8c0dSJoachim Foerster
294*b1fc8c0dSJoachim Foerster versal_mbox_free(&p);
295*b1fc8c0dSJoachim Foerster return ret;
296*b1fc8c0dSJoachim Foerster }
297*b1fc8c0dSJoachim Foerster
versal_efuse_read_user_data(uint32_t * buf,size_t len,uint32_t first,size_t num)29813dee78bSJoachim Foerster TEE_Result versal_efuse_read_user_data(uint32_t *buf, size_t len,
29913dee78bSJoachim Foerster uint32_t first, size_t num)
30013dee78bSJoachim Foerster {
301*b1fc8c0dSJoachim Foerster uint16_t offset = 0;
30213dee78bSJoachim Foerster
303*b1fc8c0dSJoachim Foerster if (first + num > EFUSE_MAX_USER_FUSES || len < num * NVM_WORD_LEN)
30413dee78bSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
30513dee78bSJoachim Foerster
306*b1fc8c0dSJoachim Foerster offset = EFUSE_CACHE_USER0_OFFSET + first * NVM_WORD_LEN;
30713dee78bSJoachim Foerster
308*b1fc8c0dSJoachim Foerster return versal_efuse_read_cache(offset, num, buf, len);
30913dee78bSJoachim Foerster }
31013dee78bSJoachim Foerster
versal_efuse_read_dna(uint32_t * buf,size_t len)31113dee78bSJoachim Foerster TEE_Result versal_efuse_read_dna(uint32_t *buf, size_t len)
31213dee78bSJoachim Foerster {
31313dee78bSJoachim Foerster if (len < EFUSE_DNA_LEN)
31413dee78bSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
31513dee78bSJoachim Foerster
316*b1fc8c0dSJoachim Foerster return versal_efuse_read_cache(EFUSE_CACHE_DNA_OFFSET,
317*b1fc8c0dSJoachim Foerster EFUSE_DNA_LEN / NVM_WORD_LEN, buf, len);
31813dee78bSJoachim Foerster }
31913dee78bSJoachim Foerster
versal_efuse_read_iv(uint32_t * buf,size_t len,enum versal_nvm_iv_type type)32013dee78bSJoachim Foerster TEE_Result versal_efuse_read_iv(uint32_t *buf, size_t len,
32113dee78bSJoachim Foerster enum versal_nvm_iv_type type)
32213dee78bSJoachim Foerster {
323*b1fc8c0dSJoachim Foerster uint16_t offset = 0;
32413dee78bSJoachim Foerster
325*b1fc8c0dSJoachim Foerster switch (type) {
326*b1fc8c0dSJoachim Foerster case EFUSE_META_HEADER_IV_RANGE:
327*b1fc8c0dSJoachim Foerster offset = EFUSE_CACHE_METAHEADER_IV_RANGE0_OFFSET;
328*b1fc8c0dSJoachim Foerster break;
329*b1fc8c0dSJoachim Foerster case EFUSE_BLACK_IV:
330*b1fc8c0dSJoachim Foerster offset = EFUSE_CACHE_BLACK_IV0_OFFSET;
331*b1fc8c0dSJoachim Foerster break;
332*b1fc8c0dSJoachim Foerster case EFUSE_PLM_IV_RANGE:
333*b1fc8c0dSJoachim Foerster offset = EFUSE_CACHE_PLM_IV_RANGE0_OFFSET;
334*b1fc8c0dSJoachim Foerster break;
335*b1fc8c0dSJoachim Foerster case EFUSE_DATA_PARTITION_IV_RANGE:
336*b1fc8c0dSJoachim Foerster offset = EFUSE_CACHE_DATA_PARTITION_IV_RANGE0_OFFSET;
337*b1fc8c0dSJoachim Foerster break;
338*b1fc8c0dSJoachim Foerster default:
33913dee78bSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
34013dee78bSJoachim Foerster }
34113dee78bSJoachim Foerster
342*b1fc8c0dSJoachim Foerster return versal_efuse_read_cache(offset, EFUSE_IV_LEN / NVM_WORD_LEN,
343*b1fc8c0dSJoachim Foerster buf, len);
34413dee78bSJoachim Foerster }
34513dee78bSJoachim Foerster
versal_efuse_read_ppk(uint32_t * buf,size_t len,enum versal_nvm_ppk_type type)34613dee78bSJoachim Foerster TEE_Result versal_efuse_read_ppk(uint32_t *buf, size_t len,
34713dee78bSJoachim Foerster enum versal_nvm_ppk_type type)
34813dee78bSJoachim Foerster {
349*b1fc8c0dSJoachim Foerster uint16_t offset = 0;
35013dee78bSJoachim Foerster
351*b1fc8c0dSJoachim Foerster switch (type) {
352*b1fc8c0dSJoachim Foerster case EFUSE_PPK0:
353*b1fc8c0dSJoachim Foerster offset = EFUSE_CACHE_PPK0_OFFSET;
354*b1fc8c0dSJoachim Foerster break;
355*b1fc8c0dSJoachim Foerster case EFUSE_PPK1:
356*b1fc8c0dSJoachim Foerster offset = EFUSE_CACHE_PPK1_OFFSET;
357*b1fc8c0dSJoachim Foerster break;
358*b1fc8c0dSJoachim Foerster case EFUSE_PPK2:
359*b1fc8c0dSJoachim Foerster offset = EFUSE_CACHE_PPK2_OFFSET;
360*b1fc8c0dSJoachim Foerster break;
361*b1fc8c0dSJoachim Foerster default:
36213dee78bSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
36313dee78bSJoachim Foerster }
36413dee78bSJoachim Foerster
365*b1fc8c0dSJoachim Foerster return versal_efuse_read_cache(offset, EFUSE_PPK_LEN / NVM_WORD_LEN,
366*b1fc8c0dSJoachim Foerster buf, len);
367*b1fc8c0dSJoachim Foerster }
368*b1fc8c0dSJoachim Foerster
versal_efuse_write_user_data(uint32_t * buf __unused,size_t len __unused,uint32_t first __unused,size_t num __unused)369*b1fc8c0dSJoachim Foerster TEE_Result versal_efuse_write_user_data(uint32_t *buf __unused,
370*b1fc8c0dSJoachim Foerster size_t len __unused,
371*b1fc8c0dSJoachim Foerster uint32_t first __unused,
372*b1fc8c0dSJoachim Foerster size_t num __unused)
37313dee78bSJoachim Foerster {
374*b1fc8c0dSJoachim Foerster return TEE_ERROR_NOT_IMPLEMENTED;
375*b1fc8c0dSJoachim Foerster }
37613dee78bSJoachim Foerster
do_write_efuses_buffer(enum versal_nvm_api_id id,uint16_t type,uint32_t * buf,size_t len)377*b1fc8c0dSJoachim Foerster static TEE_Result do_write_efuses_buffer(enum versal_nvm_api_id id,
378*b1fc8c0dSJoachim Foerster uint16_t type, uint32_t *buf,
379*b1fc8c0dSJoachim Foerster size_t len)
380*b1fc8c0dSJoachim Foerster {
381*b1fc8c0dSJoachim Foerster struct versal_ipi_cmd cmd = { };
382*b1fc8c0dSJoachim Foerster struct versal_mbox_mem p = { };
383*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
384*b1fc8c0dSJoachim Foerster uint32_t low = 0;
385*b1fc8c0dSJoachim Foerster uint32_t hi = 0;
38613dee78bSJoachim Foerster
387*b1fc8c0dSJoachim Foerster ret = versal_mbox_alloc(len, buf, &p);
388*b1fc8c0dSJoachim Foerster if (ret)
389*b1fc8c0dSJoachim Foerster return ret;
39013dee78bSJoachim Foerster
391*b1fc8c0dSJoachim Foerster reg_pair_from_64(virt_to_phys(p.buf), &hi, &low);
39213dee78bSJoachim Foerster
393*b1fc8c0dSJoachim Foerster cmd.data[0] = NVM_API_ID(id);
394*b1fc8c0dSJoachim Foerster cmd.data[1] = SHIFT_U32(type, 16) | EFUSE_ENV_DIS_FLAG;
395*b1fc8c0dSJoachim Foerster cmd.data[2] = low;
396*b1fc8c0dSJoachim Foerster cmd.data[3] = hi;
39713dee78bSJoachim Foerster
398*b1fc8c0dSJoachim Foerster cmd.ibuf[0].mem = p;
399*b1fc8c0dSJoachim Foerster
400*b1fc8c0dSJoachim Foerster ret = versal_pmc_notify(&cmd, NULL, NULL);
401*b1fc8c0dSJoachim Foerster
402*b1fc8c0dSJoachim Foerster versal_mbox_free(&p);
403*b1fc8c0dSJoachim Foerster return ret;
404*b1fc8c0dSJoachim Foerster }
405*b1fc8c0dSJoachim Foerster
do_write_efuses_value(enum versal_nvm_api_id id,uint32_t val)406*b1fc8c0dSJoachim Foerster static TEE_Result do_write_efuses_value(enum versal_nvm_api_id id, uint32_t val)
407*b1fc8c0dSJoachim Foerster {
408*b1fc8c0dSJoachim Foerster struct versal_ipi_cmd cmd = { };
409*b1fc8c0dSJoachim Foerster
410*b1fc8c0dSJoachim Foerster cmd.data[0] = NVM_API_ID(id);
411*b1fc8c0dSJoachim Foerster cmd.data[1] = EFUSE_ENV_DIS_FLAG;
412*b1fc8c0dSJoachim Foerster cmd.data[2] = val;
413*b1fc8c0dSJoachim Foerster
414*b1fc8c0dSJoachim Foerster return versal_pmc_notify(&cmd, NULL, NULL);
415*b1fc8c0dSJoachim Foerster }
416*b1fc8c0dSJoachim Foerster
do_write_efuses(enum versal_nvm_api_id id)417*b1fc8c0dSJoachim Foerster static TEE_Result do_write_efuses(enum versal_nvm_api_id id)
418*b1fc8c0dSJoachim Foerster {
419*b1fc8c0dSJoachim Foerster return do_write_efuses_value(id, 0);
42013dee78bSJoachim Foerster }
42113dee78bSJoachim Foerster
versal_efuse_write_aes_keys(struct versal_efuse_aes_keys * keys)42213dee78bSJoachim Foerster TEE_Result versal_efuse_write_aes_keys(struct versal_efuse_aes_keys *keys)
42313dee78bSJoachim Foerster {
424*b1fc8c0dSJoachim Foerster TEE_Result res = TEE_SUCCESS;
425*b1fc8c0dSJoachim Foerster TEE_Result res2 = TEE_SUCCESS;
42613dee78bSJoachim Foerster
427*b1fc8c0dSJoachim Foerster if (!keys)
428*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
42913dee78bSJoachim Foerster
430*b1fc8c0dSJoachim Foerster if (keys->prgm_aes_key) {
431*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_AES_KEY,
432*b1fc8c0dSJoachim Foerster EFUSE_AES_KEY_ID,
433*b1fc8c0dSJoachim Foerster keys->aes_key, EFUSE_AES_KEY_LEN);
434*b1fc8c0dSJoachim Foerster if (res2) {
435*b1fc8c0dSJoachim Foerster DMSG("Error programming AES key (0x%" PRIx32 ")", res2);
436*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
437*b1fc8c0dSJoachim Foerster }
438*b1fc8c0dSJoachim Foerster }
43913dee78bSJoachim Foerster
440*b1fc8c0dSJoachim Foerster if (keys->prgm_user_key0) {
441*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_AES_KEY,
442*b1fc8c0dSJoachim Foerster EFUSE_USER_KEY0_ID,
443*b1fc8c0dSJoachim Foerster keys->user_key0,
444*b1fc8c0dSJoachim Foerster EFUSE_AES_KEY_LEN);
445*b1fc8c0dSJoachim Foerster if (res2) {
446*b1fc8c0dSJoachim Foerster DMSG("Error programming User key 0 (0x%" PRIx32 ")",
447*b1fc8c0dSJoachim Foerster res2);
448*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
449*b1fc8c0dSJoachim Foerster }
450*b1fc8c0dSJoachim Foerster }
451*b1fc8c0dSJoachim Foerster
452*b1fc8c0dSJoachim Foerster if (keys->prgm_user_key1) {
453*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_AES_KEY,
454*b1fc8c0dSJoachim Foerster EFUSE_USER_KEY1_ID,
455*b1fc8c0dSJoachim Foerster keys->user_key1,
456*b1fc8c0dSJoachim Foerster EFUSE_AES_KEY_LEN);
457*b1fc8c0dSJoachim Foerster if (res2) {
458*b1fc8c0dSJoachim Foerster DMSG("Error programming User key 1 (0x%" PRIx32 ")",
459*b1fc8c0dSJoachim Foerster res2);
460*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
461*b1fc8c0dSJoachim Foerster }
462*b1fc8c0dSJoachim Foerster }
463*b1fc8c0dSJoachim Foerster
464*b1fc8c0dSJoachim Foerster return res;
46513dee78bSJoachim Foerster }
46613dee78bSJoachim Foerster
versal_efuse_write_ppk_hash(struct versal_efuse_ppk_hash * hash)46713dee78bSJoachim Foerster TEE_Result versal_efuse_write_ppk_hash(struct versal_efuse_ppk_hash *hash)
46813dee78bSJoachim Foerster {
469*b1fc8c0dSJoachim Foerster TEE_Result res = TEE_SUCCESS;
470*b1fc8c0dSJoachim Foerster TEE_Result res2 = TEE_SUCCESS;
47113dee78bSJoachim Foerster
472*b1fc8c0dSJoachim Foerster if (!hash)
473*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
47413dee78bSJoachim Foerster
475*b1fc8c0dSJoachim Foerster if (hash->prgm_ppk0_hash) {
476*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_PPK_HASH, EFUSE_PPK0,
477*b1fc8c0dSJoachim Foerster hash->ppk0_hash, EFUSE_PPK_LEN);
478*b1fc8c0dSJoachim Foerster if (res2) {
479*b1fc8c0dSJoachim Foerster DMSG("Error programming PPK hash 0 (0x%" PRIx32 ")",
480*b1fc8c0dSJoachim Foerster res2);
481*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
482*b1fc8c0dSJoachim Foerster }
483*b1fc8c0dSJoachim Foerster }
48413dee78bSJoachim Foerster
485*b1fc8c0dSJoachim Foerster if (hash->prgm_ppk1_hash) {
486*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_PPK_HASH, EFUSE_PPK1,
487*b1fc8c0dSJoachim Foerster hash->ppk1_hash, EFUSE_PPK_LEN);
488*b1fc8c0dSJoachim Foerster if (res2) {
489*b1fc8c0dSJoachim Foerster DMSG("Error programming PPK hash 1 (0x%" PRIx32 ")",
490*b1fc8c0dSJoachim Foerster res2);
491*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
492*b1fc8c0dSJoachim Foerster }
493*b1fc8c0dSJoachim Foerster }
494*b1fc8c0dSJoachim Foerster
495*b1fc8c0dSJoachim Foerster if (hash->prgm_ppk2_hash) {
496*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_PPK_HASH, EFUSE_PPK2,
497*b1fc8c0dSJoachim Foerster hash->ppk2_hash, EFUSE_PPK_LEN);
498*b1fc8c0dSJoachim Foerster if (res2) {
499*b1fc8c0dSJoachim Foerster DMSG("Error programming PPK hash 2 (0x%" PRIx32 ")",
500*b1fc8c0dSJoachim Foerster res2);
501*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
502*b1fc8c0dSJoachim Foerster }
503*b1fc8c0dSJoachim Foerster }
504*b1fc8c0dSJoachim Foerster
505*b1fc8c0dSJoachim Foerster return res;
50613dee78bSJoachim Foerster }
50713dee78bSJoachim Foerster
versal_efuse_write_iv(struct versal_efuse_ivs * p)50813dee78bSJoachim Foerster TEE_Result versal_efuse_write_iv(struct versal_efuse_ivs *p)
50913dee78bSJoachim Foerster {
510*b1fc8c0dSJoachim Foerster TEE_Result res = TEE_SUCCESS;
511*b1fc8c0dSJoachim Foerster TEE_Result res2 = TEE_SUCCESS;
51213dee78bSJoachim Foerster
513*b1fc8c0dSJoachim Foerster if (!p)
514*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
51513dee78bSJoachim Foerster
516*b1fc8c0dSJoachim Foerster if (p->prgm_meta_header_iv) {
517*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_IV,
518*b1fc8c0dSJoachim Foerster EFUSE_META_HEADER_IV_RANGE,
519*b1fc8c0dSJoachim Foerster p->meta_header_iv, EFUSE_IV_LEN);
520*b1fc8c0dSJoachim Foerster if (res2) {
521*b1fc8c0dSJoachim Foerster DMSG("Error programming meta header IV (0x%" PRIx32 ")",
522*b1fc8c0dSJoachim Foerster res2);
523*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
524*b1fc8c0dSJoachim Foerster }
525*b1fc8c0dSJoachim Foerster }
52613dee78bSJoachim Foerster
527*b1fc8c0dSJoachim Foerster if (p->prgm_blk_obfus_iv) {
528*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_IV, EFUSE_BLACK_IV,
529*b1fc8c0dSJoachim Foerster p->blk_obfus_iv, EFUSE_IV_LEN);
530*b1fc8c0dSJoachim Foerster if (res2) {
531*b1fc8c0dSJoachim Foerster DMSG("Error programming black IV (0x%" PRIx32 ")",
532*b1fc8c0dSJoachim Foerster res2);
533*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
534*b1fc8c0dSJoachim Foerster }
535*b1fc8c0dSJoachim Foerster }
536*b1fc8c0dSJoachim Foerster
537*b1fc8c0dSJoachim Foerster if (p->prgm_plm_iv) {
538*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_IV,
539*b1fc8c0dSJoachim Foerster EFUSE_PLM_IV_RANGE,
540*b1fc8c0dSJoachim Foerster p->plm_iv, EFUSE_IV_LEN);
541*b1fc8c0dSJoachim Foerster if (res2) {
542*b1fc8c0dSJoachim Foerster DMSG("Error programming plm IV (0x%" PRIx32 ")", res2);
543*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
544*b1fc8c0dSJoachim Foerster }
545*b1fc8c0dSJoachim Foerster }
546*b1fc8c0dSJoachim Foerster
547*b1fc8c0dSJoachim Foerster if (p->prgm_data_partition_iv) {
548*b1fc8c0dSJoachim Foerster res2 = do_write_efuses_buffer(EFUSE_WRITE_IV,
549*b1fc8c0dSJoachim Foerster EFUSE_DATA_PARTITION_IV_RANGE,
550*b1fc8c0dSJoachim Foerster p->data_partition_iv,
551*b1fc8c0dSJoachim Foerster EFUSE_IV_LEN);
552*b1fc8c0dSJoachim Foerster if (res2) {
553*b1fc8c0dSJoachim Foerster DMSG("Error programming data IV (0x%" PRIx32 ")", res2);
554*b1fc8c0dSJoachim Foerster res = TEE_ERROR_GENERIC;
555*b1fc8c0dSJoachim Foerster }
556*b1fc8c0dSJoachim Foerster }
557*b1fc8c0dSJoachim Foerster
558*b1fc8c0dSJoachim Foerster return res;
55913dee78bSJoachim Foerster }
56013dee78bSJoachim Foerster
versal_efuse_write_dec_only(struct versal_efuse_dec_only * p)56113dee78bSJoachim Foerster TEE_Result versal_efuse_write_dec_only(struct versal_efuse_dec_only *p)
56213dee78bSJoachim Foerster {
563*b1fc8c0dSJoachim Foerster if (!p)
564*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
56513dee78bSJoachim Foerster
566*b1fc8c0dSJoachim Foerster if (!p->prgm_dec_only)
567*b1fc8c0dSJoachim Foerster return TEE_SUCCESS;
56813dee78bSJoachim Foerster
569*b1fc8c0dSJoachim Foerster return do_write_efuses(EFUSE_WRITE_DEC_ONLY);
57013dee78bSJoachim Foerster }
57113dee78bSJoachim Foerster
versal_efuse_write_sec(struct versal_efuse_sec_ctrl_bits * p)57213dee78bSJoachim Foerster TEE_Result versal_efuse_write_sec(struct versal_efuse_sec_ctrl_bits *p)
57313dee78bSJoachim Foerster {
574*b1fc8c0dSJoachim Foerster uint32_t val = 0;
57513dee78bSJoachim Foerster
576*b1fc8c0dSJoachim Foerster if (!p)
577*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
57813dee78bSJoachim Foerster
579*b1fc8c0dSJoachim Foerster val = SHIFT_U32(p->reg_init_dis & 0x3, 30) |
580*b1fc8c0dSJoachim Foerster SHIFT_U32(p->boot_env_wr_lk & 0x1, 28) |
581*b1fc8c0dSJoachim Foerster SHIFT_U32(p->sec_lock_dbg_dis & 0x3, 21) |
582*b1fc8c0dSJoachim Foerster SHIFT_U32(p->sec_dbg_dis & 0x3, 19) |
583*b1fc8c0dSJoachim Foerster SHIFT_U32(p->user_key1_wr_lk & 0x1, 15) |
584*b1fc8c0dSJoachim Foerster SHIFT_U32(p->user_key1_crc_lk & 0x1, 14) |
585*b1fc8c0dSJoachim Foerster SHIFT_U32(p->user_key0_wr_lk & 0x1, 13) |
586*b1fc8c0dSJoachim Foerster SHIFT_U32(p->user_key0_crc_lk & 0x1, 12) |
587*b1fc8c0dSJoachim Foerster SHIFT_U32(p->aes_wr_lk & 0x1, 11) |
588*b1fc8c0dSJoachim Foerster SHIFT_U32(p->aes_crc_lk & 0x3, 9) |
589*b1fc8c0dSJoachim Foerster SHIFT_U32(p->ppk2_wr_lk & 0x1, 8) |
590*b1fc8c0dSJoachim Foerster SHIFT_U32(p->ppk1_wr_lk & 0x1, 7) |
591*b1fc8c0dSJoachim Foerster SHIFT_U32(p->ppk0_wr_lk & 0x1, 6) |
592*b1fc8c0dSJoachim Foerster SHIFT_U32(p->jtag_dis & 0x1, 2) |
593*b1fc8c0dSJoachim Foerster SHIFT_U32(p->jtag_err_out_dis & 0x1, 1) |
594*b1fc8c0dSJoachim Foerster (p->aes_dis & 0x1);
59513dee78bSJoachim Foerster
596*b1fc8c0dSJoachim Foerster return do_write_efuses_value(EFUSE_WRITE_SEC_CTRL_BITS, val);
59713dee78bSJoachim Foerster }
59813dee78bSJoachim Foerster
versal_efuse_write_misc(struct versal_efuse_misc_ctrl_bits * p)59913dee78bSJoachim Foerster TEE_Result versal_efuse_write_misc(struct versal_efuse_misc_ctrl_bits *p)
60013dee78bSJoachim Foerster {
601*b1fc8c0dSJoachim Foerster uint32_t val = 0;
60213dee78bSJoachim Foerster
603*b1fc8c0dSJoachim Foerster if (!p)
604*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
60513dee78bSJoachim Foerster
606*b1fc8c0dSJoachim Foerster val = SHIFT_U32(p->glitch_det_halt_boot_en & 0x3, 30) |
607*b1fc8c0dSJoachim Foerster SHIFT_U32(p->glitch_det_rom_monitor_en & 0x1, 29) |
608*b1fc8c0dSJoachim Foerster SHIFT_U32(p->halt_boot_error & 0x3, 21) |
609*b1fc8c0dSJoachim Foerster SHIFT_U32(p->halt_boot_env & 0x3, 19) |
610*b1fc8c0dSJoachim Foerster SHIFT_U32(p->crypto_kat_en & 0x1, 15) |
611*b1fc8c0dSJoachim Foerster SHIFT_U32(p->lbist_en & 0x1, 14) |
612*b1fc8c0dSJoachim Foerster SHIFT_U32(p->safety_mission_en & 0x1, 8) |
613*b1fc8c0dSJoachim Foerster SHIFT_U32(p->ppk2_invalid & 0x3, 6) |
614*b1fc8c0dSJoachim Foerster SHIFT_U32(p->ppk1_invalid & 0x3, 4) |
615*b1fc8c0dSJoachim Foerster SHIFT_U32(p->ppk0_invalid & 0x3, 2);
61613dee78bSJoachim Foerster
617*b1fc8c0dSJoachim Foerster return do_write_efuses_value(EFUSE_WRITE_MISC_CTRL_BITS, val);
61813dee78bSJoachim Foerster }
61913dee78bSJoachim Foerster
620*b1fc8c0dSJoachim Foerster TEE_Result
versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits * p)621*b1fc8c0dSJoachim Foerster versal_efuse_write_glitch_cfg(struct versal_efuse_glitch_cfg_bits *p)
62213dee78bSJoachim Foerster {
623*b1fc8c0dSJoachim Foerster uint32_t val = 0;
62413dee78bSJoachim Foerster
625*b1fc8c0dSJoachim Foerster if (!p)
626*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
62713dee78bSJoachim Foerster
628*b1fc8c0dSJoachim Foerster if (!p->prgm_glitch)
629*b1fc8c0dSJoachim Foerster return TEE_SUCCESS;
63013dee78bSJoachim Foerster
631*b1fc8c0dSJoachim Foerster val = SHIFT_U32(p->glitch_det_wr_lk & 0x1, 31) | p->glitch_det_trim;
632*b1fc8c0dSJoachim Foerster
633*b1fc8c0dSJoachim Foerster return do_write_efuses_value(EFUSE_WRITE_GLITCH_CONFIG, val);
63413dee78bSJoachim Foerster }
63513dee78bSJoachim Foerster
636*b1fc8c0dSJoachim Foerster TEE_Result
versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits * p)637*b1fc8c0dSJoachim Foerster versal_efuse_write_boot_env(struct versal_efuse_boot_env_ctrl_bits *p)
63813dee78bSJoachim Foerster {
639*b1fc8c0dSJoachim Foerster uint32_t val = 0;
64013dee78bSJoachim Foerster
641*b1fc8c0dSJoachim Foerster if (!p)
642*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
64313dee78bSJoachim Foerster
644*b1fc8c0dSJoachim Foerster val = SHIFT_U32(p->sysmon_temp_en & 0x1, 21) |
645*b1fc8c0dSJoachim Foerster SHIFT_U32(p->sysmon_volt_en & 0x1, 20) |
646*b1fc8c0dSJoachim Foerster SHIFT_U32(p->sysmon_temp_hot & 0x3, 17) |
647*b1fc8c0dSJoachim Foerster SHIFT_U32(p->sysmon_volt_pmc & 0x3, 12) |
648*b1fc8c0dSJoachim Foerster SHIFT_U32(p->sysmon_volt_pslp & 0x3, 10) |
649*b1fc8c0dSJoachim Foerster SHIFT_U32(p->sysmon_volt_soc & 0x3, 8) |
650*b1fc8c0dSJoachim Foerster (p->sysmon_temp_cold & 0x2);
65113dee78bSJoachim Foerster
652*b1fc8c0dSJoachim Foerster return do_write_efuses_value(EFUSE_WRITE_BOOT_ENV_CTRL_BITS, val);
65313dee78bSJoachim Foerster }
65413dee78bSJoachim Foerster
versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits * p)65513dee78bSJoachim Foerster TEE_Result versal_efuse_write_sec_misc1(struct versal_efuse_sec_misc1_bits *p)
65613dee78bSJoachim Foerster {
657*b1fc8c0dSJoachim Foerster uint32_t val = 0;
65813dee78bSJoachim Foerster
659*b1fc8c0dSJoachim Foerster if (!p)
660*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
66113dee78bSJoachim Foerster
662*b1fc8c0dSJoachim Foerster val = SHIFT_U32(p->lpd_mbist_en & 0x7, 10) |
663*b1fc8c0dSJoachim Foerster SHIFT_U32(p->pmc_mbist_en & 0x7, 7) |
664*b1fc8c0dSJoachim Foerster SHIFT_U32(p->lpd_noc_sc_en & 0x7, 4) |
665*b1fc8c0dSJoachim Foerster SHIFT_U32(p->sysmon_volt_mon_en & 0x3, 2) |
666*b1fc8c0dSJoachim Foerster (p->sysmon_temp_mon_en & 0x3);
66713dee78bSJoachim Foerster
668*b1fc8c0dSJoachim Foerster return do_write_efuses_value(EFUSE_WRITE_MISC1_CTRL_BITS, val);
66913dee78bSJoachim Foerster }
67013dee78bSJoachim Foerster
versal_efuse_write_offchip_ids(struct versal_efuse_offchip_ids * p)67113dee78bSJoachim Foerster TEE_Result versal_efuse_write_offchip_ids(struct versal_efuse_offchip_ids *p)
67213dee78bSJoachim Foerster {
673*b1fc8c0dSJoachim Foerster uint32_t id = 0;
674*b1fc8c0dSJoachim Foerster bool id_valid = false;
67513dee78bSJoachim Foerster
676*b1fc8c0dSJoachim Foerster /*
677*b1fc8c0dSJoachim Foerster * XilNvm API id 0xb10 (EFUSE_WRITE_OFFCHIP_REVOKE_ID) can write a
678*b1fc8c0dSJoachim Foerster * single OffChip Revoke Id eFuse bit at a time, only!
679*b1fc8c0dSJoachim Foerster */
680*b1fc8c0dSJoachim Foerster for (int word = 0; word <= EFUSE_OFFCHIP_REVOKE_ID_7; ++word) {
681*b1fc8c0dSJoachim Foerster uint32_t current_word = p->offchip_id[word];
68213dee78bSJoachim Foerster
683*b1fc8c0dSJoachim Foerster if (!current_word)
684*b1fc8c0dSJoachim Foerster continue;
68513dee78bSJoachim Foerster
686*b1fc8c0dSJoachim Foerster if (id_valid) {
687*b1fc8c0dSJoachim Foerster EMSG("Trying to write multiple offchip IDs");
688*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
689*b1fc8c0dSJoachim Foerster }
690*b1fc8c0dSJoachim Foerster
691*b1fc8c0dSJoachim Foerster id_valid = true;
692*b1fc8c0dSJoachim Foerster
693*b1fc8c0dSJoachim Foerster /* Determine if only 1 bit is set. */
694*b1fc8c0dSJoachim Foerster if (!IS_POWER_OF_TWO(current_word)) {
695*b1fc8c0dSJoachim Foerster EMSG("Trying to write multiple bits (0x%08x) in offchip ID %u",
696*b1fc8c0dSJoachim Foerster current_word, word);
697*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
698*b1fc8c0dSJoachim Foerster }
699*b1fc8c0dSJoachim Foerster
700*b1fc8c0dSJoachim Foerster /* Determine which bit is set. */
701*b1fc8c0dSJoachim Foerster id = (word * 32) + (31 - __builtin_clz(current_word));
702*b1fc8c0dSJoachim Foerster }
703*b1fc8c0dSJoachim Foerster
704*b1fc8c0dSJoachim Foerster if (!id_valid) {
705*b1fc8c0dSJoachim Foerster EMSG("Trying to write no offchip IDs");
706*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
707*b1fc8c0dSJoachim Foerster }
708*b1fc8c0dSJoachim Foerster
709*b1fc8c0dSJoachim Foerster /*
710*b1fc8c0dSJoachim Foerster * Do not send any command to PLM firmware, if we do not
711*b1fc8c0dSJoachim Foerster * actually want to write any eFuse. Mimics behavior of XilNvm
712*b1fc8c0dSJoachim Foerster * API id EFUSE_WRITE (0xb06) on Versal.
713*b1fc8c0dSJoachim Foerster */
714*b1fc8c0dSJoachim Foerster if (p->prgm_offchip_id)
715*b1fc8c0dSJoachim Foerster return do_write_efuses_value(EFUSE_WRITE_OFFCHIP_REVOKE_ID, id);
716*b1fc8c0dSJoachim Foerster
717*b1fc8c0dSJoachim Foerster return TEE_SUCCESS;
71813dee78bSJoachim Foerster }
71913dee78bSJoachim Foerster
versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type)72013dee78bSJoachim Foerster TEE_Result versal_efuse_write_revoke_ppk(enum versal_nvm_ppk_type type)
72113dee78bSJoachim Foerster {
722*b1fc8c0dSJoachim Foerster struct versal_efuse_misc_ctrl_bits misc_ctrl = {};
72313dee78bSJoachim Foerster
724*b1fc8c0dSJoachim Foerster switch (type) {
725*b1fc8c0dSJoachim Foerster case EFUSE_PPK0:
726*b1fc8c0dSJoachim Foerster misc_ctrl.ppk0_invalid = 0x3;
727*b1fc8c0dSJoachim Foerster break;
728*b1fc8c0dSJoachim Foerster case EFUSE_PPK1:
729*b1fc8c0dSJoachim Foerster misc_ctrl.ppk1_invalid = 0x3;
730*b1fc8c0dSJoachim Foerster break;
731*b1fc8c0dSJoachim Foerster case EFUSE_PPK2:
732*b1fc8c0dSJoachim Foerster misc_ctrl.ppk2_invalid = 0x3;
733*b1fc8c0dSJoachim Foerster break;
734*b1fc8c0dSJoachim Foerster default:
73513dee78bSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
736*b1fc8c0dSJoachim Foerster }
73713dee78bSJoachim Foerster
738*b1fc8c0dSJoachim Foerster return versal_efuse_write_misc(&misc_ctrl);
73913dee78bSJoachim Foerster }
74013dee78bSJoachim Foerster
versal_efuse_write_revoke_id(uint32_t id)74113dee78bSJoachim Foerster TEE_Result versal_efuse_write_revoke_id(uint32_t id)
74213dee78bSJoachim Foerster {
743*b1fc8c0dSJoachim Foerster if (id < VERSAL_NET_REVOKE_EFUSE_MIN ||
744*b1fc8c0dSJoachim Foerster id > VERSAL_NET_REVOKE_EFUSE_MAX)
745*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
74613dee78bSJoachim Foerster
747*b1fc8c0dSJoachim Foerster return do_write_efuses_value(EFUSE_WRITE_REVOCATION_ID, id);
74813dee78bSJoachim Foerster }
74913dee78bSJoachim Foerster
versal_efuse_read_revoke_id(uint32_t * buf,size_t len,enum versal_nvm_revocation_id id)75013dee78bSJoachim Foerster TEE_Result versal_efuse_read_revoke_id(uint32_t *buf, size_t len,
75113dee78bSJoachim Foerster enum versal_nvm_revocation_id id)
75213dee78bSJoachim Foerster {
753*b1fc8c0dSJoachim Foerster uint32_t reg = EFUSE_CACHE_REVOCATION_ID0_OFFSET;
75413dee78bSJoachim Foerster
755*b1fc8c0dSJoachim Foerster reg += id;
75613dee78bSJoachim Foerster
757*b1fc8c0dSJoachim Foerster return versal_efuse_read_cache(reg,
758*b1fc8c0dSJoachim Foerster EFUSE_REVOCATION_ID_LEN / NVM_WORD_LEN,
759*b1fc8c0dSJoachim Foerster buf, len);
76013dee78bSJoachim Foerster }
76113dee78bSJoachim Foerster
versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits * buf)76213dee78bSJoachim Foerster TEE_Result versal_efuse_read_misc_ctrl(struct versal_efuse_misc_ctrl_bits *buf)
76313dee78bSJoachim Foerster {
764*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
765*b1fc8c0dSJoachim Foerster uint32_t misc_ctrl = 0;
76613dee78bSJoachim Foerster
767*b1fc8c0dSJoachim Foerster if (!buf)
768*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
76913dee78bSJoachim Foerster
770*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_cache(EFUSE_CACHE_MISC_CTRL_OFFSET, 1,
771*b1fc8c0dSJoachim Foerster &misc_ctrl, sizeof(misc_ctrl));
772*b1fc8c0dSJoachim Foerster if (ret)
773*b1fc8c0dSJoachim Foerster return ret;
77413dee78bSJoachim Foerster
775*b1fc8c0dSJoachim Foerster buf->glitch_det_halt_boot_en = (misc_ctrl & GENMASK_32(31, 30)) >> 30;
776*b1fc8c0dSJoachim Foerster buf->glitch_det_rom_monitor_en = (misc_ctrl & BIT(29)) >> 29;
777*b1fc8c0dSJoachim Foerster buf->halt_boot_error = (misc_ctrl & GENMASK_32(22, 21)) >> 21;
778*b1fc8c0dSJoachim Foerster buf->halt_boot_env = (misc_ctrl & GENMASK_32(20, 19)) >> 19;
779*b1fc8c0dSJoachim Foerster buf->crypto_kat_en = (misc_ctrl & BIT(15)) >> 15;
780*b1fc8c0dSJoachim Foerster buf->lbist_en = (misc_ctrl & BIT(14)) >> 14;
781*b1fc8c0dSJoachim Foerster buf->safety_mission_en = (misc_ctrl & BIT(8)) >> 8;
782*b1fc8c0dSJoachim Foerster buf->ppk0_invalid = (misc_ctrl & GENMASK_32(7, 6)) >> 6;
783*b1fc8c0dSJoachim Foerster buf->ppk1_invalid = (misc_ctrl & GENMASK_32(5, 4)) >> 4;
784*b1fc8c0dSJoachim Foerster buf->ppk2_invalid = (misc_ctrl & GENMASK_32(3, 2)) >> 2;
78513dee78bSJoachim Foerster
78613dee78bSJoachim Foerster return TEE_SUCCESS;
78713dee78bSJoachim Foerster }
78813dee78bSJoachim Foerster
versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits * buf)78913dee78bSJoachim Foerster TEE_Result versal_efuse_read_sec_ctrl(struct versal_efuse_sec_ctrl_bits *buf)
79013dee78bSJoachim Foerster {
791*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
792*b1fc8c0dSJoachim Foerster uint32_t sec_ctrl = 0;
79313dee78bSJoachim Foerster
794*b1fc8c0dSJoachim Foerster if (!buf)
795*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
79613dee78bSJoachim Foerster
797*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_CTRL_OFFSET, 1,
798*b1fc8c0dSJoachim Foerster &sec_ctrl, sizeof(sec_ctrl));
799*b1fc8c0dSJoachim Foerster if (ret)
800*b1fc8c0dSJoachim Foerster return ret;
80113dee78bSJoachim Foerster
802*b1fc8c0dSJoachim Foerster buf->aes_dis = sec_ctrl & BIT(0);
803*b1fc8c0dSJoachim Foerster buf->jtag_err_out_dis = (sec_ctrl & BIT(1)) >> 1;
804*b1fc8c0dSJoachim Foerster buf->jtag_dis = (sec_ctrl & BIT(2)) >> 2;
805*b1fc8c0dSJoachim Foerster buf->ppk0_wr_lk = (sec_ctrl & BIT(6)) >> 6;
806*b1fc8c0dSJoachim Foerster buf->ppk1_wr_lk = (sec_ctrl & BIT(7)) >> 7;
807*b1fc8c0dSJoachim Foerster buf->ppk2_wr_lk = (sec_ctrl & BIT(8)) >> 8;
808*b1fc8c0dSJoachim Foerster buf->aes_crc_lk = (sec_ctrl & GENMASK_32(10, 9)) >> 9;
809*b1fc8c0dSJoachim Foerster buf->aes_wr_lk = (sec_ctrl & BIT(11)) >> 11;
810*b1fc8c0dSJoachim Foerster buf->user_key0_crc_lk = (sec_ctrl & BIT(12)) >> 12;
811*b1fc8c0dSJoachim Foerster buf->user_key0_wr_lk = (sec_ctrl & BIT(13)) >> 13;
812*b1fc8c0dSJoachim Foerster buf->user_key1_crc_lk = (sec_ctrl & BIT(14)) >> 14;
813*b1fc8c0dSJoachim Foerster buf->user_key1_wr_lk = (sec_ctrl & BIT(15)) >> 15;
814*b1fc8c0dSJoachim Foerster buf->sec_dbg_dis = (sec_ctrl & GENMASK_32(20, 19)) >> 19;
815*b1fc8c0dSJoachim Foerster buf->sec_lock_dbg_dis = (sec_ctrl & GENMASK_32(22, 21)) >> 21;
816*b1fc8c0dSJoachim Foerster buf->boot_env_wr_lk = (sec_ctrl & BIT(28)) >> 28;
817*b1fc8c0dSJoachim Foerster buf->reg_init_dis = (sec_ctrl & GENMASK_32(31, 30)) >> 30;
81813dee78bSJoachim Foerster
81913dee78bSJoachim Foerster return TEE_SUCCESS;
82013dee78bSJoachim Foerster }
82113dee78bSJoachim Foerster
versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits * buf)82213dee78bSJoachim Foerster TEE_Result versal_efuse_read_sec_misc1(struct versal_efuse_sec_misc1_bits *buf)
82313dee78bSJoachim Foerster {
824*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
825*b1fc8c0dSJoachim Foerster uint32_t sec_misc1 = 0;
82613dee78bSJoachim Foerster
827*b1fc8c0dSJoachim Foerster if (!buf)
828*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
82913dee78bSJoachim Foerster
830*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_MISC1_OFFSET, 1,
831*b1fc8c0dSJoachim Foerster &sec_misc1, sizeof(sec_misc1));
832*b1fc8c0dSJoachim Foerster if (ret)
833*b1fc8c0dSJoachim Foerster return ret;
83413dee78bSJoachim Foerster
835*b1fc8c0dSJoachim Foerster buf->lpd_mbist_en = (sec_misc1 & GENMASK_32(12, 10)) >> 10;
836*b1fc8c0dSJoachim Foerster buf->pmc_mbist_en = (sec_misc1 & GENMASK_32(9, 7)) >> 7;
837*b1fc8c0dSJoachim Foerster buf->lpd_noc_sc_en = (sec_misc1 & GENMASK_32(6, 4)) >> 4;
838*b1fc8c0dSJoachim Foerster buf->sysmon_volt_mon_en = (sec_misc1 & GENMASK_32(3, 2)) >> 2;
839*b1fc8c0dSJoachim Foerster buf->sysmon_temp_mon_en = sec_misc1 & GENMASK_32(1, 0);
84013dee78bSJoachim Foerster
84113dee78bSJoachim Foerster return TEE_SUCCESS;
84213dee78bSJoachim Foerster }
84313dee78bSJoachim Foerster
84413dee78bSJoachim Foerster TEE_Result
versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits * buf)84513dee78bSJoachim Foerster versal_efuse_read_boot_env_ctrl(struct versal_efuse_boot_env_ctrl_bits *buf)
84613dee78bSJoachim Foerster {
847*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
848*b1fc8c0dSJoachim Foerster uint32_t boot_env_ctrl = 0;
84913dee78bSJoachim Foerster
850*b1fc8c0dSJoachim Foerster if (!buf)
851*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
85213dee78bSJoachim Foerster
853*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_cache(EFUSE_CACHE_BOOT_ENV_CTRL_OFFSET, 1,
854*b1fc8c0dSJoachim Foerster &boot_env_ctrl, sizeof(boot_env_ctrl));
855*b1fc8c0dSJoachim Foerster if (ret)
856*b1fc8c0dSJoachim Foerster return ret;
85713dee78bSJoachim Foerster
858*b1fc8c0dSJoachim Foerster buf->sysmon_temp_en = (boot_env_ctrl & BIT(21)) >> 21;
859*b1fc8c0dSJoachim Foerster buf->sysmon_volt_en = (boot_env_ctrl & BIT(20)) >> 20;
860*b1fc8c0dSJoachim Foerster buf->sysmon_temp_hot = (boot_env_ctrl & GENMASK_32(18, 17)) >> 17;
861*b1fc8c0dSJoachim Foerster buf->sysmon_volt_pmc = (boot_env_ctrl & GENMASK_32(13, 12)) >> 12;
862*b1fc8c0dSJoachim Foerster buf->sysmon_volt_pslp = (boot_env_ctrl & GENMASK_32(11, 10)) >> 10;
863*b1fc8c0dSJoachim Foerster buf->sysmon_volt_soc = (boot_env_ctrl & GENMASK_32(9, 8)) >> 8;
864*b1fc8c0dSJoachim Foerster buf->sysmon_temp_cold = boot_env_ctrl & GENMASK_32(1, 0);
86513dee78bSJoachim Foerster
86613dee78bSJoachim Foerster return TEE_SUCCESS;
86713dee78bSJoachim Foerster }
86813dee78bSJoachim Foerster
versal_efuse_read_offchip_revoke_id(uint32_t * buf,size_t len,enum versal_nvm_offchip_id id)86913dee78bSJoachim Foerster TEE_Result versal_efuse_read_offchip_revoke_id(uint32_t *buf, size_t len,
87013dee78bSJoachim Foerster enum versal_nvm_offchip_id id)
87113dee78bSJoachim Foerster {
872*b1fc8c0dSJoachim Foerster uint32_t reg = EFUSE_CACHE_OFFCHIP_REVOKE_ID0_OFFSET;
87313dee78bSJoachim Foerster
87413dee78bSJoachim Foerster if (len < EFUSE_OFFCHIP_REVOCATION_ID_LEN)
87513dee78bSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
87613dee78bSJoachim Foerster
877*b1fc8c0dSJoachim Foerster reg += id;
87813dee78bSJoachim Foerster
879*b1fc8c0dSJoachim Foerster return versal_efuse_read_cache(reg,
880*b1fc8c0dSJoachim Foerster EFUSE_OFFCHIP_REVOCATION_ID_LEN /
881*b1fc8c0dSJoachim Foerster NVM_WORD_LEN,
882*b1fc8c0dSJoachim Foerster buf, len);
88313dee78bSJoachim Foerster }
88413dee78bSJoachim Foerster
versal_efuse_read_dec_only(uint32_t * buf,size_t len)88513dee78bSJoachim Foerster TEE_Result versal_efuse_read_dec_only(uint32_t *buf, size_t len)
88613dee78bSJoachim Foerster {
887*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
888*b1fc8c0dSJoachim Foerster uint32_t sec_misc0 = 0;
88913dee78bSJoachim Foerster
89013dee78bSJoachim Foerster if (len < EFUSE_DEC_ONLY_LEN)
89113dee78bSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
89213dee78bSJoachim Foerster
893*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_MISC0_OFFSET, 1,
894*b1fc8c0dSJoachim Foerster &sec_misc0, sizeof(sec_misc0));
895*b1fc8c0dSJoachim Foerster if (ret)
896*b1fc8c0dSJoachim Foerster return ret;
89713dee78bSJoachim Foerster
898*b1fc8c0dSJoachim Foerster sec_misc0 &= GENMASK_32(15, 0);
89913dee78bSJoachim Foerster
900*b1fc8c0dSJoachim Foerster memcpy(buf, &sec_misc0, EFUSE_DEC_ONLY_LEN);
90113dee78bSJoachim Foerster
90213dee78bSJoachim Foerster return TEE_SUCCESS;
90313dee78bSJoachim Foerster }
90413dee78bSJoachim Foerster
versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits * buf)905*b1fc8c0dSJoachim Foerster TEE_Result versal_efuse_read_puf_sec_ctrl(struct versal_efuse_puf_sec_ctrl_bits
906*b1fc8c0dSJoachim Foerster *buf)
90713dee78bSJoachim Foerster {
908*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
909*b1fc8c0dSJoachim Foerster uint32_t puf_ctrl = 0;
910*b1fc8c0dSJoachim Foerster uint32_t sec_ctrl = 0;
91113dee78bSJoachim Foerster
912*b1fc8c0dSJoachim Foerster if (!buf)
913*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
91413dee78bSJoachim Foerster
915*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_cache(EFUSE_CACHE_PUF_ECC_CTRL_OFFSET, 1,
916*b1fc8c0dSJoachim Foerster &puf_ctrl, sizeof(puf_ctrl));
917*b1fc8c0dSJoachim Foerster if (ret)
918*b1fc8c0dSJoachim Foerster return ret;
91913dee78bSJoachim Foerster
920*b1fc8c0dSJoachim Foerster /* Some fuses have moved from PUF_ECC_CTRL to SECURITY_CTRL */
921*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_CTRL_OFFSET, 1,
922*b1fc8c0dSJoachim Foerster &sec_ctrl, sizeof(sec_ctrl));
923*b1fc8c0dSJoachim Foerster if (ret)
924*b1fc8c0dSJoachim Foerster return ret;
925*b1fc8c0dSJoachim Foerster
926*b1fc8c0dSJoachim Foerster buf->puf_regen_dis = (puf_ctrl & BIT(31)) >> 31;
927*b1fc8c0dSJoachim Foerster buf->puf_hd_invalid = (puf_ctrl & BIT(30)) >> 30;
928*b1fc8c0dSJoachim Foerster buf->puf_test2_dis = (puf_ctrl & BIT(29)) >> 29;
929*b1fc8c0dSJoachim Foerster buf->puf_dis = (sec_ctrl & BIT(18)) >> 18;
930*b1fc8c0dSJoachim Foerster buf->puf_syn_lk = (sec_ctrl & BIT(16)) >> 16;
93113dee78bSJoachim Foerster
93213dee78bSJoachim Foerster return TEE_SUCCESS;
93313dee78bSJoachim Foerster }
93413dee78bSJoachim Foerster
versal_efuse_read_puf(struct versal_efuse_puf_header * buf)93513dee78bSJoachim Foerster TEE_Result versal_efuse_read_puf(struct versal_efuse_puf_header *buf)
93613dee78bSJoachim Foerster {
937*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
93813dee78bSJoachim Foerster
939*b1fc8c0dSJoachim Foerster if (!buf)
940*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
94113dee78bSJoachim Foerster
942*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_puf_sec_ctrl(&buf->sec_ctrl);
943*b1fc8c0dSJoachim Foerster if (ret)
944*b1fc8c0dSJoachim Foerster return ret;
94513dee78bSJoachim Foerster
946*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_cache(EFUSE_CACHE_SEC_CTRL_OFFSET, 1,
947*b1fc8c0dSJoachim Foerster &buf->aux, sizeof(uint32_t));
948*b1fc8c0dSJoachim Foerster if (ret)
949*b1fc8c0dSJoachim Foerster return ret;
950*b1fc8c0dSJoachim Foerster
951*b1fc8c0dSJoachim Foerster buf->aux &= GENMASK_32(23, 0);
952*b1fc8c0dSJoachim Foerster
953*b1fc8c0dSJoachim Foerster ret = versal_efuse_read_cache(EFUSE_CACHE_PUF_CHASH_OFFSET, 1,
954*b1fc8c0dSJoachim Foerster &buf->chash, sizeof(uint32_t));
955*b1fc8c0dSJoachim Foerster if (ret)
956*b1fc8c0dSJoachim Foerster return ret;
957*b1fc8c0dSJoachim Foerster
958*b1fc8c0dSJoachim Foerster return versal_efuse_read_cache(EFUSE_CACHE_PUF_SYN0_OFFSET,
959*b1fc8c0dSJoachim Foerster PUF_SYN_DATA_WORDS, buf->efuse_syn_data,
960*b1fc8c0dSJoachim Foerster PUF_SYN_DATA_WORDS * NVM_WORD_LEN);
96113dee78bSJoachim Foerster }
96213dee78bSJoachim Foerster
96313dee78bSJoachim Foerster TEE_Result
versal_efuse_read_puf_as_user_fuse(struct versal_efuse_puf_user_fuse * p __unused)964*b1fc8c0dSJoachim Foerster versal_efuse_read_puf_as_user_fuse(struct versal_efuse_puf_user_fuse
965*b1fc8c0dSJoachim Foerster *p __unused)
96613dee78bSJoachim Foerster {
967*b1fc8c0dSJoachim Foerster return TEE_ERROR_NOT_IMPLEMENTED;
96813dee78bSJoachim Foerster }
96913dee78bSJoachim Foerster
versal_efuse_write_puf_as_user_fuse(struct versal_efuse_puf_user_fuse * p __unused)970*b1fc8c0dSJoachim Foerster TEE_Result versal_efuse_write_puf_as_user_fuse(struct versal_efuse_puf_user_fuse
971*b1fc8c0dSJoachim Foerster *p __unused)
97213dee78bSJoachim Foerster {
973*b1fc8c0dSJoachim Foerster return TEE_ERROR_NOT_IMPLEMENTED;
97413dee78bSJoachim Foerster }
97513dee78bSJoachim Foerster
versal_efuse_write_puf(struct versal_efuse_puf_header * buf)97613dee78bSJoachim Foerster TEE_Result versal_efuse_write_puf(struct versal_efuse_puf_header *buf)
97713dee78bSJoachim Foerster {
978*b1fc8c0dSJoachim Foerster struct versal_ipi_cmd cmd = { };
979*b1fc8c0dSJoachim Foerster struct versal_mbox_mem p = { };
980*b1fc8c0dSJoachim Foerster TEE_Result ret = TEE_SUCCESS;
981*b1fc8c0dSJoachim Foerster uint32_t low = 0;
982*b1fc8c0dSJoachim Foerster uint32_t hi = 0;
983*b1fc8c0dSJoachim Foerster struct versal_efuse_write_puf_data *data = NULL;
98413dee78bSJoachim Foerster
985*b1fc8c0dSJoachim Foerster if (!buf)
986*b1fc8c0dSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
98713dee78bSJoachim Foerster
988*b1fc8c0dSJoachim Foerster ret = versal_mbox_alloc(EFUSE_WRITE_PUF_DATA_WORDS * NVM_WORD_LEN,
989*b1fc8c0dSJoachim Foerster NULL, &p);
990*b1fc8c0dSJoachim Foerster if (ret)
991*b1fc8c0dSJoachim Foerster return ret;
99213dee78bSJoachim Foerster
993*b1fc8c0dSJoachim Foerster data = p.buf;
99413dee78bSJoachim Foerster
995*b1fc8c0dSJoachim Foerster data->sec_ctrl = 0;
996*b1fc8c0dSJoachim Foerster data->prgm_puf_helper_data = buf->prmg_puf_helper_data;
997*b1fc8c0dSJoachim Foerster data->env_monitor_dis = buf->env_monitor_dis;
998*b1fc8c0dSJoachim Foerster memcpy(data->syn, buf->efuse_syn_data,
999*b1fc8c0dSJoachim Foerster PUF_SYN_DATA_WORDS * NVM_WORD_LEN);
1000*b1fc8c0dSJoachim Foerster data->chash = buf->chash;
1001*b1fc8c0dSJoachim Foerster data->aux = buf->aux;
1002*b1fc8c0dSJoachim Foerster data->ro_swap = 0;
1003*b1fc8c0dSJoachim Foerster
1004*b1fc8c0dSJoachim Foerster reg_pair_from_64(virt_to_phys(p.buf), &hi, &low);
1005*b1fc8c0dSJoachim Foerster
1006*b1fc8c0dSJoachim Foerster cmd.data[0] = NVM_API_ID(EFUSE_WRITE_PUF);
1007*b1fc8c0dSJoachim Foerster cmd.data[2] = low;
1008*b1fc8c0dSJoachim Foerster cmd.data[3] = hi;
1009*b1fc8c0dSJoachim Foerster
1010*b1fc8c0dSJoachim Foerster cmd.ibuf[0].mem = p;
1011*b1fc8c0dSJoachim Foerster
1012*b1fc8c0dSJoachim Foerster ret = versal_pmc_notify(&cmd, NULL, NULL);
1013*b1fc8c0dSJoachim Foerster
1014*b1fc8c0dSJoachim Foerster versal_mbox_free(&p);
1015*b1fc8c0dSJoachim Foerster return ret;
101613dee78bSJoachim Foerster }
101713dee78bSJoachim Foerster
versal_bbram_write_aes_key(uint8_t * key,size_t len)101813dee78bSJoachim Foerster TEE_Result versal_bbram_write_aes_key(uint8_t *key, size_t len)
101913dee78bSJoachim Foerster {
102013dee78bSJoachim Foerster struct versal_nvm_write_req req __aligned_efuse = {
102113dee78bSJoachim Foerster .efuse_id = BBRAM_WRITE_AES_KEY,
102213dee78bSJoachim Foerster .bbram.aes_key_len = len,
102313dee78bSJoachim Foerster };
102413dee78bSJoachim Foerster void *buf = NULL;
102513dee78bSJoachim Foerster
102613dee78bSJoachim Foerster if (len != 32)
102713dee78bSJoachim Foerster return TEE_ERROR_BAD_PARAMETERS;
102813dee78bSJoachim Foerster
102913dee78bSJoachim Foerster buf = alloc_cache_aligned(1024);
103013dee78bSJoachim Foerster if (!buf)
103113dee78bSJoachim Foerster return TEE_ERROR_OUT_OF_MEMORY;
103213dee78bSJoachim Foerster
103313dee78bSJoachim Foerster memcpy(buf, key, len);
103413dee78bSJoachim Foerster
103513dee78bSJoachim Foerster req.ibuf[0].buf = buf;
103613dee78bSJoachim Foerster req.ibuf[0].len = 1024;
103713dee78bSJoachim Foerster
103813dee78bSJoachim Foerster if (versal_nvm_write(&req)) {
103913dee78bSJoachim Foerster free(buf);
104013dee78bSJoachim Foerster return TEE_ERROR_GENERIC;
104113dee78bSJoachim Foerster }
104213dee78bSJoachim Foerster free(buf);
104313dee78bSJoachim Foerster
104413dee78bSJoachim Foerster return TEE_SUCCESS;
104513dee78bSJoachim Foerster }
104613dee78bSJoachim Foerster
versal_bbram_zeroize(void)104713dee78bSJoachim Foerster TEE_Result versal_bbram_zeroize(void)
104813dee78bSJoachim Foerster {
104913dee78bSJoachim Foerster struct versal_nvm_write_req req __aligned_efuse = {
105013dee78bSJoachim Foerster .efuse_id = BBRAM_ZEROIZE,
105113dee78bSJoachim Foerster };
105213dee78bSJoachim Foerster
105313dee78bSJoachim Foerster if (versal_nvm_write(&req))
105413dee78bSJoachim Foerster return TEE_ERROR_GENERIC;
105513dee78bSJoachim Foerster
105613dee78bSJoachim Foerster return TEE_SUCCESS;
105713dee78bSJoachim Foerster }
105813dee78bSJoachim Foerster
versal_bbram_write_user_data(uint32_t data)105913dee78bSJoachim Foerster TEE_Result versal_bbram_write_user_data(uint32_t data)
106013dee78bSJoachim Foerster {
106113dee78bSJoachim Foerster struct versal_nvm_write_req req __aligned_efuse = {
106213dee78bSJoachim Foerster .efuse_id = BBRAM_WRITE_USER_DATA,
106313dee78bSJoachim Foerster .bbram.user_data = data,
106413dee78bSJoachim Foerster };
106513dee78bSJoachim Foerster
106613dee78bSJoachim Foerster if (versal_nvm_write(&req))
106713dee78bSJoachim Foerster return TEE_ERROR_GENERIC;
106813dee78bSJoachim Foerster
106913dee78bSJoachim Foerster return TEE_SUCCESS;
107013dee78bSJoachim Foerster }
107113dee78bSJoachim Foerster
versal_bbram_read_user_data(uint32_t * data)107213dee78bSJoachim Foerster TEE_Result versal_bbram_read_user_data(uint32_t *data)
107313dee78bSJoachim Foerster {
107413dee78bSJoachim Foerster struct versal_nvm_read_req req = {
107513dee78bSJoachim Foerster .efuse_id = BBRAM_READ_USER_DATA,
107613dee78bSJoachim Foerster };
107713dee78bSJoachim Foerster
107813dee78bSJoachim Foerster if (versal_alloc_read_buffer(&req))
107913dee78bSJoachim Foerster return TEE_ERROR_OUT_OF_MEMORY;
108013dee78bSJoachim Foerster
108113dee78bSJoachim Foerster if (versal_nvm_read(&req)) {
108213dee78bSJoachim Foerster versal_free_read_buffer(&req);
108313dee78bSJoachim Foerster return TEE_ERROR_GENERIC;
108413dee78bSJoachim Foerster }
108513dee78bSJoachim Foerster
108613dee78bSJoachim Foerster memcpy(data, versal_get_read_buffer(&req), sizeof(*data));
108713dee78bSJoachim Foerster versal_free_read_buffer(&req);
108813dee78bSJoachim Foerster
108913dee78bSJoachim Foerster return TEE_SUCCESS;
109013dee78bSJoachim Foerster }
109113dee78bSJoachim Foerster
versal_bbram_lock_write_user_data(void)109213dee78bSJoachim Foerster TEE_Result versal_bbram_lock_write_user_data(void)
109313dee78bSJoachim Foerster {
109413dee78bSJoachim Foerster struct versal_nvm_write_req req __aligned_efuse = {
109513dee78bSJoachim Foerster .efuse_id = BBRAM_LOCK_WRITE_USER_DATA,
109613dee78bSJoachim Foerster };
109713dee78bSJoachim Foerster
109813dee78bSJoachim Foerster if (versal_nvm_write(&req))
109913dee78bSJoachim Foerster return TEE_ERROR_GENERIC;
110013dee78bSJoachim Foerster
110113dee78bSJoachim Foerster return TEE_SUCCESS;
110213dee78bSJoachim Foerster }
1103