devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms
@ 2023-09-21  8:02 Gatien Chevallier
  2023-09-21  8:02 ` [PATCH v3 1/9] dt-bindings: rng: introduce new compatible for STM32MP13x Gatien Chevallier
                   ` (10 more replies)
  0 siblings, 11 replies; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:02 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

The STM32MP13x platforms have a RNG hardware block that supports
customization, a conditional reset sequences that allows to
recover from certain situations and a configuration locking
mechanism.

This series adds support for the mentionned features. Note that
the hardware RNG can and should be managed in the secure world
for this platform, hence the rng not being default enabled on
the STM32MP135F-DK board.

Changes in V2:
	- Use pm_ptr() and add __maybe_unused on PM API
	- Correct bug using WARN_ON

Changes in V3:
	- Squash of bindings patches
	- st,rng-lock-conf property declaration rework
	- Fix stm32_rng_pm_ops declaration in patch [5/9]

Gatien Chevallier (9):
  dt-bindings: rng: introduce new compatible for STM32MP13x
  hwrng: stm32 - use devm_platform_get_and_ioremap_resource() API
  hwrng: stm32 - implement STM32MP13x support
  hwrng: stm32 - implement error concealment
  hwrng: stm32 - rework error handling in stm32_rng_read()
  hwrng: stm32 - restrain RNG noise source clock
  hwrng: stm32 - support RNG configuration locking mechanism
  hwrng: stm32 - rework power management sequences
  ARM: dts: stm32: add RNG node for STM32MP13x platforms

 .../devicetree/bindings/rng/st,stm32-rng.yaml |  20 +-
 arch/arm/boot/dts/st/stm32mp131.dtsi          |   8 +
 drivers/char/hw_random/stm32-rng.c            | 511 +++++++++++++++---
 3 files changed, 455 insertions(+), 84 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/9] dt-bindings: rng: introduce new compatible for STM32MP13x
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
@ 2023-09-21  8:02 ` Gatien Chevallier
  2023-09-22 20:49   ` Rob Herring
  2023-09-21  8:02 ` [PATCH v3 2/9] hwrng: stm32 - use devm_platform_get_and_ioremap_resource() API Gatien Chevallier
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:02 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

Introduce st,stm32mp13-rng compatible and add st,rng-lock-conf.

If st,rng-lock-conf is set, the RNG configuration in RNG_CR, RNG_HTCR
and RNG_NSCR will be locked. It is supported starting from the RNG
version present in the STM32MP13

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
---

Changes in V3:
	- Squashed with: patch [V2 07/10]
	- Declare st,rng-lock-conf at top level and restrain its uses
	  depending on the compatible. I discarded Rob's tag as for
	  the modifications.	

 .../devicetree/bindings/rng/st,stm32-rng.yaml | 20 ++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
index 187b172d0cca..717f6b321f88 100644
--- a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
@@ -15,7 +15,9 @@ maintainers:
 
 properties:
   compatible:
-    const: st,stm32-rng
+    enum:
+      - st,stm32-rng
+      - st,stm32mp13-rng
 
   reg:
     maxItems: 1
@@ -30,11 +32,27 @@ properties:
     type: boolean
     description: If set enable the clock detection management
 
+  st,rng-lock-conf:
+    type: boolean
+    description: If set, the RNG configuration in RNG_CR, RNG_HTCR and
+                  RNG_NSCR will be locked.
+
 required:
   - compatible
   - reg
   - clocks
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - st,stm32-rng
+    then:
+      properties:
+        st,rng-lock-conf: false
+
 additionalProperties: false
 
 examples:
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 2/9] hwrng: stm32 - use devm_platform_get_and_ioremap_resource() API
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
  2023-09-21  8:02 ` [PATCH v3 1/9] dt-bindings: rng: introduce new compatible for STM32MP13x Gatien Chevallier
@ 2023-09-21  8:02 ` Gatien Chevallier
  2023-09-21  8:02 ` [PATCH v3 3/9] hwrng: stm32 - implement STM32MP13x support Gatien Chevallier
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:02 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

Use devm_platform_get_and_ioremap_resource() to get and ioremap a
resource.

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
---
 drivers/char/hw_random/stm32-rng.c | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index efb6a9f9a11b..d64d25d0fee8 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -118,18 +118,13 @@ static int stm32_rng_probe(struct platform_device *ofdev)
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
 	struct stm32_rng_private *priv;
-	struct resource res;
-	int err;
+	struct resource *res;
 
 	priv = devm_kzalloc(dev, sizeof(struct stm32_rng_private), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
-	err = of_address_to_resource(np, 0, &res);
-	if (err)
-		return err;
-
-	priv->base = devm_ioremap_resource(dev, &res);
+	priv->base = devm_platform_get_and_ioremap_resource(ofdev, 0, &res);
 	if (IS_ERR(priv->base))
 		return PTR_ERR(priv->base);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 3/9] hwrng: stm32 - implement STM32MP13x support
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
  2023-09-21  8:02 ` [PATCH v3 1/9] dt-bindings: rng: introduce new compatible for STM32MP13x Gatien Chevallier
  2023-09-21  8:02 ` [PATCH v3 2/9] hwrng: stm32 - use devm_platform_get_and_ioremap_resource() API Gatien Chevallier
@ 2023-09-21  8:02 ` Gatien Chevallier
  2023-09-21  8:02 ` [PATCH v3 4/9] hwrng: stm32 - implement error concealment Gatien Chevallier
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:02 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

The RNG present on STM32MP13x platforms introduces a customizable
configuration and the conditional reset.

STM32 RNG configuration should best fit the requirements of the
platform. Therefore, put a platform-specific RNG configuration
field in the platform data. Default RNG configuration for STM32MP13
is the NIST certified configuration [1].

While there, fix and the RNG init sequence to support all RNG
versions.

[1] https://csrc.nist.gov/projects/cryptographic-module-validation-program/entropy-validations/certificate/53

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
---
 drivers/char/hw_random/stm32-rng.c | 222 ++++++++++++++++++++---------
 1 file changed, 158 insertions(+), 64 deletions(-)

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index d64d25d0fee8..54bd5807bbac 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -17,22 +17,43 @@
 #include <linux/reset.h>
 #include <linux/slab.h>
 
