Explorar o código

hwrng: omap - Fix clock resource by adding a register clock

On Armada 7K/8K we need to explicitly enable the register clock. This
clock is optional because not all the SoCs using this IP need it but at
least for Armada 7K/8K it is actually mandatory.

The binding documentation is updating accordingly.

Signed-off-by: Gregory CLEMENT <gregory.clement@bootlin.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Gregory CLEMENT %!s(int64=7) %!d(string=hai) anos
pai
achega
b166be0044

+ 6 - 1
Documentation/devicetree/bindings/rng/omap_rng.txt

@@ -13,7 +13,12 @@ Required properties:
 - interrupts : the interrupt number for the RNG module.
 - interrupts : the interrupt number for the RNG module.
 		Used for "ti,omap4-rng" and "inside-secure,safexcel-eip76"
 		Used for "ti,omap4-rng" and "inside-secure,safexcel-eip76"
 - clocks: the trng clock source. Only mandatory for the
 - clocks: the trng clock source. Only mandatory for the
-  "inside-secure,safexcel-eip76" compatible.
+  "inside-secure,safexcel-eip76" compatible, the second clock is
+  needed for the Armada 7K/8K SoCs
+- clock-names: mandatory if there is a second clock, in this case the
+  name must be "core" for the first clock and "reg" for the second
+  one
+
 
 
 Example:
 Example:
 /* AM335x */
 /* AM335x */

+ 16 - 0
drivers/char/hw_random/omap-rng.c

@@ -150,6 +150,7 @@ struct omap_rng_dev {
 	const struct omap_rng_pdata	*pdata;
 	const struct omap_rng_pdata	*pdata;
 	struct hwrng rng;
 	struct hwrng rng;
 	struct clk 			*clk;
 	struct clk 			*clk;
+	struct clk			*clk_reg;
 };
 };
 
 
 static inline u32 omap_rng_read(struct omap_rng_dev *priv, u16 reg)
 static inline u32 omap_rng_read(struct omap_rng_dev *priv, u16 reg)
@@ -480,6 +481,19 @@ static int omap_rng_probe(struct platform_device *pdev)
 		}
 		}
 	}
 	}
 
 
+	priv->clk_reg = devm_clk_get(&pdev->dev, "reg");
+	if (IS_ERR(priv->clk_reg) && PTR_ERR(priv->clk_reg) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+	if (!IS_ERR(priv->clk_reg)) {
+		ret = clk_prepare_enable(priv->clk_reg);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Unable to enable the register clk: %d\n",
+				ret);
+			goto err_register;
+		}
+	}
+
 	ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) :
 	ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) :
 				get_omap_rng_device_details(priv);
 				get_omap_rng_device_details(priv);
 	if (ret)
 	if (ret)
@@ -499,6 +513,7 @@ err_register:
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_put_sync(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
 
+	clk_disable_unprepare(priv->clk_reg);
 	clk_disable_unprepare(priv->clk);
 	clk_disable_unprepare(priv->clk);
 err_ioremap:
 err_ioremap:
 	dev_err(dev, "initialization failed.\n");
 	dev_err(dev, "initialization failed.\n");
@@ -517,6 +532,7 @@ static int omap_rng_remove(struct platform_device *pdev)
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_disable(&pdev->dev);
 
 
 	clk_disable_unprepare(priv->clk);
 	clk_disable_unprepare(priv->clk);
+	clk_disable_unprepare(priv->clk_reg);
 
 
 	return 0;
 	return 0;
 }
 }