iproc_rng200.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright 2020, Matthias Brugger <mbrugger@suse.com>
  4. *
  5. * Driver for Raspberry Pi hardware random number generator
  6. */
  7. #include <common.h>
  8. #include <dm.h>
  9. #include <linux/delay.h>
  10. #include <rng.h>
  11. #include <asm/io.h>
  12. #define usleep_range(a, b) udelay((b))
  13. #define RNG_CTRL_OFFSET 0x00
  14. #define RNG_CTRL_RNG_RBGEN_MASK 0x00001FFF
  15. #define RNG_CTRL_RNG_RBGEN_ENABLE 0x00000001
  16. #define RNG_CTRL_RNG_RBGEN_DISABLE 0x00000000
  17. #define RNG_SOFT_RESET_OFFSET 0x04
  18. #define RNG_SOFT_RESET 0x00000001
  19. #define RBG_SOFT_RESET_OFFSET 0x08
  20. #define RBG_SOFT_RESET 0x00000001
  21. #define RNG_INT_STATUS_OFFSET 0x18
  22. #define RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK 0x80000000
  23. #define RNG_INT_STATUS_NIST_FAIL_IRQ_MASK 0x00000020
  24. #define RNG_FIFO_DATA_OFFSET 0x20
  25. #define RNG_FIFO_COUNT_OFFSET 0x24
  26. #define RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK 0x000000FF
  27. struct iproc_rng200_plat {
  28. void __iomem *base;
  29. };
  30. static void iproc_rng200_enable(struct iproc_rng200_plat *pdata, bool enable)
  31. {
  32. void __iomem *rng_base = pdata->base;
  33. u32 val;
  34. val = readl(rng_base + RNG_CTRL_OFFSET);
  35. val &= ~RNG_CTRL_RNG_RBGEN_MASK;
  36. if (enable)
  37. val |= RNG_CTRL_RNG_RBGEN_ENABLE;
  38. else
  39. val &= ~RNG_CTRL_RNG_RBGEN_ENABLE;
  40. writel(val, rng_base + RNG_CTRL_OFFSET);
  41. }
  42. static void iproc_rng200_restart(struct iproc_rng200_plat *pdata)
  43. {
  44. void __iomem *rng_base = pdata->base;
  45. u32 val;
  46. iproc_rng200_enable(pdata, false);
  47. /* Clear all interrupt status */
  48. writel(0xFFFFFFFFUL, rng_base + RNG_INT_STATUS_OFFSET);
  49. /* Reset RNG and RBG */
  50. val = readl(rng_base + RBG_SOFT_RESET_OFFSET);
  51. val |= RBG_SOFT_RESET;
  52. writel(val, rng_base + RBG_SOFT_RESET_OFFSET);
  53. val = readl(rng_base + RNG_SOFT_RESET_OFFSET);
  54. val |= RNG_SOFT_RESET;
  55. writel(val, rng_base + RNG_SOFT_RESET_OFFSET);
  56. val = readl(rng_base + RNG_SOFT_RESET_OFFSET);
  57. val &= ~RNG_SOFT_RESET;
  58. writel(val, rng_base + RNG_SOFT_RESET_OFFSET);
  59. val = readl(rng_base + RBG_SOFT_RESET_OFFSET);
  60. val &= ~RBG_SOFT_RESET;
  61. writel(val, rng_base + RBG_SOFT_RESET_OFFSET);
  62. iproc_rng200_enable(pdata, true);
  63. }
  64. static int iproc_rng200_read(struct udevice *dev, void *data, size_t len)
  65. {
  66. struct iproc_rng200_plat *priv = dev_get_plat(dev);
  67. char *buf = (char *)data;
  68. u32 num_remaining = len;
  69. u32 status;
  70. #define MAX_RESETS_PER_READ 1
  71. u32 num_resets = 0;
  72. while (num_remaining > 0) {
  73. /* Is RNG sane? If not, reset it. */
  74. status = readl(priv->base + RNG_INT_STATUS_OFFSET);
  75. if ((status & (RNG_INT_STATUS_MASTER_FAIL_LOCKOUT_IRQ_MASK |
  76. RNG_INT_STATUS_NIST_FAIL_IRQ_MASK)) != 0) {
  77. if (num_resets >= MAX_RESETS_PER_READ)
  78. return len - num_remaining;
  79. iproc_rng200_restart(priv);
  80. num_resets++;
  81. }
  82. /* Are there any random numbers available? */
  83. if ((readl(priv->base + RNG_FIFO_COUNT_OFFSET) &
  84. RNG_FIFO_COUNT_RNG_FIFO_COUNT_MASK) > 0) {
  85. if (num_remaining >= sizeof(u32)) {
  86. /* Buffer has room to store entire word */
  87. *(u32 *)buf = readl(priv->base +
  88. RNG_FIFO_DATA_OFFSET);
  89. buf += sizeof(u32);
  90. num_remaining -= sizeof(u32);
  91. } else {
  92. /* Buffer can only store partial word */
  93. u32 rnd_number = readl(priv->base +
  94. RNG_FIFO_DATA_OFFSET);
  95. memcpy(buf, &rnd_number, num_remaining);
  96. buf += num_remaining;
  97. num_remaining = 0;
  98. }
  99. } else {
  100. /* Can wait, give others chance to run */
  101. usleep_range(min(num_remaining * 10, 500U), 500);
  102. }
  103. }
  104. return 0;
  105. }
  106. static int iproc_rng200_probe(struct udevice *dev)
  107. {
  108. struct iproc_rng200_plat *priv = dev_get_plat(dev);
  109. iproc_rng200_enable(priv, true);
  110. return 0;
  111. }
  112. static int iproc_rng200_remove(struct udevice *dev)
  113. {
  114. struct iproc_rng200_plat *priv = dev_get_plat(dev);
  115. iproc_rng200_enable(priv, false);
  116. return 0;
  117. }
  118. static int iproc_rng200_of_to_plat(struct udevice *dev)
  119. {
  120. struct iproc_rng200_plat *pdata = dev_get_plat(dev);
  121. pdata->base = devfdt_map_physmem(dev, sizeof(void *));
  122. if (!pdata->base)
  123. return -ENODEV;
  124. return 0;
  125. }
  126. static const struct dm_rng_ops iproc_rng200_ops = {
  127. .read = iproc_rng200_read,
  128. };
  129. static const struct udevice_id iproc_rng200_rng_match[] = {
  130. { .compatible = "brcm,bcm2711-rng200", },
  131. { .compatible = "brcm,iproc-rng200", },
  132. {},
  133. };
  134. U_BOOT_DRIVER(iproc_rng200_rng) = {
  135. .name = "iproc_rng200-rng",
  136. .id = UCLASS_RNG,
  137. .of_match = iproc_rng200_rng_match,
  138. .ops = &iproc_rng200_ops,
  139. .probe = iproc_rng200_probe,
  140. .remove = iproc_rng200_remove,
  141. .priv_auto = sizeof(struct iproc_rng200_plat),
  142. .of_to_plat = iproc_rng200_of_to_plat,
  143. };