// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * OPAL IMC interface detection driver
 * Supported on POWERNV platform
 *
 * Copyright	(C) 2017 Madhavan Srinivasan, IBM Corporation.
 *		(C) 2017 Anju T Sudhakar, IBM Corporation.
 *		(C) 2017 Hemant K Shaw, IBM Corporation.
 */
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/crash_dump.h>
#include <linux/debugfs.h>
#include <asm/opal.h>
#include <asm/io.h>
#include <asm/imc-pmu.h>
#include <asm/cputhreads.h>

static struct dentry *imc_debugfs_parent;

/* Helpers to export imc command and mode via debugfs */
static int imc_mem_get(void *data, u64 *val)
{
	*val = cpu_to_be64(*(u64 *)data);
	return 0;
}

static int imc_mem_set(void *data, u64 val)
{
	*(u64 *)data = cpu_to_be64(val);
	return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_imc_x64, imc_mem_get, imc_mem_set, "0x%016llx\n");

static void imc_debugfs_create_x64(const char *name, umode_t mode,
				   struct dentry *parent, u64  *value)
{
	debugfs_create_file_unsafe(name, mode, parent, value, &fops_imc_x64);
}

/*
 * export_imc_mode_and_cmd: Create a debugfs interface
 *                     for imc_cmd and imc_mode
 *                     for each node in the system.
 *  imc_mode and imc_cmd can be changed by echo into
 *  this interface.
 */
static void export_imc_mode_and_cmd(struct device_node *node,
				    struct imc_pmu *pmu_ptr)
{
	static u64 loc, *imc_mode_addr, *imc_cmd_addr;
	char mode[16], cmd[16];
	u32 cb_offset;
	struct imc_mem_info *ptr = pmu_ptr->mem_info;

	imc_debugfs_parent = debugfs_create_dir("imc", arch_debugfs_dir);

	if (of_property_read_u32(node, "cb_offset", &cb_offset))
		cb_offset = IMC_CNTL_BLK_OFFSET;

	while (ptr->vbase != NULL) {
		loc = (u64)(ptr->vbase) + cb_offset;
		imc_mode_addr = (u64 *)(loc + IMC_CNTL_BLK_MODE_OFFSET);
		sprintf(mode, "imc_mode_%d", (u32)(ptr->id));
		imc_debugfs_create_x64(mode, 0600, imc_debugfs_parent,
				       imc_mode_addr);

		imc_cmd_addr = (u64 *)(loc + IMC_CNTL_BLK_CMD_OFFSET);
		sprintf(cmd, "imc_cmd_%d", (u32)(ptr->id));
		imc_debugfs_create_x64(cmd, 0600, imc_debugfs_parent,
				       imc_cmd_addr);
		ptr++;
	}
}

/*
 * imc_get_mem_addr_nest: Function to get nest counter memory region
 * for each chip
 */
static int imc_get_mem_addr_nest(struct device_node *node,
				 struct imc_pmu *pmu_ptr,
				 u32 offset)
{
	int nr_chips = 0, i;
	u64 *base_addr_arr, baddr;
	u32 *chipid_arr;

	nr_chips = of_property_count_u32_elems(node, "chip-id");
	if (nr_chips <= 0)
		return -ENODEV;

	base_addr_arr = kcalloc(nr_chips, sizeof(*base_addr_arr), GFP_KERNEL);
	if (!base_addr_arr)
		return -ENOMEM;

	chipid_arr = kcalloc(nr_chips, sizeof(*chipid_arr), GFP_KERNEL);
	if (!chipid_arr) {
		kfree(base_addr_arr);
		return -ENOMEM;
	}

	if (of_property_read_u32_array(node, "chip-id", chipid_arr, nr_chips))
		goto error;

	if (of_property_read_u64_array(node, "base-addr", base_addr_arr,
								nr_chips))
		goto error;

	pmu_ptr->mem_info = kcalloc(nr_chips + 1, sizeof(*pmu_ptr->mem_info),
				    GFP_KERNEL);
	if (!pmu_ptr->mem_info)
		goto error;

	for (i = 0; i < nr_chips; i++) {
		pmu_ptr->mem_info[i].id = chipid_arr[i];
		baddr = base_addr_arr[i] + offset;
		pmu_ptr->mem_info[i].vbase = phys_to_virt(baddr);
	}

	pmu_ptr->imc_counter_mmaped = true;
	kfree(base_addr_arr);
	kfree(chipid_arr);
	return 0;

error:
	kfree(base_addr_arr);
	kfree(chipid_arr);
	return -1;
}

/*
 * imc_pmu_create : Takes the parent device which is the pmu unit, pmu_index
 *		    and domain as the inputs.
 * Allocates memory for the struct imc_pmu, sets up its domain, size and offsets
 */
static struct imc_pmu *imc_pmu_create(struct device_node *parent, int pmu_index, int domain)
{
	int ret = 0;
	struct imc_pmu *pmu_ptr;
	u32 offset;

	/* Return for unknown domain */
	if (domain < 0)
		return NULL;

	/* memory for pmu */
	pmu_ptr = kzalloc(sizeof(*pmu_ptr), GFP_KERNEL);
	if (!pmu_ptr)
		return NULL;

