// SPDX-License-Identifier: GPL-2.0
/*
 * Microchip Inter-Processor communication (IPC) driver
 *
 * Copyright (c) 2021 - 2024 Microchip Technology Inc. All rights reserved.
 *
 * Author: Valentina Fernandez <valentina.fernandezalanis@microchip.com>
 *
 */

#include <linux/io.h>
#include <linux/err.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/of_device.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/mailbox/mchp-ipc.h>
#include <asm/sbi.h>
#include <asm/vendorid_list.h>

#define IRQ_STATUS_BITS			12
#define NUM_CHANS_PER_CLUSTER		5
#define IPC_DMA_BIT_MASK		32
#define SBI_EXT_MICROCHIP_TECHNOLOGY	(SBI_EXT_VENDOR_START | \
					 MICROCHIP_VENDOR_ID)

enum {
	SBI_EXT_IPC_PROBE = 0x100,
	SBI_EXT_IPC_CH_INIT,
	SBI_EXT_IPC_SEND,
	SBI_EXT_IPC_RECEIVE,
	SBI_EXT_IPC_STATUS,
};

enum ipc_hw {
	MIV_IHC,
};

/**
 * struct mchp_ipc_mbox_info - IPC probe message format
 *
 * @hw_type:		IPC implementation available in the hardware
 * @num_channels:	number of IPC channels available in the hardware
 *
 * Used to retrieve information on the IPC implementation
 * using the SBI_EXT_IPC_PROBE SBI function id.
 */
struct mchp_ipc_mbox_info {
	enum ipc_hw hw_type;
	u8 num_channels;
};

/**
 * struct mchp_ipc_init - IPC channel init message format
 *
 * @max_msg_size:	maxmimum message size in bytes of a given channel
 *
 * struct used by the SBI_EXT_IPC_CH_INIT SBI function id to get
 * the max message size in bytes of the initialized channel.
 */
struct mchp_ipc_init {
	u16 max_msg_size;
};

/**
 * struct mchp_ipc_status - IPC status message format
 *
 * @status:	interrupt status for all channels associated to a cluster
 * @cluster:	specifies the cluster instance that originated an irq
 *
 * struct used by the SBI_EXT_IPC_STATUS SBI function id to get
 * the message present and message clear interrupt status for all the
 * channels associated to a cluster.
 */
struct mchp_ipc_status {
	u32 status;
	u8 cluster;
};

/**
 * struct mchp_ipc_sbi_msg - IPC SBI payload message
 *
 * @buf_addr:	physical address where the received data should be copied to
 * @size:	maximum size(in bytes) that can be stored in the buffer pointed to by `buf`
 * @irq_type:	mask representing the irq types that triggered an irq
 *
 * struct used by the SBI_EXT_IPC_SEND/SBI_EXT_IPC_RECEIVE SBI function
 * ids to send/receive a message from an associated processor using
 * the IPC.
 */
struct mchp_ipc_sbi_msg {
	u64 buf_addr;
	u16 size;
	u8 irq_type;
};

struct mchp_ipc_cluster_cfg {
	void *buf_base;
	phys_addr_t buf_base_addr;
	int irq;
};

struct mchp_ipc_sbi_mbox {
	struct device *dev;
	struct mbox_chan *chans;
	struct mchp_ipc_cluster_cfg *cluster_cfg;
	void *buf_base;
	unsigned long buf_base_addr;
	struct mbox_controller controller;
	enum ipc_hw hw_type;
};

static int mchp_ipc_sbi_chan_send(u32 command, u32 channel, unsigned long address)
{
	struct sbiret ret;

	ret = sbi_ecall(SBI_EXT_MICROCHIP_TECHNOLOGY, command, channel,
			address, 0, 0, 0, 0);

	if (ret.error)
		return sbi_err_map_linux_errno(ret.error);
	else
		return ret.value;
}

static int mchp_ipc_sbi_send(u32 command, unsigned long address)
{
	struct sbiret ret;

	ret = sbi_ecall(SBI_EXT_MICROCHIP_TECHNOLOGY, command, address,
			0, 0, 0, 0, 0);

	if (ret.error)
		return sbi_err_map_linux_errno(ret.error);
	else
		return ret.value;
}

static struct mchp_ipc_sbi_mbox *to_mchp_ipc_mbox(struct mbox_controller *mbox)
{
	return container_of(mbox, struct mchp_ipc_sbi_mbox, controller);
}