-#define RNG_CR 0x00
-#define RNG_CR_RNGEN BIT(2)
-#define RNG_CR_CED BIT(5)
-
-#define RNG_SR 0x04
-#define RNG_SR_SEIS BIT(6)
-#define RNG_SR_CEIS BIT(5)
-#define RNG_SR_DRDY BIT(0)
-
-#define RNG_DR 0x08
+#define RNG_CR			0x00
+#define RNG_CR_RNGEN		BIT(2)
+#define RNG_CR_CED		BIT(5)
+#define RNG_CR_CONFIG1		GENMASK(11, 8)
+#define RNG_CR_NISTC		BIT(12)
+#define RNG_CR_CONFIG2		GENMASK(15, 13)
+#define RNG_CR_CONFIG3		GENMASK(25, 20)
+#define RNG_CR_CONDRST		BIT(30)
+#define RNG_CR_CONFLOCK		BIT(31)
+#define RNG_CR_ENTROPY_SRC_MASK	(RNG_CR_CONFIG1 | RNG_CR_NISTC | RNG_CR_CONFIG2 | RNG_CR_CONFIG3)
+#define RNG_CR_CONFIG_MASK	(RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED)
+
+#define RNG_SR		0x04
+#define RNG_SR_SEIS	BIT(6)
+#define RNG_SR_CEIS	BIT(5)
+#define RNG_SR_DRDY	BIT(0)
+
+#define RNG_DR			0x08
+
+#define RNG_NSCR		0x0C
+#define RNG_NSCR_MASK		GENMASK(17, 0)
+
+#define RNG_HTCR		0x10
+
+struct stm32_rng_data {
+	u32	cr;
+	u32	nscr;
+	u32	htcr;
+	bool	has_cond_reset;
+};
 
 struct stm32_rng_private {
 	struct hwrng rng;
 	void __iomem *base;
 	struct clk *clk;
 	struct reset_control *rst;
+	const struct stm32_rng_data *data;
 	bool ced;
 };
 
@@ -87,32 +108,145 @@ static int stm32_rng_init(struct hwrng *rng)
 	struct stm32_rng_private *priv =
 	    container_of(rng, struct stm32_rng_private, rng);
 	int err;
+	u32 reg;
 
 	err = clk_prepare_enable(priv->clk);
 	if (err)
 		return err;
 
-	if (priv->ced)
-		writel_relaxed(RNG_CR_RNGEN, priv->base + RNG_CR);
-	else
-		writel_relaxed(RNG_CR_RNGEN | RNG_CR_CED,
-			       priv->base + RNG_CR);
-
 	/* clear error indicators */
 	writel_relaxed(0, priv->base + RNG_SR);
 
