// SPDX-License-Identifier: GPL-2.0
/* Marvell OcteonTX CPT driver
 *
 * Copyright (C) 2019 Marvell International Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include "otx_cpt_common.h"
#include "otx_cptpf.h"

#define DRV_NAME	"octeontx-cpt"
#define DRV_VERSION	"1.0"

static void otx_cpt_disable_mbox_interrupts(struct otx_cpt_device *cpt)
{
	/* Disable mbox(0) interrupts for all VFs */
	writeq(~0ull, cpt->reg_base + OTX_CPT_PF_MBOX_ENA_W1CX(0));
}

static void otx_cpt_enable_mbox_interrupts(struct otx_cpt_device *cpt)
{
	/* Enable mbox(0) interrupts for all VFs */
	writeq(~0ull, cpt->reg_base + OTX_CPT_PF_MBOX_ENA_W1SX(0));
}

static irqreturn_t otx_cpt_mbx0_intr_handler(int __always_unused irq,
					     void *cpt)
{
	otx_cpt_mbox_intr_handler(cpt, 0);

	return IRQ_HANDLED;
}

static void otx_cpt_reset(struct otx_cpt_device *cpt)
{
	writeq(1, cpt->reg_base + OTX_CPT_PF_RESET);
}

static void otx_cpt_find_max_enabled_cores(struct otx_cpt_device *cpt)
{
	union otx_cptx_pf_constants pf_cnsts = {0};

	pf_cnsts.u = readq(cpt->reg_base + OTX_CPT_PF_CONSTANTS);
	cpt->eng_grps.avail.max_se_cnt = pf_cnsts.s.se;
	cpt->eng_grps.avail.max_ae_cnt = pf_cnsts.s.ae;
}

static u32 otx_cpt_check_bist_status(struct otx_cpt_device *cpt)
{
	union otx_cptx_pf_bist_status bist_sts = {0};

	bist_sts.u = readq(cpt->reg_base + OTX_CPT_PF_BIST_STATUS);
	return bist_sts.u;
}

static u64 otx_cpt_check_exe_bist_status(struct otx_cpt_device *cpt)
{
	union otx_cptx_pf_exe_bist_status bist_sts = {0};

	bist_sts.u = readq(cpt->reg_base + OTX_CPT_PF_EXE_BIST_STATUS);
	return bist_sts.u;
}

static int otx_cpt_device_init(struct otx_cpt_device *cpt)
{
	struct device *dev = &cpt->pdev->dev;
	u16 sdevid;
	u64 bist;

	/* Reset the PF when probed first */
	otx_cpt_reset(cpt);
	mdelay(100);

	pci_read_config_word(cpt->pdev, PCI_SUBSYSTEM_ID, &sdevid);

	/* Check BIST status */
	bist = (u64)otx_cpt_check_bist_status(cpt);
	if (bist) {
		dev_err(dev, "RAM BIST failed with code 0x%llx\n", bist);
		return -ENODEV;
	}

	bist = otx_cpt_check_exe_bist_status(cpt);
	if (bist) {
		dev_err(dev, "Engine BIST failed with code 0x%llx\n", bist);
		return -ENODEV;
	}

	/* Get max enabled cores */
	otx_cpt_find_max_enabled_cores(cpt);

	if ((sdevid == OTX_CPT_PCI_PF_SUBSYS_ID) &&
	    (cpt->eng_grps.avail.max_se_cnt == 0)) {
		cpt->pf_type = OTX_CPT_AE;
	} else if ((sdevid == OTX_CPT_PCI_PF_SUBSYS_ID) &&
		   (cpt->eng_grps.avail.max_ae_cnt == 0)) {
		cpt->pf_type = OTX_CPT_SE;
	}

	/* Get max VQs/VFs supported by the device */
	cpt->max_vfs = pci_sriov_get_totalvfs(cpt->pdev);

	/* Disable all cores */
	otx_cpt_disable_all_cores(cpt);

	return 0;
}

static int otx_cpt_register_interrupts(struct otx_cpt_device *cpt)
{
	struct device *dev = &cpt->pdev->dev;
	u32 mbox_int_idx = OTX_CPT_PF_MBOX_INT;
	u32 num_vec = OTX_CPT_PF_MSIX_VECTORS;
	int ret;

	/* Enable MSI-X */
	ret = pci_alloc_irq_vectors(cpt->pdev, num_vec, num_vec, PCI_IRQ_MSIX);
	if (ret < 0) {
		dev_err(&cpt->pdev->dev,
			"Request for #%d msix vectors failed\n",
			num_vec);
		return ret;
	}

	/* Register mailbox interrupt handlers */
	ret = request_irq(pci_irq_vector(cpt->pdev,
				OTX_CPT_PF_INT_VEC_E_MBOXX(mbox_int_idx, 0)),
				otx_cpt_mbx0_intr_handler, 0, "CPT Mbox0", cpt);
	if (ret) {
		dev_err(dev, "Request irq failed\n");
		pci_free_irq_vectors(cpt->pdev);
		return ret;
	}
	/* Enable mailbox interrupt */
	otx_cpt_enable_mbox_interrupts(cpt);
	return 0;
}

