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