	/* Set the domain */
	pmu_ptr->domain = domain;

	ret = of_property_read_u32(parent, "size", &pmu_ptr->counter_mem_size);
	if (ret)
		goto free_pmu;

	if (!of_property_read_u32(parent, "offset", &offset)) {
		if (imc_get_mem_addr_nest(parent, pmu_ptr, offset))
			goto free_pmu;
	}

	/* Function to register IMC pmu */
	ret = init_imc_pmu(parent, pmu_ptr, pmu_index);
	if (ret) {
		pr_err("IMC PMU %s Register failed\n", pmu_ptr->pmu.name);
		kfree(pmu_ptr->pmu.name);
		if (pmu_ptr->domain == IMC_DOMAIN_NEST)
			kfree(pmu_ptr->mem_info);
		kfree(pmu_ptr);
		return NULL;
	}

	return pmu_ptr;

free_pmu:
	kfree(pmu_ptr);
	return NULL;
}

static void disable_nest_pmu_counters(void)
{
	int nid, cpu;
	const struct cpumask *l_cpumask;

	cpus_read_lock();
	for_each_node_with_cpus(nid) {
		l_cpumask = cpumask_of_node(nid);
		cpu = cpumask_first_and(l_cpumask, cpu_online_mask);
		if (cpu >= nr_cpu_ids)
			continue;
		opal_imc_counters_stop(OPAL_IMC_COUNTERS_NEST,
				       get_hard_smp_processor_id(cpu));
	}
	cpus_read_unlock();
}

static void disable_core_pmu_counters(void)
{
	int cpu, rc;

	cpus_read_lock();
	/* Disable the IMC Core functions */
	for_each_online_cpu(cpu) {
		if (cpu_first_thread_sibling(cpu) != cpu)
			continue;
		rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
					    get_hard_smp_processor_id(cpu));
		if (rc)
			pr_err("%s: Failed to stop Core (cpu = %d)\n",
				__FUNCTION__, cpu);
	}
	cpus_read_unlock();
}

int get_max_nest_dev(void)
{
	struct device_node *node;
	u32 pmu_units = 0, type;

	for_each_compatible_node(node, NULL, IMC_DTB_UNIT_COMPAT) {
		if (of_property_read_u32(node, "type", &type))
			continue;

		if (type == IMC_TYPE_CHIP)
			pmu_units++;
	}

	return pmu_units;
}

static int opal_imc_counters_probe(struct platform_device *pdev)
{
	struct device_node *imc_dev = pdev->dev.of_node;
	struct imc_pmu *pmu;
	int pmu_count = 0, domain;
	bool core_imc_reg = false, thread_imc_reg = false;
	u32 type;

	/*
	 * Check whether this is kdump kernel. If yes, force the engines to
	 * stop and return.
	 */
	if (is_kdump_kernel()) {
		disable_nest_pmu_counters();
		disable_core_pmu_counters();
		return -ENODEV;
	}

	for_each_compatible_node(imc_dev, NULL, IMC_DTB_UNIT_COMPAT) {
		pmu = NULL;
		if (of_property_read_u32(imc_dev, "type", &type)) {
			pr_warn("IMC Device without type property\n");
			continue;
		}

		switch (type) {
		case IMC_TYPE_CHIP:
			domain = IMC_DOMAIN_NEST;
			break;
		case IMC_TYPE_CORE:
			domain =IMC_DOMAIN_CORE;
			break;
		case IMC_TYPE_THREAD:
			domain = IMC_DOMAIN_THREAD;
			break;
		case IMC_TYPE_TRACE:
			domain = IMC_DOMAIN_TRACE;
			break;
		default:
			pr_warn("IMC Unknown Device type \n");
			domain = -1;
			break;
		}

		pmu = imc_pmu_create(imc_dev, pmu_count, domain);
		if (pmu != NULL) {
			if (domain == IMC_DOMAIN_NEST) {
				if (!imc_debugfs_parent)
					export_imc_mode_and_cmd(imc_dev, pmu);
				pmu_count++;
			}
			if (domain == IMC_DOMAIN_CORE)
				core_imc_reg = true;
			if (domain == IMC_DOMAIN_THREAD)
				thread_imc_reg = true;
		}
	}

	/* If core imc is not registered, unregister thread-imc */
	if (!core_imc_reg && thread_imc_reg)
		unregister_thread_imc();

	return 0;
}

static void opal_imc_counters_shutdown(struct platform_device *pdev)
{
	/*
	 * Function only stops the engines which is bare minimum.
	 * TODO: Need to handle proper memory cleanup and pmu
	 * unregister.
	 */
	disable_nest_pmu_counters();
	disable_core_pmu_counters();
}

static const struct of_device_id opal_imc_match[] = {
	{ .compatible = IMC_DTB_COMPAT },
	{},
};

static struct platform_driver opal_imc_driver = {
	.driver = {
		.name = "opal-imc-counters",
		.of_match_table = opal_imc_match,
	},
	.probe = opal_imc_counters_probe,
	.shutdown = opal_imc_counters_shutdown,
};

builtin_platform_driver(opal_imc_driver);