static inline void mchp_ipc_prepare_receive_req(struct mbox_chan *chan)
{
	struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
	struct mchp_ipc_sbi_msg request;

	request.buf_addr = chan_info->msg_buf_rx_addr;
	request.size = chan_info->max_msg_size;
	memcpy(chan_info->buf_base_rx, &request, sizeof(struct mchp_ipc_sbi_msg));
}

static inline void mchp_ipc_process_received_data(struct mbox_chan *chan,
						  struct mchp_ipc_msg *ipc_msg)
{
	struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
	struct mchp_ipc_sbi_msg sbi_msg;

	memcpy(&sbi_msg, chan_info->buf_base_rx, sizeof(struct mchp_ipc_sbi_msg));
	ipc_msg->buf = (u32 *)chan_info->msg_buf_rx;
	ipc_msg->size = sbi_msg.size;
}

static irqreturn_t mchp_ipc_cluster_aggr_isr(int irq, void *data)
{
	struct mbox_chan *chan;
	struct mchp_ipc_sbi_chan *chan_info;
	struct mchp_ipc_sbi_mbox *ipc = (struct mchp_ipc_sbi_mbox *)data;
	struct mchp_ipc_msg ipc_msg;
	struct mchp_ipc_status status_msg;
	int ret;
	u32 i, chan_index, chan_id;
	bool found = false;

	/* Find out the hart that originated the irq */
	for_each_online_cpu(i) {
		if (irq == ipc->cluster_cfg[i].irq) {
			found = true;
			break;
		}
	}

	if (unlikely(!found))
		return IRQ_NONE;

	status_msg.cluster = cpuid_to_hartid_map(i);
	memcpy(ipc->cluster_cfg[i].buf_base, &status_msg, sizeof(struct mchp_ipc_status));

	ret = mchp_ipc_sbi_send(SBI_EXT_IPC_STATUS, ipc->cluster_cfg[i].buf_base_addr);
	if (ret < 0) {
		dev_err_ratelimited(ipc->dev, "could not get IHC irq status ret=%d\n", ret);
		return IRQ_HANDLED;
	}

	memcpy(&status_msg, ipc->cluster_cfg[i].buf_base, sizeof(struct mchp_ipc_status));

	/*
	 * Iterate over each bit set in the IHC interrupt status register (IRQ_STATUS) to identify
	 * the channel(s) that have a message to be processed/acknowledged.
	 * The bits are organized in alternating format, where each pair of bits represents
	 * the status of the message present and message clear interrupts for each cluster/hart
	 * (from hart 0 to hart 5). Each cluster can have up to 5 fixed channels associated.
	 */

	for_each_set_bit(i, (unsigned long *)&status_msg.status, IRQ_STATUS_BITS) {
		/* Find out the destination hart that triggered the interrupt */
		chan_index = i / 2;

		/*
		 * The IP has no loopback channels, so we need to decrement the index when
		 * the target hart has a greater index than our own
		 */
		if (chan_index >= status_msg.cluster)
			chan_index--;

		/*
		 * Calculate the channel id given the hart and channel index. Channel IDs
		 * are unique across all clusters of an IPC, and iterate contiguously
		 * across all clusters.
		 */
		chan_id = status_msg.cluster * (NUM_CHANS_PER_CLUSTER + chan_index);

		chan = &ipc->chans[chan_id];
		chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;

		if (i % 2 == 0) {
			mchp_ipc_prepare_receive_req(chan);
			ret = mchp_ipc_sbi_chan_send(SBI_EXT_IPC_RECEIVE, chan_id,
						     chan_info->buf_base_rx_addr);
			if (ret < 0)
				continue;

			mchp_ipc_process_received_data(chan, &ipc_msg);
			mbox_chan_received_data(&ipc->chans[chan_id], (void *)&ipc_msg);

		} else {
			ret = mchp_ipc_sbi_chan_send(SBI_EXT_IPC_RECEIVE, chan_id,
						     chan_info->buf_base_rx_addr);
			mbox_chan_txdone(&ipc->chans[chan_id], ret);
		}
	}
	return IRQ_HANDLED;
}

static int mchp_ipc_send_data(struct mbox_chan *chan, void *data)
{
	struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
	const struct mchp_ipc_msg *msg = data;
	struct mchp_ipc_sbi_msg sbi_payload;

	memcpy(chan_info->msg_buf_tx, msg->buf, msg->size);
	sbi_payload.buf_addr = chan_info->msg_buf_tx_addr;
	sbi_payload.size = msg->size;
	memcpy(chan_info->buf_base_tx, &sbi_payload, sizeof(sbi_payload));

	return mchp_ipc_sbi_chan_send(SBI_EXT_IPC_SEND, chan_info->id, chan_info->buf_base_tx_addr);
}

