stm32mp1_rng.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2019, Linaro Limited
  4. */
  5. #define LOG_CATEGORY UCLASS_RNG
  6. #include <common.h>
  7. #include <clk.h>
  8. #include <dm.h>
  9. #include <log.h>
  10. #include <reset.h>
  11. #include <rng.h>
  12. #include <linux/bitops.h>
  13. #include <linux/delay.h>
  14. #include <asm/io.h>
  15. #include <linux/iopoll.h>
  16. #include <linux/kernel.h>
  17. #define RNG_CR 0x00
  18. #define RNG_CR_RNGEN BIT(2)
  19. #define RNG_CR_CED BIT(5)
  20. #define RNG_CR_CONDRST BIT(30)
  21. #define RNG_SR 0x04
  22. #define RNG_SR_SEIS BIT(6)
  23. #define RNG_SR_CEIS BIT(5)
  24. #define RNG_SR_SECS BIT(2)
  25. #define RNG_SR_DRDY BIT(0)
  26. #define RNG_DR 0x08
  27. struct stm32_rng_data {
  28. bool has_cond_reset;
  29. };
  30. struct stm32_rng_plat {
  31. fdt_addr_t base;
  32. struct clk clk;
  33. struct reset_ctl rst;
  34. const struct stm32_rng_data *data;
  35. };
  36. static int stm32_rng_read(struct udevice *dev, void *data, size_t len)
  37. {
  38. int retval, i;
  39. u32 sr, count, reg;
  40. size_t increment;
  41. struct stm32_rng_plat *pdata = dev_get_plat(dev);
  42. while (len > 0) {
  43. retval = readl_poll_timeout(pdata->base + RNG_SR, sr,
  44. sr & RNG_SR_DRDY, 10000);
  45. if (retval)
  46. return retval;
  47. if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) {
  48. /* As per SoC TRM */
  49. clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS);
  50. for (i = 0; i < 12; i++)
  51. readl(pdata->base + RNG_DR);
  52. if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) {
  53. log_err("RNG Noise");
  54. return -EIO;
  55. }
  56. /* start again */
  57. continue;
  58. }
  59. /*
  60. * Once the DRDY bit is set, the RNG_DR register can
  61. * be read four consecutive times.
  62. */
  63. count = 4;
  64. while (len && count) {
  65. reg = readl(pdata->base + RNG_DR);
  66. memcpy(data, &reg, min(len, sizeof(u32)));
  67. increment = min(len, sizeof(u32));
  68. data += increment;
  69. len -= increment;
  70. count--;
  71. }
  72. }
  73. return 0;
  74. }
  75. static int stm32_rng_init(struct stm32_rng_plat *pdata)
  76. {
  77. int err;
  78. u32 cr, sr;
  79. err = clk_enable(&pdata->clk);
  80. if (err)
  81. return err;
  82. cr = readl(pdata->base + RNG_CR);
  83. /* Disable CED */
  84. cr |= RNG_CR_CED;
  85. if (pdata->data->has_cond_reset) {
  86. cr |= RNG_CR_CONDRST;
  87. writel(cr, pdata->base + RNG_CR);
  88. cr &= ~RNG_CR_CONDRST;
  89. writel(cr, pdata->base + RNG_CR);
  90. err = readl_poll_timeout(pdata->base + RNG_CR, cr,
  91. (!(cr & RNG_CR_CONDRST)), 10000);
  92. if (err)
  93. return err;
  94. }
  95. /* clear error indicators */
  96. writel(0, pdata->base + RNG_SR);
  97. cr |= RNG_CR_RNGEN;
  98. writel(cr, pdata->base + RNG_CR);
  99. err = readl_poll_timeout(pdata->base + RNG_SR, sr,
  100. sr & RNG_SR_DRDY, 10000);
  101. return err;
  102. }
  103. static int stm32_rng_cleanup(struct stm32_rng_plat *pdata)
  104. {
  105. writel(0, pdata->base + RNG_CR);
  106. return clk_disable(&pdata->clk);
  107. }
  108. static int stm32_rng_probe(struct udevice *dev)
  109. {
  110. struct stm32_rng_plat *pdata = dev_get_plat(dev);
  111. pdata->data = (struct stm32_rng_data *)dev_get_driver_data(dev);
  112. reset_assert(&pdata->rst);
  113. udelay(20);
  114. reset_deassert(&pdata->rst);
  115. return stm32_rng_init(pdata);
  116. }
  117. static int stm32_rng_remove(struct udevice *dev)
  118. {
  119. struct stm32_rng_plat *pdata = dev_get_plat(dev);
  120. return stm32_rng_cleanup(pdata);
  121. }
  122. static int stm32_rng_of_to_plat(struct udevice *dev)
  123. {
  124. struct stm32_rng_plat *pdata = dev_get_plat(dev);
  125. int err;
  126. pdata->base = dev_read_addr(dev);
  127. if (!pdata->base)
  128. return -ENOMEM;
  129. err = clk_get_by_index(dev, 0, &pdata->clk);
  130. if (err)
  131. return err;
  132. err = reset_get_by_index(dev, 0, &pdata->rst);
  133. if (err)
  134. return err;
  135. return 0;
  136. }
  137. static const struct dm_rng_ops stm32_rng_ops = {
  138. .read = stm32_rng_read,
  139. };
  140. static const struct stm32_rng_data stm32mp13_rng_data = {
  141. .has_cond_reset = true,
  142. };
  143. static const struct stm32_rng_data stm32_rng_data = {
  144. .has_cond_reset = false,
  145. };
  146. static const struct udevice_id stm32_rng_match[] = {
  147. {.compatible = "st,stm32mp13-rng", .data = (ulong)&stm32mp13_rng_data},
  148. {.compatible = "st,stm32-rng", .data = (ulong)&stm32_rng_data},
  149. {},
  150. };
  151. U_BOOT_DRIVER(stm32_rng) = {
  152. .name = "stm32-rng",
  153. .id = UCLASS_RNG,
  154. .of_match = stm32_rng_match,
  155. .ops = &stm32_rng_ops,
  156. .probe = stm32_rng_probe,
  157. .remove = stm32_rng_remove,
  158. .plat_auto = sizeof(struct stm32_rng_plat),
  159. .of_to_plat = stm32_rng_of_to_plat,
  160. };