blob: f51443b96377157f714a1d15e25311a367edbedc [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright 2021 Foundries.io Ltd.
*
* Jorge Ramirez-Ortiz <jorge@foundries.io>
*/
#include <drivers/zynqmp_csu.h>
#include <drivers/zynqmp_csu_aes.h>
#include <drivers/zynqmp_csu_puf.h>
#include <initcall.h>
#include <io.h>
#include <kernel/delay.h>
#include <mm/core_memprot.h>
#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);