// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2021 Marvell. */

#include <linux/soc/marvell/octeontx2/asm.h>
#include "otx2_cptpf.h"
#include "otx2_cptvf.h"
#include "otx2_cptlf.h"
#include "cn10k_cpt.h"

static void cn10k_cpt_send_cmd(union otx2_cpt_inst_s *cptinst, u32 insts_num,
			       struct otx2_cptlf_info *lf);

static struct cpt_hw_ops otx2_hw_ops = {
	.send_cmd = otx2_cpt_send_cmd,
	.cpt_get_compcode = otx2_cpt_get_compcode,
	.cpt_get_uc_compcode = otx2_cpt_get_uc_compcode,
	.cpt_sg_info_create = otx2_sg_info_create,
};

static struct cpt_hw_ops cn10k_hw_ops = {
	.send_cmd = cn10k_cpt_send_cmd,
	.cpt_get_compcode = cn10k_cpt_get_compcode,
	.cpt_get_uc_compcode = cn10k_cpt_get_uc_compcode,
	.cpt_sg_info_create = otx2_sg_info_create,
};

static void cn10k_cpt_send_cmd(union otx2_cpt_inst_s *cptinst, u32 insts_num,
			       struct otx2_cptlf_info *lf)
{
	void __iomem *lmtline = lf->lmtline;
	u64 val = (lf->slot & 0x7FF);
	u64 tar_addr = 0;

	/* tar_addr<6:4> = Size of first LMTST - 1 in units of 128b. */
	tar_addr |= (__force u64)lf->ioreg |
		    (((OTX2_CPT_INST_SIZE/16) - 1) & 0x7) << 4;
	/*
	 * Make sure memory areas pointed in CPT_INST_S
	 * are flushed before the instruction is sent to CPT
	 */
	dma_wmb();

	/* Copy CPT command to LMTLINE */
	memcpy_toio(lmtline, cptinst, insts_num * OTX2_CPT_INST_SIZE);
	cn10k_lmt_flush(val, tar_addr);
}

int cn10k_cptpf_lmtst_init(struct otx2_cptpf_dev *cptpf)
{
	struct pci_dev *pdev = cptpf->pdev;
	resource_size_t size;
	u64 lmt_base;

	if (!test_bit(CN10K_LMTST, &cptpf->cap_flag)) {
		cptpf->lfs.ops = &otx2_hw_ops;
		return 0;
	}

	cptpf->lfs.ops = &cn10k_hw_ops;
	lmt_base = readq(cptpf->reg_base + RVU_PF_LMTLINE_ADDR);
	if (!lmt_base) {
		dev_err(&pdev->dev, "PF LMTLINE address not configured\n");
		return -ENOMEM;
	}
	size = pci_resource_len(pdev, PCI_MBOX_BAR_NUM);
	size -= ((1 + cptpf->max_vfs) * MBOX_SIZE);
	cptpf->lfs.lmt_base = devm_ioremap_wc(&pdev->dev, lmt_base, size);
	if (!cptpf->lfs.lmt_base) {
		dev_err(&pdev->dev,
			"Mapping of PF LMTLINE address failed\n");
		return -ENOMEM;
	}

	return 0;
}
EXPORT_SYMBOL_NS_GPL(cn10k_cptpf_lmtst_init, CRYPTO_DEV_OCTEONTX2_CPT);

int cn10k_cptvf_lmtst_init(struct otx2_cptvf_dev *cptvf)
{
	struct pci_dev *pdev = cptvf->pdev;
	resource_size_t offset, size;

	if (!test_bit(CN10K_LMTST, &cptvf->cap_flag))
		return 0;

	offset = pci_resource_start(pdev, PCI_MBOX_BAR_NUM);
	size = pci_resource_len(pdev, PCI_MBOX_BAR_NUM);
	/* Map VF LMILINE region */
	cptvf->lfs.lmt_base = devm_ioremap_wc(&pdev->dev, offset, size);
	if (!cptvf->lfs.lmt_base) {
		dev_err(&pdev->dev, "Unable to map BAR4\n");
		return -ENOMEM;
	}

	return 0;
}
EXPORT_SYMBOL_NS_GPL(cn10k_cptvf_lmtst_init, CRYPTO_DEV_OCTEONTX2_CPT);

