rng_plat.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /*
  2. * Copyright (c) 2024, MediaTek Inc. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <stdbool.h>
  8. #include <stdint.h>
  9. #include <common/debug.h>
  10. #include <drivers/delay_timer.h>
  11. #include <lib/mmio.h>
  12. #include <lib/smccc.h>
  13. #include <plat/common/platform.h>
  14. #include <platform_def.h>
  15. #include <services/trng_svc.h>
  16. #include <smccc_helpers.h>
  17. #include "rng_plat.h"
  18. static void trng_external_swrst(void)
  19. {
  20. /* External swrst to reset whole rng module */
  21. mmio_setbits_32(TRNG_SWRST_SET_REG, RNG_SWRST_B);
  22. mmio_setbits_32(TRNG_SWRST_CLR_REG, RNG_SWRST_B);
  23. /* Disable irq */
  24. mmio_clrbits_32(RNG_IRQ_CFG, IRQ_EN);
  25. /* Set default cutoff value */
  26. mmio_write_32(RNG_HTEST, RNG_DEFAULT_CUTOFF);
  27. /* Enable rng */
  28. mmio_setbits_32(RNG_EN, DRBG_EN | NRBG_EN);
  29. }
  30. static bool get_entropy_32(uint32_t *out)
  31. {
  32. uint64_t time = timeout_init_us(MTK_TIMEOUT_POLL);
  33. int retry_times = 0;
  34. while (!(mmio_read_32(RNG_STATUS) & DRBG_VALID)) {
  35. if (mmio_read_32(RNG_STATUS) & (RNG_ERROR | APB_ERROR)) {
  36. mmio_clrbits_32(RNG_EN, DRBG_EN | NRBG_EN);
  37. mmio_clrbits_32(RNG_SWRST, SWRST_B);
  38. mmio_setbits_32(RNG_SWRST, SWRST_B);
  39. mmio_setbits_32(RNG_EN, DRBG_EN | NRBG_EN);
  40. }
  41. if (timeout_elapsed(time)) {
  42. trng_external_swrst();
  43. time = timeout_init_us(MTK_TIMEOUT_POLL);
  44. retry_times++;
  45. }
  46. if (retry_times > MTK_RETRY_CNT) {
  47. ERROR("%s: trng NOT ready\n", __func__);
  48. return false;
  49. }
  50. }
  51. *out = mmio_read_32(RNG_OUT);
  52. return true;
  53. }
  54. /* Get random number from HWRNG and return 8 bytes of entropy.
  55. * Return 'true' when random value generated successfully, otherwise return
  56. * 'false'.
  57. */
  58. bool plat_get_entropy(uint64_t *out)
  59. {
  60. uint32_t seed[2] = { 0 };
  61. int i = 0;
  62. assert(out);
  63. assert(!check_uptr_overflow((uintptr_t)out, sizeof(*out)));
  64. /* Disable interrupt mode */
  65. mmio_clrbits_32(RNG_IRQ_CFG, IRQ_EN);
  66. /* Set rng health test cutoff value */
  67. mmio_write_32(RNG_HTEST, RNG_DEFAULT_CUTOFF);
  68. /* Enable rng module */
  69. mmio_setbits_32(RNG_EN, DRBG_EN | NRBG_EN);
  70. for (i = 0; i < ARRAY_SIZE(seed); i++) {
  71. if (!get_entropy_32(&seed[i]))
  72. return false;
  73. }
  74. /* Output 8 bytes entropy by combining 2 32-bit random numbers. */
  75. *out = ((uint64_t)seed[0] << 32) | seed[1];
  76. return true;
  77. }