/*
 * Copyright (c) 2022 Andes Technology Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/drivers/mbox.h>

#define LOG_LEVEL CONFIG_MBOX_LOG_LEVEL
#include <zephyr/logging/log.h>
#include <zephyr/irq.h>
LOG_MODULE_REGISTER(mbox_andes_plic_sw);

#define DT_DRV_COMPAT	andestech_plic_sw

#define IRQ_REG(n) (n >> 5)
#define PLIC_BASE(dev) \
	((const struct mbox_andes_conf * const)(dev)->config)->base

#define REG_PRIORITY(dev, irq) \
	(PLIC_BASE(dev) + 0x0 + (irq << 2))
#define REG_PENDING(dev, irq) \
	(PLIC_BASE(dev) + 0x1000 + (IRQ_REG(irq) << 2))
#define REG_ENABLE(dev, hart, irq) \
	(PLIC_BASE(dev) + 0x2000 + (hart << 7) + IRQ_REG(irq))
#define REG_CLAIM(dev, hart) \
	(PLIC_BASE(dev) + 0x200004 + (hart << 12))

#define IPI_NUM DT_INST_PROP(0, channel_max)

static struct mbox_andes_data {
	mbox_callback_t cb[IPI_NUM];
	void *user_data[IPI_NUM];
	uint32_t enabled_channel[CONFIG_MP_NUM_CPUS];
#ifdef CONFIG_SCHED_IPI_SUPPORTED
	uint32_t reg_cb_channel;
	uint32_t ipi_channel;
#endif
} andes_mbox_data;

static struct mbox_andes_conf {
	uint32_t base;
	uint32_t channel_max;
} andes_mbox_conf = {
	.base = DT_INST_REG_ADDR(0),
	.channel_max = IPI_NUM,
};

static struct k_spinlock mbox_syn;

static void plic_sw_irq_set_pending(const struct device *dev, uint32_t irq)
{
	uint32_t pend;
	k_spinlock_key_t key = k_spin_lock(&mbox_syn);

	pend = sys_read32(REG_PENDING(dev, irq));
	pend |= BIT(irq);
	sys_write32(pend, REG_PENDING(dev, irq));

	k_spin_unlock(&mbox_syn, key);
}

static inline bool is_channel_valid(const struct device *dev, uint32_t ch)
{
	const struct mbox_andes_conf *conf = dev->config;

	return (ch <= conf->channel_max);
}

static int mbox_andes_send(const struct device *dev, uint32_t ch,
			   const struct mbox_msg *msg)
{
	if (msg) {
		LOG_WRN("Sending data not supported");
	}

	if (!is_channel_valid(dev, ch)) {
		return -EINVAL;
	}

	/* Send IPI by triggering the pending register of PLIC SW. */
	plic_sw_irq_set_pending(dev, ch + 1);

	return 0;
}

static int mbox_andes_register_callback(const struct device *dev, uint32_t ch,
					mbox_callback_t cb, void *user_data)
{
	struct mbox_andes_data *data = dev->data;
	const struct mbox_andes_conf *conf = dev->config;
	int ret = 0;

	k_spinlock_key_t key = k_spin_lock(&mbox_syn);

	if (ch > conf->channel_max) {
		ret = -EINVAL;
		goto out;
	}

#ifdef CONFIG_SCHED_IPI_SUPPORTED
	if (ch & data->ipi_channel & data->reg_cb_channel) {
		ret = -EALREADY;
		goto out;
	}

	data->reg_cb_channel |= BIT(ch);
#endif
	data->cb[ch] = cb;
	data->user_data[ch] = user_data;

out:
	k_spin_unlock(&mbox_syn, key);

	return 0;
}

static int mbox_andes_mtu_get(const struct device *dev)
{
	/* We only support signalling */
	return 0;
}

static uint32_t mbox_andes_max_channels_get(const struct device *dev)
{
	const struct mbox_andes_conf *conf = dev->config;

	return conf->channel_max;
}

static int mbox_andes_set_enabled(const struct device *dev, uint32_t ch,
				  bool enable)
{
	uint32_t en, is_enabled_ch, hartid, cpu_id, irq;
	struct mbox_andes_data *data = dev->data;
	int ret = 0;

	k_spinlock_key_t key = k_spin_lock(&mbox_syn);

	if (!is_channel_valid(dev, ch)) {
		ret = -EINVAL;
		goto out;
	}

	irq = ch + 1;
	hartid = arch_proc_id();
	cpu_id = _current_cpu->id;

	is_enabled_ch = data->enabled_channel[cpu_id] & BIT(ch);

	if ((!enable && !is_enabled_ch) || (enable && is_enabled_ch)) {
		ret = -EALREADY;
		goto out;
	}

	if (enable && !(data->cb[ch])) {
		LOG_WRN("Enabling channel without a registered callback\n");
	}

	en = sys_read32(REG_ENABLE(dev, hartid, irq));

	if (enable) {
		data->enabled_channel[cpu_id] |= BIT(ch);
		sys_write32(1, REG_PRIORITY(dev, irq));
		en |= BIT(irq);
	} else {
		data->enabled_channel[cpu_id] &= ~BIT(ch);
		en &= ~BIT(irq);
	}

	sys_write32(en, REG_ENABLE(dev, hartid, irq));
out:
	k_spin_unlock(&mbox_syn, key);

	return ret;
}

static void andes_plic_sw_irq_handler(const struct device *dev)
{
	struct mbox_andes_data *data = dev->data;
	uint32_t irq, ch, hartid;

	hartid = arch_proc_id();

	/* PLIC claim: Get the SW IRQ number generating the interrupt. */
	irq = sys_read32(REG_CLAIM(dev, hartid));
	ch = irq - 1;

	if (irq) {
		sys_write32(irq, REG_CLAIM(dev, hartid));

		if (data->cb[ch]) {
			/* Only one MAILBOX, id is unused and set to 0 */
			data->cb[ch](dev, ch, data->user_data[ch], NULL);
		}
	}
}

static int mbox_andes_init(const struct device *dev)
{
	/* Setup IRQ handler for PLIC SW driver */
	IRQ_CONNECT(RISCV_MACHINE_SOFT_IRQ, 1,
		    andes_plic_sw_irq_handler, DEVICE_DT_INST_GET(0), 0);

#ifndef CONFIG_SMP
	irq_enable(RISCV_MACHINE_SOFT_IRQ);
#endif
	return 0;
}

static const struct mbox_driver_api mbox_andes_driver_api = {
	.send = mbox_andes_send,
	.register_callback = mbox_andes_register_callback,
	.mtu_get = mbox_andes_mtu_get,
	.max_channels_get = mbox_andes_max_channels_get,
	.set_enabled = mbox_andes_set_enabled,
};

DEVICE_DT_INST_DEFINE(0, mbox_andes_init, NULL, &andes_mbox_data,
		      &andes_mbox_conf, PRE_KERNEL_1, CONFIG_MBOX_INIT_PRIORITY,
		      &mbox_andes_driver_api);
