// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (c) 2019, Linaro Limited
 */

#include <common.h>
#include <clk.h>
#include <dm.h>
#include <reset.h>
#include <rng.h>

#include <asm/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.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_SECS BIT(2)
#define RNG_SR_DRDY BIT(0)

#define RNG_DR 0x08

struct stm32_rng_platdata {
	fdt_addr_t base;
	struct clk clk;
	struct reset_ctl rst;
};

static int stm32_rng_read(struct udevice *dev, void *data, size_t len)
{
	int retval, i;
	u32 sr, count, reg;
	size_t increment;
	struct stm32_rng_platdata *pdata = dev_get_platdata(dev);

	while (len > 0) {
		retval = readl_poll_timeout(pdata->base + RNG_SR, sr,
					    sr & RNG_SR_DRDY, 10000);
		if (retval)
			return retval;

		if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) {
			/* As per SoC TRM */
			clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS);
			for (i = 0; i < 12; i++)
				readl(pdata->base + RNG_DR);
			if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) {
				printf("RNG Noise");
				return -EIO;
			}
			/* start again */
			continue;
		}

		/*
		 * Once the DRDY bit is set, the RNG_DR register can
		 * be read four consecutive times.
		 */
		count = 4;
		while (len && count) {
			reg = readl(pdata->base + RNG_DR);
			memcpy(data, &reg, min(len, sizeof(u32)));
			increment = min(len, sizeof(u32));
			data += increment;
			len -= increment;
			count--;
		}
	}

	return 0;
}

static int stm32_rng_init(struct stm32_rng_platdata *pdata)
{
	int err;

	err = clk_enable(&pdata->clk);
	if (err)
		return err;

	/* Disable CED */
	writel(RNG_CR_RNGEN | RNG_CR_CED, pdata->base + RNG_CR);

	/* clear error indicators */
	writel(0, pdata->base + RNG_SR);

	return 0;
}

static int stm32_rng_cleanup(struct stm32_rng_platdata *pdata)
{
	writel(0, pdata->base + RNG_CR);

	return clk_disable(&pdata->clk);
}

static int stm32_rng_probe(struct udevice *dev)
{
	struct stm32_rng_platdata *pdata = dev_get_platdata(dev);

	reset_assert(&pdata->rst);
	udelay(20);
	reset_deassert(&pdata->rst);

	return stm32_rng_init(pdata);
}

static int stm32_rng_remove(struct udevice *dev)
{
	struct stm32_rng_platdata *pdata = dev_get_platdata(dev);

	return stm32_rng_cleanup(pdata);
}

static int stm32_rng_ofdata_to_platdata(struct udevice *dev)
{
	struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
	int err;

	pdata->base = dev_read_addr(dev);
	if (!pdata->base)
		return -ENOMEM;

	err = clk_get_by_index(dev, 0, &pdata->clk);
	if (err)
		return err;

	err = reset_get_by_index(dev, 0, &pdata->rst);
	if (err)
		return err;

	return 0;
}

static const struct dm_rng_ops stm32_rng_ops = {
	.read = stm32_rng_read,
};

static const struct udevice_id stm32_rng_match[] = {
	{
		.compatible = "st,stm32-rng",
	},
	{},
};

U_BOOT_DRIVER(stm32_rng) = {
	.name = "stm32-rng",
	.id = UCLASS_RNG,
	.of_match = stm32_rng_match,
	.ops = &stm32_rng_ops,
	.probe = stm32_rng_probe,
	.remove = stm32_rng_remove,
	.platdata_auto_alloc_size = sizeof(struct stm32_rng_platdata),
	.ofdata_to_platdata = stm32_rng_ofdata_to_platdata,
};