static void otx_cpt_unregister_interrupts(struct otx_cpt_device *cpt)
{
	u32 mbox_int_idx = OTX_CPT_PF_MBOX_INT;

	otx_cpt_disable_mbox_interrupts(cpt);
	free_irq(pci_irq_vector(cpt->pdev,
				OTX_CPT_PF_INT_VEC_E_MBOXX(mbox_int_idx, 0)),
				cpt);
	pci_free_irq_vectors(cpt->pdev);
}


static int otx_cpt_sriov_configure(struct pci_dev *pdev, int numvfs)
{
	struct otx_cpt_device *cpt = pci_get_drvdata(pdev);
	int ret = 0;

	if (numvfs > cpt->max_vfs)
		numvfs = cpt->max_vfs;

	if (numvfs > 0) {
		ret = otx_cpt_try_create_default_eng_grps(cpt->pdev,
							  &cpt->eng_grps,
							  cpt->pf_type);
		if (ret)
			return ret;

		cpt->vfs_enabled = numvfs;
		ret = pci_enable_sriov(pdev, numvfs);
		if (ret) {
			cpt->vfs_enabled = 0;
			return ret;
		}
		otx_cpt_set_eng_grps_is_rdonly(&cpt->eng_grps, true);
		try_module_get(THIS_MODULE);
		ret = numvfs;
	} else {
		pci_disable_sriov(pdev);
		otx_cpt_set_eng_grps_is_rdonly(&cpt->eng_grps, false);
		module_put(THIS_MODULE);
		cpt->vfs_enabled = 0;
	}
	dev_notice(&cpt->pdev->dev, "VFs enabled: %d\n", ret);

	return ret;
}

static int otx_cpt_probe(struct pci_dev *pdev,
			 const struct pci_device_id __always_unused *ent)
{
	struct device *dev = &pdev->dev;
	struct otx_cpt_device *cpt;
	int err;

	cpt = devm_kzalloc(dev, sizeof(*cpt), GFP_KERNEL);
	if (!cpt)
		return -ENOMEM;

	pci_set_drvdata(pdev, cpt);
	cpt->pdev = pdev;

	err = pci_enable_device(pdev);
	if (err) {
		dev_err(dev, "Failed to enable PCI device\n");
		goto err_clear_drvdata;
	}

	err = pci_request_regions(pdev, DRV_NAME);
	if (err) {
		dev_err(dev, "PCI request regions failed 0x%x\n", err);
		goto err_disable_device;
	}

	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(48));
	if (err) {
		dev_err(dev, "Unable to get usable DMA configuration\n");
		goto err_release_regions;
	}

	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(48));
	if (err) {
		dev_err(dev, "Unable to get 48-bit DMA for consistent allocations\n");
		goto err_release_regions;
	}

	/* MAP PF's configuration registers */
	cpt->reg_base = pci_iomap(pdev, OTX_CPT_PF_PCI_CFG_BAR, 0);
	if (!cpt->reg_base) {
		dev_err(dev, "Cannot map config register space, aborting\n");
		err = -ENOMEM;
		goto err_release_regions;
	}

	/* CPT device HW initialization */
	err = otx_cpt_device_init(cpt);
	if (err)
		goto err_unmap_region;

	/* Register interrupts */
	err = otx_cpt_register_interrupts(cpt);
	if (err)
		goto err_unmap_region;

	/* Initialize engine groups */
	err = otx_cpt_init_eng_grps(pdev, &cpt->eng_grps, cpt->pf_type);
	if (err)
		goto err_unregister_interrupts;

	return 0;

err_unregister_interrupts:
	otx_cpt_unregister_interrupts(cpt);
err_unmap_region:
	pci_iounmap(pdev, cpt->reg_base);
err_release_regions:
	pci_release_regions(pdev);
err_disable_device:
	pci_disable_device(pdev);
err_clear_drvdata:
	pci_set_drvdata(pdev, NULL);

	return err;
}

static void otx_cpt_remove(struct pci_dev *pdev)
{
	struct otx_cpt_device *cpt = pci_get_drvdata(pdev);

	if (!cpt)
		return;

	/* Disable VFs */
	pci_disable_sriov(pdev);
	/* Cleanup engine groups */
	otx_cpt_cleanup_eng_grps(pdev, &cpt->eng_grps);
	/* Disable CPT PF interrupts */
	otx_cpt_unregister_interrupts(cpt);
	/* Disengage SE and AE cores from all groups */
	otx_cpt_disable_all_cores(cpt);
	pci_iounmap(pdev, cpt->reg_base);
	pci_release_regions(pdev);
	pci_disable_device(pdev);
	pci_set_drvdata(pdev, NULL);
}

/* Supported devices */
static const struct pci_device_id otx_cpt_id_table[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, OTX_CPT_PCI_PF_DEVICE_ID) },
	{ 0, }  /* end of table */
};

static struct pci_driver otx_cpt_pci_driver = {
	.name = DRV_NAME,
	.id_table = otx_cpt_id_table,
	.probe = otx_cpt_probe,
	.remove = otx_cpt_remove,
	.sriov_configure = otx_cpt_sriov_configure
};

module_pci_driver(otx_cpt_pci_driver);

MODULE_AUTHOR("Marvell International Ltd.");
MODULE_DESCRIPTION("Marvell OcteonTX CPT Physical Function Driver");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(DRV_VERSION);
MODULE_DEVICE_TABLE(pci, otx_cpt_id_table);
