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