static int mchp_ipc_startup(struct mbox_chan *chan)
{
	struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
	struct mchp_ipc_sbi_mbox *ipc = to_mchp_ipc_mbox(chan->mbox);
	struct mchp_ipc_init ch_init_msg;
	int ret;

	/*
	 * The TX base buffer is used to transmit two types of messages:
	 * - struct mchp_ipc_init to initialize the channel
	 * - struct mchp_ipc_sbi_msg to transmit user data/payload
	 * Ensure the TX buffer size is large enough to accommodate either message type.
	 */
	size_t max_size = max(sizeof(struct mchp_ipc_init), sizeof(struct mchp_ipc_sbi_msg));

	chan_info->buf_base_tx = kmalloc(max_size, GFP_KERNEL);
	if (!chan_info->buf_base_tx) {
		ret = -ENOMEM;
		goto fail;
	}

	chan_info->buf_base_tx_addr = __pa(chan_info->buf_base_tx);

	chan_info->buf_base_rx = kmalloc(max_size, GFP_KERNEL);
	if (!chan_info->buf_base_rx) {
		ret = -ENOMEM;
		goto fail_free_buf_base_tx;
	}

	chan_info->buf_base_rx_addr = __pa(chan_info->buf_base_rx);

	ret = mchp_ipc_sbi_chan_send(SBI_EXT_IPC_CH_INIT, chan_info->id,
				     chan_info->buf_base_tx_addr);
	if (ret < 0) {
		dev_err(ipc->dev, "channel %u init failed\n", chan_info->id);
		goto fail_free_buf_base_rx;
	}

	memcpy(&ch_init_msg, chan_info->buf_base_tx, sizeof(struct mchp_ipc_init));
	chan_info->max_msg_size = ch_init_msg.max_msg_size;

	chan_info->msg_buf_tx = kmalloc(chan_info->max_msg_size, GFP_KERNEL);
	if (!chan_info->msg_buf_tx) {
		ret = -ENOMEM;
		goto fail_free_buf_base_rx;
	}

	chan_info->msg_buf_tx_addr = __pa(chan_info->msg_buf_tx);

	chan_info->msg_buf_rx = kmalloc(chan_info->max_msg_size, GFP_KERNEL);
	if (!chan_info->msg_buf_rx) {
		ret = -ENOMEM;
		goto fail_free_buf_msg_tx;
	}

	chan_info->msg_buf_rx_addr = __pa(chan_info->msg_buf_rx);

	switch (ipc->hw_type) {
	case MIV_IHC:
		return 0;
	default:
		goto fail_free_buf_msg_rx;
	}

fail_free_buf_msg_rx:
	kfree(chan_info->msg_buf_rx);
fail_free_buf_msg_tx:
	kfree(chan_info->msg_buf_tx);
fail_free_buf_base_rx:
	kfree(chan_info->buf_base_rx);
fail_free_buf_base_tx:
	kfree(chan_info->buf_base_tx);
fail:
	return ret;
}

static void mchp_ipc_shutdown(struct mbox_chan *chan)
{
	struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;

	kfree(chan_info->buf_base_tx);
	kfree(chan_info->buf_base_rx);
	kfree(chan_info->msg_buf_tx);
	kfree(chan_info->msg_buf_rx);
}

static const struct mbox_chan_ops mchp_ipc_ops = {
	.startup = mchp_ipc_startup,
	.send_data = mchp_ipc_send_data,
	.shutdown = mchp_ipc_shutdown,
};

static struct mbox_chan *mchp_ipc_mbox_xlate(struct mbox_controller *controller,
					     const struct of_phandle_args *spec)
{
	struct mchp_ipc_sbi_mbox *ipc = to_mchp_ipc_mbox(controller);
	unsigned int chan_id = spec->args[0];

	if (chan_id >= ipc->controller.num_chans) {
		dev_err(ipc->dev, "invalid channel id %d\n", chan_id);
		return ERR_PTR(-EINVAL);
	}

	return &ipc->chans[chan_id];
}

