1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016, Linaro Limited 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* Driver for the internal Random Number Generator of HiSilicon P660/Hi16xx */ 30 31 #include <initcall.h> 32 #include <io.h> 33 #include <kernel/mutex.h> 34 #include <kernel/tee_time.h> 35 #include <mm/core_memprot.h> 36 #include <mm/core_mmu.h> 37 #include <platform_config.h> 38 #include <rng_support.h> 39 #include <trace.h> 40 #include <types_ext.h> 41 #include <util.h> 42 43 /* ALG sub-controller registers */ 44 45 #define ALG_SC_RNG_RESET_DREQ 0xAB4 /* RNG reset cancel */ 46 # define ALG_SC_SRST_DREQ_RNG BIT(0) 47 48 /* RNG registers */ 49 50 #define RNG_SEED 0x0 /* Initial seed */ 51 #define RNG_CTRL 0x4 /* Control register */ 52 # define RNG_SEED_SEL BIT(2) /* Re-seed source: 1: ring osc., 0: LFSR */ 53 # define RNG_RING_EN BIT(1) /* Enable ring oscillator */ 54 # define RNG_EN BIT(0) /* Enable RNG */ 55 #define RNG_NUM 0x10 /* Random number output */ 56 #define RNG_PHY_SEED 0x14 /* Ring oscillator output */ 57 58 register_phys_mem(MEM_AREA_IO_SEC, ALG_SC_BASE, ALG_SC_REG_SIZE); 59 register_phys_mem(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); 60 61 static struct mutex rng_mutex = MUTEX_INITIALIZER; 62 63 static TEE_Result hi16xx_rng_init(void) 64 { 65 vaddr_t alg = (vaddr_t)phys_to_virt(ALG_SC_BASE, MEM_AREA_IO_SEC); 66 vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC); 67 TEE_Time time; 68 69 /* ALG sub-controller must allow RNG out of reset */ 70 write32(ALG_SC_SRST_DREQ_RNG, alg + ALG_SC_RNG_RESET_DREQ); 71 72 /* Set initial seed */ 73 tee_time_get_sys_time(&time); 74 write32(time.seconds * 1000 + time.millis, rng + RNG_SEED); 75 76 /* 77 * Enable RNG and configure it to re-seed automatically from the 78 * internal ring oscillator 79 */ 80 write32(RNG_EN | RNG_RING_EN | RNG_SEED_SEL, rng + RNG_CTRL); 81 82 IMSG("Hi16xx RNG initialized"); 83 return TEE_SUCCESS; 84 } 85 86 uint8_t hw_get_random_byte(void) 87 { 88 static vaddr_t r; 89 static int pos; 90 static union { 91 uint32_t val; 92 uint8_t byte[4]; 93 } random; 94 uint8_t ret; 95 96 mutex_lock(&rng_mutex); 97 98 if (!r) 99 r = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC) + RNG_NUM; 100 101 if (!pos) 102 random.val = read32(r); 103 104 ret = random.byte[pos++]; 105 106 if (pos == 4) 107 pos = 0; 108 109 mutex_unlock(&rng_mutex); 110 111 return ret; 112 } 113 114 driver_init(hi16xx_rng_init); 115