// SPDX-License-Identifier: GPL-2.0
/*
 * amlgoic-core.c - hardware cryptographic offloader for Amlogic GXL SoC
 *
 * Copyright (C) 2018-2019 Corentin Labbe <clabbe@baylibre.com>
 *
 * Core file which registers crypto algorithms supported by the hardware.
 */
#include <linux/clk.h>
#include <linux/crypto.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <crypto/internal/skcipher.h>
#include <linux/dma-mapping.h>

#include "amlogic-gxl.h"

static irqreturn_t meson_irq_handler(int irq, void *data)
{
	struct meson_dev *mc = (struct meson_dev *)data;
	int flow;
	u32 p;

	for (flow = 0; flow < MAXFLOW; flow++) {
		if (mc->irqs[flow] == irq) {
			p = readl(mc->base + ((0x04 + flow) << 2));
			if (p) {
				writel_relaxed(0xF, mc->base + ((0x4 + flow) << 2));
				mc->chanlist[flow].status = 1;
				complete(&mc->chanlist[flow].complete);
				return IRQ_HANDLED;
			}
			dev_err(mc->dev, "%s %d Got irq for flow %d but ctrl is empty\n", __func__, irq, flow);
		}
	}

	dev_err(mc->dev, "%s %d from unknown irq\n", __func__, irq);
	return IRQ_HANDLED;
}

static struct meson_alg_template mc_algs[] = {
{
	.type = CRYPTO_ALG_TYPE_SKCIPHER,
	.blockmode = MESON_OPMODE_CBC,
	.alg.skcipher = {
		.base = {
			.cra_name = "cbc(aes)",
			.cra_driver_name = "cbc-aes-gxl",
			.cra_priority = 400,
			.cra_blocksize = AES_BLOCK_SIZE,
			.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER |
				CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY |
				CRYPTO_ALG_NEED_FALLBACK,
			.cra_ctxsize = sizeof(struct meson_cipher_tfm_ctx),
			.cra_module = THIS_MODULE,
			.cra_alignmask = 0xf,
			.cra_init = meson_cipher_init,
			.cra_exit = meson_cipher_exit,
		},
		.min_keysize	= AES_MIN_KEY_SIZE,
		.max_keysize	= AES_MAX_KEY_SIZE,
		.ivsize		= AES_BLOCK_SIZE,
		.setkey		= meson_aes_setkey,
		.encrypt	= meson_skencrypt,
		.decrypt	= meson_skdecrypt,
	}
},
{
	.type = CRYPTO_ALG_TYPE_SKCIPHER,
	.blockmode = MESON_OPMODE_ECB,
	.alg.skcipher = {
		.base = {
			.cra_name = "ecb(aes)",
			.cra_driver_name = "ecb-aes-gxl",
			.cra_priority = 400,
			.cra_blocksize = AES_BLOCK_SIZE,
			.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER |
				CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY |
				CRYPTO_ALG_NEED_FALLBACK,
			.cra_ctxsize = sizeof(struct meson_cipher_tfm_ctx),
			.cra_module = THIS_MODULE,
			.cra_alignmask = 0xf,
			.cra_init = meson_cipher_init,
			.cra_exit = meson_cipher_exit,
		},
		.min_keysize	= AES_MIN_KEY_SIZE,
		.max_keysize	= AES_MAX_KEY_SIZE,
		.setkey		= meson_aes_setkey,
		.encrypt	= meson_skencrypt,
		.decrypt	= meson_skdecrypt,
	}
},
};

#ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG
static int meson_debugfs_show(struct seq_file *seq, void *v)
{
	struct meson_dev *mc = seq->private;
	int i;

	for (i = 0; i < MAXFLOW; i++)
		seq_printf(seq, "Channel %d: nreq %lu\n", i, mc->chanlist[i].stat_req);

	for (i = 0; i < ARRAY_SIZE(mc_algs); i++) {
		switch (mc_algs[i].type) {
		case CRYPTO_ALG_TYPE_SKCIPHER:
			seq_printf(seq, "%s %s %lu %lu\n",
				   mc_algs[i].alg.skcipher.base.cra_driver_name,
				   mc_algs[i].alg.skcipher.base.cra_name,
				   mc_algs[i].stat_req, mc_algs[i].stat_fb);
			break;
		}
	}
	return 0;
}
DEFINE_SHOW_ATTRIBUTE(meson_debugfs);
#endif

static void meson_free_chanlist(struct meson_dev *mc, int i)
{
	while (i >= 0) {
		crypto_engine_exit(mc->chanlist[i].engine);
		if (mc->chanlist[i].tl)
			dma_free_coherent(mc->dev, sizeof(struct meson_desc) * MAXDESC,
					  mc->chanlist[i].tl,
					  mc->chanlist[i].t_phy);
		i--;
	}
}

/*
 * Allocate the channel list structure
 */
