Implement stm32_rng_suspend()/stm32_rng_resume() low-power APIs called when the hardware block context will be lost. There is no need to save the RNG_CR register in stm32_rng_runtime_suspend() as the context is not lost. Therefore, only enable/disable the RNG in the runtime sequences.
Showing the changes to drivers/char (1 of 1 file). Show all
Unified · Split
| @@ -55,11 +55,25 @@ struct stm32_rng_data { · 54 unmodified lines | ||
| 55 | 55 | bool has_cond_reset; |
| 56 | 56 | }; |
| 57 | 57 | |
| 58 | +/** | |
| 59 | + * struct stm32_rng_config - RNG configuration data | |
| 60 | + * | |
| 61 | + * @cr: RNG configuration. 0 means default hardware RNG configuration | |
| 62 | + * @nscr: Noise sources control configuration. | |
| 63 | + * @htcr: Health tests configuration. | |
| 64 | + */ | |
| 65 | +struct stm32_rng_config { | |
| 66 | + u32 cr; | |
| 67 | + u32 nscr; | |
| 68 | + u32 htcr; | |
| 69 | +}; | |
| 70 | + | |
| 58 | 71 | struct stm32_rng_private { |
| 59 | 72 | struct hwrng rng; |
| 60 | 73 | void __iomem *base; |
| 61 | 74 | struct clk *clk; |
| 62 | 75 | struct reset_control *rst; |
| 76 | + struct stm32_rng_config pm_conf; | |
| 63 | 77 | const struct stm32_rng_data *data; |
| 64 | 78 | bool ced; |
| 65 | 79 | bool lock_conf; |
| @@ -355,11 +369,10 @@ static int stm32_rng_remove(struct platform_device *ofdev) · 289 unmodified lines | ||
| 355 | 369 | return 0; |
| 356 | 370 | } |
| 357 | 371 | |
| 358 | −#ifdef CONFIG_PM | |
| 359 | −static int stm32_rng_runtime_suspend(struct device *dev) | |
| 372 | +static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev) | |
| 360 | 373 | { |
| 361 | − u32 reg; | |
| 362 | 374 | struct stm32_rng_private *priv = dev_get_drvdata(dev); |
| 375 | + u32 reg; | |
| 363 | 376 | |
| 364 | 377 | reg = readl_relaxed(priv->base + RNG_CR); |
| 365 | 378 | reg &= ~RNG_CR_RNGEN; |
| @@ -369,25 +382,98 @@ static int stm32_rng_runtime_suspend(struct device *dev) · 3 unmodified lines | ||
| 369 | 382 | return 0; |
| 370 | 383 | } |
| 371 | 384 | |
| 372 | −static int stm32_rng_runtime_resume(struct device *dev) | |
| 385 | +static int __maybe_unused stm32_rng_suspend(struct device *dev) | |
| 386 | +{ | |
| 387 | + struct stm32_rng_private *priv = dev_get_drvdata(dev); | |
| 388 | + | |
| 389 | + if (priv->data->has_cond_reset) { | |
| 390 | + priv->pm_conf.nscr = readl_relaxed(priv->base + RNG_NSCR); | |
| 391 | + priv->pm_conf.htcr = readl_relaxed(priv->base + RNG_HTCR); | |
| 392 | + } | |
| 393 | + | |
| 394 | + /* Do not save that RNG is enabled as it will be handled at resume */ | |
| 395 | + priv->pm_conf.cr = readl_relaxed(priv->base + RNG_CR) & ~RNG_CR_RNGEN; | |
| 396 | + | |
| 397 | + writel_relaxed(priv->pm_conf.cr, priv->base + RNG_CR); | |
| 398 | + | |
| 399 | + clk_disable_unprepare(priv->clk); | |
| 400 | + | |
| 401 | + return 0; | |
| 402 | +} | |
| 403 | + | |
| 404 | +static int __maybe_unused stm32_rng_runtime_resume(struct device *dev) | |
| 373 | 405 | { |
| 374 | − u32 reg; | |
| 375 | 406 | struct stm32_rng_private *priv = dev_get_drvdata(dev); |
| 407 | + int err; | |
| 408 | + u32 reg; | |
| 409 | + | |
| 410 | + err = clk_prepare_enable(priv->clk); | |
| 411 | + if (err) | |
| 412 | + return err; | |
| 413 | + | |
| 414 | + /* Clean error indications */ | |
| 415 | + writel_relaxed(0, priv->base + RNG_SR); | |
| 376 | 416 | |
| 377 | − clk_prepare_enable(priv->clk); | |
| 378 | 417 | reg = readl_relaxed(priv->base + RNG_CR); |
| 379 | 418 | reg |= RNG_CR_RNGEN; |
| 380 | 419 | writel_relaxed(reg, priv->base + RNG_CR); |
| 381 | 420 | |
| 382 | 421 | return 0; |
| 383 | 422 | } |
| 384 | −#endif | |
| 385 | 423 | |
| 386 | −static const struct dev_pm_ops stm32_rng_pm_ops = { | |
| 424 | +static int __maybe_unused stm32_rng_resume(struct device *dev) | |
| 425 | +{ | |
| 426 | + struct stm32_rng_private *priv = dev_get_drvdata(dev); | |
| 427 | + int err; | |
| 428 | + u32 reg; | |
| 429 | + | |
| 430 | + err = clk_prepare_enable(priv->clk); | |
| 431 | + if (err) | |
| 432 | + return err; | |
| 433 | + | |
| 434 | + /* Clean error indications */ | |
| 435 | + writel_relaxed(0, priv->base + RNG_SR); | |
| 436 | + | |
| 437 | + if (priv->data->has_cond_reset) { | |
| 438 | + /* | |
| 439 | + * Correct configuration in bits [29:4] must be set in the same | |
| 440 | + * access that set RNG_CR_CONDRST bit. Else config setting is | |
| 441 | + * not taken into account. CONFIGLOCK bit must also be unset but | |
| 442 | + * it is not handled at the moment. | |
| 443 | + */ | |
| 444 | + writel_relaxed(priv->pm_conf.cr | RNG_CR_CONDRST, priv->base + RNG_CR); | |
| 445 | + | |
| 446 | + writel_relaxed(priv->pm_conf.nscr, priv->base + RNG_NSCR); | |
| 447 | + writel_relaxed(priv->pm_conf.htcr, priv->base + RNG_HTCR); | |
| 448 | + | |
| 449 | + reg = readl_relaxed(priv->base + RNG_CR); | |
| 450 | + reg |= RNG_CR_RNGEN; | |
| 451 | + reg &= ~RNG_CR_CONDRST; | |
| 452 | + writel_relaxed(reg, priv->base + RNG_CR); | |
| 453 | + | |
| 454 | + err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg, | |
| 455 | + reg & ~RNG_CR_CONDRST, 10, 100000); | |
| 456 | + | |
| 457 | + if (err) { | |
| 458 | + clk_disable_unprepare(priv->clk); | |
| 459 | + dev_err((struct device *)priv->rng.priv, | |
| 460 | + "%s: timeout:%x CR: %x!\n", __func__, err, reg); | |
| 461 | + return -EINVAL; | |
| 462 | + } | |
| 463 | + } else { | |
| 464 | + reg = priv->pm_conf.cr; | |
| 465 | + reg |= RNG_CR_RNGEN; | |
| 466 | + writel_relaxed(reg, priv->base + RNG_CR); | |
| 467 | + } | |
| 468 | + | |
| 469 | + return 0; | |
| 470 | +} | |
| 471 | + | |
| 472 | +static const struct dev_pm_ops __maybe_unused stm32_rng_pm_ops = { | |
| 387 | 473 | SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend, |
| 388 | 474 | stm32_rng_runtime_resume, NULL) |
| 389 | − SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, | |
| 390 | − pm_runtime_force_resume) | |
| 475 | + SET_SYSTEM_SLEEP_PM_OPS(stm32_rng_suspend, | |
| 476 | + stm32_rng_resume) | |
| 391 | 477 | }; |
| 392 | 478 | |
| 393 | 479 | static const struct stm32_rng_data stm32mp13_rng_data = { |
| @@ -467,7 +553,7 @@ static int stm32_rng_probe(struct platform_device *ofdev) · 73 unmodified lines | ||
| 467 | 553 | static struct platform_driver stm32_rng_driver = { |
| 468 | 554 | .driver = { |
| 469 | 555 | .name = "stm32-rng", |
| 470 | − .pm = &stm32_rng_pm_ops, | |
| 556 | + .pm = pm_ptr(&stm32_rng_pm_ops), | |
| 471 | 557 | .of_match_table = stm32_rng_match, |
| 472 | 558 | }, |
| 473 | 559 | .probe = stm32_rng_probe, |