// SPDX-License-Identifier: GPL-2.0
/*
 * sun8i-ss-prng.c - hardware cryptographic offloader for
 * Allwinner A80/A83T SoC
 *
 * Copyright (C) 2015-2020 Corentin Labbe <clabbe@baylibre.com>
 *
 * This file handle the PRNG found in the SS
 *
 * You could find a link for the datasheet in Documentation/arm/sunxi.rst
 */
#include "sun8i-ss.h"
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <crypto/internal/rng.h>

int sun8i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed,
		       unsigned int slen)
{
	struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);

	if (ctx->seed && ctx->slen != slen) {
		memzero_explicit(ctx->seed, ctx->slen);
		kfree(ctx->seed);
		ctx->slen = 0;
		ctx->seed = NULL;
	}
	if (!ctx->seed)
		ctx->seed = kmalloc(slen, GFP_KERNEL | GFP_DMA);
	if (!ctx->seed)
		return -ENOMEM;

	memcpy(ctx->seed, seed, slen);
	ctx->slen = slen;

	return 0;
}

int sun8i_ss_prng_init(struct crypto_tfm *tfm)
{
	struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);

	memset(ctx, 0, sizeof(struct sun8i_ss_rng_tfm_ctx));
	return 0;
}

void sun8i_ss_prng_exit(struct crypto_tfm *tfm)
{
	struct sun8i_ss_rng_tfm_ctx *ctx = crypto_tfm_ctx(tfm);

	memzero_explicit(ctx->seed, ctx->slen);
	kfree(ctx->seed);
	ctx->seed = NULL;
	ctx->slen = 0;
}

int sun8i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src,
			   unsigned int slen, u8 *dst, unsigned int dlen)
{
	struct sun8i_ss_rng_tfm_ctx *ctx = crypto_rng_ctx(tfm);
	struct rng_alg *alg = crypto_rng_alg(tfm);
	struct sun8i_ss_alg_template *algt;
	struct sun8i_ss_dev *ss;
	dma_addr_t dma_iv, dma_dst;
	unsigned int todo;
	int err = 0;
	int flow;
	void *d;
	u32 v;

	algt = container_of(alg, struct sun8i_ss_alg_template, alg.rng);
	ss = algt->ss;

	if (ctx->slen == 0) {
		dev_err(ss->dev, "The PRNG is not seeded\n");
		return -EINVAL;
	}

	/* The SS does not give an updated seed, so we need to get a new one.
	 * So we will ask for an extra PRNG_SEED_SIZE data.
	 * We want dlen + seedsize rounded up to a multiple of PRNG_DATA_SIZE
	 */
	todo = dlen + PRNG_SEED_SIZE + PRNG_DATA_SIZE;
	todo -= todo % PRNG_DATA_SIZE;

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

	flow = sun8i_ss_get_engine_number(ss);

#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG
	algt->stat_req++;
	algt->stat_bytes += todo;
#endif

	v = SS_ALG_PRNG | SS_PRNG_CONTINUE | SS_START;
	if (flow)
		v |= SS_FLOW1;
	else
		v |= SS_FLOW0;

	dma_iv = dma_map_single(ss->dev, ctx->seed, ctx->slen, DMA_TO_DEVICE);
	if (dma_mapping_error(ss->dev, dma_iv)) {
		dev_err(ss->dev, "Cannot DMA MAP IV\n");
		return -EFAULT;
	}

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

	err = pm_runtime_get_sync(ss->dev);
	if (err < 0) {
		pm_runtime_put_noidle(ss->dev);
		goto err_pm;
	}
	err = 0;

	mutex_lock(&ss->mlock);
	writel(dma_iv, ss->base + SS_IV_ADR_REG);
	/* the PRNG act badly (failing rngtest) without SS_KEY_ADR_REG set */
	writel(dma_iv, ss->base + SS_KEY_ADR_REG);
	writel(dma_dst, ss->base + SS_DST_ADR_REG);
	writel(todo / 4, ss->base + SS_LEN_ADR_REG);

	reinit_completion(&ss->flows[flow].complete);
	ss->flows[flow].status = 0;
	/* Be sure all data is written before enabling the task */
	wmb();

	writel(v, ss->base + SS_CTL_REG);

	wait_for_completion_interruptible_timeout(&ss->flows[flow].complete,
						  msecs_to_jiffies(todo));
	if (ss->flows[flow].status == 0) {
		dev_err(ss->dev, "DMA timeout for PRNG (size=%u)\n", todo);
		err = -EFAULT;
	}
	/* Since cipher and hash use the linux/cryptoengine and that we have
	 * a cryptoengine per flow, we are sure that they will issue only one
	 * request per flow.
	 * Since the cryptoengine wait for completion before submitting a new
	 * one, the mlock could be left just after the final writel.
	 * But cryptoengine cannot handle crypto_rng, so we need to be sure
	 * nothing will use our flow.
	 * The easiest way is to grab mlock until the hardware end our requests.
	 * We could have used a per flow lock, but this would increase
	 * complexity.
	 * The drawback is that no request could be handled for the other flow.
	 */
	mutex_unlock(&ss->mlock);

	pm_runtime_put(ss->dev);

err_pm:
	dma_unmap_single(ss->dev, dma_dst, todo, DMA_FROM_DEVICE);
err_iv:
	dma_unmap_single(ss->dev, dma_iv, ctx->slen, DMA_TO_DEVICE);

	if (!err) {
		memcpy(dst, d, dlen);
		/* Update seed */
		memcpy(ctx->seed, d + dlen, ctx->slen);
	}
	memzero_explicit(d, todo);
	kfree(d);

	return err;
}
