// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (c) 2023 Mediatek Inc. All Rights Reserved.
 *
 * Author: Ren-Ting Wang <ren-ting.wang@mediatek.com>
 */

#include <linux/bitmap.h>
#include <linux/bitops.h>
#include <linux/err.h>
#include <linux/lockdep.h>
#include <linux/spinlock.h>

#include "pce/cdrt.h"
#include "pce/internal.h"
#include "pce/netsys.h"

/* decrypt use cdrt idx 1 ~ 15, encrypt use cdrt idx 16 ~ 31 */
#define CDRT_ENC_MAX_ENTRY		16
#define CDRT_ENC_IDX_OFS		16
#define CDRT_DEC_MAX_ENTRY		15
#define CDRT_DEC_IDX_OFS		1

struct cdrt_hardware {
	DECLARE_BITMAP(enc_used, CDRT_ENC_MAX_ENTRY);
	DECLARE_BITMAP(dec_used, CDRT_DEC_MAX_ENTRY);
	struct cdrt_entry enc_tbl[CDRT_ENC_MAX_ENTRY];
	struct cdrt_entry dec_tbl[CDRT_DEC_MAX_ENTRY];
	spinlock_t lock;
};

struct cdrt_hardware cdrt_hw;

int mtk_pce_cdrt_desc_write(struct cdrt_desc *desc, u32 idx)
{
	struct fe_mem_msg msg;
	int ret;

	if (unlikely(!desc || idx >= FE_MEM_CDRT_MAX_INDEX / 3))
		return -EINVAL;

	memset(&msg.raw, 0, sizeof(msg.raw));

	/* write CDR 0 ~ 3 */
	mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CDRT,
				  3 * idx);
	memcpy(&msg.raw, &desc->raw1, sizeof(desc->raw1));

	ret = mtk_pce_fe_mem_msg_send(&msg);
	if (ret)
		return ret;

	/* write CDR 4 ~ 7 */
	mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CDRT,
				  3 * idx + 1);
	memcpy(&msg.raw, &desc->raw2, sizeof(desc->raw2));

	ret = mtk_pce_fe_mem_msg_send(&msg);
	if (ret)
		return ret;

	/* write CDR 8 ~ 11 */
	mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_WRITE, FE_MEM_TYPE_CDRT,
				  3 * idx + 2);
	memcpy(&msg.raw, &desc->raw3, sizeof(desc->raw3));

	ret = mtk_pce_fe_mem_msg_send(&msg);

	return ret;
}

int mtk_pce_cdrt_desc_read(struct cdrt_desc *desc, u32 idx)
{
	struct fe_mem_msg msg;
	int ret;

	if (unlikely(!desc || idx >= FE_MEM_CDRT_MAX_INDEX / 3))
		return -EINVAL;

	memset(&msg.raw, 0, sizeof(msg.raw));

	/* read CDR 0 ~ 3 */
	mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CDRT,
				  3 * idx);
	ret = mtk_pce_fe_mem_msg_send(&msg);
	if (ret)
		return ret;

	memcpy(&desc->raw1, &msg.raw, sizeof(desc->raw1));

	/* read CDR 4 ~ 7 */
	mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CDRT,
				  3 * idx + 1);
	ret = mtk_pce_fe_mem_msg_send(&msg);
	if (ret)
		return ret;

	memcpy(&desc->raw2, &msg.raw, sizeof(desc->raw2));

	/* read CDR 8 ~ 11 */
	mtk_pce_fe_mem_msg_config(&msg, FE_MEM_CMD_READ, FE_MEM_TYPE_CDRT,
				  3 * idx + 2);
	ret = mtk_pce_fe_mem_msg_send(&msg);
	if (ret)
		return ret;

	memcpy(&desc->raw3, &msg.raw, sizeof(desc->raw3));

	return ret;
}

int mtk_pce_cdrt_entry_write(struct cdrt_entry *cdrt)
{
	if (unlikely(!cdrt))
		return -EINVAL;

	return mtk_pce_cdrt_desc_write(&cdrt->desc, cdrt->idx);
}
EXPORT_SYMBOL(mtk_pce_cdrt_entry_write);

struct cdrt_entry *mtk_pce_cdrt_entry_find(u32 cdrt_idx)
{
	struct cdrt_entry *cdrt;
	unsigned long flag;
	u32 idx;

	if (unlikely(!cdrt_idx || cdrt_idx >= FE_MEM_CDRT_MAX_INDEX))
		return ERR_PTR(-EINVAL);

	spin_lock_irqsave(&cdrt_hw.lock, flag);

	if (cdrt_idx < CDRT_DEC_IDX_OFS + CDRT_DEC_MAX_ENTRY) {
		idx = cdrt_idx - CDRT_DEC_IDX_OFS;
		if (!test_bit(idx, cdrt_hw.dec_used))
			return ERR_PTR(-ENODEV);

		cdrt = &cdrt_hw.dec_tbl[idx];
	} else {
		idx = cdrt_idx - CDRT_ENC_IDX_OFS;
		if (!test_bit(idx, cdrt_hw.enc_used))
			return ERR_PTR(-ENODEV);

		cdrt = &cdrt_hw.enc_tbl[idx];
	}

