xref: /rk3399_ARM-atf/plat/mediatek/drivers/rng/mt8186/rng_plat.c (revision d684e7fbb34b53bdccbafa6d78211e7c77688bb9)
1*8c1740e2SSuyuan Su /*
2*8c1740e2SSuyuan Su  * Copyright (c) 2024, MediaTek Inc. All rights reserved.
3*8c1740e2SSuyuan Su  *
4*8c1740e2SSuyuan Su  * SPDX-License-Identifier: BSD-3-Clause
5*8c1740e2SSuyuan Su  */
6*8c1740e2SSuyuan Su 
7*8c1740e2SSuyuan Su #include <assert.h>
8*8c1740e2SSuyuan Su #include <errno.h>
9*8c1740e2SSuyuan Su #include <stdint.h>
10*8c1740e2SSuyuan Su 
11*8c1740e2SSuyuan Su #include <common/debug.h>
12*8c1740e2SSuyuan Su #include <drivers/delay_timer.h>
13*8c1740e2SSuyuan Su #include <lib/mmio.h>
14*8c1740e2SSuyuan Su #include <lib/smccc.h>
15*8c1740e2SSuyuan Su #include <lib/spinlock.h>
16*8c1740e2SSuyuan Su #include <plat/common/platform.h>
17*8c1740e2SSuyuan Su #include <platform_def.h>
18*8c1740e2SSuyuan Su #include <services/trng_svc.h>
19*8c1740e2SSuyuan Su #include <smccc_helpers.h>
20*8c1740e2SSuyuan Su 
21*8c1740e2SSuyuan Su #include <mtk_mmap_pool.h>
22*8c1740e2SSuyuan Su #include <mtk_sip_svc.h>
23*8c1740e2SSuyuan Su #include "rng_plat.h"
24*8c1740e2SSuyuan Su 
25*8c1740e2SSuyuan Su static spinlock_t rng_lock;
26*8c1740e2SSuyuan Su 
trng_wait(uint32_t reg,uint32_t expected_value)27*8c1740e2SSuyuan Su static int trng_wait(uint32_t reg, uint32_t expected_value)
28*8c1740e2SSuyuan Su {
29*8c1740e2SSuyuan Su 	uint64_t timeout = timeout_init_us(TRNG_TIME_OUT);
30*8c1740e2SSuyuan Su 	uint32_t value = 0;
31*8c1740e2SSuyuan Su 
32*8c1740e2SSuyuan Su 	do {
33*8c1740e2SSuyuan Su 		value = mmio_read_32(reg);
34*8c1740e2SSuyuan Su 		if ((value & expected_value) == expected_value)
35*8c1740e2SSuyuan Su 			return 0;
36*8c1740e2SSuyuan Su 
37*8c1740e2SSuyuan Su 		udelay(10);
38*8c1740e2SSuyuan Su 	} while (!timeout_elapsed(timeout));
39*8c1740e2SSuyuan Su 
40*8c1740e2SSuyuan Su 	return -ETIMEDOUT;
41*8c1740e2SSuyuan Su }
42*8c1740e2SSuyuan Su 
trng_write(uint32_t reg,uint32_t value,uint32_t read_reg,uint32_t expected_value)43*8c1740e2SSuyuan Su static int trng_write(uint32_t reg, uint32_t value,
44*8c1740e2SSuyuan Su 			   uint32_t read_reg, uint32_t expected_value)
45*8c1740e2SSuyuan Su {
46*8c1740e2SSuyuan Su 	int retry = MTK_TRNG_MAX_ROUND;
47*8c1740e2SSuyuan Su 	uint32_t read_value = 0;
48*8c1740e2SSuyuan Su 
49*8c1740e2SSuyuan Su 	do {
50*8c1740e2SSuyuan Su 		mmio_write_32(reg, value);
51*8c1740e2SSuyuan Su 
52*8c1740e2SSuyuan Su 		read_value = mmio_read_32(read_reg);
53*8c1740e2SSuyuan Su 		if ((read_value & value) == expected_value)
54*8c1740e2SSuyuan Su 			return 0;
55*8c1740e2SSuyuan Su 
56*8c1740e2SSuyuan Su 		udelay(10);
57*8c1740e2SSuyuan Su 	} while (--retry > 0);
58*8c1740e2SSuyuan Su 
59*8c1740e2SSuyuan Su 	return -ETIMEDOUT;
60*8c1740e2SSuyuan Su }
61*8c1740e2SSuyuan Su 
trng_prng(uint32_t * rand)62*8c1740e2SSuyuan Su static uint32_t trng_prng(uint32_t *rand)
63*8c1740e2SSuyuan Su {
64*8c1740e2SSuyuan Su 	int32_t ret = 0;
65*8c1740e2SSuyuan Su 	uint32_t seed[4] = {0};
66*8c1740e2SSuyuan Su 
67*8c1740e2SSuyuan Su 	if (rand == NULL)
68*8c1740e2SSuyuan Su 		return MTK_SIP_E_INVALID_PARAM;
69*8c1740e2SSuyuan Su 
70*8c1740e2SSuyuan Su 	/* ungate */
71*8c1740e2SSuyuan Su 	ret = trng_write(TRNG_PDN_CLR, TRNG_PDN_VALUE, TRNG_PDN_STATUS, 0);
72*8c1740e2SSuyuan Su 	if (ret) {
73*8c1740e2SSuyuan Su 		ERROR("%s: ungate fail\n", __func__);
74*8c1740e2SSuyuan Su 		return MTK_SIP_E_NOT_SUPPORTED;
75*8c1740e2SSuyuan Su 	}
76*8c1740e2SSuyuan Su 
77*8c1740e2SSuyuan Su 	/* read random data once and drop it */
78*8c1740e2SSuyuan Su 	seed[0] = mmio_read_32(TRNG_DATA);
79*8c1740e2SSuyuan Su 
80*8c1740e2SSuyuan Su 	/* enable von-neumann extractor */
81*8c1740e2SSuyuan Su 	mmio_setbits_32(TRNG_CONF, TRNG_CONF_VON_EN);
82*8c1740e2SSuyuan Su 
83*8c1740e2SSuyuan Su 	/* start */
84*8c1740e2SSuyuan Su 	mmio_setbits_32(TRNG_CTRL, TRNG_CTRL_START);
85*8c1740e2SSuyuan Su 
86*8c1740e2SSuyuan Su 	/* get seeds from trng */
87*8c1740e2SSuyuan Su 	for (int i = 0; i < ARRAY_SIZE(seed); i++) {
88*8c1740e2SSuyuan Su 		ret = trng_wait(TRNG_CTRL, TRNG_CTRL_RDY);
89*8c1740e2SSuyuan Su 		if (ret) {
90*8c1740e2SSuyuan Su 			ERROR("%s: trng NOT ready\n", __func__);
91*8c1740e2SSuyuan Su 			return MTK_SIP_E_NOT_SUPPORTED;
92*8c1740e2SSuyuan Su 		}
93*8c1740e2SSuyuan Su 
94*8c1740e2SSuyuan Su 		seed[i] = mmio_read_32(TRNG_DATA);
95*8c1740e2SSuyuan Su 	}
96*8c1740e2SSuyuan Su 
97*8c1740e2SSuyuan Su 	/* stop */
98*8c1740e2SSuyuan Su 	mmio_clrbits_32(TRNG_CTRL, TRNG_CTRL_START);
99*8c1740e2SSuyuan Su 
100*8c1740e2SSuyuan Su 	/* gate */
101*8c1740e2SSuyuan Su 	ret = trng_write(TRNG_PDN_SET, TRNG_PDN_VALUE, TRNG_PDN_STATUS, TRNG_PDN_VALUE);
102*8c1740e2SSuyuan Su 	if (ret) {
103*8c1740e2SSuyuan Su 		ERROR("%s: gate fail\n", __func__);
104*8c1740e2SSuyuan Su 		return MTK_SIP_E_NOT_SUPPORTED;
105*8c1740e2SSuyuan Su 	}
106*8c1740e2SSuyuan Su 
107*8c1740e2SSuyuan Su 	for (int i = 0; i < ARRAY_SIZE(seed); i++)
108*8c1740e2SSuyuan Su 		rand[i] = seed[i];
109*8c1740e2SSuyuan Su 
110*8c1740e2SSuyuan Su 	return 0;
111*8c1740e2SSuyuan Su }
112*8c1740e2SSuyuan Su 
get_true_rnd(uint32_t * val,uint32_t num)113*8c1740e2SSuyuan Su static uint32_t get_true_rnd(uint32_t *val, uint32_t num)
114*8c1740e2SSuyuan Su {
115*8c1740e2SSuyuan Su 	uint32_t rand[4] = {0};
116*8c1740e2SSuyuan Su 	uint32_t ret;
117*8c1740e2SSuyuan Su 
118*8c1740e2SSuyuan Su 	if (val == NULL || num > ARRAY_SIZE(rand))
119*8c1740e2SSuyuan Su 		return MTK_SIP_E_INVALID_PARAM;
120*8c1740e2SSuyuan Su 
121*8c1740e2SSuyuan Su 	spin_lock(&rng_lock);
122*8c1740e2SSuyuan Su 	ret = trng_prng(rand);
123*8c1740e2SSuyuan Su 	spin_unlock(&rng_lock);
124*8c1740e2SSuyuan Su 
125*8c1740e2SSuyuan Su 	for (int i = 0; i < num; i++)
126*8c1740e2SSuyuan Su 		val[i] = rand[i];
127*8c1740e2SSuyuan Su 
128*8c1740e2SSuyuan Su 	return ret;
129*8c1740e2SSuyuan Su }
130*8c1740e2SSuyuan Su 
131*8c1740e2SSuyuan Su /*
132*8c1740e2SSuyuan Su  * plat_get_entropy - get 64-bit random number data which is used form
133*8c1740e2SSuyuan Su  * atf early stage
134*8c1740e2SSuyuan Su  * output - out: output 64-bit entropy combine with 2 32-bit random number
135*8c1740e2SSuyuan Su  */
plat_get_entropy(uint64_t * out)136*8c1740e2SSuyuan Su bool plat_get_entropy(uint64_t *out)
137*8c1740e2SSuyuan Su {
138*8c1740e2SSuyuan Su 	uint32_t entropy_pool[2] = {0};
139*8c1740e2SSuyuan Su 	uint32_t ret;
140*8c1740e2SSuyuan Su 
141*8c1740e2SSuyuan Su 	assert(out);
142*8c1740e2SSuyuan Su 	assert(!check_uptr_overflow((uintptr_t)out, sizeof(*out)));
143*8c1740e2SSuyuan Su 
144*8c1740e2SSuyuan Su 	/* Get 2 32-bits entropy */
145*8c1740e2SSuyuan Su 	ret = get_true_rnd(entropy_pool, ARRAY_SIZE(entropy_pool));
146*8c1740e2SSuyuan Su 	if (ret)
147*8c1740e2SSuyuan Su 		return false;
148*8c1740e2SSuyuan Su 
149*8c1740e2SSuyuan Su 	/* Output 8 bytes entropy combine with 2 32-bit random number. */
150*8c1740e2SSuyuan Su 	*out = ((uint64_t)entropy_pool[0] << 32) | entropy_pool[1];
151*8c1740e2SSuyuan Su 
152*8c1740e2SSuyuan Su 	return true;
153*8c1740e2SSuyuan Su }
154