// 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",
				__func__, 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);
