// SPDX-License-Identifier: GPL-2.0
/*
 * sun8i-ce-trng.c - hardware cryptographic offloader for
 * Allwinner H3/A64/H5/H2+/H6/R40 SoC
 *
 * Copyright (C) 2015-2020 Corentin Labbe <clabbe@baylibre.com>
 *
 * This file handle the TRNG
 *
 * You could find a link for the datasheet in Documentation/arch/arm/sunxi.rst
 */
#include "sun8i-ce.h"
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/hw_random.h>
/*
 * Note that according to the algorithm ID, 2 versions of the TRNG exists,
 * The first present in H3/H5/R40/A64 and the second present in H6.
 * This file adds support for both, but only the second is working
 * reliabily according to rngtest.
 **/

static int sun8i_ce_trng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
	struct sun8i_ce_dev *ce;
	dma_addr_t dma_dst;
	int err = 0;
	int flow = 3;
	unsigned int todo;
	struct sun8i_ce_flow *chan;
	struct ce_task *cet;
	u32 common;
	void *d;

	ce = container_of(rng, struct sun8i_ce_dev, trng);

	/* round the data length to a multiple of 32*/
	todo = max + 32;
	todo -= todo % 32;

	d = kzalloc(todo, GFP_KERNEL | GFP_DMA);
	if (!d)
		return -ENOMEM;

#ifdef CONFIG_CRYPTO_DEV_SUN8I_CE_DEBUG
	ce->hwrng_stat_req++;
	ce->hwrng_stat_bytes += todo;
#endif

	dma_dst = dma_map_single(ce->dev, d, todo, DMA_FROM_DEVICE);
	if (dma_mapping_error(ce->dev, dma_dst)) {
		dev_err(ce->dev, "Cannot DMA MAP DST\n");
		err = -EFAULT;
		goto err_dst;
	}

	err = pm_runtime_resume_and_get(ce->dev);
	if (err < 0)
		goto err_pm;

	mutex_lock(&ce->rnglock);
	chan = &ce->chanlist[flow];

	cet = &chan->tl[0];
	memset(cet, 0, sizeof(struct ce_task));

	cet->t_id = cpu_to_le32(flow);
	common = ce->variant->trng | CE_COMM_INT;
	cet->t_common_ctl = cpu_to_le32(common);

	/* recent CE (H6) need length in bytes, in word otherwise */
	if (ce->variant->trng_t_dlen_in_bytes)
		cet->t_dlen = cpu_to_le32(todo);
	else
		cet->t_dlen = cpu_to_le32(todo / 4);

	cet->t_sym_ctl = 0;
	cet->t_asym_ctl = 0;

	cet->t_dst[0].addr = desc_addr_val_le32(ce, dma_dst);
	cet->t_dst[0].len = cpu_to_le32(todo / 4);
	ce->chanlist[flow].timeout = todo;

	err = sun8i_ce_run_task(ce, 3, "TRNG");
	mutex_unlock(&ce->rnglock);

	pm_runtime_put(ce->dev);

err_pm:
	dma_unmap_single(ce->dev, dma_dst, todo, DMA_FROM_DEVICE);

	if (!err) {
		memcpy(data, d, max);
		err = max;
	}
err_dst:
	kfree_sensitive(d);
	return err;
}

int sun8i_ce_hwrng_register(struct sun8i_ce_dev *ce)
{
	int ret;

	if (ce->variant->trng == CE_ID_NOTSUPP) {
		dev_info(ce->dev, "TRNG not supported\n");
		return 0;
	}
	ce->trng.name = "sun8i Crypto Engine TRNG";
	ce->trng.read = sun8i_ce_trng_read;

	ret = hwrng_register(&ce->trng);
	if (ret)
		dev_err(ce->dev, "Fail to register the TRNG\n");
	return ret;
}

void sun8i_ce_hwrng_unregister(struct sun8i_ce_dev *ce)
{
	if (ce->variant->trng == CE_ID_NOTSUPP)
		return;
	hwrng_unregister(&ce->trng);
}
