xref: /OK3568_Linux_fs/u-boot/drivers/rng/rockchip_rng.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun #include <common.h>
6*4882a593Smuzhiyun #include <clk-uclass.h>
7*4882a593Smuzhiyun #include <dm.h>
8*4882a593Smuzhiyun #include <rng.h>
9*4882a593Smuzhiyun #include <asm/arch-rockchip/hardware.h>
10*4882a593Smuzhiyun #include <asm/io.h>
11*4882a593Smuzhiyun #include <linux/iopoll.h>
12*4882a593Smuzhiyun #include <linux/string.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #define RK_HW_RNG_MAX 32
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #define _SBF(s, v)	((v) << (s))
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun /* start of CRYPTO V1 register define */
19*4882a593Smuzhiyun #define CRYPTO_V1_CTRL				0x0008
20*4882a593Smuzhiyun #define CRYPTO_V1_RNG_START			BIT(8)
21*4882a593Smuzhiyun #define CRYPTO_V1_RNG_FLUSH			BIT(9)
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define CRYPTO_V1_TRNG_CTRL			0x0200
24*4882a593Smuzhiyun #define CRYPTO_V1_OSC_ENABLE			BIT(16)
25*4882a593Smuzhiyun #define CRYPTO_V1_TRNG_SAMPLE_PERIOD(x)		(x)
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define CRYPTO_V1_TRNG_DOUT_0			0x0204
28*4882a593Smuzhiyun /* end of CRYPTO V1 register define */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun /* start of CRYPTO V2 register define */
31*4882a593Smuzhiyun #define CRYPTO_V2_RNG_CTL			0x0400
32*4882a593Smuzhiyun #define CRYPTO_V2_RNG_64_BIT_LEN		_SBF(4, 0x00)
33*4882a593Smuzhiyun #define CRYPTO_V2_RNG_128_BIT_LEN		_SBF(4, 0x01)
34*4882a593Smuzhiyun #define CRYPTO_V2_RNG_192_BIT_LEN		_SBF(4, 0x02)
35*4882a593Smuzhiyun #define CRYPTO_V2_RNG_256_BIT_LEN		_SBF(4, 0x03)
36*4882a593Smuzhiyun #define CRYPTO_V2_RNG_FATESY_SOC_RING		_SBF(2, 0x00)
37*4882a593Smuzhiyun #define CRYPTO_V2_RNG_SLOWER_SOC_RING_0		_SBF(2, 0x01)
38*4882a593Smuzhiyun #define CRYPTO_V2_RNG_SLOWER_SOC_RING_1		_SBF(2, 0x02)
39*4882a593Smuzhiyun #define CRYPTO_V2_RNG_SLOWEST_SOC_RING		_SBF(2, 0x03)
40*4882a593Smuzhiyun #define CRYPTO_V2_RNG_ENABLE			BIT(1)
41*4882a593Smuzhiyun #define CRYPTO_V2_RNG_START			BIT(0)
42*4882a593Smuzhiyun #define CRYPTO_V2_RNG_SAMPLE_CNT		0x0404
43*4882a593Smuzhiyun #define CRYPTO_V2_RNG_DOUT_0			0x0410
44*4882a593Smuzhiyun /* end of CRYPTO V2 register define */
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun /* start of TRNG V1 register define */
47*4882a593Smuzhiyun #define TRNG_V1_CTRL				0x0000
48*4882a593Smuzhiyun #define TRNG_V1_CTRL_NOP			_SBF(0, 0x00)
49*4882a593Smuzhiyun #define TRNG_V1_CTRL_RAND			_SBF(0, 0x01)
50*4882a593Smuzhiyun #define TRNG_V1_CTRL_SEED			_SBF(0, 0x02)
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #define TRNG_V1_MODE				0x0008
53*4882a593Smuzhiyun #define TRNG_V1_MODE_128_BIT			_SBF(3, 0x00)
54*4882a593Smuzhiyun #define TRNG_V1_MODE_256_BIT			_SBF(3, 0x01)
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun #define TRNG_V1_IE				0x0010
57*4882a593Smuzhiyun #define TRNG_V1_IE_GLBL_EN			BIT(31)
58*4882a593Smuzhiyun #define TRNG_V1_IE_SEED_DONE_EN			BIT(1)
59*4882a593Smuzhiyun #define TRNG_V1_IE_RAND_RDY_EN			BIT(0)
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #define TRNG_V1_ISTAT				0x0014
62*4882a593Smuzhiyun #define TRNG_V1_ISTAT_RAND_RDY			BIT(0)
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /* RAND0 ~ RAND7 */
65*4882a593Smuzhiyun #define TRNG_V1_RAND0				0x0020
66*4882a593Smuzhiyun #define TRNG_V1_RAND7				0x003C
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun #define TRNG_V1_AUTO_RQSTS			0x0060
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun #define TRNG_V1_VERSION				0x00F0
71*4882a593Smuzhiyun #define TRNG_v1_VERSION_CODE			0x46BC
72*4882a593Smuzhiyun /* end of TRNG V1 register define */
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /* start of RKRNG register define */
75*4882a593Smuzhiyun #define RKRNG_CTRL				0x0010
76*4882a593Smuzhiyun #define RKRNG_CTRL_INST_REQ			BIT(0)
77*4882a593Smuzhiyun #define RKRNG_CTRL_RESEED_REQ			BIT(1)
78*4882a593Smuzhiyun #define RKRNG_CTRL_TEST_REQ			BIT(2)
79*4882a593Smuzhiyun #define RKRNG_CTRL_SW_DRNG_REQ			BIT(3)
80*4882a593Smuzhiyun #define RKRNG_CTRL_SW_TRNG_REQ			BIT(4)
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun #define RKRNG_STATE				0x0014
83*4882a593Smuzhiyun #define RKRNG_STATE_INST_ACK			BIT(0)
84*4882a593Smuzhiyun #define RKRNG_STATE_RESEED_ACK			BIT(1)
85*4882a593Smuzhiyun #define RKRNG_STATE_TEST_ACK			BIT(2)
86*4882a593Smuzhiyun #define RKRNG_STATE_SW_DRNG_ACK			BIT(3)
87*4882a593Smuzhiyun #define RKRNG_STATE_SW_TRNG_ACK			BIT(4)
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /* DRNG_DATA_0 ~ DNG_DATA_7 */
90*4882a593Smuzhiyun #define RKRNG_DRNG_DATA_0			0x0070
91*4882a593Smuzhiyun #define RKRNG_DRNG_DATA_7			0x008C
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun /* end of RKRNG register define */
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun #define RK_RNG_TIME_OUT	50000  /* max 50ms */
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun #define trng_write(pdata, pos, val)	writel(val, (pdata)->base + (pos))
98*4882a593Smuzhiyun #define trng_read(pdata, pos)		readl((pdata)->base + (pos))
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun struct rk_rng_soc_data {
101*4882a593Smuzhiyun 	int (*rk_rng_init)(struct udevice *dev);
102*4882a593Smuzhiyun 	int (*rk_rng_read)(struct udevice *dev, void *data, size_t len);
103*4882a593Smuzhiyun };
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun struct rk_rng_platdata {
106*4882a593Smuzhiyun 	fdt_addr_t base;
107*4882a593Smuzhiyun 	struct rk_rng_soc_data *soc_data;
108*4882a593Smuzhiyun 	struct clk hclk;
109*4882a593Smuzhiyun };
110*4882a593Smuzhiyun 
rk_rng_do_enable_clk(struct udevice * dev,int enable)111*4882a593Smuzhiyun static int rk_rng_do_enable_clk(struct udevice *dev, int enable)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
114*4882a593Smuzhiyun 	int ret;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	if (!pdata->hclk.dev)
117*4882a593Smuzhiyun 		return 0;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	ret = enable ? clk_enable(&pdata->hclk) : clk_disable(&pdata->hclk);
120*4882a593Smuzhiyun 	if (ret == -ENOSYS || !ret)
121*4882a593Smuzhiyun 		return 0;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	printf("rk rng: failed to %s clk, ret=%d\n",
124*4882a593Smuzhiyun 	       enable ? "enable" : "disable", ret);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	return ret;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
rk_rng_enable_clk(struct udevice * dev)129*4882a593Smuzhiyun static int rk_rng_enable_clk(struct udevice *dev)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	return rk_rng_do_enable_clk(dev, 1);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun 
rk_rng_disable_clk(struct udevice * dev)134*4882a593Smuzhiyun static int rk_rng_disable_clk(struct udevice *dev)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun 	return rk_rng_do_enable_clk(dev, 0);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
rk_rng_read_regs(fdt_addr_t addr,void * buf,size_t size)139*4882a593Smuzhiyun static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun 	u32 count = RK_HW_RNG_MAX / sizeof(u32);
142*4882a593Smuzhiyun 	u32 reg, tmp_len;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	if (size > RK_HW_RNG_MAX)
145*4882a593Smuzhiyun 		return -EINVAL;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	while (size && count) {
148*4882a593Smuzhiyun 		reg = readl(addr);
149*4882a593Smuzhiyun 		tmp_len = min(size, sizeof(u32));
150*4882a593Smuzhiyun 		memcpy(buf, &reg, tmp_len);
151*4882a593Smuzhiyun 		addr += sizeof(u32);
152*4882a593Smuzhiyun 		buf += tmp_len;
153*4882a593Smuzhiyun 		size -= tmp_len;
154*4882a593Smuzhiyun 		count--;
155*4882a593Smuzhiyun 	}
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	return 0;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun 
cryptov1_rng_read(struct udevice * dev,void * data,size_t len)160*4882a593Smuzhiyun static int cryptov1_rng_read(struct udevice *dev, void *data, size_t len)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
163*4882a593Smuzhiyun 	u32 reg = 0;
164*4882a593Smuzhiyun 	int retval;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	if (len > RK_HW_RNG_MAX)
167*4882a593Smuzhiyun 		return -EINVAL;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	/* enable osc_ring to get entropy, sample period is set as 100 */
170*4882a593Smuzhiyun 	writel(CRYPTO_V1_OSC_ENABLE | CRYPTO_V1_TRNG_SAMPLE_PERIOD(100),
171*4882a593Smuzhiyun 	       pdata->base + CRYPTO_V1_TRNG_CTRL);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	rk_clrsetreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START,
174*4882a593Smuzhiyun 		     CRYPTO_V1_RNG_START);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	retval = readl_poll_timeout(pdata->base + CRYPTO_V1_CTRL, reg,
177*4882a593Smuzhiyun 				    !(reg & CRYPTO_V1_RNG_START),
178*4882a593Smuzhiyun 				    RK_RNG_TIME_OUT);
179*4882a593Smuzhiyun 	if (retval)
180*4882a593Smuzhiyun 		goto exit;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	rk_rng_read_regs(pdata->base + CRYPTO_V1_TRNG_DOUT_0, data, len);
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun exit:
185*4882a593Smuzhiyun 	/* close TRNG */
186*4882a593Smuzhiyun 	rk_clrreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	return 0;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun 
cryptov2_rng_read(struct udevice * dev,void * data,size_t len)191*4882a593Smuzhiyun static int cryptov2_rng_read(struct udevice *dev, void *data, size_t len)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
194*4882a593Smuzhiyun 	u32 reg = 0;
195*4882a593Smuzhiyun 	int retval;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	if (len > RK_HW_RNG_MAX)
198*4882a593Smuzhiyun 		return -EINVAL;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	/* enable osc_ring to get entropy, sample period is set as 100 */
201*4882a593Smuzhiyun 	writel(100, pdata->base + CRYPTO_V2_RNG_SAMPLE_CNT);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	reg |= CRYPTO_V2_RNG_256_BIT_LEN;
204*4882a593Smuzhiyun 	reg |= CRYPTO_V2_RNG_SLOWER_SOC_RING_0;
205*4882a593Smuzhiyun 	reg |= CRYPTO_V2_RNG_ENABLE;
206*4882a593Smuzhiyun 	reg |= CRYPTO_V2_RNG_START;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	rk_clrsetreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff, reg);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	retval = readl_poll_timeout(pdata->base + CRYPTO_V2_RNG_CTL, reg,
211*4882a593Smuzhiyun 				    !(reg & CRYPTO_V2_RNG_START),
212*4882a593Smuzhiyun 				    RK_RNG_TIME_OUT);
213*4882a593Smuzhiyun 	if (retval)
214*4882a593Smuzhiyun 		goto exit;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	rk_rng_read_regs(pdata->base + CRYPTO_V2_RNG_DOUT_0, data, len);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun exit:
219*4882a593Smuzhiyun 	/* close TRNG */
220*4882a593Smuzhiyun 	rk_clrreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	return retval;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
trngv1_init(struct udevice * dev)225*4882a593Smuzhiyun static int trngv1_init(struct udevice *dev)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	u32 status, version;
228*4882a593Smuzhiyun 	u32 auto_reseed_cnt = 1000;
229*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	version = trng_read(pdata, TRNG_V1_VERSION);
232*4882a593Smuzhiyun 	if (version != TRNG_v1_VERSION_CODE) {
233*4882a593Smuzhiyun 		printf("wrong trng version, expected = %08x, actual = %08x",
234*4882a593Smuzhiyun 		       TRNG_V1_VERSION, version);
235*4882a593Smuzhiyun 		return -EFAULT;
236*4882a593Smuzhiyun 	}
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	/* wait in case of RND_RDY triggered at firs power on */
239*4882a593Smuzhiyun 	readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, status,
240*4882a593Smuzhiyun 			   (status & TRNG_V1_ISTAT_RAND_RDY),
241*4882a593Smuzhiyun 			   RK_RNG_TIME_OUT);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	/* clear RAND_RDY flag for first power on */
244*4882a593Smuzhiyun 	trng_write(pdata, TRNG_V1_ISTAT, status);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	/* auto reseed after (auto_reseed_cnt * 16) byte rand generate */
247*4882a593Smuzhiyun 	trng_write(pdata, TRNG_V1_AUTO_RQSTS, auto_reseed_cnt);
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	return 0;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
trngv1_rng_read(struct udevice * dev,void * data,size_t len)252*4882a593Smuzhiyun static int trngv1_rng_read(struct udevice *dev, void *data, size_t len)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
255*4882a593Smuzhiyun 	u32 reg = 0;
256*4882a593Smuzhiyun 	int retval;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	if (len > RK_HW_RNG_MAX)
259*4882a593Smuzhiyun 		return -EINVAL;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	trng_write(pdata, TRNG_V1_MODE, TRNG_V1_MODE_256_BIT);
262*4882a593Smuzhiyun 	trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_RAND);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	retval = readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, reg,
265*4882a593Smuzhiyun 				    (reg & TRNG_V1_ISTAT_RAND_RDY),
266*4882a593Smuzhiyun 				    RK_RNG_TIME_OUT);
267*4882a593Smuzhiyun 	/* clear ISTAT */
268*4882a593Smuzhiyun 	trng_write(pdata, TRNG_V1_ISTAT, reg);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	if (retval)
271*4882a593Smuzhiyun 		goto exit;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	rk_rng_read_regs(pdata->base + TRNG_V1_RAND0, data, len);
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun exit:
276*4882a593Smuzhiyun 	/* close TRNG */
277*4882a593Smuzhiyun 	trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_NOP);
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	return retval;
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
rkrng_init(struct udevice * dev)282*4882a593Smuzhiyun static int rkrng_init(struct udevice *dev)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
285*4882a593Smuzhiyun 	u32 reg = 0;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	reg = trng_read(pdata, RKRNG_STATE);
290*4882a593Smuzhiyun 	trng_write(pdata, RKRNG_STATE, reg);
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	return 0;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun 
rkrng_rng_read(struct udevice * dev,void * data,size_t len)295*4882a593Smuzhiyun static int rkrng_rng_read(struct udevice *dev, void *data, size_t len)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
298*4882a593Smuzhiyun 	u32 reg = 0;
299*4882a593Smuzhiyun 	int retval;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	if (len > RK_HW_RNG_MAX)
302*4882a593Smuzhiyun 		return -EINVAL;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	rk_rng_enable_clk(dev);
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	reg = RKRNG_CTRL_SW_DRNG_REQ;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	rk_clrsetreg(pdata->base + RKRNG_CTRL, 0xffff, reg);
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	retval = readl_poll_timeout(pdata->base + RKRNG_STATE, reg,
311*4882a593Smuzhiyun 				    (reg & RKRNG_STATE_SW_DRNG_ACK),
312*4882a593Smuzhiyun 				    RK_RNG_TIME_OUT);
313*4882a593Smuzhiyun 	if (retval)
314*4882a593Smuzhiyun 		goto exit;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	trng_write(pdata, RKRNG_STATE, reg);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	rk_rng_read_regs(pdata->base + RKRNG_DRNG_DATA_0, data, len);
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun exit:
321*4882a593Smuzhiyun 	/* close TRNG */
322*4882a593Smuzhiyun 	rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	rk_rng_disable_clk(dev);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	return retval;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun 
rockchip_rng_read(struct udevice * dev,void * data,size_t len)329*4882a593Smuzhiyun static int rockchip_rng_read(struct udevice *dev, void *data, size_t len)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	unsigned char *buf = data;
332*4882a593Smuzhiyun 	unsigned int i;
333*4882a593Smuzhiyun 	int ret = -EIO;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if (!len)
338*4882a593Smuzhiyun 		return 0;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	if (!pdata->soc_data || !pdata->soc_data->rk_rng_read)
341*4882a593Smuzhiyun 		return -EINVAL;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	for (i = 0; i < len / RK_HW_RNG_MAX; i++, buf += RK_HW_RNG_MAX) {
344*4882a593Smuzhiyun 		ret = pdata->soc_data->rk_rng_read(dev, buf, RK_HW_RNG_MAX);
345*4882a593Smuzhiyun 		if (ret)
346*4882a593Smuzhiyun 			goto exit;
347*4882a593Smuzhiyun 	}
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	if (len % RK_HW_RNG_MAX)
350*4882a593Smuzhiyun 		ret = pdata->soc_data->rk_rng_read(dev, buf,
351*4882a593Smuzhiyun 						   len % RK_HW_RNG_MAX);
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun exit:
354*4882a593Smuzhiyun 	return ret;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
rockchip_rng_ofdata_to_platdata(struct udevice * dev)357*4882a593Smuzhiyun static int rockchip_rng_ofdata_to_platdata(struct udevice *dev)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	memset(pdata, 0x00, sizeof(*pdata));
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	pdata->base = (fdt_addr_t)dev_read_addr_ptr(dev);
364*4882a593Smuzhiyun 	if (!pdata->base)
365*4882a593Smuzhiyun 		return -ENOMEM;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	clk_get_by_index(dev, 0, &pdata->hclk);
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun 	return 0;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun 
rockchip_rng_probe(struct udevice * dev)372*4882a593Smuzhiyun static int rockchip_rng_probe(struct udevice *dev)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun 	struct rk_rng_platdata *pdata = dev_get_priv(dev);
375*4882a593Smuzhiyun 	int ret = 0;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun 	pdata->soc_data = (struct rk_rng_soc_data *)dev_get_driver_data(dev);
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 	if (pdata->soc_data->rk_rng_init)
380*4882a593Smuzhiyun 		ret = pdata->soc_data->rk_rng_init(dev);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	return ret;
383*4882a593Smuzhiyun }
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun static const struct rk_rng_soc_data cryptov1_soc_data = {
386*4882a593Smuzhiyun 	.rk_rng_read = cryptov1_rng_read,
387*4882a593Smuzhiyun };
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun static const struct rk_rng_soc_data cryptov2_soc_data = {
390*4882a593Smuzhiyun 	.rk_rng_read = cryptov2_rng_read,
391*4882a593Smuzhiyun };
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun static const struct rk_rng_soc_data trngv1_soc_data = {
394*4882a593Smuzhiyun 	.rk_rng_init = trngv1_init,
395*4882a593Smuzhiyun 	.rk_rng_read = trngv1_rng_read,
396*4882a593Smuzhiyun };
397*4882a593Smuzhiyun 
398*4882a593Smuzhiyun static const struct rk_rng_soc_data rkrng_soc_data = {
399*4882a593Smuzhiyun 	.rk_rng_init = rkrng_init,
400*4882a593Smuzhiyun 	.rk_rng_read = rkrng_rng_read,
401*4882a593Smuzhiyun };
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun static const struct dm_rng_ops rockchip_rng_ops = {
404*4882a593Smuzhiyun 	.read = rockchip_rng_read,
405*4882a593Smuzhiyun };
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun static const struct udevice_id rockchip_rng_match[] = {
408*4882a593Smuzhiyun 	{
409*4882a593Smuzhiyun 		.compatible = "rockchip,cryptov1-rng",
410*4882a593Smuzhiyun 		.data = (ulong)&cryptov1_soc_data,
411*4882a593Smuzhiyun 	},
412*4882a593Smuzhiyun 	{
413*4882a593Smuzhiyun 		.compatible = "rockchip,cryptov2-rng",
414*4882a593Smuzhiyun 		.data = (ulong)&cryptov2_soc_data,
415*4882a593Smuzhiyun 	},
416*4882a593Smuzhiyun 	{
417*4882a593Smuzhiyun 		.compatible = "rockchip,trngv1",
418*4882a593Smuzhiyun 		.data = (ulong)&trngv1_soc_data,
419*4882a593Smuzhiyun 	},
420*4882a593Smuzhiyun 	{
421*4882a593Smuzhiyun 		.compatible = "rockchip,rkrng",
422*4882a593Smuzhiyun 		.data = (ulong)&rkrng_soc_data,
423*4882a593Smuzhiyun 	},
424*4882a593Smuzhiyun 	{},
425*4882a593Smuzhiyun };
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun U_BOOT_DRIVER(rockchip_rng) = {
428*4882a593Smuzhiyun 	.name = "rockchip-rng",
429*4882a593Smuzhiyun 	.id = UCLASS_RNG,
430*4882a593Smuzhiyun 	.of_match = rockchip_rng_match,
431*4882a593Smuzhiyun 	.ops = &rockchip_rng_ops,
432*4882a593Smuzhiyun 	.probe = rockchip_rng_probe,
433*4882a593Smuzhiyun 	.ofdata_to_platdata = rockchip_rng_ofdata_to_platdata,
434*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rk_rng_platdata),
435*4882a593Smuzhiyun };
436