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