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