msm: Add PRNG to MSM9615 device.

Add configuration parameters for MSM9615 device.
PRNG hardware registers initialization in msm_rng.c is done
currently for MSM9615.

Change-Id: I2a05e9e582ce94a25bec71e1acaee95d62cd9469
Signed-off-by: Ramesh Masavarapu <rameshm@codeaurora.org>
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index 3a2cd9a..5937c78 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/types.h>
+#include <mach/socinfo.h>
 
 #define DRIVER_NAME "msm_rng"
 
@@ -78,11 +79,11 @@
 	/* read random data from h/w */
 	do {
 		/* check status bit if data is available */
-		if (!(readl(base + PRNG_STATUS_OFFSET) & 0x00000001))
+		if (!(readl_relaxed(base + PRNG_STATUS_OFFSET) & 0x00000001))
 			break;	/* no data to read so just bail */
 
 		/* read FIFO */
-		val = readl(base + PRNG_DATA_OUT_OFFSET);
+		val = readl_relaxed(base + PRNG_DATA_OUT_OFFSET);
 		if (!val)
 			break;	/* no data to read so just bail */
 
@@ -106,6 +107,45 @@
 	.read = msm_rng_read,
 };
 
+static int __devinit msm_rng_enable_hw(struct msm_rng_device *msm_rng_dev)
+{
+	unsigned long val = 0;
+	int ret = 0;
+	int error = 0;
+
+	ret = clk_enable(msm_rng_dev->prng_clk);
+	if (ret) {
+		dev_err(&(msm_rng_dev->pdev)->dev,
+				"failed to enable clock in probe\n");
+		error = -EPERM;
+		return error;
+	}
+
+	/* enable PRNG h/w*/
+	val = readl_relaxed(msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET) &
+			PRNG_LFSR_CFG_MASK;
+	val |= PRNG_LFSR_CFG_MASK;
+	writel_relaxed(val, msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
+
+	/* The PRNG CONFIG register should be read after writing to the
+	* PRNG_LFSR_CFG register.
+	*/
+	mb();
+	val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET) &
+			PRNG_CONFIG_MASK;
+	val |= PRNG_CONFIG_ENABLE;
+	writel_relaxed(val, msm_rng_dev->base + PRNG_CONFIG_OFFSET);
+
+	/* The PRNG clk should be disabled only after we have enabled the
+	* PRNG H/W by writting to the PRNG_CONFIG register.
+	*/
+	mb();
+
+	clk_disable(msm_rng_dev->prng_clk);
+
+	return error;
+}
+
 static int __devinit msm_rng_probe(struct platform_device *pdev)
 {
 	struct resource *res;
@@ -147,18 +187,25 @@
 	msm_rng_dev->pdev = pdev;
 	platform_set_drvdata(pdev, msm_rng_dev);
 
+	/* Enable rng h/w */
+	if (cpu_is_msm9615())
+		error = msm_rng_enable_hw(msm_rng_dev);
+
+	if (error)
+		goto rollback_clk;
+
 	/* register with hwrng framework */
 	msm_rng.priv = (unsigned long) msm_rng_dev;
 	error = hwrng_register(&msm_rng);
 	if (error) {
 		dev_err(&pdev->dev, "failed to register hwrng\n");
 		error = -EPERM;
-		goto err_hw_register;
+		goto rollback_clk;
 	}
 
 	return 0;
 
-err_hw_register:
+rollback_clk:
 	clk_put(msm_rng_dev->prng_clk);
 err_clk_get:
 	iounmap(msm_rng_dev->base);