meson-rng.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
  4. *
  5. * Driver for Amlogic hardware random number generator
  6. */
  7. #include <common.h>
  8. #include <clk.h>
  9. #include <dm.h>
  10. #include <rng.h>
  11. #include <asm/io.h>
  12. struct meson_rng_plat {
  13. fdt_addr_t base;
  14. struct clk clk;
  15. };
  16. /**
  17. * meson_rng_read() - fill buffer with random bytes
  18. *
  19. * @buffer: buffer to receive data
  20. * @size: size of buffer
  21. *
  22. * Return: 0
  23. */
  24. static int meson_rng_read(struct udevice *dev, void *data, size_t len)
  25. {
  26. struct meson_rng_plat *pdata = dev_get_plat(dev);
  27. char *buffer = (char *)data;
  28. while (len) {
  29. u32 rand = readl(pdata->base);
  30. size_t step;
  31. if (len >= 4)
  32. step = 4;
  33. else
  34. step = len;
  35. memcpy(buffer, &rand, step);
  36. buffer += step;
  37. len -= step;
  38. }
  39. return 0;
  40. }
  41. /**
  42. * meson_rng_probe() - probe rng device
  43. *
  44. * @dev: device
  45. * Return: 0 if ok
  46. */
  47. static int meson_rng_probe(struct udevice *dev)
  48. {
  49. struct meson_rng_plat *pdata = dev_get_plat(dev);
  50. int err;
  51. err = clk_enable(&pdata->clk);
  52. if (err)
  53. return err;
  54. return 0;
  55. }
  56. /**
  57. * meson_rng_remove() - deinitialize rng device
  58. *
  59. * @dev: device
  60. * Return: 0 if ok
  61. */
  62. static int meson_rng_remove(struct udevice *dev)
  63. {
  64. struct meson_rng_plat *pdata = dev_get_plat(dev);
  65. return clk_disable(&pdata->clk);
  66. }
  67. /**
  68. * meson_rng_of_to_plat() - transfer device tree data to plaform data
  69. *
  70. * @dev: device
  71. * Return: 0 if ok
  72. */
  73. static int meson_rng_of_to_plat(struct udevice *dev)
  74. {
  75. struct meson_rng_plat *pdata = dev_get_plat(dev);
  76. int err;
  77. pdata->base = dev_read_addr(dev);
  78. if (!pdata->base)
  79. return -ENODEV;
  80. /* Get optional "core" clock */
  81. err = clk_get_by_name(dev, "core", &pdata->clk);
  82. if (err && err != -ENODATA)
  83. return err;
  84. return 0;
  85. }
  86. static const struct dm_rng_ops meson_rng_ops = {
  87. .read = meson_rng_read,
  88. };
  89. static const struct udevice_id meson_rng_match[] = {
  90. {
  91. .compatible = "amlogic,meson-rng",
  92. },
  93. {},
  94. };
  95. U_BOOT_DRIVER(meson_rng) = {
  96. .name = "meson-rng",
  97. .id = UCLASS_RNG,
  98. .of_match = meson_rng_match,
  99. .ops = &meson_rng_ops,
  100. .probe = meson_rng_probe,
  101. .remove = meson_rng_remove,
  102. .plat_auto = sizeof(struct meson_rng_plat),
  103. .of_to_plat = meson_rng_of_to_plat,
  104. };