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