hc
2024-05-10 23fa18eaa71266feff7ba8d83022d9e1cc83c65a
u-boot/drivers/rng/rockchip_rng.c
....@@ -2,13 +2,14 @@
22 /*
33 * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
44 */
5
+#include <common.h>
6
+#include <clk-uclass.h>
7
+#include <dm.h>
8
+#include <rng.h>
59 #include <asm/arch-rockchip/hardware.h>
610 #include <asm/io.h>
7
-#include <common.h>
8
-#include <dm.h>
911 #include <linux/iopoll.h>
1012 #include <linux/string.h>
11
-#include <rng.h>
1213
1314 #define RK_HW_RNG_MAX 32
1415
....@@ -70,6 +71,27 @@
7071 #define TRNG_v1_VERSION_CODE 0x46BC
7172 /* end of TRNG V1 register define */
7273
74
+/* start of RKRNG register define */
75
+#define RKRNG_CTRL 0x0010
76
+#define RKRNG_CTRL_INST_REQ BIT(0)
77
+#define RKRNG_CTRL_RESEED_REQ BIT(1)
78
+#define RKRNG_CTRL_TEST_REQ BIT(2)
79
+#define RKRNG_CTRL_SW_DRNG_REQ BIT(3)
80
+#define RKRNG_CTRL_SW_TRNG_REQ BIT(4)
81
+
82
+#define RKRNG_STATE 0x0014
83
+#define RKRNG_STATE_INST_ACK BIT(0)
84
+#define RKRNG_STATE_RESEED_ACK BIT(1)
85
+#define RKRNG_STATE_TEST_ACK BIT(2)
86
+#define RKRNG_STATE_SW_DRNG_ACK BIT(3)
87
+#define RKRNG_STATE_SW_TRNG_ACK BIT(4)
88
+
89
+/* DRNG_DATA_0 ~ DNG_DATA_7 */
90
+#define RKRNG_DRNG_DATA_0 0x0070
91
+#define RKRNG_DRNG_DATA_7 0x008C
92
+
93
+/* end of RKRNG register define */
94
+
7395 #define RK_RNG_TIME_OUT 50000 /* max 50ms */
7496
7597 #define trng_write(pdata, pos, val) writel(val, (pdata)->base + (pos))
....@@ -83,7 +105,36 @@
83105 struct rk_rng_platdata {
84106 fdt_addr_t base;
85107 struct rk_rng_soc_data *soc_data;
108
+ struct clk hclk;
86109 };
110
+
111
+static int rk_rng_do_enable_clk(struct udevice *dev, int enable)
112
+{
113
+ struct rk_rng_platdata *pdata = dev_get_priv(dev);
114
+ int ret;
115
+
116
+ if (!pdata->hclk.dev)
117
+ return 0;
118
+
119
+ ret = enable ? clk_enable(&pdata->hclk) : clk_disable(&pdata->hclk);
120
+ if (ret == -ENOSYS || !ret)
121
+ return 0;
122
+
123
+ printf("rk rng: failed to %s clk, ret=%d\n",
124
+ enable ? "enable" : "disable", ret);
125
+
126
+ return ret;
127
+}
128
+
129
+static int rk_rng_enable_clk(struct udevice *dev)
130
+{
131
+ return rk_rng_do_enable_clk(dev, 1);
132
+}
133
+
134
+static int rk_rng_disable_clk(struct udevice *dev)
135
+{
136
+ return rk_rng_do_enable_clk(dev, 0);
137
+}
87138
88139 static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size)
89140 {
....@@ -106,7 +157,7 @@
106157 return 0;
107158 }
108159
109
-static int rk_cryptov1_rng_read(struct udevice *dev, void *data, size_t len)
160
+static int cryptov1_rng_read(struct udevice *dev, void *data, size_t len)
110161 {
111162 struct rk_rng_platdata *pdata = dev_get_priv(dev);
112163 u32 reg = 0;
....@@ -137,7 +188,7 @@
137188 return 0;
138189 }
139190
140
-static int rk_cryptov2_rng_read(struct udevice *dev, void *data, size_t len)
191
+static int cryptov2_rng_read(struct udevice *dev, void *data, size_t len)
141192 {
142193 struct rk_rng_platdata *pdata = dev_get_priv(dev);
143194 u32 reg = 0;
....@@ -171,7 +222,7 @@
171222 return retval;
172223 }
173224
174
-static int rk_trngv1_init(struct udevice *dev)
225
+static int trngv1_init(struct udevice *dev)
175226 {
176227 u32 status, version;
177228 u32 auto_reseed_cnt = 1000;
....@@ -198,7 +249,7 @@
198249 return 0;
199250 }
200251
201
-static int rk_trngv1_rng_read(struct udevice *dev, void *data, size_t len)
252
+static int trngv1_rng_read(struct udevice *dev, void *data, size_t len)
202253 {
203254 struct rk_rng_platdata *pdata = dev_get_priv(dev);
204255 u32 reg = 0;
....@@ -224,6 +275,53 @@
224275 exit:
225276 /* close TRNG */
226277 trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_NOP);
278
+
279
+ return retval;
280
+}
281
+
282
+static int rkrng_init(struct udevice *dev)
283
+{
284
+ struct rk_rng_platdata *pdata = dev_get_priv(dev);
285
+ u32 reg = 0;
286
+
287
+ rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
288
+
289
+ reg = trng_read(pdata, RKRNG_STATE);
290
+ trng_write(pdata, RKRNG_STATE, reg);
291
+
292
+ return 0;
293
+}
294
+
295
+static int rkrng_rng_read(struct udevice *dev, void *data, size_t len)
296
+{
297
+ struct rk_rng_platdata *pdata = dev_get_priv(dev);
298
+ u32 reg = 0;
299
+ int retval;
300
+
301
+ if (len > RK_HW_RNG_MAX)
302
+ return -EINVAL;
303
+
304
+ rk_rng_enable_clk(dev);
305
+
306
+ reg = RKRNG_CTRL_SW_DRNG_REQ;
307
+
308
+ rk_clrsetreg(pdata->base + RKRNG_CTRL, 0xffff, reg);
309
+
310
+ retval = readl_poll_timeout(pdata->base + RKRNG_STATE, reg,
311
+ (reg & RKRNG_STATE_SW_DRNG_ACK),
312
+ RK_RNG_TIME_OUT);
313
+ if (retval)
314
+ goto exit;
315
+
316
+ trng_write(pdata, RKRNG_STATE, reg);
317
+
318
+ rk_rng_read_regs(pdata->base + RKRNG_DRNG_DATA_0, data, len);
319
+
320
+exit:
321
+ /* close TRNG */
322
+ rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
323
+
324
+ rk_rng_disable_clk(dev);
227325
228326 return retval;
229327 }
....@@ -266,6 +364,8 @@
266364 if (!pdata->base)
267365 return -ENOMEM;
268366
367
+ clk_get_by_index(dev, 0, &pdata->hclk);
368
+
269369 return 0;
270370 }
271371
....@@ -282,17 +382,22 @@
282382 return ret;
283383 }
284384
285
-static const struct rk_rng_soc_data rk_cryptov1_soc_data = {
286
- .rk_rng_read = rk_cryptov1_rng_read,
385
+static const struct rk_rng_soc_data cryptov1_soc_data = {
386
+ .rk_rng_read = cryptov1_rng_read,
287387 };
288388
289
-static const struct rk_rng_soc_data rk_cryptov2_soc_data = {
290
- .rk_rng_read = rk_cryptov2_rng_read,
389
+static const struct rk_rng_soc_data cryptov2_soc_data = {
390
+ .rk_rng_read = cryptov2_rng_read,
291391 };
292392
293
-static const struct rk_rng_soc_data rk_trngv1_soc_data = {
294
- .rk_rng_init = rk_trngv1_init,
295
- .rk_rng_read = rk_trngv1_rng_read,
393
+static const struct rk_rng_soc_data trngv1_soc_data = {
394
+ .rk_rng_init = trngv1_init,
395
+ .rk_rng_read = trngv1_rng_read,
396
+};
397
+
398
+static const struct rk_rng_soc_data rkrng_soc_data = {
399
+ .rk_rng_init = rkrng_init,
400
+ .rk_rng_read = rkrng_rng_read,
296401 };
297402
298403 static const struct dm_rng_ops rockchip_rng_ops = {
....@@ -302,15 +407,19 @@
302407 static const struct udevice_id rockchip_rng_match[] = {
303408 {
304409 .compatible = "rockchip,cryptov1-rng",
305
- .data = (ulong)&rk_cryptov1_soc_data,
410
+ .data = (ulong)&cryptov1_soc_data,
306411 },
307412 {
308413 .compatible = "rockchip,cryptov2-rng",
309
- .data = (ulong)&rk_cryptov2_soc_data,
414
+ .data = (ulong)&cryptov2_soc_data,
310415 },
311416 {
312417 .compatible = "rockchip,trngv1",
313
- .data = (ulong)&rk_trngv1_soc_data,
418
+ .data = (ulong)&trngv1_soc_data,
419
+ },
420
+ {
421
+ .compatible = "rockchip,rkrng",
422
+ .data = (ulong)&rkrng_soc_data,
314423 },
315424 {},
316425 };