// SPDX-License-Identifier: GPL-2.0
/*
 * CDX host controller driver for AMD versal-net platform.
 *
 * Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
 */

#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/cdx/cdx_bus.h>
#include <linux/irqdomain.h>

#include "cdx_controller.h"
#include "../cdx.h"
#include "mcdi_functions.h"
#include "mcdid.h"

static unsigned int cdx_mcdi_rpc_timeout(struct cdx_mcdi *cdx, unsigned int cmd)
{
	return MCDI_RPC_TIMEOUT;
}

static void cdx_mcdi_request(struct cdx_mcdi *cdx,
			     const struct cdx_dword *hdr, size_t hdr_len,
			     const struct cdx_dword *sdu, size_t sdu_len)
{
	if (cdx_rpmsg_send(cdx, hdr, hdr_len, sdu, sdu_len))
		dev_err(&cdx->rpdev->dev, "Failed to send rpmsg data\n");
}

static const struct cdx_mcdi_ops mcdi_ops = {
	.mcdi_rpc_timeout = cdx_mcdi_rpc_timeout,
	.mcdi_request = cdx_mcdi_request,
};

static int cdx_bus_enable(struct cdx_controller *cdx, u8 bus_num)
{
	return cdx_mcdi_bus_enable(cdx->priv, bus_num);
}

static int cdx_bus_disable(struct cdx_controller *cdx, u8 bus_num)
{
	return cdx_mcdi_bus_disable(cdx->priv, bus_num);
}

void cdx_rpmsg_post_probe(struct cdx_controller *cdx)
{
	/* Register CDX controller with CDX bus driver */
	if (cdx_register_controller(cdx))
		dev_err(cdx->dev, "Failed to register CDX controller\n");
}

void cdx_rpmsg_pre_remove(struct cdx_controller *cdx)
{
	cdx_unregister_controller(cdx);
	cdx_mcdi_wait_for_quiescence(cdx->priv, MCDI_RPC_TIMEOUT);
}

static int cdx_configure_device(struct cdx_controller *cdx,
				u8 bus_num, u8 dev_num,
				struct cdx_device_config *dev_config)
{
	u16 msi_index;
	int ret = 0;
	u32 data;
	u64 addr;

	switch (dev_config->type) {
	case CDX_DEV_MSI_CONF:
		msi_index = dev_config->msi.msi_index;
		data = dev_config->msi.data;
		addr = dev_config->msi.addr;

		ret = cdx_mcdi_write_msi(cdx->priv, bus_num, dev_num, msi_index, addr, data);
		break;
	case CDX_DEV_RESET_CONF:
		ret = cdx_mcdi_reset_device(cdx->priv, bus_num, dev_num);
		break;
	case CDX_DEV_BUS_MASTER_CONF:
		ret = cdx_mcdi_bus_master_enable(cdx->priv, bus_num, dev_num,
						 dev_config->bus_master_enable);
		break;
	case CDX_DEV_MSI_ENABLE:
		ret = cdx_mcdi_msi_enable(cdx->priv, bus_num, dev_num, dev_config->msi_enable);
		break;
	default:
		ret = -EINVAL;
	}

	return ret;
}

static int cdx_scan_devices(struct cdx_controller *cdx)
{
	struct cdx_mcdi *cdx_mcdi = cdx->priv;
	u8 bus_num, dev_num, num_cdx_bus;
	int ret;

	/* MCDI FW Read: Fetch the number of CDX buses on this controller */
	ret = cdx_mcdi_get_num_buses(cdx_mcdi);
	if (ret < 0) {
		dev_err(cdx->dev,
			"Get number of CDX buses failed: %d\n", ret);
		return ret;
	}
	num_cdx_bus = (u8)ret;

	for (bus_num = 0; bus_num < num_cdx_bus; bus_num++) {
		struct device *bus_dev;
		u8 num_cdx_dev;

		/* Add the bus on cdx subsystem */
		bus_dev = cdx_bus_add(cdx, bus_num);
		if (!bus_dev)
			continue;

		/* MCDI FW Read: Fetch the number of devices present */
		ret = cdx_mcdi_get_num_devs(cdx_mcdi, bus_num);
		if (ret < 0) {
			dev_err(cdx->dev,
				"Get devices on CDX bus %d failed: %d\n", bus_num, ret);
			continue;
		}
		num_cdx_dev = (u8)ret;

		for (dev_num = 0; dev_num < num_cdx_dev; dev_num++) {
			struct cdx_dev_params dev_params;

			/* MCDI FW: Get the device config */
			ret = cdx_mcdi_get_dev_config(cdx_mcdi, bus_num,
						      dev_num, &dev_params);
			if (ret) {
				dev_err(cdx->dev,
					"CDX device config get failed for %d(bus):%d(dev), %d\n",
					bus_num, dev_num, ret);
				continue;
			}
			dev_params.cdx = cdx;
			dev_params.parent = bus_dev;

			/* Add the device to the cdx bus */
			ret = cdx_device_add(&dev_params);
			if (ret) {
				dev_err(cdx->dev, "registering cdx dev: %d failed: %d\n",
					dev_num, ret);
				continue;
			}

			dev_dbg(cdx->dev, "CDX dev: %d on cdx bus: %d created\n",
				dev_num, bus_num);
		}
	}

	return 0;
}

