1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
5 #include <asm/arch-rockchip/hardware.h>
9 #include <linux/bitops.h>
10 #include <linux/iopoll.h>
11 #include <linux/string.h>
14 #define RK_HW_RNG_MAX 32
16 #define _SBF(s, v) ((v) << (s))
18 /* start of CRYPTO V1 register define */
19 #define CRYPTO_V1_CTRL 0x0008
20 #define CRYPTO_V1_RNG_START BIT(8)
21 #define CRYPTO_V1_RNG_FLUSH BIT(9)
23 #define CRYPTO_V1_TRNG_CTRL 0x0200
24 #define CRYPTO_V1_OSC_ENABLE BIT(16)
25 #define CRYPTO_V1_TRNG_SAMPLE_PERIOD(x) (x)
27 #define CRYPTO_V1_TRNG_DOUT_0 0x0204
28 /* end of CRYPTO V1 register define */
30 /* start of CRYPTO V2 register define */
31 #define CRYPTO_V2_RNG_CTL 0x0400
32 #define CRYPTO_V2_RNG_64_BIT_LEN _SBF(4, 0x00)
33 #define CRYPTO_V2_RNG_128_BIT_LEN _SBF(4, 0x01)
34 #define CRYPTO_V2_RNG_192_BIT_LEN _SBF(4, 0x02)
35 #define CRYPTO_V2_RNG_256_BIT_LEN _SBF(4, 0x03)
36 #define CRYPTO_V2_RNG_FATESY_SOC_RING _SBF(2, 0x00)
37 #define CRYPTO_V2_RNG_SLOWER_SOC_RING_0 _SBF(2, 0x01)
38 #define CRYPTO_V2_RNG_SLOWER_SOC_RING_1 _SBF(2, 0x02)
39 #define CRYPTO_V2_RNG_SLOWEST_SOC_RING _SBF(2, 0x03)
40 #define CRYPTO_V2_RNG_ENABLE BIT(1)
41 #define CRYPTO_V2_RNG_START BIT(0)
42 #define CRYPTO_V2_RNG_SAMPLE_CNT 0x0404
43 #define CRYPTO_V2_RNG_DOUT_0 0x0410
44 /* end of CRYPTO V2 register define */
46 /* start of TRNG V1 register define */
47 #define TRNG_V1_CTRL 0x0000
48 #define TRNG_V1_CTRL_NOP _SBF(0, 0x00)
49 #define TRNG_V1_CTRL_RAND _SBF(0, 0x01)
50 #define TRNG_V1_CTRL_SEED _SBF(0, 0x02)
52 #define TRNG_V1_MODE 0x0008
53 #define TRNG_V1_MODE_128_BIT _SBF(3, 0x00)
54 #define TRNG_V1_MODE_256_BIT _SBF(3, 0x01)
56 #define TRNG_V1_IE 0x0010
57 #define TRNG_V1_IE_GLBL_EN BIT(31)
58 #define TRNG_V1_IE_SEED_DONE_EN BIT(1)
59 #define TRNG_V1_IE_RAND_RDY_EN BIT(0)
61 #define TRNG_V1_ISTAT 0x0014
62 #define TRNG_V1_ISTAT_RAND_RDY BIT(0)
65 #define TRNG_V1_RAND0 0x0020
66 #define TRNG_V1_RAND7 0x003C
68 #define TRNG_V1_AUTO_RQSTS 0x0060
70 #define TRNG_V1_VERSION 0x00F0
71 #define TRNG_v1_VERSION_CODE 0x46BC
72 /* end of TRNG V1 register define */
74 #define RK_RNG_TIME_OUT 50000 /* max 50ms */
76 #define trng_write(pdata, pos, val) writel(val, (pdata)->base + (pos))
77 #define trng_read(pdata, pos) readl((pdata)->base + (pos))
79 struct rk_rng_soc_data
{
80 int (*rk_rng_init
)(struct udevice
*dev
);
81 int (*rk_rng_read
)(struct udevice
*dev
, void *data
, size_t len
);
86 struct rk_rng_soc_data
*soc_data
;
89 static int rk_rng_read_regs(fdt_addr_t addr
, void *buf
, size_t size
)
91 u32 count
= RK_HW_RNG_MAX
/ sizeof(u32
);
94 if (size
> RK_HW_RNG_MAX
)
97 while (size
&& count
) {
99 tmp_len
= min(size
, sizeof(u32
));
100 memcpy(buf
, ®
, tmp_len
);
110 static int rk_cryptov1_rng_read(struct udevice
*dev
, void *data
, size_t len
)
112 struct rk_rng_plat
*pdata
= dev_get_priv(dev
);
116 if (len
> RK_HW_RNG_MAX
)
119 /* enable osc_ring to get entropy, sample period is set as 100 */
120 writel(CRYPTO_V1_OSC_ENABLE
| CRYPTO_V1_TRNG_SAMPLE_PERIOD(100),
121 pdata
->base
+ CRYPTO_V1_TRNG_CTRL
);
123 rk_clrsetreg(pdata
->base
+ CRYPTO_V1_CTRL
, CRYPTO_V1_RNG_START
,
124 CRYPTO_V1_RNG_START
);
126 retval
= readl_poll_timeout(pdata
->base
+ CRYPTO_V1_CTRL
, reg
,
127 !(reg
& CRYPTO_V1_RNG_START
),
132 rk_rng_read_regs(pdata
->base
+ CRYPTO_V1_TRNG_DOUT_0
, data
, len
);
136 rk_clrreg(pdata
->base
+ CRYPTO_V1_CTRL
, CRYPTO_V1_RNG_START
);
141 static int rk_cryptov2_rng_read(struct udevice
*dev
, void *data
, size_t len
)
143 struct rk_rng_plat
*pdata
= dev_get_priv(dev
);
147 if (len
> RK_HW_RNG_MAX
)
150 /* enable osc_ring to get entropy, sample period is set as 100 */
151 writel(100, pdata
->base
+ CRYPTO_V2_RNG_SAMPLE_CNT
);
153 reg
|= CRYPTO_V2_RNG_256_BIT_LEN
;
154 reg
|= CRYPTO_V2_RNG_SLOWER_SOC_RING_0
;
155 reg
|= CRYPTO_V2_RNG_ENABLE
;
156 reg
|= CRYPTO_V2_RNG_START
;
158 rk_clrsetreg(pdata
->base
+ CRYPTO_V2_RNG_CTL
, 0xffff, reg
);
160 retval
= readl_poll_timeout(pdata
->base
+ CRYPTO_V2_RNG_CTL
, reg
,
161 !(reg
& CRYPTO_V2_RNG_START
),
166 rk_rng_read_regs(pdata
->base
+ CRYPTO_V2_RNG_DOUT_0
, data
, len
);
170 rk_clrreg(pdata
->base
+ CRYPTO_V2_RNG_CTL
, 0xffff);
175 static int rk_trngv1_init(struct udevice
*dev
)
178 u32 auto_reseed_cnt
= 1000;
179 struct rk_rng_plat
*pdata
= dev_get_priv(dev
);
181 version
= trng_read(pdata
, TRNG_V1_VERSION
);
182 if (version
!= TRNG_v1_VERSION_CODE
) {
183 printf("wrong trng version, expected = %08x, actual = %08x",
184 TRNG_V1_VERSION
, version
);
188 /* wait in case of RND_RDY triggered at firs power on */
189 readl_poll_timeout(pdata
->base
+ TRNG_V1_ISTAT
, status
,
190 (status
& TRNG_V1_ISTAT_RAND_RDY
),
193 /* clear RAND_RDY flag for first power on */
194 trng_write(pdata
, TRNG_V1_ISTAT
, status
);
196 /* auto reseed after (auto_reseed_cnt * 16) byte rand generate */
197 trng_write(pdata
, TRNG_V1_AUTO_RQSTS
, auto_reseed_cnt
);
202 static int rk_trngv1_rng_read(struct udevice
*dev
, void *data
, size_t len
)
204 struct rk_rng_plat
*pdata
= dev_get_priv(dev
);
208 if (len
> RK_HW_RNG_MAX
)
211 trng_write(pdata
, TRNG_V1_MODE
, TRNG_V1_MODE_256_BIT
);
212 trng_write(pdata
, TRNG_V1_CTRL
, TRNG_V1_CTRL_RAND
);
214 retval
= readl_poll_timeout(pdata
->base
+ TRNG_V1_ISTAT
, reg
,
215 (reg
& TRNG_V1_ISTAT_RAND_RDY
),
218 trng_write(pdata
, TRNG_V1_ISTAT
, reg
);
223 rk_rng_read_regs(pdata
->base
+ TRNG_V1_RAND0
, data
, len
);
227 trng_write(pdata
, TRNG_V1_CTRL
, TRNG_V1_CTRL_NOP
);
232 static int rockchip_rng_read(struct udevice
*dev
, void *data
, size_t len
)
234 unsigned char *buf
= data
;
238 struct rk_rng_plat
*pdata
= dev_get_priv(dev
);
243 if (!pdata
->soc_data
|| !pdata
->soc_data
->rk_rng_read
)
246 for (i
= 0; i
< len
/ RK_HW_RNG_MAX
; i
++, buf
+= RK_HW_RNG_MAX
) {
247 ret
= pdata
->soc_data
->rk_rng_read(dev
, buf
, RK_HW_RNG_MAX
);
252 if (len
% RK_HW_RNG_MAX
)
253 ret
= pdata
->soc_data
->rk_rng_read(dev
, buf
,
254 len
% RK_HW_RNG_MAX
);
260 static int rockchip_rng_of_to_plat(struct udevice
*dev
)
262 struct rk_rng_plat
*pdata
= dev_get_priv(dev
);
264 memset(pdata
, 0x00, sizeof(*pdata
));
266 pdata
->base
= (fdt_addr_t
)dev_read_addr_ptr(dev
);
273 static int rockchip_rng_probe(struct udevice
*dev
)
275 struct rk_rng_plat
*pdata
= dev_get_priv(dev
);
278 pdata
->soc_data
= (struct rk_rng_soc_data
*)dev_get_driver_data(dev
);
280 if (pdata
->soc_data
->rk_rng_init
)
281 ret
= pdata
->soc_data
->rk_rng_init(dev
);
286 static const struct rk_rng_soc_data rk_cryptov1_soc_data
= {
287 .rk_rng_read
= rk_cryptov1_rng_read
,
290 static const struct rk_rng_soc_data rk_cryptov2_soc_data
= {
291 .rk_rng_read
= rk_cryptov2_rng_read
,
294 static const struct rk_rng_soc_data rk_trngv1_soc_data
= {
295 .rk_rng_init
= rk_trngv1_init
,
296 .rk_rng_read
= rk_trngv1_rng_read
,
299 static const struct dm_rng_ops rockchip_rng_ops
= {
300 .read
= rockchip_rng_read
,
303 static const struct udevice_id rockchip_rng_match
[] = {
305 .compatible
= "rockchip,cryptov1-rng",
306 .data
= (ulong
)&rk_cryptov1_soc_data
,
309 .compatible
= "rockchip,cryptov2-rng",
310 .data
= (ulong
)&rk_cryptov2_soc_data
,
313 .compatible
= "rockchip,trngv1",
314 .data
= (ulong
)&rk_trngv1_soc_data
,
319 U_BOOT_DRIVER(rockchip_rng
) = {
320 .name
= "rockchip-rng",
322 .of_match
= rockchip_rng_match
,
323 .ops
= &rockchip_rng_ops
,
324 .probe
= rockchip_rng_probe
,
325 .of_to_plat
= rockchip_rng_of_to_plat
,
326 .priv_auto
= sizeof(struct rk_rng_plat
),