xref: /optee_os/core/drivers/versal_net_nvm.c (revision b1fc8c0d90a9e10d1724acb84cd0eb70ef0f96a0)
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