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
dra7_rng_read64(uint32_t * low_word,uint32_t * high_word)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
hw_get_random_bytes(void * buf,size_t len)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
dra7_rng_init(void)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