// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2021 Foundries.io Ltd. * * Jorge Ramirez-Ortiz */ #include #include #include #include #include #include #include #define PUF_CMD_OFFSET 0x00 #define PUF_CFG0_OFFSET 0x04 #define PUF_CFG1_OFFSET 0x08 #define PUF_SHUT_OFFSET 0x0C #define PUF_STATUS_OFFSET 0x10 #define PUF_WORD_OFFSET 0x18 #define PUF_REGENERATION 4 #define PUF_RESET 6 #define PUF_CFG0_DEFAULT 0x02 #define PUF_SHUT_DEFAULT 0x01000100 #define PUF_REGEN_TIME_MS 3 TEE_Result zynqmp_csu_puf_regenerate(void) { vaddr_t puf = core_mmu_get_va(ZYNQMP_CSU_PUF_BASE, MEM_AREA_IO_SEC, ZYNQMP_CSU_PUF_SIZE); vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); uint32_t status = 0; if (!puf || !csu) return TEE_ERROR_GENERIC; io_write32(puf + PUF_CFG0_OFFSET, PUF_CFG0_DEFAULT); io_write32(puf + PUF_SHUT_OFFSET, PUF_SHUT_DEFAULT); io_write32(puf + PUF_CMD_OFFSET, PUF_REGENERATION); mdelay(PUF_REGEN_TIME_MS); status = io_read32(csu + ZYNQMP_CSU_ISR_OFFSET); if (status & ZYNQMP_CSU_ISR_PUF_ACC_ERROR_MASK) { EMSG("regeneration failed"); return TEE_ERROR_GENERIC; } return TEE_SUCCESS; } void zynqmp_csu_puf_reset(void) { vaddr_t puf = core_mmu_get_va(ZYNQMP_CSU_PUF_BASE, MEM_AREA_IO_SEC, ZYNQMP_CSU_PUF_SIZE); io_write32(puf + PUF_CMD_OFFSET, PUF_RESET); } static TEE_Result zynqmp_csu_puf_init(void) { vaddr_t csu = core_mmu_get_va(CSU_BASE, MEM_AREA_IO_SEC, CSU_SIZE); uint32_t status = 0; /* if the bootloader has been authenticated, reserve the PUF */ status = io_read32(csu + ZYNQMP_CSU_STATUS_OFFSET); if (status & ZYNQMP_CSU_STATUS_AUTH) return zynqmp_csu_aes_dt_enable_secure_status(); return TEE_SUCCESS; } driver_init(zynqmp_csu_puf_init);