xref: /rk3399_ARM-atf/plat/mediatek/drivers/rng/mt8188/rng_plat.c (revision 522c175d2d03470de4073a4e5716851073d2bf22)
1 /*
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 
22 static 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 
36 static 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  */
72 bool 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 }
97