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
5555 bool has_cond_reset;
5656 };
5757
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+
5871 struct stm32_rng_private {
5972 struct hwrng rng;
6073 void __iomem *base;
6174 struct clk *clk;
6275 struct reset_control *rst;
76+ struct stm32_rng_config pm_conf;
6377 const struct stm32_rng_data *data;
6478 bool ced;
6579 bool lock_conf;
@@ -355,11 +369,10 @@ static int stm32_rng_remove(struct platform_device *ofdev) · 289 unmodified lines
355369 return 0;
356370 }
357371
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)
360373 {
361− u32 reg;
362374 struct stm32_rng_private *priv = dev_get_drvdata(dev);
375+ u32 reg;
363376
364377 reg = readl_relaxed(priv->base + RNG_CR);
365378 reg &= ~RNG_CR_RNGEN;
@@ -369,25 +382,98 @@ static int stm32_rng_runtime_suspend(struct device *dev) · 3 unmodified lines
369382 return 0;
370383 }
371384
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)
373405 {
374− u32 reg;
375406 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);
376416
377− clk_prepare_enable(priv->clk);
378417 reg = readl_relaxed(priv->base + RNG_CR);
379418 reg |= RNG_CR_RNGEN;
380419 writel_relaxed(reg, priv->base + RNG_CR);
381420
382421 return 0;
383422 }
384−#endif
385423
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 = {
387473 SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend,
388474 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)
391477 };
392478
393479 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
467553 static struct platform_driver stm32_rng_driver = {
468554 .driver = {
469555 .name = "stm32-rng",
470− .pm = &stm32_rng_pm_ops,
556+ .pm = pm_ptr(&stm32_rng_pm_ops),
471557 .of_match_table = stm32_rng_match,
472558 },
473559 .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