// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2019, Rick Chen <rick@andestech.com>
 *
 * U-Boot syscon driver for Andes' PLICSW
 * The PLICSW block is an Andes-specific design for software interrupts,
 * contains memory-mapped priority, enable, claim and pending registers
 * similar to RISC-V PLIC.
 */

#include <dm.h>
#include <asm/global_data.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/uclass-internal.h>
#include <regmap.h>
#include <syscon.h>
#include <asm/io.h>
#include <asm/syscon.h>
#include <cpu.h>
#include <linux/err.h>

/* pending register */
#define PENDING_REG(base)	((ulong)(base) + 0x1000)
/* enable register */
#define ENABLE_REG(base, hart)	((ulong)(base) + 0x2000 + (hart) * 0x80)
/* claim register */
#define CLAIM_REG(base, hart)	((ulong)(base) + 0x200004 + (hart) * 0x1000)
/* priority register */
#define PRIORITY_REG(base)	((ulong)(base) + PLICSW_PRIORITY_BASE)

/* Bit 0 of PLIC-SW pending array is hardwired to zero, so we start from bit 1 */
#define FIRST_AVAILABLE_BIT	0x2
#define SEND_IPI_TO_HART(hart)	(FIRST_AVAILABLE_BIT << (hart))
#define PLICSW_PRIORITY_BASE        0x4
#define PLICSW_INTERRUPT_PER_HART   0x1

DECLARE_GLOBAL_DATA_PTR;

static int enable_ipi(int hart)
{
	unsigned int en;

	en = FIRST_AVAILABLE_BIT << hart;
	writel(en, (void __iomem *)ENABLE_REG(gd->arch.plicsw, hart));

	return 0;
}

static void init_priority_ipi(int hart_num)
{
    uint32_t *priority = (void *)PRIORITY_REG(gd->arch.plicsw);

    for (int i = 0; i < hart_num * PLICSW_INTERRUPT_PER_HART; i++) {
        writel(1, &priority[i]);
    }

    return;
}

int riscv_init_ipi(void)
{
	int ret;
	int hart_num = 0;
	long *base = syscon_get_first_range(RISCV_SYSCON_PLICSW);
	ofnode node;
	struct udevice *dev;
	u32 reg;

	if (IS_ERR(base))
		return PTR_ERR(base);
	gd->arch.plicsw = base;

	ret = uclass_find_first_device(UCLASS_CPU, &dev);
	if (ret)
		return ret;
	if (!dev)
		return -ENODEV;

	ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) {
		const char *device_type;

		device_type = ofnode_read_string(node, "device_type");
		if (!device_type)
			continue;

		if (strcmp(device_type, "cpu"))
			continue;

		/* skip if hart is marked as not available */
		if (!ofnode_is_enabled(node))
			continue;

		/* read hart ID of CPU */
		ret = ofnode_read_u32(node, "reg", &reg);
		if (ret == 0)
			enable_ipi(reg);
		hart_num++;
	}

	init_priority_ipi(hart_num);
	return 0;
}

int riscv_send_ipi(int hart)
{
	unsigned int ipi = SEND_IPI_TO_HART(hart);

	writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plicsw));

	return 0;
}

int riscv_clear_ipi(int hart)
{
	u32 source_id;

	source_id = readl((void __iomem *)CLAIM_REG(gd->arch.plicsw, hart));
	writel(source_id, (void __iomem *)CLAIM_REG(gd->arch.plicsw, hart));

	return 0;
}

int riscv_get_ipi(int hart, int *pending)
{
	unsigned int ipi = SEND_IPI_TO_HART(hart);

	*pending = readl((void __iomem *)PENDING_REG(gd->arch.plicsw));
	*pending = !!(*pending & ipi);

	return 0;
}

static const struct udevice_id andes_plicsw_ids[] = {
	{ .compatible = "andestech,plicsw", .data = RISCV_SYSCON_PLICSW },
	{ }
};

U_BOOT_DRIVER(andes_plicsw) = {
	.name		= "andes_plicsw",
	.id		= UCLASS_SYSCON,
	.of_match	= andes_plicsw_ids,
	.flags		= DM_FLAG_PRE_RELOC,
};
