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