1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016, Linaro Limited 4 * All rights reserved. 5 */ 6 7 /* Driver for the internal Random Number Generator of HiSilicon P660/Hi16xx */ 8 9 #include <initcall.h> 10 #include <io.h> 11 #include <kernel/mutex.h> 12 #include <kernel/tee_time.h> 13 #include <mm/core_memprot.h> 14 #include <mm/core_mmu.h> 15 #include <platform_config.h> 16 #include <rng_support.h> 17 #include <trace.h> 18 #include <types_ext.h> 19 #include <util.h> 20 21 /* ALG sub-controller registers */ 22 23 #define ALG_SC_RNG_RESET_DREQ 0xAB4 /* RNG reset cancel */ 24 # define ALG_SC_SRST_DREQ_RNG BIT(0) 25 26 /* RNG registers */ 27 28 #define RNG_SEED 0x0 /* Initial seed */ 29 #define RNG_CTRL 0x4 /* Control register */ 30 # define RNG_SEED_SEL BIT(2) /* Re-seed source: 1: ring osc., 0: LFSR */ 31 # define RNG_RING_EN BIT(1) /* Enable ring oscillator */ 32 # define RNG_EN BIT(0) /* Enable RNG */ 33 #define RNG_NUM 0x10 /* Random number output */ 34 #define RNG_PHY_SEED 0x14 /* Ring oscillator output */ 35 36 register_phys_mem(MEM_AREA_IO_SEC, ALG_SC_BASE, ALG_SC_REG_SIZE); 37 register_phys_mem(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); 38 39 static struct mutex rng_mutex = MUTEX_INITIALIZER; 40 41 static TEE_Result hi16xx_rng_init(void) 42 { 43 vaddr_t alg = (vaddr_t)phys_to_virt(ALG_SC_BASE, MEM_AREA_IO_SEC); 44 vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC); 45 TEE_Time time; 46 47 /* ALG sub-controller must allow RNG out of reset */ 48 write32(ALG_SC_SRST_DREQ_RNG, alg + ALG_SC_RNG_RESET_DREQ); 49 50 /* Set initial seed */ 51 tee_time_get_sys_time(&time); 52 write32(time.seconds * 1000 + time.millis, rng + RNG_SEED); 53 54 /* 55 * Enable RNG and configure it to re-seed automatically from the 56 * internal ring oscillator 57 */ 58 write32(RNG_EN | RNG_RING_EN | RNG_SEED_SEL, rng + RNG_CTRL); 59 60 IMSG("Hi16xx RNG initialized"); 61 return TEE_SUCCESS; 62 } 63 64 uint8_t hw_get_random_byte(void) 65 { 66 static vaddr_t r; 67 static int pos; 68 static union { 69 uint32_t val; 70 uint8_t byte[4]; 71 } random; 72 uint8_t ret; 73 74 mutex_lock(&rng_mutex); 75 76 if (!r) 77 r = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC) + RNG_NUM; 78 79 if (!pos) 80 random.val = read32(r); 81 82 ret = random.byte[pos++]; 83 84 if (pos == 4) 85 pos = 0; 86 87 mutex_unlock(&rng_mutex); 88 89 return ret; 90 } 91 92 driver_init(hi16xx_rng_init); 93