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