.. | .. |
---|
2 | 2 | /* |
---|
3 | 3 | * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd |
---|
4 | 4 | */ |
---|
| 5 | +#include <common.h> |
---|
| 6 | +#include <clk-uclass.h> |
---|
| 7 | +#include <dm.h> |
---|
| 8 | +#include <rng.h> |
---|
5 | 9 | #include <asm/arch-rockchip/hardware.h> |
---|
6 | 10 | #include <asm/io.h> |
---|
7 | | -#include <common.h> |
---|
8 | | -#include <dm.h> |
---|
9 | 11 | #include <linux/iopoll.h> |
---|
10 | 12 | #include <linux/string.h> |
---|
11 | | -#include <rng.h> |
---|
12 | 13 | |
---|
13 | 14 | #define RK_HW_RNG_MAX 32 |
---|
14 | 15 | |
---|
.. | .. |
---|
70 | 71 | #define TRNG_v1_VERSION_CODE 0x46BC |
---|
71 | 72 | /* end of TRNG V1 register define */ |
---|
72 | 73 | |
---|
| 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 | + |
---|
73 | 95 | #define RK_RNG_TIME_OUT 50000 /* max 50ms */ |
---|
74 | 96 | |
---|
75 | 97 | #define trng_write(pdata, pos, val) writel(val, (pdata)->base + (pos)) |
---|
.. | .. |
---|
83 | 105 | struct rk_rng_platdata { |
---|
84 | 106 | fdt_addr_t base; |
---|
85 | 107 | struct rk_rng_soc_data *soc_data; |
---|
| 108 | + struct clk hclk; |
---|
86 | 109 | }; |
---|
| 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 | +} |
---|
87 | 138 | |
---|
88 | 139 | static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size) |
---|
89 | 140 | { |
---|
.. | .. |
---|
106 | 157 | return 0; |
---|
107 | 158 | } |
---|
108 | 159 | |
---|
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) |
---|
110 | 161 | { |
---|
111 | 162 | struct rk_rng_platdata *pdata = dev_get_priv(dev); |
---|
112 | 163 | u32 reg = 0; |
---|
.. | .. |
---|
137 | 188 | return 0; |
---|
138 | 189 | } |
---|
139 | 190 | |
---|
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) |
---|
141 | 192 | { |
---|
142 | 193 | struct rk_rng_platdata *pdata = dev_get_priv(dev); |
---|
143 | 194 | u32 reg = 0; |
---|
.. | .. |
---|
171 | 222 | return retval; |
---|
172 | 223 | } |
---|
173 | 224 | |
---|
174 | | -static int rk_trngv1_init(struct udevice *dev) |
---|
| 225 | +static int trngv1_init(struct udevice *dev) |
---|
175 | 226 | { |
---|
176 | 227 | u32 status, version; |
---|
177 | 228 | u32 auto_reseed_cnt = 1000; |
---|
.. | .. |
---|
198 | 249 | return 0; |
---|
199 | 250 | } |
---|
200 | 251 | |
---|
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) |
---|
202 | 253 | { |
---|
203 | 254 | struct rk_rng_platdata *pdata = dev_get_priv(dev); |
---|
204 | 255 | u32 reg = 0; |
---|
.. | .. |
---|
224 | 275 | exit: |
---|
225 | 276 | /* close TRNG */ |
---|
226 | 277 | 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); |
---|
227 | 325 | |
---|
228 | 326 | return retval; |
---|
229 | 327 | } |
---|
.. | .. |
---|
266 | 364 | if (!pdata->base) |
---|
267 | 365 | return -ENOMEM; |
---|
268 | 366 | |
---|
| 367 | + clk_get_by_index(dev, 0, &pdata->hclk); |
---|
| 368 | + |
---|
269 | 369 | return 0; |
---|
270 | 370 | } |
---|
271 | 371 | |
---|
.. | .. |
---|
282 | 382 | return ret; |
---|
283 | 383 | } |
---|
284 | 384 | |
---|
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, |
---|
287 | 387 | }; |
---|
288 | 388 | |
---|
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, |
---|
291 | 391 | }; |
---|
292 | 392 | |
---|
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, |
---|
296 | 401 | }; |
---|
297 | 402 | |
---|
298 | 403 | static const struct dm_rng_ops rockchip_rng_ops = { |
---|
.. | .. |
---|
302 | 407 | static const struct udevice_id rockchip_rng_match[] = { |
---|
303 | 408 | { |
---|
304 | 409 | .compatible = "rockchip,cryptov1-rng", |
---|
305 | | - .data = (ulong)&rk_cryptov1_soc_data, |
---|
| 410 | + .data = (ulong)&cryptov1_soc_data, |
---|
306 | 411 | }, |
---|
307 | 412 | { |
---|
308 | 413 | .compatible = "rockchip,cryptov2-rng", |
---|
309 | | - .data = (ulong)&rk_cryptov2_soc_data, |
---|
| 414 | + .data = (ulong)&cryptov2_soc_data, |
---|
310 | 415 | }, |
---|
311 | 416 | { |
---|
312 | 417 | .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, |
---|
314 | 423 | }, |
---|
315 | 424 | {}, |
---|
316 | 425 | }; |
---|