void cn10k_cpt_hw_ctx_clear(struct pci_dev *pdev,
			    struct cn10k_cpt_errata_ctx *er_ctx)
{
	u64 cptr_dma;

	if (!is_dev_cn10ka_ax(pdev))
		return;

	cptr_dma = er_ctx->cptr_dma & ~(BIT_ULL(60));
	cn10k_cpt_ctx_flush(pdev, cptr_dma, true);
	dma_unmap_single(&pdev->dev, cptr_dma, CN10K_CPT_HW_CTX_SIZE,
			 DMA_BIDIRECTIONAL);
	kfree(er_ctx->hw_ctx);
}
EXPORT_SYMBOL_NS_GPL(cn10k_cpt_hw_ctx_clear, CRYPTO_DEV_OCTEONTX2_CPT);

void cn10k_cpt_hw_ctx_set(union cn10k_cpt_hw_ctx *hctx, u16 ctx_sz)
{
	hctx->w0.aop_valid = 1;
	hctx->w0.ctx_hdr_sz = 0;
	hctx->w0.ctx_sz = ctx_sz;
	hctx->w0.ctx_push_sz = 1;
}
EXPORT_SYMBOL_NS_GPL(cn10k_cpt_hw_ctx_set, CRYPTO_DEV_OCTEONTX2_CPT);

int cn10k_cpt_hw_ctx_init(struct pci_dev *pdev,
			  struct cn10k_cpt_errata_ctx *er_ctx)
{
	union cn10k_cpt_hw_ctx *hctx;
	u64 cptr_dma;

	er_ctx->cptr_dma = 0;
	er_ctx->hw_ctx = NULL;

	if (!is_dev_cn10ka_ax(pdev))
		return 0;

	hctx = kmalloc(CN10K_CPT_HW_CTX_SIZE, GFP_KERNEL);
	if (unlikely(!hctx))
		return -ENOMEM;
	cptr_dma = dma_map_single(&pdev->dev, hctx, CN10K_CPT_HW_CTX_SIZE,
				  DMA_BIDIRECTIONAL);

	cn10k_cpt_hw_ctx_set(hctx, 1);
	er_ctx->hw_ctx = hctx;
	er_ctx->cptr_dma = cptr_dma | BIT_ULL(60);

	return 0;
}
EXPORT_SYMBOL_NS_GPL(cn10k_cpt_hw_ctx_init, CRYPTO_DEV_OCTEONTX2_CPT);

void cn10k_cpt_ctx_flush(struct pci_dev *pdev, u64 cptr, bool inval)
{
	struct otx2_cptvf_dev *cptvf = pci_get_drvdata(pdev);
	struct otx2_cptlfs_info *lfs = &cptvf->lfs;
	u64 reg;

	reg = (uintptr_t)cptr >> 7;
	if (inval)
		reg = reg | BIT_ULL(46);

	otx2_cpt_write64(lfs->reg_base, lfs->blkaddr, lfs->lf[0].slot,
			 OTX2_CPT_LF_CTX_FLUSH, reg);
	/* Make sure that the FLUSH operation is complete */
	wmb();
	otx2_cpt_read64(lfs->reg_base, lfs->blkaddr, lfs->lf[0].slot,
			OTX2_CPT_LF_CTX_ERR);
}
EXPORT_SYMBOL_NS_GPL(cn10k_cpt_ctx_flush, CRYPTO_DEV_OCTEONTX2_CPT);

void cptvf_hw_ops_get(struct otx2_cptvf_dev *cptvf)
{
	if (test_bit(CN10K_LMTST, &cptvf->cap_flag))
		cptvf->lfs.ops = &cn10k_hw_ops;
	else
		cptvf->lfs.ops = &otx2_hw_ops;
}
EXPORT_SYMBOL_NS_GPL(cptvf_hw_ops_get, CRYPTO_DEV_OCTEONTX2_CPT);