static int mchp_ipc_get_cluster_aggr_irq(struct mchp_ipc_sbi_mbox *ipc)
{
	struct platform_device *pdev = to_platform_device(ipc->dev);
	char *irq_name;
	int cpuid, ret;
	unsigned long hartid;
	bool irq_found = false;

	for_each_online_cpu(cpuid) {
		hartid = cpuid_to_hartid_map(cpuid);
		irq_name = devm_kasprintf(ipc->dev, GFP_KERNEL, "hart-%lu", hartid);
		ret = platform_get_irq_byname_optional(pdev, irq_name);
		if (ret <= 0)
			continue;

		ipc->cluster_cfg[cpuid].irq = ret;
		ret = devm_request_irq(ipc->dev, ipc->cluster_cfg[cpuid].irq,
				       mchp_ipc_cluster_aggr_isr, IRQF_SHARED,
				       "miv-ihc-irq", ipc);
		if (ret)
			return ret;

		ipc->cluster_cfg[cpuid].buf_base = devm_kmalloc(ipc->dev,
								sizeof(struct mchp_ipc_status),
								GFP_KERNEL);

		if (!ipc->cluster_cfg[cpuid].buf_base)
			return -ENOMEM;

		ipc->cluster_cfg[cpuid].buf_base_addr = __pa(ipc->cluster_cfg[cpuid].buf_base);

		irq_found = true;
	}

	return irq_found;
}

static int mchp_ipc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct mchp_ipc_mbox_info ipc_info;
	struct mchp_ipc_sbi_mbox *ipc;
	struct mchp_ipc_sbi_chan *priv;
	bool irq_avail = false;
	int ret;
	u32 chan_id;

	ret = sbi_probe_extension(SBI_EXT_MICROCHIP_TECHNOLOGY);
	if (ret <= 0)
		return dev_err_probe(dev, -ENODEV, "Microchip SBI extension not detected\n");

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

	platform_set_drvdata(pdev, ipc);

	ipc->buf_base = devm_kmalloc(dev, sizeof(struct mchp_ipc_mbox_info), GFP_KERNEL);
	if (!ipc->buf_base)
		return -ENOMEM;

	ipc->buf_base_addr = __pa(ipc->buf_base);

	ret = mchp_ipc_sbi_send(SBI_EXT_IPC_PROBE, ipc->buf_base_addr);
	if (ret < 0)
		return dev_err_probe(dev, ret, "could not probe IPC SBI service\n");

	memcpy(&ipc_info, ipc->buf_base, sizeof(struct mchp_ipc_mbox_info));
	ipc->controller.num_chans = ipc_info.num_channels;
	ipc->hw_type = ipc_info.hw_type;

	ipc->chans = devm_kcalloc(dev, ipc->controller.num_chans, sizeof(*ipc->chans), GFP_KERNEL);
	if (!ipc->chans)
		return -ENOMEM;

	ipc->dev = dev;
	ipc->controller.txdone_irq = true;
	ipc->controller.dev = ipc->dev;
	ipc->controller.ops = &mchp_ipc_ops;
	ipc->controller.chans = ipc->chans;
	ipc->controller.of_xlate = mchp_ipc_mbox_xlate;

	for (chan_id = 0; chan_id < ipc->controller.num_chans; chan_id++) {
		priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
		if (!priv)
			return -ENOMEM;

		ipc->chans[chan_id].con_priv = priv;
		priv->id = chan_id;
	}

	if (ipc->hw_type == MIV_IHC) {
		ipc->cluster_cfg = devm_kcalloc(dev, num_online_cpus(),
						sizeof(struct mchp_ipc_cluster_cfg),
						GFP_KERNEL);
		if (!ipc->cluster_cfg)
			return -ENOMEM;

		if (mchp_ipc_get_cluster_aggr_irq(ipc))
			irq_avail = true;
	}

	if (!irq_avail)
		return dev_err_probe(dev, -ENODEV, "missing interrupt property\n");

	ret = devm_mbox_controller_register(dev, &ipc->controller);
	if (ret)
		return dev_err_probe(dev, ret,
				    "Inter-Processor communication (IPC) registration failed\n");

	return 0;
}

static const struct of_device_id mchp_ipc_of_match[] = {
	{.compatible = "microchip,sbi-ipc", },
	{}
};
MODULE_DEVICE_TABLE(of, mchp_ipc_of_match);

static struct platform_driver mchp_ipc_driver = {
	.driver = {
		.name = "microchip_ipc",
		.of_match_table = mchp_ipc_of_match,
	},
	.probe = mchp_ipc_probe,
};

module_platform_driver(mchp_ipc_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Valentina Fernandez <valentina.fernandezalanis@microchip.com>");
MODULE_DESCRIPTION("Microchip Inter-Processor Communication (IPC) driver");
