static int msm_rng_drbg_read(struct hwrng *rng,
			void *data, size_t max, bool wait)
{
	struct msm_rng_device *msm_rng_dev;
	struct platform_device *pdev;
	void __iomem *base;
	size_t currsize = 0;
	u32 val;
	u32 *retdata = data;
	int ret, ret1;
	int failed = 0;

	msm_rng_dev = (struct msm_rng_device *)rng->priv;
	pdev = msm_rng_dev->pdev;
	base = msm_rng_dev->base;

	/* no room for word data */
	if (max < 4)
		return 0;

	mutex_lock(&msm_rng_dev->rng_lock);

	/* read random data from CTR-AES based DRBG */
	if (FIPS140_DRBG_ENABLED == msm_rng_dev->fips140_drbg_enabled) {
		ret1 = fips_drbg_gen(msm_rng_dev->drbg_ctx, data, max);
		if (FIPS140_PRNG_ERR == ret1)
			panic("random number generator generator error.\n");
	} else
		ret1 = 1;

	if (msm_rng_dev->qrng_perf_client) {
		ret = msm_bus_scale_client_update_request(
				msm_rng_dev->qrng_perf_client, 1);
		if (ret)
			pr_err("bus_scale_client_update_req failed!\n");
	}

	/* read random data from h/w */
	/* enable PRNG clock */
	ret = clk_prepare_enable(msm_rng_dev->prng_clk);
	if (ret) {
		dev_err(&pdev->dev, "failed to enable clock in callback\n");
		goto err;
	}
	/* read random data from h/w */
	do {
		/* check status bit if data is available */
		while (!(readl_relaxed(base + PRNG_STATUS_OFFSET)
				& 0x00000001)) {
			if (failed == 10) {
				pr_err("Data not available after retry\n");
				break;
			}
			pr_err("msm_rng:Data not available!\n");
			msleep_interruptible(10);
			failed++;
		}

		/* read FIFO */
		val = readl_relaxed(base + PRNG_DATA_OUT_OFFSET);
		if (!val)
			break;	/* no data to read so just bail */

		/* write data back to callers pointer */
		if (0 != ret1)
			*(retdata++) = val;
		currsize += 4;

		/* make sure we stay on 32bit boundary */
		if ((max - currsize) < 4)
			break;
	} while (currsize < max);
	/* vote to turn off clock */
	clk_disable_unprepare(msm_rng_dev->prng_clk);
err:
	if (msm_rng_dev->qrng_perf_client) {
		ret = msm_bus_scale_client_update_request(
				msm_rng_dev->qrng_perf_client, 0);
		if (ret)
			pr_err("bus_scale_client_update_req failed!\n");
	}

	mutex_unlock(&msm_rng_dev->rng_lock);

	return currsize;
}
static int msm_rng_drbg_read(struct hwrng *rng,
			void *data, size_t max, bool wait)
{
	struct msm_rng_device *msm_rng_dev;
	struct platform_device *pdev;
	void __iomem *base;
	size_t maxsize;
	size_t currsize = 0;
	u32 val;
	u32 *retdata = data;
	int ret, ret1;

	msm_rng_dev = (struct msm_rng_device *)rng->priv;
	pdev = msm_rng_dev->pdev;
	base = msm_rng_dev->base;


	down(&msm_rng_dev->drbg_sem);

	/* calculate max size bytes to transfer back to caller */
	maxsize = min_t(size_t, MAX_HW_FIFO_SIZE, max);

	/* no room for word data */
	if (maxsize < 4)
		return 0;

	/* read random data from CTR-AES based DRBG */
	if (FIPS140_DRBG_ENABLED == msm_rng_dev->fips140_drbg_enabled) {
		ret1 = fips_drbg_gen(msm_rng_dev->drbg_ctx, data, maxsize);
		if (FIPS140_PRNG_ERR == ret1)
			panic("random number generator generator error.\n");
	} else
		ret1 = 1;

	/* read random data from h/w */
	/* enable PRNG clock */
	ret = clk_prepare_enable(msm_rng_dev->prng_clk);
	if (ret) {
		dev_err(&pdev->dev, "failed to enable clock in callback\n");
		up(&msm_rng_dev->drbg_sem);
		return 0;
	}
	/* read random data from h/w */
	do {
		/* check status bit if data is available */
		if (!(readl_relaxed(base + PRNG_STATUS_OFFSET) & 0x00000001))
			break;	/* no data to read so just bail */

		/* read FIFO */
		val = readl_relaxed(base + PRNG_DATA_OUT_OFFSET);
		if (!val)
			break;	/* no data to read so just bail */

		/* write data back to callers pointer */
		if (0 != ret1)
			*(retdata++) = val;
		currsize += 4;

		/* make sure we stay on 32bit boundary */
		if ((maxsize - currsize) < 4)
			break;
	} while (currsize < maxsize);
	/* vote to turn off clock */
	clk_disable_unprepare(msm_rng_dev->prng_clk);

	up(&msm_rng_dev->drbg_sem);

	return currsize;
}