+	reg = readl_relaxed(priv->base + RNG_CR);
+
+	/*
+	 * Keep default RNG configuration if none was specified.
+	 * 0 is an invalid value as it disables all entropy sources.
+	 */
+	if (priv->data->has_cond_reset && priv->data->cr) {
+		reg &= ~RNG_CR_CONFIG_MASK;
+		reg |= RNG_CR_CONDRST | (priv->data->cr & RNG_CR_ENTROPY_SRC_MASK);
+		if (priv->ced)
+			reg &= ~RNG_CR_CED;
+		else
+			reg |= RNG_CR_CED;
+		writel_relaxed(reg, priv->base + RNG_CR);
+
+		/* Health tests and noise control registers */
+		writel_relaxed(priv->data->htcr, priv->base + RNG_HTCR);
+		writel_relaxed(priv->data->nscr & RNG_NSCR_MASK, priv->base + RNG_NSCR);
+
+		reg &= ~RNG_CR_CONDRST;
+		reg |= RNG_CR_RNGEN;
+		writel_relaxed(reg, priv->base + RNG_CR);
+
+		err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg,
+							(!(reg & RNG_CR_CONDRST)),
+							10, 50000);
+		if (err) {
+			dev_err((struct device *)priv->rng.priv,
+				"%s: timeout %x!\n", __func__, reg);
+			return -EINVAL;
+		}
+	} else {
+		/* Handle all RNG versions by checking if conditional reset should be set */
+		if (priv->data->has_cond_reset)
+			reg |= RNG_CR_CONDRST;
+
+		if (priv->ced)
+			reg &= ~RNG_CR_CED;
+		else
+			reg |= RNG_CR_CED;
+
+		writel_relaxed(reg, priv->base + RNG_CR);
+
+		if (priv->data->has_cond_reset)
+			reg &= ~RNG_CR_CONDRST;
+
+		reg |= RNG_CR_RNGEN;
+
+		writel_relaxed(reg, priv->base + RNG_CR);
+	}
+
+	err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, reg,
+						reg & RNG_SR_DRDY,
+						10, 100000);
+	if (err | (reg & ~RNG_SR_DRDY)) {
+		clk_disable_unprepare(priv->clk);
+		dev_err((struct device *)priv->rng.priv,
+			"%s: timeout:%x SR: %x!\n", __func__, err, reg);
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
-static void stm32_rng_cleanup(struct hwrng *rng)
+static int stm32_rng_remove(struct platform_device *ofdev)
 {
-	struct stm32_rng_private *priv =
-	    container_of(rng, struct stm32_rng_private, rng);
+	pm_runtime_disable(&ofdev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int stm32_rng_runtime_suspend(struct device *dev)
+{
+	u32 reg;
+	struct stm32_rng_private *priv = dev_get_drvdata(dev);
 
-	writel_relaxed(0, priv->base + RNG_CR);
+	reg = readl_relaxed(priv->base + RNG_CR);
+	reg &= ~RNG_CR_RNGEN;
+	writel_relaxed(reg, priv->base + RNG_CR);
 	clk_disable_unprepare(priv->clk);
+
+	return 0;
 }
 
+static int stm32_rng_runtime_resume(struct device *dev)
+{
+	u32 reg;
+	struct stm32_rng_private *priv = dev_get_drvdata(dev);
+
+	clk_prepare_enable(priv->clk);
+	reg = readl_relaxed(priv->base + RNG_CR);
+	reg |= RNG_CR_RNGEN;
+	writel_relaxed(reg, priv->base + RNG_CR);
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops stm32_rng_pm_ops = {
+	SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend,
+			   stm32_rng_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+};
+
+static const struct stm32_rng_data stm32mp13_rng_data = {
+	.has_cond_reset = true,
+	.cr = 0x00F00D00,
+	.nscr = 0x2B5BB,
+	.htcr = 0x969D,
+};
+
+static const struct stm32_rng_data stm32_rng_data = {
+	.has_cond_reset = false,
+};
+
+static const struct of_device_id stm32_rng_match[] = {
+	{
+		.compatible = "st,stm32mp13-rng",
+		.data = &stm32mp13_rng_data,
+	},
+	{
+		.compatible = "st,stm32-rng",
+		.data = &stm32_rng_data,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, stm32_rng_match);
+
 static int stm32_rng_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
@@ -141,13 +275,14 @@ static int stm32_rng_probe(struct platform_device *ofdev)
 
 	priv->ced = of_property_read_bool(np, "clock-error-detect");
 
+	priv->data = of_device_get_match_data(dev);
+	if (!priv->data)
+		return -ENODEV;
+
 	dev_set_drvdata(dev, priv);
 
 	priv->rng.name = dev_driver_string(dev);
-#ifndef CONFIG_PM
 	priv->rng.init = stm32_rng_init;
-	priv->rng.cleanup = stm32_rng_cleanup;
-#endif
 	priv->rng.read = stm32_rng_read;
 	priv->rng.priv = (unsigned long) dev;
 	priv->rng.quality = 900;
@@ -159,47 +294,6 @@ static int stm32_rng_probe(struct platform_device *ofdev)
 	return devm_hwrng_register(dev, &priv->rng);
 }
 
-static int stm32_rng_remove(struct platform_device *ofdev)
-{
-	pm_runtime_disable(&ofdev->dev);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int stm32_rng_runtime_suspend(struct device *dev)
-{
-	struct stm32_rng_private *priv = dev_get_drvdata(dev);
-
-	stm32_rng_cleanup(&priv->rng);
-
-	return 0;
-}
-
-static int stm32_rng_runtime_resume(struct device *dev)
-{
-	struct stm32_rng_private *priv = dev_get_drvdata(dev);
-
-	return stm32_rng_init(&priv->rng);
-}
-#endif
-
-static const struct dev_pm_ops stm32_rng_pm_ops = {
-	SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend,
-			   stm32_rng_runtime_resume, NULL)
-	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-				pm_runtime_force_resume)
-};
-
-
-static const struct of_device_id stm32_rng_match[] = {
-	{
-		.compatible = "st,stm32-rng",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, stm32_rng_match);
-
 static struct platform_driver stm32_rng_driver = {
 	.driver = {
 		.name = "stm32-rng",
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 4/9] hwrng: stm32 - implement error concealment
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
                   ` (2 preceding siblings ...)
  2023-09-21  8:02 ` [PATCH v3 3/9] hwrng: stm32 - implement STM32MP13x support Gatien Chevallier
@ 2023-09-21  8:02 ` Gatien Chevallier
  2023-09-21  8:02 ` [PATCH v3 5/9] hwrng: stm32 - rework error handling in stm32_rng_read() Gatien Chevallier
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:02 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

The RNG driver should be capable of recovering from an error. Implement
an error concealment API. This avoids irrecoverable RNG state.

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
---
 drivers/char/hw_random/stm32-rng.c | 114 ++++++++++++++++++++++++++++-
 1 file changed, 110 insertions(+), 4 deletions(-)

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 54bd5807bbac..adefe8edfd07 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -29,10 +29,12 @@
 #define RNG_CR_ENTROPY_SRC_MASK	(RNG_CR_CONFIG1 | RNG_CR_NISTC | RNG_CR_CONFIG2 | RNG_CR_CONFIG3)
 #define RNG_CR_CONFIG_MASK	(RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED)
 
-#define RNG_SR		0x04
-#define RNG_SR_SEIS	BIT(6)
-#define RNG_SR_CEIS	BIT(5)
-#define RNG_SR_DRDY	BIT(0)
+#define RNG_SR			0x04
+#define RNG_SR_DRDY		BIT(0)
+#define RNG_SR_CECS		BIT(1)
+#define RNG_SR_SECS		BIT(2)
+#define RNG_SR_CEIS		BIT(5)
+#define RNG_SR_SEIS		BIT(6)
 
 #define RNG_DR			0x08
 
@@ -57,6 +59,107 @@ struct stm32_rng_private {
 	bool ced;
 };
 
+/*
+ * Extracts from the STM32 RNG specification when RNG supports CONDRST.
+ *
+ * When a noise source (or seed) error occurs, the RNG stops generating
+ * random numbers and sets to “1” both SEIS and SECS bits to indicate
+ * that a seed error occurred. (...)
+ *
+ * 1. Software reset by writing CONDRST at 1 and at 0 (see bitfield
+ * description for details). This step is needed only if SECS is set.
+ * Indeed, when SEIS is set and SECS is cleared it means RNG performed
+ * the reset automatically (auto-reset).
+ * 2. If SECS was set in step 1 (no auto-reset) wait for CONDRST
+ * to be cleared in the RNG_CR register, then confirm that SEIS is
+ * cleared in the RNG_SR register. Otherwise just clear SEIS bit in
+ * the RNG_SR register.
+ * 3. If SECS was set in step 1 (no auto-reset) wait for SECS to be
+ * cleared by RNG. The random number generation is now back to normal.
+ */
+static int stm32_rng_conceal_seed_error_cond_reset(struct stm32_rng_private *priv)
+{
+	struct device *dev = (struct device *)priv->rng.priv;
+	u32 sr = readl_relaxed(priv->base + RNG_SR);
+	u32 cr = readl_relaxed(priv->base + RNG_CR);
+	int err;
+
+	if (sr & RNG_SR_SECS) {
+		/* Conceal by resetting the subsystem (step 1.) */
+		writel_relaxed(cr | RNG_CR_CONDRST, priv->base + RNG_CR);
+		writel_relaxed(cr & ~RNG_CR_CONDRST, priv->base + RNG_CR);
+	} else {
+		/* RNG auto-reset (step 2.) */
+		writel_relaxed(sr & ~RNG_SR_SEIS, priv->base + RNG_SR);
+		goto end;
+	}
+
+	err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, cr, !(cr & RNG_CR_CONDRST), 10,
+						100000);
+	if (err) {
+		dev_err(dev, "%s: timeout %x\n", __func__, sr);
+		return err;
+	}
+
+	/* Check SEIS is cleared (step 2.) */
+	if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS)
+		return -EINVAL;
+
+	err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, sr, !(sr & RNG_SR_SECS), 10,
+						100000);
+	if (err) {
+		dev_err(dev, "%s: timeout %x\n", __func__, sr);
+		return err;
+	}
+
+end:
+	return 0;
+}
+
+/*
+ * Extracts from the STM32 RNG specification, when CONDRST is not supported
+ *
+ * When a noise source (or seed) error occurs, the RNG stops generating
+ * random numbers and sets to “1” both SEIS and SECS bits to indicate
+ * that a seed error occurred. (...)
+ *
+ * The following sequence shall be used to fully recover from a seed
+ * error after the RNG initialization:
+ * 1. Clear the SEIS bit by writing it to “0”.
+ * 2. Read out 12 words from the RNG_DR register, and discard each of
+ * them in order to clean the pipeline.
+ * 3. Confirm that SEIS is still cleared. Random number generation is
+ * back to normal.
+ */
+static int stm32_rng_conceal_seed_error_sw_reset(struct stm32_rng_private *priv)
+{
+	unsigned int i = 0;
+	u32 sr = readl_relaxed(priv->base + RNG_SR);
+
+	writel_relaxed(sr & ~RNG_SR_SEIS, priv->base + RNG_SR);
+
+	for (i = 12; i != 0; i--)
+		(void)readl_relaxed(priv->base + RNG_DR);
+
+	if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int stm32_rng_conceal_seed_error(struct hwrng *rng)
+{
+	struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng);
+
+	dev_dbg((struct device *)priv->rng.priv, "Concealing seed error\n");
+
+	if (priv->data->has_cond_reset)
+		return stm32_rng_conceal_seed_error_cond_reset(priv);
+	else
+		return stm32_rng_conceal_seed_error_sw_reset(priv);
+};
+
+
 static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 {
 	struct stm32_rng_private *priv =
@@ -66,6 +169,9 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 
 	pm_runtime_get_sync((struct device *) priv->rng.priv);
 
+	if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS)
+		stm32_rng_conceal_seed_error(rng);
+
 	while (max >= sizeof(u32)) {
 		sr = readl_relaxed(priv->base + RNG_SR);
 		/* Manage timeout which is based on timer and take */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 5/9] hwrng: stm32 - rework error handling in stm32_rng_read()
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
                   ` (3 preceding siblings ...)
  2023-09-21  8:02 ` [PATCH v3 4/9] hwrng: stm32 - implement error concealment Gatien Chevallier
@ 2023-09-21  8:02 ` Gatien Chevallier
  2023-09-21  8:02 ` [PATCH v3 6/9] hwrng: stm32 - restrain RNG noise source clock Gatien Chevallier
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:02 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

Try to conceal seed errors when possible. If, despite the error
concealing tries, a seed error is still present, then return an error.

A clock error does not compromise the hardware block and data can
still be read from RNG_DR. Just warn that the RNG clock is too slow
and clear RNG_SR.

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
---

Changes in V2:
	- Use WARN_ONCE instead of WARN_ON as it was buggy

 drivers/char/hw_random/stm32-rng.c | 53 +++++++++++++++++++++++-------
 1 file changed, 41 insertions(+), 12 deletions(-)

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index adefe8edfd07..9dac177d5286 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -43,6 +43,8 @@
 
 #define RNG_HTCR		0x10
 
+#define RNG_NB_RECOVER_TRIES	3
+
 struct stm32_rng_data {
 	u32	cr;
 	u32	nscr;
@@ -162,10 +164,10 @@ static int stm32_rng_conceal_seed_error(struct hwrng *rng)
 
 static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 {
-	struct stm32_rng_private *priv =
-	    container_of(rng, struct stm32_rng_private, rng);
+	struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng);
+	unsigned int i = 0;
+	int retval = 0, err = 0;
 	u32 sr;
-	int retval = 0;
 
 	pm_runtime_get_sync((struct device *) priv->rng.priv);
 
@@ -174,30 +176,57 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 
 	while (max >= sizeof(u32)) {
 		sr = readl_relaxed(priv->base + RNG_SR);
-		/* Manage timeout which is based on timer and take */
-		/* care of initial delay time when enabling rng	*/
+		/*
+		 * Manage timeout which is based on timer and take
+		 * care of initial delay time when enabling the RNG.
+		 */
 		if (!sr && wait) {
-			int err;
-
 			err = readl_relaxed_poll_timeout_atomic(priv->base
 								   + RNG_SR,
 								   sr, sr,
 								   10, 50000);
-			if (err)
+			if (err) {
 				dev_err((struct device *)priv->rng.priv,
 					"%s: timeout %x!\n", __func__, sr);
+				break;
+			}
+		} else if (!sr) {
+			/* The FIFO is being filled up */
+			break;
 		}
 
-		/* If error detected or data not ready... */
 		if (sr != RNG_SR_DRDY) {
-			if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
-					"bad RNG status - %x\n", sr))
+			if (sr & RNG_SR_SEIS) {
+				err = stm32_rng_conceal_seed_error(rng);
+				i++;
+				if (err && i > RNG_NB_RECOVER_TRIES) {
+					dev_err((struct device *)priv->rng.priv,
+						"Couldn't recover from seed error\n");
+					return -ENOTRECOVERABLE;
+				}
+
+				continue;
+			}
+
+			if (WARN_ONCE((sr & RNG_SR_CEIS), "RNG clock too slow - %x\n", sr))
 				writel_relaxed(0, priv->base + RNG_SR);
-			break;
 		}
 
+		/* Late seed error case: DR being 0 is an error status */
 		*(u32 *)data = readl_relaxed(priv->base + RNG_DR);
+		if (!*(u32 *)data) {
+			err = stm32_rng_conceal_seed_error(rng);
+			i++;
+			if (err && i > RNG_NB_RECOVER_TRIES) {
+				dev_err((struct device *)priv->rng.priv,
+					"Couldn't recover from seed error");
+				return -ENOTRECOVERABLE;
+			}
+
+			continue;
+		}
 
+		i = 0;
 		retval += sizeof(u32);
 		data += sizeof(u32);
 		max -= sizeof(u32);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 6/9] hwrng: stm32 - restrain RNG noise source clock
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
                   ` (4 preceding siblings ...)
  2023-09-21  8:02 ` [PATCH v3 5/9] hwrng: stm32 - rework error handling in stm32_rng_read() Gatien Chevallier
@ 2023-09-21  8:02 ` Gatien Chevallier
  2023-09-21  8:02 ` [PATCH v3 7/9] hwrng: stm32 - support RNG configuration locking mechanism Gatien Chevallier
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:02 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

For NIST certification the noise source sampling may need to be
restrained.

This change implements an algorithm that gets the rate of the RNG
clock and apply the correct value in CLKDIV field in RNG_CR register
to force the RNG clock rate to be "max_clock_rate" maximum.

As it is platform-specific, implement it as a compat data.

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
---
 drivers/char/hw_random/stm32-rng.c | 34 ++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 9dac177d5286..819f062f454d 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -23,11 +23,13 @@
 #define RNG_CR_CONFIG1		GENMASK(11, 8)
 #define RNG_CR_NISTC		BIT(12)
 #define RNG_CR_CONFIG2		GENMASK(15, 13)
+#define RNG_CR_CLKDIV_SHIFT	16
+#define RNG_CR_CLKDIV		GENMASK(19, 16)
 #define RNG_CR_CONFIG3		GENMASK(25, 20)
 #define RNG_CR_CONDRST		BIT(30)
 #define RNG_CR_CONFLOCK		BIT(31)
 #define RNG_CR_ENTROPY_SRC_MASK	(RNG_CR_CONFIG1 | RNG_CR_NISTC | RNG_CR_CONFIG2 | RNG_CR_CONFIG3)
-#define RNG_CR_CONFIG_MASK	(RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED)
+#define RNG_CR_CONFIG_MASK	(RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED | RNG_CR_CLKDIV)
 
 #define RNG_SR			0x04
 #define RNG_SR_DRDY		BIT(0)
@@ -46,6 +48,7 @@
 #define RNG_NB_RECOVER_TRIES	3
 
 struct stm32_rng_data {
+	uint	max_clock_rate;
 	u32	cr;
 	u32	nscr;
 	u32	htcr;
@@ -238,6 +241,28 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
 	return retval || !wait ? retval : -EIO;
 }
 
+static uint stm32_rng_clock_freq_restrain(struct hwrng *rng)
+{
+	struct stm32_rng_private *priv =
+	    container_of(rng, struct stm32_rng_private, rng);
+	unsigned long clock_rate = 0;
+	uint clock_div = 0;
+
+	clock_rate = clk_get_rate(priv->clk);
+
+	/*
+	 * Get the exponent to apply on the CLKDIV field in RNG_CR register
+	 * No need to handle the case when clock-div > 0xF as it is physically
+	 * impossible
+	 */
+	while ((clock_rate >> clock_div) > priv->data->max_clock_rate)
+		clock_div++;
+
+	pr_debug("RNG clk rate : %lu\n", clk_get_rate(priv->clk) >> clock_div);
+
+	return clock_div;
+}
+
 static int stm32_rng_init(struct hwrng *rng)
 {
 	struct stm32_rng_private *priv =
@@ -259,8 +284,11 @@ static int stm32_rng_init(struct hwrng *rng)
 	 * 0 is an invalid value as it disables all entropy sources.
 	 */
 	if (priv->data->has_cond_reset && priv->data->cr) {
+		uint clock_div = stm32_rng_clock_freq_restrain(rng);
+
 		reg &= ~RNG_CR_CONFIG_MASK;
-		reg |= RNG_CR_CONDRST | (priv->data->cr & RNG_CR_ENTROPY_SRC_MASK);
+		reg |= RNG_CR_CONDRST | (priv->data->cr & RNG_CR_ENTROPY_SRC_MASK) |
+		       (clock_div << RNG_CR_CLKDIV_SHIFT);
 		if (priv->ced)
 			reg &= ~RNG_CR_CED;
 		else
@@ -360,6 +388,7 @@ static const struct dev_pm_ops stm32_rng_pm_ops = {
 
 static const struct stm32_rng_data stm32mp13_rng_data = {
 	.has_cond_reset = true,
+	.max_clock_rate = 48000000,
 	.cr = 0x00F00D00,
 	.nscr = 0x2B5BB,
 	.htcr = 0x969D,
@@ -367,6 +396,7 @@ static const struct stm32_rng_data stm32mp13_rng_data = {
 
 static const struct stm32_rng_data stm32_rng_data = {
 	.has_cond_reset = false,
+	.max_clock_rate = 3000000,
 };
 
 static const struct of_device_id stm32_rng_match[] = {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 7/9] hwrng: stm32 - support RNG configuration locking mechanism
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
                   ` (5 preceding siblings ...)
  2023-09-21  8:02 ` [PATCH v3 6/9] hwrng: stm32 - restrain RNG noise source clock Gatien Chevallier
@ 2023-09-21  8:02 ` Gatien Chevallier
  2023-09-21  8:03 ` [PATCH v3 8/9] hwrng: stm32 - rework power management sequences Gatien Chevallier
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:02 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

If "st,rng-lock-conf" DT binding property is set for a stm32-rng node,
the RNG configuration will be locked until next hardware block reset
or platform reset.

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
---
 drivers/char/hw_random/stm32-rng.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 819f062f454d..4a602d666dad 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -62,6 +62,7 @@ struct stm32_rng_private {
 	struct reset_control *rst;
 	const struct stm32_rng_data *data;
 	bool ced;
+	bool lock_conf;
 };
 
 /*
@@ -301,6 +302,9 @@ static int stm32_rng_init(struct hwrng *rng)
 
 		reg &= ~RNG_CR_CONDRST;
 		reg |= RNG_CR_RNGEN;
+		if (priv->lock_conf)
+			reg |= RNG_CR_CONFLOCK;
+
 		writel_relaxed(reg, priv->base + RNG_CR);
 
 		err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg,
@@ -439,6 +443,7 @@ static int stm32_rng_probe(struct platform_device *ofdev)
 	}
 
 	priv->ced = of_property_read_bool(np, "clock-error-detect");
+	priv->lock_conf = of_property_read_bool(np, "st,rng-lock-conf");
 
 	priv->data = of_device_get_match_data(dev);
 	if (!priv->data)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 8/9] hwrng: stm32 - rework power management sequences
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
                   ` (6 preceding siblings ...)
  2023-09-21  8:02 ` [PATCH v3 7/9] hwrng: stm32 - support RNG configuration locking mechanism Gatien Chevallier
@ 2023-09-21  8:03 ` Gatien Chevallier
  2023-09-21  8:03 ` [PATCH v3 9/9] ARM: dts: stm32: add RNG node for STM32MP13x platforms Gatien Chevallier
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:03 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

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.

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
---

Changes in V2:
	- Use pm_ptr() and add __maybe_unused to the pm API

Changes in V3:
	- Fix stm32_rng_pm_ops declaration

 drivers/char/hw_random/stm32-rng.c | 108 ++++++++++++++++++++++++++---
 1 file changed, 97 insertions(+), 11 deletions(-)

diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
index 4a602d666dad..41e1dbea5d2e 100644
--- a/drivers/char/hw_random/stm32-rng.c
+++ b/drivers/char/hw_random/stm32-rng.c
@@ -55,11 +55,25 @@ struct stm32_rng_data {
 	bool	has_cond_reset;
 };
 
+/**
+ * struct stm32_rng_config - RNG configuration data
+ *
+ * @cr:			RNG configuration. 0 means default hardware RNG configuration
+ * @nscr:		Noise sources control configuration.
+ * @htcr:		Health tests configuration.
+ */
+struct stm32_rng_config {
+	u32 cr;
+	u32 nscr;
+	u32 htcr;
+};
+
 struct stm32_rng_private {
 	struct hwrng rng;
 	void __iomem *base;
 	struct clk *clk;
 	struct reset_control *rst;
+	struct stm32_rng_config pm_conf;
 	const struct stm32_rng_data *data;
 	bool ced;
 	bool lock_conf;
@@ -355,11 +369,10 @@ static int stm32_rng_remove(struct platform_device *ofdev)
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int stm32_rng_runtime_suspend(struct device *dev)
+static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev)
 {
-	u32 reg;
 	struct stm32_rng_private *priv = dev_get_drvdata(dev);
+	u32 reg;
 
 	reg = readl_relaxed(priv->base + RNG_CR);
 	reg &= ~RNG_CR_RNGEN;
@@ -369,25 +382,98 @@ static int stm32_rng_runtime_suspend(struct device *dev)
 	return 0;
 }
 
-static int stm32_rng_runtime_resume(struct device *dev)
+static int __maybe_unused stm32_rng_suspend(struct device *dev)
+{
+	struct stm32_rng_private *priv = dev_get_drvdata(dev);
+
+	if (priv->data->has_cond_reset) {
+		priv->pm_conf.nscr = readl_relaxed(priv->base + RNG_NSCR);
+		priv->pm_conf.htcr = readl_relaxed(priv->base + RNG_HTCR);
+	}
+
+	/* Do not save that RNG is enabled as it will be handled at resume */
+	priv->pm_conf.cr = readl_relaxed(priv->base + RNG_CR) & ~RNG_CR_RNGEN;
+
+	writel_relaxed(priv->pm_conf.cr, priv->base + RNG_CR);
+
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static int __maybe_unused stm32_rng_runtime_resume(struct device *dev)
 {
-	u32 reg;
 	struct stm32_rng_private *priv = dev_get_drvdata(dev);
+	int err;
+	u32 reg;
+
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
+
+	/* Clean error indications */
+	writel_relaxed(0, priv->base + RNG_SR);
 
-	clk_prepare_enable(priv->clk);
 	reg = readl_relaxed(priv->base + RNG_CR);
 	reg |= RNG_CR_RNGEN;
 	writel_relaxed(reg, priv->base + RNG_CR);
 
 	return 0;
 }
-#endif
 
-static const struct dev_pm_ops stm32_rng_pm_ops = {
+static int __maybe_unused stm32_rng_resume(struct device *dev)
+{
+	struct stm32_rng_private *priv = dev_get_drvdata(dev);
+	int err;
+	u32 reg;
+
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
+
+	/* Clean error indications */
+	writel_relaxed(0, priv->base + RNG_SR);
+
+	if (priv->data->has_cond_reset) {
+		/*
+		 * Correct configuration in bits [29:4] must be set in the same
+		 * access that set RNG_CR_CONDRST bit. Else config setting is
+		 * not taken into account. CONFIGLOCK bit must also be unset but
+		 * it is not handled at the moment.
+		 */
+		writel_relaxed(priv->pm_conf.cr | RNG_CR_CONDRST, priv->base + RNG_CR);
+
+		writel_relaxed(priv->pm_conf.nscr, priv->base + RNG_NSCR);
+		writel_relaxed(priv->pm_conf.htcr, priv->base + RNG_HTCR);
+
+		reg = readl_relaxed(priv->base + RNG_CR);
+		reg |= RNG_CR_RNGEN;
+		reg &= ~RNG_CR_CONDRST;
+		writel_relaxed(reg, priv->base + RNG_CR);
+
+		err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg,
+							reg & ~RNG_CR_CONDRST, 10, 100000);
+
+		if (err) {
+			clk_disable_unprepare(priv->clk);
+			dev_err((struct device *)priv->rng.priv,
+				"%s: timeout:%x CR: %x!\n", __func__, err, reg);
+			return -EINVAL;
+		}
+	} else {
+		reg = priv->pm_conf.cr;
+		reg |= RNG_CR_RNGEN;
+		writel_relaxed(reg, priv->base + RNG_CR);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops __maybe_unused stm32_rng_pm_ops = {
 	SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend,
 			   stm32_rng_runtime_resume, NULL)
-	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
-				pm_runtime_force_resume)
+	SET_SYSTEM_SLEEP_PM_OPS(stm32_rng_suspend,
+				stm32_rng_resume)
 };
 
 static const struct stm32_rng_data stm32mp13_rng_data = {
@@ -467,7 +553,7 @@ static int stm32_rng_probe(struct platform_device *ofdev)
 static struct platform_driver stm32_rng_driver = {
 	.driver = {
 		.name = "stm32-rng",
-		.pm = &stm32_rng_pm_ops,
+		.pm = pm_ptr(&stm32_rng_pm_ops),
 		.of_match_table = stm32_rng_match,
 	},
 	.probe = stm32_rng_probe,
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 9/9] ARM: dts: stm32: add RNG node for STM32MP13x platforms
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
                   ` (7 preceding siblings ...)
  2023-09-21  8:03 ` [PATCH v3 8/9] hwrng: stm32 - rework power management sequences Gatien Chevallier
@ 2023-09-21  8:03 ` Gatien Chevallier
  2023-09-22  8:20   ` [EXTERNAL] " Kamlesh Gurudasani
  2023-10-01  8:33 ` [PATCH v3 0/9] hwrng: stm32: support " Herbert Xu
  2023-10-09 12:02 ` Alexandre TORGUE
  10 siblings, 1 reply; 15+ messages in thread
From: Gatien Chevallier @ 2023-09-21  8:03 UTC (permalink / raw)
  To: Olivia Mackall, Herbert Xu, Rob Herring, Krzysztof Kozlowski,
	Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

The RNG on STM32MP13 offers upgrades like customization of its
configuration and the conditional reset.

The hardware RNG should be managed in the secure world for but it
is supported on Linux. Therefore, is it not default enabled.

Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
---
 arch/arm/boot/dts/st/stm32mp131.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/st/stm32mp131.dtsi b/arch/arm/boot/dts/st/stm32mp131.dtsi
index ac90fcbf0c09..39db82b782eb 100644
--- a/arch/arm/boot/dts/st/stm32mp131.dtsi
+++ b/arch/arm/boot/dts/st/stm32mp131.dtsi
@@ -1220,6 +1220,14 @@ mdma: dma-controller@58000000 {
 			dma-requests = <48>;
 		};
 
+		rng: rng@54004000 {
+			compatible = "st,stm32mp13-rng";
+			reg = <0x54004000 0x400>;
+			clocks = <&rcc RNG1_K>;
+			resets = <&rcc RNG1_R>;
+			status = "disabled";
+		};
+
 		fmc: memory-controller@58002000 {
 			compatible = "st,stm32mp1-fmc2-ebi";
 			reg = <0x58002000 0x1000>;
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [EXTERNAL] [PATCH v3 9/9] ARM: dts: stm32: add RNG node for STM32MP13x platforms
  2023-09-21  8:03 ` [PATCH v3 9/9] ARM: dts: stm32: add RNG node for STM32MP13x platforms Gatien Chevallier
@ 2023-09-22  8:20   ` Kamlesh Gurudasani
  2023-09-25  9:31     ` Gatien CHEVALLIER
  0 siblings, 1 reply; 15+ messages in thread
From: Kamlesh Gurudasani @ 2023-09-22  8:20 UTC (permalink / raw)
  To: Gatien Chevallier, Olivia Mackall, Herbert Xu, Rob Herring,
	Krzysztof Kozlowski, Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel, Gatien Chevallier

Gatien Chevallier <gatien.chevallier@foss.st.com> writes:

> The RNG on STM32MP13 offers upgrades like customization of its
> configuration and the conditional reset.
>
> The hardware RNG should be managed in the secure world for but it
> is supported on Linux. Therefore, is it not default enabled.
Just curious, will there be concurrent access? If yes, how do you manage
the entropy in that case?

If you allow access to RNG from normal world, can attacker change the
setting to generate more predicatable numbers leading this to secure
world as well.

I understand that you're leaving the enablement part to customer but
you still have to allow RNG access to normal world for that.

-Kamlesh

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 1/9] dt-bindings: rng: introduce new compatible for STM32MP13x
  2023-09-21  8:02 ` [PATCH v3 1/9] dt-bindings: rng: introduce new compatible for STM32MP13x Gatien Chevallier
@ 2023-09-22 20:49   ` Rob Herring
  0 siblings, 0 replies; 15+ messages in thread
From: Rob Herring @ 2023-09-22 20:49 UTC (permalink / raw)
  To: Gatien Chevallier
  Cc: Alexandre Torgue, Lionel Debieve, linux-stm32, Herbert Xu,
	linux-arm-kernel, linux-crypto, Krzysztof Kozlowski, Rob Herring,
	linux-kernel, Maxime Coquelin, Olivia Mackall, devicetree


On Thu, 21 Sep 2023 10:02:53 +0200, Gatien Chevallier wrote:
> Introduce st,stm32mp13-rng compatible and add st,rng-lock-conf.
> 
> If st,rng-lock-conf is set, the RNG configuration in RNG_CR, RNG_HTCR
> and RNG_NSCR will be locked. It is supported starting from the RNG
> version present in the STM32MP13
> 
> Signed-off-by: Gatien Chevallier <gatien.chevallier@foss.st.com>
> ---
> 
> Changes in V3:
> 	- Squashed with: patch [V2 07/10]
> 	- Declare st,rng-lock-conf at top level and restrain its uses
> 	  depending on the compatible. I discarded Rob's tag as for
> 	  the modifications.
> 
>  .../devicetree/bindings/rng/st,stm32-rng.yaml | 20 ++++++++++++++++++-
>  1 file changed, 19 insertions(+), 1 deletion(-)
> 

Reviewed-by: Rob Herring <robh@kernel.org>


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [EXTERNAL] [PATCH v3 9/9] ARM: dts: stm32: add RNG node for STM32MP13x platforms
  2023-09-22  8:20   ` [EXTERNAL] " Kamlesh Gurudasani
@ 2023-09-25  9:31     ` Gatien CHEVALLIER
  0 siblings, 0 replies; 15+ messages in thread
From: Gatien CHEVALLIER @ 2023-09-25  9:31 UTC (permalink / raw)
  To: Kamlesh Gurudasani, Olivia Mackall, Herbert Xu, Rob Herring,
	Krzysztof Kozlowski, Maxime Coquelin, Alexandre Torgue
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel

Hi Kamlesh,

On 9/22/23 10:20, Kamlesh Gurudasani wrote:
> Gatien Chevallier <gatien.chevallier@foss.st.com> writes:
> 
>> The RNG on STM32MP13 offers upgrades like customization of its
>> configuration and the conditional reset.
>>
>> The hardware RNG should be managed in the secure world for but it
>> is supported on Linux. Therefore, is it not default enabled.
> Just curious, will there be concurrent access? If yes, how do you manage
> the entropy in that case?
> 

Any read on the data register leads to its refreshment. There can be
only one access at a time at the bus level. The rest (FIFO is empty
after request, etc...) is managed by the code in this patchset.

> If you allow access to RNG from normal world, can attacker change the
> setting to generate more predicatable numbers leading this to secure
> world as well.
> 
> I understand that you're leaving the enablement part to customer but
> you still have to allow RNG access to normal world for that.
> 
> -Kamlesh

If RNG is secure, then it should be managed by the secure world and
accessed via some interface. Ours is OP-TEE RNG PTA. The secure level
of the peripheral is managed by the ETZPC, which manages the security
configuration of the board's peripherals.

If the RNG is assigned to the non-secure world, then yes, the non-secure
world can access the RNG configuration. Now, your question is: what
happens to the secure world in such case? The answer is that it should
run on a pseudo-random software RNG seeded at boot by the hardware RNG.
So there's no link anymore if non-secure world deteriorates the
hardware RNG configuration.

Of course, if such choice is made, it's up to the customer to see the
whole picture.

Best regards,
Gatien

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
                   ` (8 preceding siblings ...)
  2023-09-21  8:03 ` [PATCH v3 9/9] ARM: dts: stm32: add RNG node for STM32MP13x platforms Gatien Chevallier
@ 2023-10-01  8:33 ` Herbert Xu
  2023-10-09 12:02 ` Alexandre TORGUE
  10 siblings, 0 replies; 15+ messages in thread
From: Herbert Xu @ 2023-10-01  8:33 UTC (permalink / raw)
  To: Gatien Chevallier
  Cc: Olivia Mackall, Rob Herring, Krzysztof Kozlowski, Maxime Coquelin,
	Alexandre Torgue, Lionel Debieve, linux-crypto, devicetree,
	linux-stm32, linux-arm-kernel, linux-kernel

On Thu, Sep 21, 2023 at 10:02:52AM +0200, Gatien Chevallier wrote:
> The STM32MP13x platforms have a RNG hardware block that supports
> customization, a conditional reset sequences that allows to
> recover from certain situations and a configuration locking
> mechanism.
> 
> This series adds support for the mentionned features. Note that
> the hardware RNG can and should be managed in the secure world
> for this platform, hence the rng not being default enabled on
> the STM32MP135F-DK board.
> 
> Changes in V2:
> 	- Use pm_ptr() and add __maybe_unused on PM API
> 	- Correct bug using WARN_ON
> 
> Changes in V3:
> 	- Squash of bindings patches
> 	- st,rng-lock-conf property declaration rework
> 	- Fix stm32_rng_pm_ops declaration in patch [5/9]
> 
> Gatien Chevallier (9):
>   dt-bindings: rng: introduce new compatible for STM32MP13x
>   hwrng: stm32 - use devm_platform_get_and_ioremap_resource() API
>   hwrng: stm32 - implement STM32MP13x support
>   hwrng: stm32 - implement error concealment
>   hwrng: stm32 - rework error handling in stm32_rng_read()
>   hwrng: stm32 - restrain RNG noise source clock
>   hwrng: stm32 - support RNG configuration locking mechanism
>   hwrng: stm32 - rework power management sequences
>   ARM: dts: stm32: add RNG node for STM32MP13x platforms
> 
>  .../devicetree/bindings/rng/st,stm32-rng.yaml |  20 +-
>  arch/arm/boot/dts/st/stm32mp131.dtsi          |   8 +
>  drivers/char/hw_random/stm32-rng.c            | 511 +++++++++++++++---
>  3 files changed, 455 insertions(+), 84 deletions(-)
> 
> -- 
> 2.25.1

Patches 1-8 applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms
  2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
                   ` (9 preceding siblings ...)
  2023-10-01  8:33 ` [PATCH v3 0/9] hwrng: stm32: support " Herbert Xu
@ 2023-10-09 12:02 ` Alexandre TORGUE
  10 siblings, 0 replies; 15+ messages in thread
From: Alexandre TORGUE @ 2023-10-09 12:02 UTC (permalink / raw)
  To: Gatien Chevallier, Olivia Mackall, Herbert Xu, Rob Herring,
	Krzysztof Kozlowski, Maxime Coquelin
  Cc: Lionel Debieve, linux-crypto, devicetree, linux-stm32,
	linux-arm-kernel, linux-kernel

Hi

On 9/21/23 10:02, Gatien Chevallier wrote:
> The STM32MP13x platforms have a RNG hardware block that supports
> customization, a conditional reset sequences that allows to
> recover from certain situations and a configuration locking
> mechanism.
> 
> This series adds support for the mentionned features. Note that
> the hardware RNG can and should be managed in the secure world
> for this platform, hence the rng not being default enabled on
> the STM32MP135F-DK board.
> 
> Changes in V2:
> 	- Use pm_ptr() and add __maybe_unused on PM API
> 	- Correct bug using WARN_ON
> 
> Changes in V3:
> 	- Squash of bindings patches
> 	- st,rng-lock-conf property declaration rework
> 	- Fix stm32_rng_pm_ops declaration in patch [5/9]
> 
> Gatien Chevallier (9):
>    dt-bindings: rng: introduce new compatible for STM32MP13x
>    hwrng: stm32 - use devm_platform_get_and_ioremap_resource() API
>    hwrng: stm32 - implement STM32MP13x support
>    hwrng: stm32 - implement error concealment
>    hwrng: stm32 - rework error handling in stm32_rng_read()
>    hwrng: stm32 - restrain RNG noise source clock
>    hwrng: stm32 - support RNG configuration locking mechanism
>    hwrng: stm32 - rework power management sequences
>    ARM: dts: stm32: add RNG node for STM32MP13x platforms
> 
>   .../devicetree/bindings/rng/st,stm32-rng.yaml |  20 +-
>   arch/arm/boot/dts/st/stm32mp131.dtsi          |   8 +
>   drivers/char/hw_random/stm32-rng.c            | 511 +++++++++++++++---
>   3 files changed, 455 insertions(+), 84 deletions(-)
> 

Patch[9] applied on stm32-next.

thanks
alex

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-10-09 12:02 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-21  8:02 [PATCH v3 0/9] hwrng: stm32: support STM32MP13x platforms Gatien Chevallier
2023-09-21  8:02 ` [PATCH v3 1/9] dt-bindings: rng: introduce new compatible for STM32MP13x Gatien Chevallier
2023-09-22 20:49   ` Rob Herring
2023-09-21  8:02 ` [PATCH v3 2/9] hwrng: stm32 - use devm_platform_get_and_ioremap_resource() API Gatien Chevallier
2023-09-21  8:02 ` [PATCH v3 3/9] hwrng: stm32 - implement STM32MP13x support Gatien Chevallier
2023-09-21  8:02 ` [PATCH v3 4/9] hwrng: stm32 - implement error concealment Gatien Chevallier
2023-09-21  8:02 ` [PATCH v3 5/9] hwrng: stm32 - rework error handling in stm32_rng_read() Gatien Chevallier
2023-09-21  8:02 ` [PATCH v3 6/9] hwrng: stm32 - restrain RNG noise source clock Gatien Chevallier
2023-09-21  8:02 ` [PATCH v3 7/9] hwrng: stm32 - support RNG configuration locking mechanism Gatien Chevallier
2023-09-21  8:03 ` [PATCH v3 8/9] hwrng: stm32 - rework power management sequences Gatien Chevallier
2023-09-21  8:03 ` [PATCH v3 9/9] ARM: dts: stm32: add RNG node for STM32MP13x platforms Gatien Chevallier
2023-09-22  8:20   ` [EXTERNAL] " Kamlesh Gurudasani
2023-09-25  9:31     ` Gatien CHEVALLIER
2023-10-01  8:33 ` [PATCH v3 0/9] hwrng: stm32: support " Herbert Xu
2023-10-09 12:02 ` Alexandre TORGUE

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).