From b8a9277e7ed8643dca7c12dccabedd4fd9523a58 Mon Sep 17 00:00:00 2001 From: Ed Tubbs Date: Fri, 3 Jan 2025 14:13:59 -0600 Subject: [PATCH] plat-rockchip: rk3588: add TRNG support Add TRNG support for Rockchip rk3588 Signed-off-by: Ed Tubbs Acked-by: Etienne Carriere Acked-by: Jens Wiklander --- core/arch/arm/plat-rockchip/platform_config.h | 3 + core/arch/arm/plat-rockchip/platform_rk3588.c | 109 +++++++++++++++++- 2 files changed, 106 insertions(+), 6 deletions(-) diff --git a/core/arch/arm/plat-rockchip/platform_config.h b/core/arch/arm/plat-rockchip/platform_config.h index e6e9b9c8ac4..990c8875e50 100644 --- a/core/arch/arm/plat-rockchip/platform_config.h +++ b/core/arch/arm/plat-rockchip/platform_config.h @@ -112,6 +112,9 @@ #define FIREWALL_DSU_BASE 0xfe010000 #define FIREWALL_DSU_SIZE SIZE_K(32) +#define TRNG_S_BASE 0xfe398000 +#define TRNG_S_SIZE SIZE_K(32) + #else #error "Unknown platform flavor" #endif diff --git a/core/arch/arm/plat-rockchip/platform_rk3588.c b/core/arch/arm/plat-rockchip/platform_rk3588.c index bbeb3f4de20..f876f475404 100644 --- a/core/arch/arm/plat-rockchip/platform_rk3588.c +++ b/core/arch/arm/plat-rockchip/platform_rk3588.c @@ -7,22 +7,50 @@ #include #include #include +#include #include #include #include +#include +#include -#define FIREWALL_DDR_RGN(i) ((i) * 0x4) -#define FIREWALL_DDR_CON 0xf0 -#define FIREWALL_DSU_RGN(i) ((i) * 0x4) -#define FIREWALL_DSU_CON(i) (0xf0 + ((i) * 0x4)) +#define FIREWALL_DDR_RGN(i) ((i) * 0x4) +#define FIREWALL_DDR_CON 0xf0 +#define FIREWALL_DSU_RGN(i) ((i) * 0x4) +#define FIREWALL_DSU_CON(i) (0xf0 + ((i) * 0x4)) -#define RG_MAP_SECURE(top, base) \ +#define RG_MAP_SECURE(top, base) \ (((((top) - 1) & 0x7fff) << 16) | ((base) & 0x7fff)) -#define DDR_CHN_CNT 4 +#define DDR_CHN_CNT 4 + +#define TRNG_S_CTRL 0x0000 +#define TRNG_S_STAT 0x0004 +#define TRNG_S_MODE 0x0008 +#define TRNG_S_IE 0x0010 +#define TRNG_S_ISTAT 0x0014 +#define TRNG_S_RAND 0x0020 +#define TRNG_S_AUTO_RQSTS 0x0060 + +#define CMD_NOP 0 +#define CMD_RAND 1 +#define CMD_SEED 2 + +#define LEN_128BIT 0 +#define LEN_256BIT 3 + +#define TRNG_S_SEEDED_BIT BIT32(9) +#define TRNG_S_SEED_DONE_BIT BIT32(1) +#define TRNG_S_RAND_RDY_BIT BIT32(0) + +#define TRNG_POLL_PERIOD_US 0 +#define TRNG_POLL_TIMEOUT_US 1000 register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE); register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DSU_BASE, FIREWALL_DSU_SIZE); +register_phys_mem_pgdir(MEM_AREA_IO_SEC, TRNG_S_BASE, TRNG_S_SIZE); + +static struct mutex trng_mutex = MUTEX_INITIALIZER; int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz) { @@ -63,3 +91,72 @@ int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz) return 0; } + +TEE_Result hw_get_random_bytes(void *buf, size_t blen) +{ + vaddr_t trng_s_base = (vaddr_t)phys_to_virt_io(TRNG_S_BASE, + TRNG_S_SIZE); + size_t remaining = blen; + size_t copy_len = 0; + uint32_t val = 0; + uint32_t rnd = 0; + + mutex_lock(&trng_mutex); + + if (!trng_s_base) + panic("TRNG_S base not mapped"); + + /* Ensure TRNG is seeded and ready */ + val = io_read32(trng_s_base + TRNG_S_STAT); + if (!(val & TRNG_S_SEEDED_BIT)) { + /* TRNG not seeded, issue SEED command */ + io_write32(trng_s_base + TRNG_S_CTRL, CMD_SEED); + + /* Wait for SEED_DONE flag with timeout */ + if (IO_READ32_POLL_TIMEOUT(trng_s_base + TRNG_S_ISTAT, val, + val & TRNG_S_SEED_DONE_BIT, + TRNG_POLL_PERIOD_US, + TRNG_POLL_TIMEOUT_US)) { + mutex_unlock(&trng_mutex); + return TEE_ERROR_BUSY; + } + + /* SEED_DONE flag set, clear SEED_DONE */ + io_write32(trng_s_base + TRNG_S_ISTAT, TRNG_S_SEED_DONE_BIT); + } + + /* Set RNG length to 256 bits */ + io_write32(trng_s_base + TRNG_S_MODE, LEN_256BIT); + + while (remaining > 0) { + /* Set RAND command to generate random numbers */ + io_write32(trng_s_base + TRNG_S_CTRL, CMD_RAND); + + /* Wait for RAND_RDY flag with timeout */ + if (IO_READ32_POLL_TIMEOUT(trng_s_base + TRNG_S_ISTAT, val, + val & TRNG_S_RAND_RDY_BIT, + TRNG_POLL_PERIOD_US, + TRNG_POLL_TIMEOUT_US)) { + mutex_unlock(&trng_mutex); + return TEE_ERROR_BUSY; + } + + /* Read random data from RAND register */ + rnd = io_read32(trng_s_base + TRNG_S_RAND); + + /* Copy as many bytes as required */ + copy_len = MIN(remaining, sizeof(uint32_t)); + memcpy((uint8_t *)buf + (blen - remaining), &rnd, copy_len); + remaining -= copy_len; + + /* Clear RAND_RDY flag */ + io_write32(trng_s_base + TRNG_S_ISTAT, TRNG_S_RAND_RDY_BIT); + } + + /* Reset RNG mode to NOP */ + io_write32(trng_s_base + TRNG_S_CTRL, CMD_NOP); + + mutex_unlock(&trng_mutex); + + return TEE_SUCCESS; +}