11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 23de7021fSJerome Forissier /* 33de7021fSJerome Forissier * Copyright (c) 2016, Linaro Limited 43de7021fSJerome Forissier */ 53de7021fSJerome Forissier 63de7021fSJerome Forissier /* Driver for the internal Random Number Generator of HiSilicon P660/Hi16xx */ 73de7021fSJerome Forissier 83de7021fSJerome Forissier #include <initcall.h> 93de7021fSJerome Forissier #include <io.h> 106c9c7a3fSJerome Forissier #include <kernel/spinlock.h> 113de7021fSJerome Forissier #include <kernel/tee_time.h> 123de7021fSJerome Forissier #include <mm/core_memprot.h> 133de7021fSJerome Forissier #include <mm/core_mmu.h> 143de7021fSJerome Forissier #include <platform_config.h> 153de7021fSJerome Forissier #include <rng_support.h> 163de7021fSJerome Forissier #include <trace.h> 173de7021fSJerome Forissier #include <types_ext.h> 183de7021fSJerome Forissier #include <util.h> 193de7021fSJerome Forissier 203de7021fSJerome Forissier /* ALG sub-controller registers */ 213de7021fSJerome Forissier 223de7021fSJerome Forissier #define ALG_SC_RNG_RESET_DREQ 0xAB4 /* RNG reset cancel */ 233de7021fSJerome Forissier # define ALG_SC_SRST_DREQ_RNG BIT(0) 243de7021fSJerome Forissier 253de7021fSJerome Forissier /* RNG registers */ 263de7021fSJerome Forissier 273de7021fSJerome Forissier #define RNG_SEED 0x0 /* Initial seed */ 283de7021fSJerome Forissier #define RNG_CTRL 0x4 /* Control register */ 293de7021fSJerome Forissier # define RNG_SEED_SEL BIT(2) /* Re-seed source: 1: ring osc., 0: LFSR */ 303de7021fSJerome Forissier # define RNG_RING_EN BIT(1) /* Enable ring oscillator */ 313de7021fSJerome Forissier # define RNG_EN BIT(0) /* Enable RNG */ 323de7021fSJerome Forissier #define RNG_NUM 0x10 /* Random number output */ 333de7021fSJerome Forissier #define RNG_PHY_SEED 0x14 /* Ring oscillator output */ 343de7021fSJerome Forissier 35a5e82dc7SJerome Forissier register_phys_mem_pgdir(MEM_AREA_IO_SEC, ALG_SC_BASE, ALG_SC_REG_SIZE); 36a5e82dc7SJerome Forissier register_phys_mem_pgdir(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); 373de7021fSJerome Forissier 386c9c7a3fSJerome Forissier static unsigned int rng_lock = SPINLOCK_UNLOCK; 393de7021fSJerome Forissier 403de7021fSJerome Forissier static TEE_Result hi16xx_rng_init(void) 413de7021fSJerome Forissier { 42*c2e4eb43SAnton Rybakov vaddr_t alg = (vaddr_t)phys_to_virt(ALG_SC_BASE, MEM_AREA_IO_SEC, 43*c2e4eb43SAnton Rybakov ALG_SC_REG_SIZE); 44*c2e4eb43SAnton Rybakov vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, 45*c2e4eb43SAnton Rybakov RNG_REG_SIZE); 463de7021fSJerome Forissier TEE_Time time; 473de7021fSJerome Forissier 483de7021fSJerome Forissier /* ALG sub-controller must allow RNG out of reset */ 49918bb3a5SEtienne Carriere io_write32(alg + ALG_SC_RNG_RESET_DREQ, ALG_SC_SRST_DREQ_RNG); 503de7021fSJerome Forissier 513de7021fSJerome Forissier /* Set initial seed */ 523de7021fSJerome Forissier tee_time_get_sys_time(&time); 53918bb3a5SEtienne Carriere io_write32(rng + RNG_SEED, time.seconds * 1000 + time.millis); 543de7021fSJerome Forissier 553de7021fSJerome Forissier /* 563de7021fSJerome Forissier * Enable RNG and configure it to re-seed automatically from the 573de7021fSJerome Forissier * internal ring oscillator 583de7021fSJerome Forissier */ 59918bb3a5SEtienne Carriere io_write32(rng + RNG_CTRL, RNG_EN | RNG_RING_EN | RNG_SEED_SEL); 603de7021fSJerome Forissier 613de7021fSJerome Forissier IMSG("Hi16xx RNG initialized"); 623de7021fSJerome Forissier return TEE_SUCCESS; 633de7021fSJerome Forissier } 643de7021fSJerome Forissier 653de7021fSJerome Forissier uint8_t hw_get_random_byte(void) 663de7021fSJerome Forissier { 673de7021fSJerome Forissier static vaddr_t r; 683de7021fSJerome Forissier static int pos; 693de7021fSJerome Forissier static union { 703de7021fSJerome Forissier uint32_t val; 713de7021fSJerome Forissier uint8_t byte[4]; 723de7021fSJerome Forissier } random; 733de7021fSJerome Forissier uint8_t ret; 746c9c7a3fSJerome Forissier uint32_t exceptions; 753de7021fSJerome Forissier 766c9c7a3fSJerome Forissier exceptions = cpu_spin_lock_xsave(&rng_lock); 773de7021fSJerome Forissier 783de7021fSJerome Forissier if (!r) 79*c2e4eb43SAnton Rybakov r = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, 1) + 80*c2e4eb43SAnton Rybakov RNG_NUM; 813de7021fSJerome Forissier 823de7021fSJerome Forissier if (!pos) 83918bb3a5SEtienne Carriere random.val = io_read32(r); 843de7021fSJerome Forissier 853de7021fSJerome Forissier ret = random.byte[pos++]; 863de7021fSJerome Forissier 873de7021fSJerome Forissier if (pos == 4) 883de7021fSJerome Forissier pos = 0; 893de7021fSJerome Forissier 906c9c7a3fSJerome Forissier cpu_spin_unlock_xrestore(&rng_lock, exceptions); 913de7021fSJerome Forissier 923de7021fSJerome Forissier return ret; 933de7021fSJerome Forissier } 943de7021fSJerome Forissier 953de7021fSJerome Forissier driver_init(hi16xx_rng_init); 96