xref: /optee_os/core/drivers/zynqmp_csu_puf.c (revision 2c9522664f6443e172745b619e0dc59a44a29d59)
1e4a0a852SJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-2-Clause
2e4a0a852SJorge Ramirez-Ortiz /*
3e4a0a852SJorge Ramirez-Ortiz  * Copyright 2021 Foundries.io Ltd.
4e4a0a852SJorge Ramirez-Ortiz  *
5e4a0a852SJorge Ramirez-Ortiz  * Jorge Ramirez-Ortiz <jorge@foundries.io>
6e4a0a852SJorge Ramirez-Ortiz  */
7e4a0a852SJorge Ramirez-Ortiz #include <drivers/zynqmp_csu.h>
8e4a0a852SJorge Ramirez-Ortiz #include <drivers/zynqmp_csu_aes.h>
9e4a0a852SJorge Ramirez-Ortiz #include <drivers/zynqmp_csu_puf.h>
10e4a0a852SJorge Ramirez-Ortiz #include <initcall.h>
11e4a0a852SJorge Ramirez-Ortiz #include <io.h>
12e4a0a852SJorge Ramirez-Ortiz #include <kernel/delay.h>
13e4a0a852SJorge Ramirez-Ortiz #include <mm/core_memprot.h>
14e4a0a852SJorge Ramirez-Ortiz 
15e4a0a852SJorge Ramirez-Ortiz #define PUF_CMD_OFFSET			0x00
16e4a0a852SJorge Ramirez-Ortiz #define PUF_CFG0_OFFSET			0x04
17e4a0a852SJorge Ramirez-Ortiz #define PUF_CFG1_OFFSET			0x08
18e4a0a852SJorge Ramirez-Ortiz #define PUF_SHUT_OFFSET			0x0C
19e4a0a852SJorge Ramirez-Ortiz #define PUF_STATUS_OFFSET		0x10
20e4a0a852SJorge Ramirez-Ortiz #define PUF_WORD_OFFSET			0x18
21e4a0a852SJorge Ramirez-Ortiz 
22e4a0a852SJorge Ramirez-Ortiz #define PUF_REGENERATION		4
23e4a0a852SJorge Ramirez-Ortiz #define PUF_RESET			6
24e4a0a852SJorge Ramirez-Ortiz 
25e4a0a852SJorge Ramirez-Ortiz #define PUF_CFG0_DEFAULT		0x02
26e4a0a852SJorge Ramirez-Ortiz #define PUF_SHUT_DEFAULT		0x01000100
27*2c952266SNeal Frager #define PUF_REGEN_TIME_MS		6
28e4a0a852SJorge Ramirez-Ortiz 
zynqmp_csu_puf_regenerate(void)29e4a0a852SJorge Ramirez-Ortiz TEE_Result zynqmp_csu_puf_regenerate(void)
30e4a0a852SJorge Ramirez-Ortiz {
31e4a0a852SJorge Ramirez-Ortiz 	vaddr_t puf = core_mmu_get_va(ZYNQMP_CSU_PUF_BASE, MEM_AREA_IO_SEC,
32e4a0a852SJorge Ramirez-Ortiz 				      ZYNQMP_CSU_PUF_SIZE);
33e4a0a852SJorge Ramirez-Ortiz 	vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE);
34e4a0a852SJorge Ramirez-Ortiz 	uint32_t status = 0;
35e4a0a852SJorge Ramirez-Ortiz 
36e4a0a852SJorge Ramirez-Ortiz 	if (!puf || !csu)
37e4a0a852SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
38e4a0a852SJorge Ramirez-Ortiz 
39e4a0a852SJorge Ramirez-Ortiz 	io_write32(puf + PUF_CFG0_OFFSET, PUF_CFG0_DEFAULT);
40e4a0a852SJorge Ramirez-Ortiz 	io_write32(puf + PUF_SHUT_OFFSET, PUF_SHUT_DEFAULT);
41e4a0a852SJorge Ramirez-Ortiz 	io_write32(puf + PUF_CMD_OFFSET, PUF_REGENERATION);
42e4a0a852SJorge Ramirez-Ortiz 	mdelay(PUF_REGEN_TIME_MS);
43e4a0a852SJorge Ramirez-Ortiz 
44e4a0a852SJorge Ramirez-Ortiz 	status = io_read32(csu + ZYNQMP_CSU_ISR_OFFSET);
45e4a0a852SJorge Ramirez-Ortiz 	if (status & ZYNQMP_CSU_ISR_PUF_ACC_ERROR_MASK) {
46e4a0a852SJorge Ramirez-Ortiz 		EMSG("regeneration failed");
47e4a0a852SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
48e4a0a852SJorge Ramirez-Ortiz 	}
49e4a0a852SJorge Ramirez-Ortiz 
50e4a0a852SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
51e4a0a852SJorge Ramirez-Ortiz }
52e4a0a852SJorge Ramirez-Ortiz 
zynqmp_csu_puf_reset(void)53e4a0a852SJorge Ramirez-Ortiz void zynqmp_csu_puf_reset(void)
54e4a0a852SJorge Ramirez-Ortiz {
55e4a0a852SJorge Ramirez-Ortiz 	vaddr_t puf = core_mmu_get_va(ZYNQMP_CSU_PUF_BASE, MEM_AREA_IO_SEC,
56e4a0a852SJorge Ramirez-Ortiz 				      ZYNQMP_CSU_PUF_SIZE);
57e4a0a852SJorge Ramirez-Ortiz 
58e4a0a852SJorge Ramirez-Ortiz 	io_write32(puf + PUF_CMD_OFFSET, PUF_RESET);
59e4a0a852SJorge Ramirez-Ortiz }
601d23b02eSJorge Ramirez-Ortiz 
zynqmp_csu_puf_init(void)611d23b02eSJorge Ramirez-Ortiz static TEE_Result zynqmp_csu_puf_init(void)
621d23b02eSJorge Ramirez-Ortiz {
631d23b02eSJorge Ramirez-Ortiz 	vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE);
641d23b02eSJorge Ramirez-Ortiz 	uint32_t status = 0;
651d23b02eSJorge Ramirez-Ortiz 
661d23b02eSJorge Ramirez-Ortiz 	/* if the bootloader has been authenticated, reserve the PUF */
671d23b02eSJorge Ramirez-Ortiz 	status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET);
681d23b02eSJorge Ramirez-Ortiz 	if (status & ZYNQMP_CSU_STATUS_AUTH)
691d23b02eSJorge Ramirez-Ortiz 		return zynqmp_csu_aes_dt_enable_secure_status();
701d23b02eSJorge Ramirez-Ortiz 
711d23b02eSJorge Ramirez-Ortiz 	return TEE_SUCCESS;
721d23b02eSJorge Ramirez-Ortiz }
731d23b02eSJorge Ramirez-Ortiz 
741d23b02eSJorge Ramirez-Ortiz driver_init(zynqmp_csu_puf_init);
75