| .. | .. |
|---|
| 87 | 87 | #define TRNG_v1_VERSION_CODE 0x46bc |
|---|
| 88 | 88 | /* end of TRNG_V1 register define */ |
|---|
| 89 | 89 | |
|---|
| 90 | +/* start of RKRNG register define */ |
|---|
| 91 | +#define RKRNG_CTRL 0x0010 |
|---|
| 92 | +#define RKRNG_CTRL_INST_REQ BIT(0) |
|---|
| 93 | +#define RKRNG_CTRL_RESEED_REQ BIT(1) |
|---|
| 94 | +#define RKRNG_CTRL_TEST_REQ BIT(2) |
|---|
| 95 | +#define RKRNG_CTRL_SW_DRNG_REQ BIT(3) |
|---|
| 96 | +#define RKRNG_CTRL_SW_TRNG_REQ BIT(4) |
|---|
| 97 | + |
|---|
| 98 | +#define RKRNG_STATE 0x0014 |
|---|
| 99 | +#define RKRNG_STATE_INST_ACK BIT(0) |
|---|
| 100 | +#define RKRNG_STATE_RESEED_ACK BIT(1) |
|---|
| 101 | +#define RKRNG_STATE_TEST_ACK BIT(2) |
|---|
| 102 | +#define RKRNG_STATE_SW_DRNG_ACK BIT(3) |
|---|
| 103 | +#define RKRNG_STATE_SW_TRNG_ACK BIT(4) |
|---|
| 104 | + |
|---|
| 105 | +/* DRNG_DATA_0 ~ DNG_DATA_7 */ |
|---|
| 106 | +#define RKRNG_DRNG_DATA_0 0x0070 |
|---|
| 107 | +#define RKRNG_DRNG_DATA_7 0x008C |
|---|
| 108 | + |
|---|
| 109 | +/* end of RKRNG register define */ |
|---|
| 110 | + |
|---|
| 90 | 111 | struct rk_rng_soc_data { |
|---|
| 91 | 112 | u32 default_offset; |
|---|
| 92 | 113 | |
|---|
| .. | .. |
|---|
| 178 | 199 | *(u32 *)(buf + i) = be32_to_cpu(rk_rng_readl(rng, offset + i)); |
|---|
| 179 | 200 | } |
|---|
| 180 | 201 | |
|---|
| 181 | | -static int rk_crypto_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait) |
|---|
| 202 | +static int crypto_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait) |
|---|
| 182 | 203 | { |
|---|
| 183 | 204 | int ret = 0; |
|---|
| 184 | 205 | u32 reg_ctrl = 0; |
|---|
| .. | .. |
|---|
| 192 | 213 | |
|---|
| 193 | 214 | rk_rng_writel(rk_rng, reg_ctrl, CRYPTO_V1_CTRL); |
|---|
| 194 | 215 | |
|---|
| 195 | | - ret = readl_poll_timeout(rk_rng->mem + CRYPTO_V1_CTRL, reg_ctrl, |
|---|
| 196 | | - !(reg_ctrl & CRYPTO_V1_RNG_START), |
|---|
| 197 | | - ROCKCHIP_POLL_PERIOD_US, |
|---|
| 198 | | - ROCKCHIP_POLL_TIMEOUT_US); |
|---|
| 216 | + ret = read_poll_timeout(rk_rng_readl, reg_ctrl, |
|---|
| 217 | + !(reg_ctrl & CRYPTO_V1_RNG_START), |
|---|
| 218 | + ROCKCHIP_POLL_PERIOD_US, |
|---|
| 219 | + ROCKCHIP_POLL_TIMEOUT_US, false, |
|---|
| 220 | + rk_rng, CRYPTO_V1_CTRL); |
|---|
| 221 | + |
|---|
| 199 | 222 | if (ret < 0) |
|---|
| 200 | 223 | goto out; |
|---|
| 201 | 224 | |
|---|
| .. | .. |
|---|
| 211 | 234 | return ret; |
|---|
| 212 | 235 | } |
|---|
| 213 | 236 | |
|---|
| 214 | | -static int rk_crypto_v2_read(struct hwrng *rng, void *buf, size_t max, bool wait) |
|---|
| 237 | +static int crypto_v2_read(struct hwrng *rng, void *buf, size_t max, bool wait) |
|---|
| 215 | 238 | { |
|---|
| 216 | 239 | int ret = 0; |
|---|
| 217 | 240 | u32 reg_ctrl = 0; |
|---|
| .. | .. |
|---|
| 228 | 251 | rk_rng_writel(rk_rng, HIWORD_UPDATE(reg_ctrl, 0xffff, 0), |
|---|
| 229 | 252 | CRYPTO_V2_RNG_CTL); |
|---|
| 230 | 253 | |
|---|
| 231 | | - ret = readl_poll_timeout(rk_rng->mem + CRYPTO_V2_RNG_CTL, reg_ctrl, |
|---|
| 232 | | - !(reg_ctrl & CRYPTO_V2_RNG_START), |
|---|
| 233 | | - ROCKCHIP_POLL_PERIOD_US, |
|---|
| 234 | | - ROCKCHIP_POLL_TIMEOUT_US); |
|---|
| 254 | + ret = read_poll_timeout(rk_rng_readl, reg_ctrl, |
|---|
| 255 | + !(reg_ctrl & CRYPTO_V2_RNG_START), |
|---|
| 256 | + ROCKCHIP_POLL_PERIOD_US, |
|---|
| 257 | + ROCKCHIP_POLL_TIMEOUT_US, false, |
|---|
| 258 | + rk_rng, CRYPTO_V2_RNG_CTL); |
|---|
| 235 | 259 | if (ret < 0) |
|---|
| 236 | 260 | goto out; |
|---|
| 237 | 261 | |
|---|
| .. | .. |
|---|
| 246 | 270 | return ret; |
|---|
| 247 | 271 | } |
|---|
| 248 | 272 | |
|---|
| 249 | | -static int rk_trng_v1_init(struct hwrng *rng) |
|---|
| 273 | +static int trng_v1_init(struct hwrng *rng) |
|---|
| 250 | 274 | { |
|---|
| 251 | 275 | int ret; |
|---|
| 252 | 276 | uint32_t auto_reseed_cnt = 1000; |
|---|
| 253 | 277 | uint32_t reg_ctrl, status, version; |
|---|
| 254 | 278 | struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); |
|---|
| 255 | | - |
|---|
| 256 | | - ret = pm_runtime_get_sync(rk_rng->dev); |
|---|
| 257 | | - if (ret < 0) { |
|---|
| 258 | | - pm_runtime_put_noidle(rk_rng->dev); |
|---|
| 259 | | - return ret; |
|---|
| 260 | | - } |
|---|
| 261 | 279 | |
|---|
| 262 | 280 | version = rk_rng_readl(rk_rng, TRNG_V1_VERSION); |
|---|
| 263 | 281 | if (version != TRNG_v1_VERSION_CODE) { |
|---|
| .. | .. |
|---|
| 281 | 299 | udelay(10); |
|---|
| 282 | 300 | |
|---|
| 283 | 301 | /* wait for GENERATING and RESEEDING flag to clear */ |
|---|
| 284 | | - readl_poll_timeout(rk_rng->mem + TRNG_V1_STAT, reg_ctrl, |
|---|
| 285 | | - (reg_ctrl & mask) == TRNG_V1_STAT_SEEDED, |
|---|
| 286 | | - ROCKCHIP_POLL_PERIOD_US, |
|---|
| 287 | | - ROCKCHIP_POLL_TIMEOUT_US); |
|---|
| 302 | + read_poll_timeout(rk_rng_readl, reg_ctrl, |
|---|
| 303 | + (reg_ctrl & mask) == TRNG_V1_STAT_SEEDED, |
|---|
| 304 | + ROCKCHIP_POLL_PERIOD_US, |
|---|
| 305 | + ROCKCHIP_POLL_TIMEOUT_US, false, |
|---|
| 306 | + rk_rng, TRNG_V1_STAT); |
|---|
| 288 | 307 | } |
|---|
| 289 | 308 | |
|---|
| 290 | 309 | /* clear ISTAT flag because trng may auto reseeding when power on */ |
|---|
| .. | .. |
|---|
| 296 | 315 | |
|---|
| 297 | 316 | ret = 0; |
|---|
| 298 | 317 | exit: |
|---|
| 299 | | - pm_runtime_mark_last_busy(rk_rng->dev); |
|---|
| 300 | | - pm_runtime_put_sync_autosuspend(rk_rng->dev); |
|---|
| 301 | 318 | |
|---|
| 302 | 319 | return ret; |
|---|
| 303 | 320 | } |
|---|
| 304 | 321 | |
|---|
| 305 | | -static int rk_trng_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait) |
|---|
| 322 | +static int trng_v1_read(struct hwrng *rng, void *buf, size_t max, bool wait) |
|---|
| 306 | 323 | { |
|---|
| 307 | 324 | int ret = 0; |
|---|
| 308 | 325 | u32 reg_ctrl = 0; |
|---|
| .. | .. |
|---|
| 324 | 341 | reg_ctrl = rk_rng_readl(rk_rng, TRNG_V1_ISTAT); |
|---|
| 325 | 342 | if (!(reg_ctrl & TRNG_V1_ISTAT_RAND_RDY)) { |
|---|
| 326 | 343 | /* wait RAND_RDY triggered */ |
|---|
| 327 | | - ret = readl_poll_timeout(rk_rng->mem + TRNG_V1_ISTAT, reg_ctrl, |
|---|
| 328 | | - (reg_ctrl & TRNG_V1_ISTAT_RAND_RDY), |
|---|
| 329 | | - ROCKCHIP_POLL_PERIOD_US, |
|---|
| 330 | | - ROCKCHIP_POLL_TIMEOUT_US); |
|---|
| 344 | + ret = read_poll_timeout(rk_rng_readl, reg_ctrl, |
|---|
| 345 | + (reg_ctrl & TRNG_V1_ISTAT_RAND_RDY), |
|---|
| 346 | + ROCKCHIP_POLL_PERIOD_US, |
|---|
| 347 | + ROCKCHIP_POLL_TIMEOUT_US, false, |
|---|
| 348 | + rk_rng, TRNG_V1_ISTAT); |
|---|
| 331 | 349 | if (ret < 0) |
|---|
| 332 | 350 | goto out; |
|---|
| 333 | 351 | } |
|---|
| .. | .. |
|---|
| 345 | 363 | return ret; |
|---|
| 346 | 364 | } |
|---|
| 347 | 365 | |
|---|
| 348 | | -static const struct rk_rng_soc_data rk_crypto_v1_soc_data = { |
|---|
| 366 | +static int rkrng_init(struct hwrng *rng) |
|---|
| 367 | +{ |
|---|
| 368 | + struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); |
|---|
| 369 | + u32 reg = 0; |
|---|
| 370 | + |
|---|
| 371 | + rk_rng_writel(rk_rng, HIWORD_UPDATE(0, 0xffff, 0), RKRNG_CTRL); |
|---|
| 372 | + |
|---|
| 373 | + reg = rk_rng_readl(rk_rng, RKRNG_STATE); |
|---|
| 374 | + rk_rng_writel(rk_rng, reg, RKRNG_STATE); |
|---|
| 375 | + |
|---|
| 376 | + return 0; |
|---|
| 377 | +} |
|---|
| 378 | + |
|---|
| 379 | +static int rkrng_read(struct hwrng *rng, void *buf, size_t max, bool wait) |
|---|
| 380 | +{ |
|---|
| 381 | + struct rk_rng *rk_rng = container_of(rng, struct rk_rng, rng); |
|---|
| 382 | + u32 reg_ctrl = 0; |
|---|
| 383 | + int ret; |
|---|
| 384 | + |
|---|
| 385 | + reg_ctrl = RKRNG_CTRL_SW_DRNG_REQ; |
|---|
| 386 | + |
|---|
| 387 | + rk_rng_writel(rk_rng, HIWORD_UPDATE(reg_ctrl, 0xffff, 0), RKRNG_CTRL); |
|---|
| 388 | + |
|---|
| 389 | + ret = readl_poll_timeout(rk_rng->mem + RKRNG_STATE, reg_ctrl, |
|---|
| 390 | + (reg_ctrl & RKRNG_STATE_SW_DRNG_ACK), |
|---|
| 391 | + ROCKCHIP_POLL_PERIOD_US, |
|---|
| 392 | + ROCKCHIP_POLL_TIMEOUT_US); |
|---|
| 393 | + |
|---|
| 394 | + if (ret) |
|---|
| 395 | + goto exit; |
|---|
| 396 | + |
|---|
| 397 | + rk_rng_writel(rk_rng, reg_ctrl, RKRNG_STATE); |
|---|
| 398 | + |
|---|
| 399 | + ret = min_t(size_t, max, RK_MAX_RNG_BYTE); |
|---|
| 400 | + |
|---|
| 401 | + rk_rng_read_regs(rk_rng, RKRNG_DRNG_DATA_0, buf, ret); |
|---|
| 402 | + |
|---|
| 403 | +exit: |
|---|
| 404 | + /* close TRNG */ |
|---|
| 405 | + rk_rng_writel(rk_rng, HIWORD_UPDATE(0, 0xffff, 0), RKRNG_CTRL); |
|---|
| 406 | + |
|---|
| 407 | + return ret; |
|---|
| 408 | +} |
|---|
| 409 | + |
|---|
| 410 | +static const struct rk_rng_soc_data crypto_v1_soc_data = { |
|---|
| 349 | 411 | .default_offset = 0, |
|---|
| 350 | 412 | |
|---|
| 351 | | - .rk_rng_read = rk_crypto_v1_read, |
|---|
| 413 | + .rk_rng_read = crypto_v1_read, |
|---|
| 352 | 414 | }; |
|---|
| 353 | 415 | |
|---|
| 354 | | -static const struct rk_rng_soc_data rk_crypto_v2_soc_data = { |
|---|
| 416 | +static const struct rk_rng_soc_data crypto_v2_soc_data = { |
|---|
| 355 | 417 | .default_offset = CRYPTO_V2_RNG_DEFAULT_OFFSET, |
|---|
| 356 | 418 | |
|---|
| 357 | | - .rk_rng_read = rk_crypto_v2_read, |
|---|
| 419 | + .rk_rng_read = crypto_v2_read, |
|---|
| 358 | 420 | }; |
|---|
| 359 | 421 | |
|---|
| 360 | | -static const struct rk_rng_soc_data rk_trng_v1_soc_data = { |
|---|
| 422 | +static const struct rk_rng_soc_data trng_v1_soc_data = { |
|---|
| 361 | 423 | .default_offset = 0, |
|---|
| 362 | 424 | |
|---|
| 363 | | - .rk_rng_init = rk_trng_v1_init, |
|---|
| 364 | | - .rk_rng_read = rk_trng_v1_read, |
|---|
| 425 | + .rk_rng_init = trng_v1_init, |
|---|
| 426 | + .rk_rng_read = trng_v1_read, |
|---|
| 427 | +}; |
|---|
| 428 | + |
|---|
| 429 | +static const struct rk_rng_soc_data rkrng_soc_data = { |
|---|
| 430 | + .default_offset = 0, |
|---|
| 431 | + |
|---|
| 432 | + .rk_rng_init = rkrng_init, |
|---|
| 433 | + .rk_rng_read = rkrng_read, |
|---|
| 365 | 434 | }; |
|---|
| 366 | 435 | |
|---|
| 367 | 436 | static const struct of_device_id rk_rng_dt_match[] = { |
|---|
| 368 | 437 | { |
|---|
| 369 | 438 | .compatible = "rockchip,cryptov1-rng", |
|---|
| 370 | | - .data = (void *)&rk_crypto_v1_soc_data, |
|---|
| 439 | + .data = (void *)&crypto_v1_soc_data, |
|---|
| 371 | 440 | }, |
|---|
| 372 | 441 | { |
|---|
| 373 | 442 | .compatible = "rockchip,cryptov2-rng", |
|---|
| 374 | | - .data = (void *)&rk_crypto_v2_soc_data, |
|---|
| 443 | + .data = (void *)&crypto_v2_soc_data, |
|---|
| 375 | 444 | }, |
|---|
| 376 | 445 | { |
|---|
| 377 | 446 | .compatible = "rockchip,trngv1", |
|---|
| 378 | | - .data = (void *)&rk_trng_v1_soc_data, |
|---|
| 447 | + .data = (void *)&trng_v1_soc_data, |
|---|
| 448 | + }, |
|---|
| 449 | + { |
|---|
| 450 | + .compatible = "rockchip,rkrng", |
|---|
| 451 | + .data = (void *)&rkrng_soc_data, |
|---|
| 379 | 452 | }, |
|---|
| 380 | 453 | { }, |
|---|
| 381 | 454 | }; |
|---|
| .. | .. |
|---|
| 445 | 518 | } |
|---|
| 446 | 519 | |
|---|
| 447 | 520 | /* for some platform need hardware operation when probe */ |
|---|
| 448 | | - if (rk_rng->soc_data->rk_rng_init) |
|---|
| 521 | + if (rk_rng->soc_data->rk_rng_init) { |
|---|
| 522 | + pm_runtime_get_sync(rk_rng->dev); |
|---|
| 523 | + |
|---|
| 449 | 524 | ret = rk_rng->soc_data->rk_rng_init(&rk_rng->rng); |
|---|
| 450 | 525 | |
|---|
| 526 | + pm_runtime_mark_last_busy(rk_rng->dev); |
|---|
| 527 | + pm_runtime_put_sync_autosuspend(rk_rng->dev); |
|---|
| 528 | + } |
|---|
| 529 | + |
|---|
| 451 | 530 | return ret; |
|---|
| 452 | 531 | } |
|---|
| 453 | 532 | |
|---|