History

hwrng: stm32 - rework power management sequences

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.

Gatien Chevallier committed 3 years ago

Commit ff4e4611 parent a1b03e71 file · +97 −11Browse files

Unified · Split

drivers/char/hw_random/stm32-rng.c+97−11
@@ -55,11 +55,25 @@ struct stm32_rng_data { · 54 unmodified lines
55 bool has_cond_reset;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 */
65struct stm32_rng_config {
66 u32 cr;
67 u32 nscr;
68 u32 htcr;
69};
70
58struct stm32_rng_private {71struct stm32_rng_private {
59 struct hwrng rng;72 struct hwrng rng;
60 void __iomem *base;73 void __iomem *base;
61 struct clk *clk;74 struct clk *clk;
62 struct reset_control *rst;75 struct reset_control *rst;
76 struct stm32_rng_config pm_conf;
63 const struct stm32_rng_data *data;77 const struct stm32_rng_data *data;
64 bool ced;78 bool ced;
65 bool lock_conf;79 bool lock_conf;
@@ -355,11 +369,10 @@ static int stm32_rng_remove(struct platform_device *ofdev) · 289 unmodified lines
355 return 0;369 return 0;
356}370}
357 371
358#ifdef CONFIG_PM372static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev)
359static int stm32_rng_runtime_suspend(struct device *dev)
360{373{
361 u32 reg;
362 struct stm32_rng_private *priv = dev_get_drvdata(dev);374 struct stm32_rng_private *priv = dev_get_drvdata(dev);
375 u32 reg;
363 376
364 reg = readl_relaxed(priv->base + RNG_CR);377 reg = readl_relaxed(priv->base + RNG_CR);
365 reg &= ~RNG_CR_RNGEN;378 reg &= ~RNG_CR_RNGEN;
@@ -369,25 +382,98 @@ static int stm32_rng_runtime_suspend(struct device *dev) · 3 unmodified lines
369 return 0;382 return 0;
370}383}
371 384
372static int stm32_rng_runtime_resume(struct device *dev)385static 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
404static int __maybe_unused stm32_rng_runtime_resume(struct device *dev)
373{405{
374 u32 reg;
375 struct stm32_rng_private *priv = dev_get_drvdata(dev);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 reg = readl_relaxed(priv->base + RNG_CR);417 reg = readl_relaxed(priv->base + RNG_CR);
379 reg |= RNG_CR_RNGEN;418 reg |= RNG_CR_RNGEN;
380 writel_relaxed(reg, priv->base + RNG_CR);419 writel_relaxed(reg, priv->base + RNG_CR);
381 420
382 return 0;421 return 0;
383}422}
384#endif
385 423
386static const struct dev_pm_ops stm32_rng_pm_ops = {424static 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
472static const struct dev_pm_ops __maybe_unused stm32_rng_pm_ops = {
387 SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend,473 SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend,
388 stm32_rng_runtime_resume, NULL)474 stm32_rng_runtime_resume, NULL)
389 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,475 SET_SYSTEM_SLEEP_PM_OPS(stm32_rng_suspend,
390 pm_runtime_force_resume)476 stm32_rng_resume)
391};477};
392 478
393static const struct stm32_rng_data stm32mp13_rng_data = {479static const struct stm32_rng_data stm32mp13_rng_data = {
@@ -467,7 +553,7 @@ static int stm32_rng_probe(struct platform_device *ofdev) · 73 unmodified lines
467static struct platform_driver stm32_rng_driver = {553static struct platform_driver stm32_rng_driver = {
468 .driver = {554 .driver = {
469 .name = "stm32-rng",555 .name = "stm32-rng",
470 .pm = &stm32_rng_pm_ops,556 .pm = pm_ptr(&stm32_rng_pm_ops),
471 .of_match_table = stm32_rng_match,557 .of_match_table = stm32_rng_match,
472 },558 },
473 .probe = stm32_rng_probe,559 .probe = stm32_rng_probe,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t