stm32_rng.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * Copyright (c) 2022, STMicroelectronics - All Rights Reserved
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <stdbool.h>
  9. #include <arch_helpers.h>
  10. #include <drivers/clk.h>
  11. #include <drivers/delay_timer.h>
  12. #include <drivers/st/stm32_rng.h>
  13. #include <drivers/st/stm32mp_reset.h>
  14. #include <lib/mmio.h>
  15. #include <libfdt.h>
  16. #include <platform_def.h>
  17. #if STM32_RNG_VER == 2
  18. #define DT_RNG_COMPAT "st,stm32-rng"
  19. #endif
  20. #if STM32_RNG_VER == 4
  21. #define DT_RNG_COMPAT "st,stm32mp13-rng"
  22. #endif
  23. #define RNG_CR 0x00U
  24. #define RNG_SR 0x04U
  25. #define RNG_DR 0x08U
  26. #define RNG_CR_RNGEN BIT(2)
  27. #define RNG_CR_IE BIT(3)
  28. #define RNG_CR_CED BIT(5)
  29. #define RNG_CR_CLKDIV GENMASK(19, 16)
  30. #define RNG_CR_CLKDIV_SHIFT 16U
  31. #define RNG_CR_CONDRST BIT(30)
  32. #define RNG_SR_DRDY BIT(0)
  33. #define RNG_SR_CECS BIT(1)
  34. #define RNG_SR_SECS BIT(2)
  35. #define RNG_SR_CEIS BIT(5)
  36. #define RNG_SR_SEIS BIT(6)
  37. #define RNG_TIMEOUT_US 100000U
  38. #define RNG_TIMEOUT_STEP_US 10U
  39. #define TIMEOUT_US_1MS 1000U
  40. #define RNG_NIST_CONFIG_A 0x00F40F00U
  41. #define RNG_NIST_CONFIG_B 0x01801000U
  42. #define RNG_NIST_CONFIG_C 0x00F00D00U
  43. #define RNG_NIST_CONFIG_MASK GENMASK(25, 8)
  44. #define RNG_MAX_NOISE_CLK_FREQ 48000000U
  45. struct stm32_rng_instance {
  46. uintptr_t base;
  47. unsigned long clock;
  48. };
  49. static struct stm32_rng_instance stm32_rng;
  50. static void seed_error_recovery(void)
  51. {
  52. uint8_t i __maybe_unused;
  53. /* Recommended by the SoC reference manual */
  54. mmio_clrbits_32(stm32_rng.base + RNG_SR, RNG_SR_SEIS);
  55. dmbsy();
  56. #if STM32_RNG_VER == 2
  57. /* No Auto-reset on version 2, need to clean FIFO */
  58. for (i = 12U; i != 0U; i--) {
  59. (void)mmio_read_32(stm32_rng.base + RNG_DR);
  60. }
  61. dmbsy();
  62. #endif
  63. if ((mmio_read_32(stm32_rng.base + RNG_SR) & RNG_SR_SEIS) != 0U) {
  64. ERROR("RNG noise\n");
  65. panic();
  66. }
  67. }
  68. static uint32_t stm32_rng_clock_freq_restrain(void)
  69. {
  70. unsigned long clock_rate;
  71. uint32_t clock_div = 0U;
  72. clock_rate = clk_get_rate(stm32_rng.clock);
  73. /*
  74. * Get the exponent to apply on the CLKDIV field in RNG_CR register
  75. * No need to handle the case when clock-div > 0xF as it is physically
  76. * impossible
  77. */
  78. while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ) {
  79. clock_div++;
  80. }
  81. VERBOSE("RNG clk rate : %lu\n", clk_get_rate(stm32_rng.clock) >> clock_div);
  82. return clock_div;
  83. }
  84. static int stm32_rng_enable(void)
  85. {
  86. uint32_t sr;
  87. uint64_t timeout;
  88. uint32_t clock_div __maybe_unused;
  89. #if STM32_RNG_VER == 2
  90. mmio_write_32(stm32_rng.base + RNG_CR, RNG_CR_RNGEN | RNG_CR_CED);
  91. #endif
  92. #if STM32_RNG_VER == 4
  93. /* Reset internal block and disable CED bit */
  94. clock_div = stm32_rng_clock_freq_restrain();
  95. /* Update configuration fields */
  96. mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_NIST_CONFIG_MASK,
  97. RNG_NIST_CONFIG_A | RNG_CR_CONDRST | RNG_CR_CED);
  98. mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CLKDIV,
  99. (clock_div << RNG_CR_CLKDIV_SHIFT));
  100. mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN);
  101. #endif
  102. timeout = timeout_init_us(RNG_TIMEOUT_US);
  103. sr = mmio_read_32(stm32_rng.base + RNG_SR);
  104. while ((sr & RNG_SR_DRDY) == 0U) {
  105. if (timeout_elapsed(timeout)) {
  106. WARN("Timeout waiting\n");
  107. return -ETIMEDOUT;
  108. }
  109. if ((sr & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) {
  110. seed_error_recovery();
  111. timeout = timeout_init_us(RNG_TIMEOUT_US);
  112. }
  113. udelay(RNG_TIMEOUT_STEP_US);
  114. sr = mmio_read_32(stm32_rng.base + RNG_SR);
  115. }
  116. VERBOSE("Init RNG done\n");
  117. return 0;
  118. }
  119. /*
  120. * stm32_rng_read - Read a number of random bytes from RNG
  121. * out: pointer to the output buffer
  122. * size: number of bytes to be read
  123. * Return 0 on success, non-0 on failure
  124. */
  125. int stm32_rng_read(uint8_t *out, uint32_t size)
  126. {
  127. uint8_t *buf = out;
  128. size_t len = size;
  129. int nb_tries;
  130. uint32_t data32;
  131. int rc = 0;
  132. unsigned int count;
  133. if (stm32_rng.base == 0U) {
  134. return -EPERM;
  135. }
  136. while (len != 0U) {
  137. nb_tries = RNG_TIMEOUT_US / RNG_TIMEOUT_STEP_US;
  138. do {
  139. uint32_t status = mmio_read_32(stm32_rng.base + RNG_SR);
  140. if ((status & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) {
  141. seed_error_recovery();
  142. }
  143. udelay(RNG_TIMEOUT_STEP_US);
  144. nb_tries--;
  145. if (nb_tries == 0) {
  146. rc = -ETIMEDOUT;
  147. goto bail;
  148. }
  149. } while ((mmio_read_32(stm32_rng.base + RNG_SR) &
  150. RNG_SR_DRDY) == 0U);
  151. count = 4U;
  152. while (len != 0U) {
  153. if ((mmio_read_32(stm32_rng.base + RNG_SR) & RNG_SR_DRDY) == 0U) {
  154. break;
  155. }
  156. data32 = mmio_read_32(stm32_rng.base + RNG_DR);
  157. count--;
  158. memcpy(buf, &data32, MIN(len, sizeof(uint32_t)));
  159. buf += MIN(len, sizeof(uint32_t));
  160. len -= MIN(len, sizeof(uint32_t));
  161. if (count == 0U) {
  162. break;
  163. }
  164. }
  165. }
  166. bail:
  167. if (rc != 0) {
  168. memset(out, 0, buf - out);
  169. }
  170. return rc;
  171. }
  172. /*
  173. * stm32_rng_init: Initialize rng from DT
  174. * return 0 on success, negative value on failure
  175. */
  176. int stm32_rng_init(void)
  177. {
  178. void *fdt;
  179. struct dt_node_info dt_rng;
  180. int node;
  181. if (stm32_rng.base != 0U) {
  182. /* Driver is already initialized */
  183. return 0;
  184. }
  185. if (fdt_get_address(&fdt) == 0) {
  186. panic();
  187. }
  188. node = dt_get_node(&dt_rng, -1, DT_RNG_COMPAT);
  189. if (node < 0) {
  190. return 0;
  191. }
  192. if (dt_rng.status == DT_DISABLED) {
  193. return 0;
  194. }
  195. assert(dt_rng.base != 0U);
  196. stm32_rng.base = dt_rng.base;
  197. if (dt_rng.clock < 0) {
  198. panic();
  199. }
  200. stm32_rng.clock = (unsigned long)dt_rng.clock;
  201. clk_enable(stm32_rng.clock);
  202. if (dt_rng.reset >= 0) {
  203. int ret;
  204. ret = stm32mp_reset_assert((unsigned long)dt_rng.reset,
  205. TIMEOUT_US_1MS);
  206. if (ret != 0) {
  207. panic();
  208. }
  209. udelay(20);
  210. ret = stm32mp_reset_deassert((unsigned long)dt_rng.reset,
  211. TIMEOUT_US_1MS);
  212. if (ret != 0) {
  213. panic();
  214. }
  215. }
  216. return stm32_rng_enable();
  217. }