	spin_unlock_irqrestore(&cdrt_hw.lock, flag);

	return cdrt;
}
EXPORT_SYMBOL(mtk_pce_cdrt_entry_find);

static struct cdrt_entry *mtk_pce_cdrt_entry_encrypt_alloc(void)
{
	u32 idx;

	lockdep_assert_held(&cdrt_hw.lock);

	idx = find_first_zero_bit(cdrt_hw.enc_used, CDRT_ENC_MAX_ENTRY);
	if (idx == CDRT_ENC_MAX_ENTRY)
		return ERR_PTR(-ENOMEM);

	set_bit(idx, cdrt_hw.enc_used);

	return &cdrt_hw.enc_tbl[idx];
}

static struct cdrt_entry *mtk_pce_cdrt_entry_decrypt_alloc(void)
{
	u32 idx;

	lockdep_assert_held(&cdrt_hw.lock);

	idx = find_first_zero_bit(cdrt_hw.dec_used, CDRT_DEC_MAX_ENTRY);
	if (idx == CDRT_DEC_MAX_ENTRY)
		return ERR_PTR(-ENOMEM);

	set_bit(idx, cdrt_hw.dec_used);

	return &cdrt_hw.dec_tbl[idx];
}

struct cdrt_entry *mtk_pce_cdrt_entry_alloc(enum cdrt_type type)
{
	struct cdrt_entry *cdrt;
	unsigned long flag;

	if (type >= __CDRT_TYPE_MAX)
		return ERR_PTR(-EINVAL);

	spin_lock_irqsave(&cdrt_hw.lock, flag);

	if (type == CDRT_ENCRYPT)
		cdrt = mtk_pce_cdrt_entry_encrypt_alloc();
	else
		cdrt = mtk_pce_cdrt_entry_decrypt_alloc();

	spin_unlock_irqrestore(&cdrt_hw.lock, flag);

	return cdrt;
}
EXPORT_SYMBOL(mtk_pce_cdrt_entry_alloc);

void mtk_pce_cdrt_entry_free(struct cdrt_entry *cdrt)
{
	unsigned long flag;

	if (!cdrt)
		return;

	cdrt->cls = NULL;

	memset(&cdrt->desc.raw1, 0, sizeof(cdrt->desc.raw1));
	memset(&cdrt->desc.raw2, 0, sizeof(cdrt->desc.raw2));
	memset(&cdrt->desc.raw3, 0, sizeof(cdrt->desc.raw3));

	spin_lock_irqsave(&cdrt_hw.lock, flag);

	if (cdrt->type == CDRT_ENCRYPT)
		clear_bit(cdrt->idx, cdrt_hw.enc_used);
	else
		clear_bit(cdrt->idx, cdrt_hw.dec_used);

	spin_unlock_irqrestore(&cdrt_hw.lock, flag);
}
EXPORT_SYMBOL(mtk_pce_cdrt_entry_free);

static void mtk_pce_cdrt_clean_up(void)
{
	struct fe_mem_msg msg = {
		.cmd = FE_MEM_CMD_WRITE,
		.type = FE_MEM_TYPE_CDRT,
	};
	unsigned long flag;
	int ret = 0;
	u32 i;

	memset(&msg.raw, 0, sizeof(msg.raw));

	spin_lock_irqsave(&cdrt_hw.lock, flag);

	for (i = 0; i < FE_MEM_CDRT_MAX_INDEX; i++) {
		msg.index = i;

		ret = mtk_pce_fe_mem_msg_send(&msg);
		if (ret)
			return;

		/* TODO: clean up bit map? */
	}

	spin_unlock_irqrestore(&cdrt_hw.lock, flag);
}

int mtk_pce_cdrt_enable(void)
{
	mtk_pce_netsys_setbits(GLO_MEM_CFG, CDM_CDRT_EN);

	return 0;
}

void mtk_pce_cdrt_disable(void)
{
	mtk_pce_netsys_clrbits(GLO_MEM_CFG, CDM_CDRT_EN);
}

int mtk_pce_cdrt_init(struct platform_device *pdev)
{
	u32 i;

	spin_lock_init(&cdrt_hw.lock);

	mtk_pce_cdrt_clean_up();

	for (i = 0; i < CDRT_DEC_MAX_ENTRY; i++) {
		cdrt_hw.dec_tbl[i].idx = i + CDRT_DEC_IDX_OFS;
		cdrt_hw.dec_tbl[i].type = CDRT_DECRYPT;
	}

	for (i = 0; i < CDRT_ENC_MAX_ENTRY; i++) {
		cdrt_hw.enc_tbl[i].idx = i + CDRT_ENC_IDX_OFS;
		cdrt_hw.enc_tbl[i].type = CDRT_ENCRYPT;
	}

	return 0;
}

void mtk_pce_cdrt_deinit(struct platform_device *pdev)
{
	mtk_pce_cdrt_clean_up();
}