static int meson_allocate_chanlist(struct meson_dev *mc)
{
	int i, err;

	mc->chanlist = devm_kcalloc(mc->dev, MAXFLOW,
				    sizeof(struct meson_flow), GFP_KERNEL);
	if (!mc->chanlist)
		return -ENOMEM;

	for (i = 0; i < MAXFLOW; i++) {
		init_completion(&mc->chanlist[i].complete);

		mc->chanlist[i].engine = crypto_engine_alloc_init(mc->dev, true);
		if (!mc->chanlist[i].engine) {
			dev_err(mc->dev, "Cannot allocate engine\n");
			i--;
			err = -ENOMEM;
			goto error_engine;
		}
		err = crypto_engine_start(mc->chanlist[i].engine);
		if (err) {
			dev_err(mc->dev, "Cannot start engine\n");
			goto error_engine;
		}
		mc->chanlist[i].tl = dma_alloc_coherent(mc->dev,
							sizeof(struct meson_desc) * MAXDESC,
							&mc->chanlist[i].t_phy,
							GFP_KERNEL);
		if (!mc->chanlist[i].tl) {
			err = -ENOMEM;
			goto error_engine;
		}
	}
	return 0;
error_engine:
	meson_free_chanlist(mc, i);
	return err;
}

static int meson_register_algs(struct meson_dev *mc)
{
	int err, i;

	for (i = 0; i < ARRAY_SIZE(mc_algs); i++) {
		mc_algs[i].mc = mc;
		switch (mc_algs[i].type) {
		case CRYPTO_ALG_TYPE_SKCIPHER:
			err = crypto_register_skcipher(&mc_algs[i].alg.skcipher);
			if (err) {
				dev_err(mc->dev, "Fail to register %s\n",
					mc_algs[i].alg.skcipher.base.cra_name);
				mc_algs[i].mc = NULL;
				return err;
			}
			break;
		}
	}

	return 0;
}

static void meson_unregister_algs(struct meson_dev *mc)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(mc_algs); i++) {
		if (!mc_algs[i].mc)
			continue;
		switch (mc_algs[i].type) {
		case CRYPTO_ALG_TYPE_SKCIPHER:
			crypto_unregister_skcipher(&mc_algs[i].alg.skcipher);
			break;
		}
	}
}

static int meson_crypto_probe(struct platform_device *pdev)
{
	struct meson_dev *mc;
	int err, i;

	if (!pdev->dev.of_node)
		return -ENODEV;

	mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
	if (!mc)
		return -ENOMEM;

	mc->dev = &pdev->dev;
	platform_set_drvdata(pdev, mc);

	mc->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(mc->base)) {
		err = PTR_ERR(mc->base);
		dev_err(&pdev->dev, "Cannot request MMIO err=%d\n", err);
		return err;
	}
	mc->busclk = devm_clk_get(&pdev->dev, "blkmv");
	if (IS_ERR(mc->busclk)) {
		err = PTR_ERR(mc->busclk);
		dev_err(&pdev->dev, "Cannot get core clock err=%d\n", err);
		return err;
	}

	mc->irqs = devm_kcalloc(mc->dev, MAXFLOW, sizeof(int), GFP_KERNEL);
	for (i = 0; i < MAXFLOW; i++) {
		mc->irqs[i] = platform_get_irq(pdev, i);
		if (mc->irqs[i] < 0)
			return mc->irqs[i];

		err = devm_request_irq(&pdev->dev, mc->irqs[i], meson_irq_handler, 0,
				       "gxl-crypto", mc);
		if (err < 0) {
			dev_err(mc->dev, "Cannot request IRQ for flow %d\n", i);
			return err;
		}
	}

	err = clk_prepare_enable(mc->busclk);
	if (err != 0) {
		dev_err(&pdev->dev, "Cannot prepare_enable busclk\n");
		return err;
	}

	err = meson_allocate_chanlist(mc);
	if (err)
		goto error_flow;

	err = meson_register_algs(mc);
	if (err)
		goto error_alg;

#ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG
	mc->dbgfs_dir = debugfs_create_dir("gxl-crypto", NULL);
	debugfs_create_file("stats", 0444, mc->dbgfs_dir, mc, &meson_debugfs_fops);
#endif

	return 0;
error_alg:
	meson_unregister_algs(mc);
error_flow:
	meson_free_chanlist(mc, MAXFLOW - 1);
	clk_disable_unprepare(mc->busclk);
	return err;
}

static int meson_crypto_remove(struct platform_device *pdev)
{
	struct meson_dev *mc = platform_get_drvdata(pdev);

#ifdef CONFIG_CRYPTO_DEV_AMLOGIC_GXL_DEBUG
	debugfs_remove_recursive(mc->dbgfs_dir);
#endif

	meson_unregister_algs(mc);

	meson_free_chanlist(mc, MAXFLOW - 1);

	clk_disable_unprepare(mc->busclk);
	return 0;
}

static const struct of_device_id meson_crypto_of_match_table[] = {
	{ .compatible = "amlogic,gxl-crypto", },
	{}
};
MODULE_DEVICE_TABLE(of, meson_crypto_of_match_table);

static struct platform_driver meson_crypto_driver = {
	.probe		 = meson_crypto_probe,
	.remove		 = meson_crypto_remove,
	.driver		 = {
		.name		   = "gxl-crypto",
		.of_match_table	= meson_crypto_of_match_table,
	},
};

module_platform_driver(meson_crypto_driver);

MODULE_DESCRIPTION("Amlogic GXL cryptographic offloader");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Corentin Labbe <clabbe@baylibre.com>");
