1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016, Linaro Limited 4 * All rights reserved. 5 */ 6 7 #include <initcall.h> 8 #include <io.h> 9 #include <keep.h> 10 #include <kernel/interrupt.h> 11 #include <kernel/misc.h> 12 #include <kernel/spinlock.h> 13 #include <mm/core_memprot.h> 14 #include <mm/core_mmu.h> 15 #include <platform_config.h> 16 #include <rng_support.h> 17 18 #define RNG_OUTPUT_L 0x0000 19 #define RNG_OUTPUT_H 0x0004 20 #define RNG_STATUS 0x0008 21 # define RNG_READY BIT(0) 22 # define SHUTDOWN_OFLO BIT(1) 23 #define RNG_INTMASK 0x000C 24 #define RNG_INTACK 0x0010 25 #define RNG_CONTROL 0x0014 26 # define ENABLE_TRNG BIT(10) 27 #define RNG_CONFIG 0x0018 28 #define RNG_ALARMCNT 0x001C 29 #define RNG_FROENABLE 0x0020 30 #define RNG_FRODETUNE 0x0024 31 #define RNG_ALARMMASK 0x0028 32 #define RNG_ALARMSTOP 0x002C 33 #define RNG_LFSR_L 0x0030 34 #define RNG_LFSR_M 0x0034 35 #define RNG_LFSR_H 0x0038 36 #define RNG_COUNT 0x003C 37 #define RNG_OPTIONS 0x0078 38 #define RNG_EIP_REV 0x007C 39 #define RNG_MMR_STATUS_EN 0x1FD8 40 #define RNG_REV 0x1FE0 41 #define RNG_SYS_CONFIG_REG 0x1FE4 42 # define RNG_AUTOIDLE BIT(0) 43 #define RNG_MMR_STATUS_SET 0x1FEC 44 #define RNG_SOFT_RESET_REG 0x1FF0 45 # define RNG_SOFT_RESET BIT(0) 46 #define RNG_IRQ_EOI_REG 0x1FF4 47 #define RNG_IRQSTATUS 0x1FF8 48 49 #define RNG_CONTROL_STARTUP_CYCLES_SHIFT 16 50 #define RNG_CONTROL_STARTUP_CYCLES_MASK GENMASK_32(31, 16) 51 52 #define RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT 16 53 #define RNG_CONFIG_MAX_REFIL_CYCLES_MASK GENMASK_32(31, 16) 54 #define RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT 0 55 #define RNG_CONFIG_MIN_REFIL_CYCLES_MASK GENMASK_32(7, 0) 56 57 #define RNG_ALARMCNT_ALARM_TH_SHIFT 0 58 #define RNG_ALARMCNT_ALARM_TH_MASK GENMASK_32(7, 0) 59 #define RNG_ALARMCNT_SHUTDOWN_TH_SHIFT 16 60 #define RNG_ALARMCNT_SHUTDOWN_TH_MASK GENMASK_32(20, 16) 61 62 #define RNG_CONTROL_STARTUP_CYCLES 0xff 63 #define RNG_CONFIG_MIN_REFIL_CYCLES 0x21 64 #define RNG_CONFIG_MAX_REFIL_CYCLES 0x22 65 #define RNG_ALARM_THRESHOLD 0xff 66 #define RNG_SHUTDOWN_THRESHOLD 0x4 67 68 #define RNG_FRO_MASK GENMASK_32(23, 0) 69 70 #define RNG_REG_SIZE 0x2000 71 72 register_phys_mem(MEM_AREA_IO_SEC, RNG_BASE, RNG_REG_SIZE); 73 74 static unsigned int rng_lock = SPINLOCK_UNLOCK; 75 76 uint8_t hw_get_random_byte(void) 77 { 78 static int pos; 79 static union { 80 uint32_t val[2]; 81 uint8_t byte[8]; 82 } random; 83 vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC); 84 uint8_t ret; 85 86 uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL); 87 cpu_spin_lock(&rng_lock); 88 89 if (!pos) { 90 /* Is the result ready (available)? */ 91 while (!(read32(rng + RNG_STATUS) & RNG_READY)) { 92 /* Is the shutdown threshold reached? */ 93 if (read32(rng + RNG_STATUS) & SHUTDOWN_OFLO) { 94 uint32_t alarm = read32(rng + RNG_ALARMSTOP); 95 uint32_t tuning = read32(rng + RNG_FRODETUNE); 96 /* Clear the alarm events */ 97 write32(0x0, rng + RNG_ALARMMASK); 98 write32(0x0, rng + RNG_ALARMSTOP); 99 /* De-tune offending FROs */ 100 write32(tuning ^ alarm, rng + RNG_FRODETUNE); 101 /* Re-enable the shut down FROs */ 102 write32(RNG_FRO_MASK, rng + RNG_FROENABLE); 103 /* Clear the shutdown overflow event */ 104 write32(SHUTDOWN_OFLO, rng + RNG_INTACK); 105 106 DMSG("Fixed FRO shutdown\n"); 107 } 108 } 109 /* Read random value */ 110 random.val[0] = read32(rng + RNG_OUTPUT_L); 111 random.val[1] = read32(rng + RNG_OUTPUT_H); 112 /* Acknowledge read complete */ 113 write32(RNG_READY, rng + RNG_INTACK); 114 } 115 116 ret = random.byte[pos]; 117 118 pos = (pos + 1) % 8; 119 120 cpu_spin_unlock(&rng_lock); 121 thread_set_exceptions(exceptions); 122 123 return ret; 124 } 125 126 static TEE_Result dra7_rng_init(void) 127 { 128 vaddr_t rng = (vaddr_t)phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC); 129 uint32_t val; 130 131 /* Execute a software reset */ 132 write32(RNG_SOFT_RESET, rng + RNG_SOFT_RESET_REG); 133 134 /* Wait for the software reset completion by polling */ 135 while (read32(rng + RNG_SOFT_RESET_REG) & RNG_SOFT_RESET) 136 ; 137 138 /* Switch to low-power operating mode */ 139 write32(RNG_AUTOIDLE, rng + RNG_SYS_CONFIG_REG); 140 141 /* 142 * Select the number of clock input cycles to the 143 * FROs between two samples 144 */ 145 val = 0; 146 147 /* Ensure initial latency */ 148 val |= RNG_CONFIG_MIN_REFIL_CYCLES << 149 RNG_CONFIG_MIN_REFIL_CYCLES_SHIFT; 150 val |= RNG_CONFIG_MAX_REFIL_CYCLES << 151 RNG_CONFIG_MAX_REFIL_CYCLES_SHIFT; 152 write32(val, rng + RNG_CONFIG); 153 154 /* Configure the desired FROs */ 155 write32(0x0, rng + RNG_FRODETUNE); 156 157 /* Enable all FROs */ 158 write32(0xffffff, rng + RNG_FROENABLE); 159 160 /* 161 * Select the maximum number of samples after 162 * which if a repeating pattern is still detected, an 163 * alarm event is generated 164 */ 165 val = RNG_ALARM_THRESHOLD << RNG_ALARMCNT_ALARM_TH_SHIFT; 166 167 /* 168 * Set the shutdown threshold to the number of FROs 169 * allowed to be shut downed 170 */ 171 val |= RNG_SHUTDOWN_THRESHOLD << RNG_ALARMCNT_SHUTDOWN_TH_SHIFT; 172 write32(val, rng + RNG_ALARMCNT); 173 174 /* Enable the RNG module */ 175 val = RNG_CONTROL_STARTUP_CYCLES << RNG_CONTROL_STARTUP_CYCLES_SHIFT; 176 val |= ENABLE_TRNG; 177 write32(val, rng + RNG_CONTROL); 178 179 IMSG("DRA7x TRNG initialized"); 180 181 return TEE_SUCCESS; 182 } 183 driver_init(dra7_rng_init); 184