static struct cdx_ops cdx_ops = {
	.bus_enable		= cdx_bus_enable,
	.bus_disable	= cdx_bus_disable,
	.scan		= cdx_scan_devices,
	.dev_configure	= cdx_configure_device,
};

static int xlnx_cdx_probe(struct platform_device *pdev)
{
	struct cdx_controller *cdx;
	struct cdx_mcdi *cdx_mcdi;
	int ret;

	cdx_mcdi = kzalloc_obj(*cdx_mcdi);
	if (!cdx_mcdi)
		return -ENOMEM;

	/* Store the MCDI ops */
	cdx_mcdi->mcdi_ops = &mcdi_ops;
	/* MCDI FW: Initialize the FW path */
	ret = cdx_mcdi_init(cdx_mcdi);
	if (ret) {
		dev_err_probe(&pdev->dev, ret, "MCDI Initialization failed\n");
		goto mcdi_init_fail;
	}

	cdx = kzalloc_obj(*cdx);
	if (!cdx) {
		ret = -ENOMEM;
		goto cdx_alloc_fail;
	}
	platform_set_drvdata(pdev, cdx);

	cdx->dev = &pdev->dev;
	cdx->priv = cdx_mcdi;
	cdx->ops = &cdx_ops;

	/* Create MSI domain */
	if (IS_ENABLED(CONFIG_GENERIC_MSI_IRQ))
		cdx->msi_domain = cdx_msi_domain_init(&pdev->dev);
	if (!cdx->msi_domain) {
		ret = dev_err_probe(&pdev->dev, -ENODEV, "cdx_msi_domain_init() failed");
		goto cdx_msi_fail;
	}

	ret = cdx_setup_rpmsg(pdev);
	if (ret) {
		dev_err_probe(&pdev->dev, ret, "Failed to register CDX RPMsg transport\n");
		goto cdx_rpmsg_fail;
	}

	return 0;

cdx_rpmsg_fail:
	irq_domain_remove(cdx->msi_domain);
cdx_msi_fail:
	kfree(cdx);
cdx_alloc_fail:
	cdx_mcdi_finish(cdx_mcdi);
mcdi_init_fail:
	kfree(cdx_mcdi);

	return ret;
}

static void xlnx_cdx_remove(struct platform_device *pdev)
{
	struct cdx_controller *cdx = platform_get_drvdata(pdev);
	struct cdx_mcdi *cdx_mcdi = cdx->priv;

	cdx_destroy_rpmsg(pdev);

	irq_domain_remove(cdx->msi_domain);
	kfree(cdx);

	cdx_mcdi_finish(cdx_mcdi);
	kfree(cdx_mcdi);
}

static const struct of_device_id cdx_match_table[] = {
	{.compatible = "xlnx,versal-net-cdx",},
	{ },
};

MODULE_DEVICE_TABLE(of, cdx_match_table);

static struct platform_driver cdx_pdriver = {
	.driver = {
		   .name = "cdx-controller",
		   .of_match_table = cdx_match_table,
		   },
	.probe = xlnx_cdx_probe,
	.remove = xlnx_cdx_remove,
};

module_platform_driver(cdx_pdriver);

MODULE_AUTHOR("AMD Inc.");
MODULE_DESCRIPTION("CDX controller for AMD devices");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("CDX_BUS_CONTROLLER");
