1 /* 2 * Copyright (c) 2022-2025, STMicroelectronics - All Rights Reserved 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <stdbool.h> 10 11 #include <arch_helpers.h> 12 #include <common/fdt_wrappers.h> 13 #include <drivers/clk.h> 14 #include <drivers/delay_timer.h> 15 #include <drivers/st/stm32_rng.h> 16 #include <drivers/st/stm32mp_reset.h> 17 #include <lib/mmio.h> 18 #include <libfdt.h> 19 20 #include <platform_def.h> 21 22 #if STM32_RNG_VER == 2 23 #define DT_RNG_COMPAT "st,stm32-rng" 24 #endif 25 #if STM32_RNG_VER == 4 26 #define DT_RNG_COMPAT "st,stm32mp13-rng" 27 #endif 28 #define RNG_CR 0x00U 29 #define RNG_SR 0x04U 30 #define RNG_DR 0x08U 31 32 #define RNG_CR_RNGEN BIT(2) 33 #define RNG_CR_IE BIT(3) 34 #define RNG_CR_CED BIT(5) 35 #define RNG_CR_CLKDIV GENMASK(19, 16) 36 #define RNG_CR_CLKDIV_SHIFT 16U 37 #define RNG_CR_CONDRST BIT(30) 38 39 #define RNG_SR_DRDY BIT(0) 40 #define RNG_SR_CECS BIT(1) 41 #define RNG_SR_SECS BIT(2) 42 #define RNG_SR_CEIS BIT(5) 43 #define RNG_SR_SEIS BIT(6) 44 45 #define RNG_TIMEOUT_US 100000U 46 #define RNG_TIMEOUT_STEP_US 10U 47 48 #define TIMEOUT_US_1MS 1000U 49 50 #define RNG_NIST_CONFIG_A 0x00F40F00U 51 #define RNG_NIST_CONFIG_B 0x01801000U 52 #define RNG_NIST_CONFIG_C 0x00F00D00U 53 #define RNG_NIST_CONFIG_MASK GENMASK(25, 8) 54 55 #define RNG_MAX_NOISE_CLK_FREQ 48000000U 56 57 struct stm32_rng_instance { 58 uintptr_t base; 59 unsigned long clock; 60 }; 61 62 static struct stm32_rng_instance stm32_rng; 63 64 static void seed_error_recovery(void) 65 { 66 uint8_t i __maybe_unused; 67 68 /* Recommended by the SoC reference manual */ 69 mmio_clrbits_32(stm32_rng.base + RNG_SR, RNG_SR_SEIS); 70 dmbsy(); 71 72 #if STM32_RNG_VER == 2 73 /* No Auto-reset on version 2, need to clean FIFO */ 74 for (i = 12U; i != 0U; i--) { 75 (void)mmio_read_32(stm32_rng.base + RNG_DR); 76 } 77 78 dmbsy(); 79 #endif 80 81 if ((mmio_read_32(stm32_rng.base + RNG_SR) & RNG_SR_SEIS) != 0U) { 82 ERROR("RNG noise\n"); 83 panic(); 84 } 85 } 86 87 static uint32_t stm32_rng_clock_freq_restrain(void) 88 { 89 unsigned long clock_rate; 90 uint32_t clock_div = 0U; 91 92 clock_rate = clk_get_rate(stm32_rng.clock); 93 94 /* 95 * Get the exponent to apply on the CLKDIV field in RNG_CR register 96 * No need to handle the case when clock-div > 0xF as it is physically 97 * impossible 98 */ 99 while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ) { 100 clock_div++; 101 } 102 103 VERBOSE("RNG clk rate : %lu\n", clk_get_rate(stm32_rng.clock) >> clock_div); 104 105 return clock_div; 106 } 107 108 static int stm32_rng_enable(void) 109 { 110 uint32_t sr; 111 uint64_t timeout; 112 uint32_t clock_div __maybe_unused; 113 114 #if STM32_RNG_VER == 2 115 mmio_write_32(stm32_rng.base + RNG_CR, RNG_CR_RNGEN | RNG_CR_CED); 116 #endif 117 #if STM32_RNG_VER == 4 118 /* Reset internal block and disable CED bit */ 119 clock_div = stm32_rng_clock_freq_restrain(); 120 121 /* Update configuration fields */ 122 mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_NIST_CONFIG_MASK, 123 RNG_NIST_CONFIG_A | RNG_CR_CONDRST | RNG_CR_CED); 124 125 mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CLKDIV, 126 (clock_div << RNG_CR_CLKDIV_SHIFT)); 127 128 mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN); 129 #endif 130 timeout = timeout_init_us(RNG_TIMEOUT_US); 131 sr = mmio_read_32(stm32_rng.base + RNG_SR); 132 while ((sr & RNG_SR_DRDY) == 0U) { 133 if (timeout_elapsed(timeout)) { 134 WARN("Timeout waiting\n"); 135 return -ETIMEDOUT; 136 } 137 138 if ((sr & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) { 139 seed_error_recovery(); 140 timeout = timeout_init_us(RNG_TIMEOUT_US); 141 } 142 143 udelay(RNG_TIMEOUT_STEP_US); 144 sr = mmio_read_32(stm32_rng.base + RNG_SR); 145 } 146 147 VERBOSE("Init RNG done\n"); 148 149 return 0; 150 } 151 152 static int check_data_validity(void) 153 { 154 int nb_tries = RNG_TIMEOUT_US / RNG_TIMEOUT_STEP_US; 155 uint32_t status = mmio_read_32(stm32_rng.base + RNG_SR); 156 157 /* Exit if data is ready without any seed error */ 158 if ((status & (RNG_SR_SECS | RNG_SR_SEIS | RNG_SR_DRDY)) != RNG_SR_DRDY) { 159 do { 160 161 if ((status & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) { 162 seed_error_recovery(); 163 } 164 165 udelay(RNG_TIMEOUT_STEP_US); 166 nb_tries--; 167 if (nb_tries == 0) { 168 return -ETIMEDOUT; 169 } 170 171 status = mmio_read_32(stm32_rng.base + RNG_SR); 172 } while ((status & RNG_SR_DRDY) == 0U); 173 } 174 175 return 0; 176 } 177 178 /* 179 * stm32_rng_read - Read a number of random bytes from RNG 180 * out: pointer to the output buffer 181 * size: number of bytes to be read 182 * Return 0 on success, non-0 on failure 183 */ 184 int stm32_rng_read(uint8_t *out, uint32_t size) 185 { 186 uint8_t *buf = out; 187 size_t len = size; 188 uint32_t data32; 189 int rc = 0; 190 unsigned int count; 191 192 if (stm32_rng.base == 0U) { 193 return -EPERM; 194 } 195 196 while (len != 0U) { 197 rc = check_data_validity(); 198 if (rc != 0) { 199 goto bail; 200 } 201 202 count = 4U; 203 while (len != 0U) { 204 if ((mmio_read_32(stm32_rng.base + RNG_SR) & RNG_SR_DRDY) == 0U) { 205 break; 206 } 207 208 data32 = mmio_read_32(stm32_rng.base + RNG_DR); 209 210 while (data32 == 0U) { 211 rc = check_data_validity(); 212 if (rc != 0) { 213 goto bail; 214 } 215 216 data32 = mmio_read_32(stm32_rng.base + RNG_DR); 217 } 218 219 count--; 220 221 (void)memcpy(buf, (uint8_t *)&data32, MIN(len, sizeof(uint32_t))); 222 buf += MIN(len, sizeof(uint32_t)); 223 len -= MIN(len, sizeof(uint32_t)); 224 225 if (count == 0U) { 226 break; 227 } 228 } 229 } 230 231 bail: 232 if (rc != 0) { 233 (void)memset(out, 0, buf - out); 234 } 235 236 return rc; 237 } 238 239 /* 240 * stm32_rng_select: Select a specified RNG instance from its base address. 241 * This function only works if the driver is uninitialized. 242 */ 243 void stm32_rng_select(uintptr_t rng_base) 244 { 245 if ((stm32_rng.base == 0U) || (stm32_rng.clock == 0U)) { 246 /* RNG instance is selected once */ 247 stm32_rng.base = rng_base; 248 } 249 } 250 251 /* 252 * stm32_rng_init: Initialize rng from DT 253 * return 0 on success, negative value on failure 254 */ 255 int stm32_rng_init(void) 256 { 257 struct stm32_rng_instance rng = {0, 0}; 258 void *fdt; 259 int node; 260 int success = 0; 261 int disabled = 0; 262 263 if (stm32_rng.base != 0U) { 264 if (stm32_rng.clock != 0U) { 265 /* Driver is already initialized */ 266 return 0; 267 } 268 269 rng.base = stm32_rng.base; 270 } 271 272 if (fdt_get_address(&fdt) == 0) { 273 panic(); 274 } 275 276 fdt_for_each_compatible_node(fdt, node, DT_RNG_COMPAT) { 277 struct dt_node_info dt_rng; 278 int ret; 279 280 dt_fill_device_info(&dt_rng, node); 281 282 VERBOSE("Setting up rng@%x, status: %x\n", dt_rng.base, dt_rng.status); 283 284 /* 285 * All the valid RNG peripherals available in device tree are 286 * activated but only the last RNG found is assigned to the RNG 287 * instance of the driver. 288 */ 289 if ((dt_rng.status == DT_DISABLED) || (dt_rng.base == 0U)) { 290 disabled++; 291 continue; 292 } 293 294 stm32_rng.base = dt_rng.base; 295 296 if (dt_rng.clock < 0) { 297 panic(); 298 } 299 300 stm32_rng.clock = (unsigned long)dt_rng.clock; 301 clk_enable(stm32_rng.clock); 302 303 if (stm32_rng.base == rng.base) { 304 /* Set the rng instance as the rng to use by TF-A */ 305 rng.clock = stm32_rng.clock; 306 } 307 308 if (dt_rng.reset >= 0) { 309 310 ret = stm32mp_reset_assert((unsigned long)dt_rng.reset, TIMEOUT_US_1MS); 311 if (ret != 0) { 312 panic(); 313 } 314 315 udelay(20); 316 317 ret = stm32mp_reset_deassert((unsigned long)dt_rng.reset, TIMEOUT_US_1MS); 318 if (ret != 0) { 319 panic(); 320 } 321 } 322 323 ret = stm32_rng_enable(); 324 if (ret != 0) { 325 ERROR("Failed to enable rng@%x\n", dt_rng.base); 326 } else { 327 success++; 328 } 329 } 330 331 if ((success == 0) && (disabled > 0)) { 332 WARN("%s: No RNG found in device tree.\n", __func__); 333 return 0; 334 } else if (success > 0) { 335 if ((rng.clock != 0U) && (rng.base != 0U)) { 336 stm32_rng = rng; 337 } 338 return 0; 339 } else { 340 return -ENODEV; 341 } 342 } 343