// SPDX-License-Identifier: GPL-2.0
/*
 * RISC-V performance counter support.
 *
 * Copyright (C) 2021 Western Digital Corporation or its affiliates.
 *
 * This implementation is based on old RISC-V perf and ARM perf event code
 * which are in turn based on sparc64 and x86 code.
 */

#include <linux/mod_devicetable.h>
#include <linux/perf/riscv_pmu.h>
#include <linux/platform_device.h>

#define RISCV_PMU_LEGACY_CYCLE		0
#define RISCV_PMU_LEGACY_INSTRET	2

static bool pmu_init_done;

static int pmu_legacy_ctr_get_idx(struct perf_event *event)
{
	struct perf_event_attr *attr = &event->attr;

	if (event->attr.type != PERF_TYPE_HARDWARE)
		return -EOPNOTSUPP;
	if (attr->config == PERF_COUNT_HW_CPU_CYCLES)
		return RISCV_PMU_LEGACY_CYCLE;
	else if (attr->config == PERF_COUNT_HW_INSTRUCTIONS)
		return RISCV_PMU_LEGACY_INSTRET;
	else
		return -EOPNOTSUPP;
}

/* For legacy config & counter index are same */
static int pmu_legacy_event_map(struct perf_event *event, u64 *config)
{
	return pmu_legacy_ctr_get_idx(event);
}

/* cycle & instret are always 64 bit, one bit less according to SBI spec */
static int pmu_legacy_ctr_get_width(int idx)
{
	return 63;
}

static u64 pmu_legacy_read_ctr(struct perf_event *event)
{
	struct hw_perf_event *hwc = &event->hw;
	int idx = hwc->idx;
	u64 val;

	if (idx == RISCV_PMU_LEGACY_CYCLE) {
		val = riscv_pmu_ctr_read_csr(CSR_CYCLE);
		if (IS_ENABLED(CONFIG_32BIT))
			val = (u64)riscv_pmu_ctr_read_csr(CSR_CYCLEH) << 32 | val;
	} else if (idx == RISCV_PMU_LEGACY_INSTRET) {
		val = riscv_pmu_ctr_read_csr(CSR_INSTRET);
		if (IS_ENABLED(CONFIG_32BIT))
			val = ((u64)riscv_pmu_ctr_read_csr(CSR_INSTRETH)) << 32 | val;
	} else
		return 0;

	return val;
}

static void pmu_legacy_ctr_start(struct perf_event *event, u64 ival)
{
	struct hw_perf_event *hwc = &event->hw;
	u64 initial_val = pmu_legacy_read_ctr(event);

	/**
	 * The legacy method doesn't really have a start/stop method.
	 * It also can not update the counter with a initial value.
	 * But we still need to set the prev_count so that read() can compute
	 * the delta. Just use the current counter value to set the prev_count.
	 */
	local64_set(&hwc->prev_count, initial_val);
}

static uint8_t pmu_legacy_csr_index(struct perf_event *event)
{
	return event->hw.idx;
}

static void pmu_legacy_event_mapped(struct perf_event *event, struct mm_struct *mm)
{
	if (event->attr.config != PERF_COUNT_HW_CPU_CYCLES &&
	    event->attr.config != PERF_COUNT_HW_INSTRUCTIONS)
		return;

	event->hw.flags |= PERF_EVENT_FLAG_USER_READ_CNT;
}

static void pmu_legacy_event_unmapped(struct perf_event *event, struct mm_struct *mm)
{
	if (event->attr.config != PERF_COUNT_HW_CPU_CYCLES &&
	    event->attr.config != PERF_COUNT_HW_INSTRUCTIONS)
		return;

	event->hw.flags &= ~PERF_EVENT_FLAG_USER_READ_CNT;
}

/*
 * This is just a simple implementation to allow legacy implementations
 * compatible with new RISC-V PMU driver framework.
 * This driver only allows reading two counters i.e CYCLE & INSTRET.
 * However, it can not start or stop the counter. Thus, it is not very useful
 * will be removed in future.
 */
static void pmu_legacy_init(struct riscv_pmu *pmu)
{
	pr_info("Legacy PMU implementation is available\n");

	pmu->cmask = BIT(RISCV_PMU_LEGACY_CYCLE) |
		BIT(RISCV_PMU_LEGACY_INSTRET);
	pmu->ctr_start = pmu_legacy_ctr_start;
	pmu->ctr_stop = NULL;
	pmu->event_map = pmu_legacy_event_map;
	pmu->ctr_get_idx = pmu_legacy_ctr_get_idx;
	pmu->ctr_get_width = pmu_legacy_ctr_get_width;
	pmu->ctr_clear_idx = NULL;
	pmu->ctr_read = pmu_legacy_read_ctr;
	pmu->event_mapped = pmu_legacy_event_mapped;
	pmu->event_unmapped = pmu_legacy_event_unmapped;
	pmu->csr_index = pmu_legacy_csr_index;
	pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
	pmu->pmu.capabilities |= PERF_PMU_CAP_NO_EXCLUDE;

	perf_pmu_register(&pmu->pmu, "cpu", PERF_TYPE_RAW);
}

static int pmu_legacy_device_probe(struct platform_device *pdev)
{
	struct riscv_pmu *pmu = NULL;

	pmu = riscv_pmu_alloc();
	if (!pmu)
		return -ENOMEM;
	pmu_legacy_init(pmu);

	return 0;
}

static struct platform_driver pmu_legacy_driver = {
	.probe		= pmu_legacy_device_probe,
	.driver		= {
		.name	= RISCV_PMU_LEGACY_PDEV_NAME,
	},
};

static int __init riscv_pmu_legacy_devinit(void)
{
	int ret;
	struct platform_device *pdev;

	if (likely(pmu_init_done))
		return 0;

	ret = platform_driver_register(&pmu_legacy_driver);
	if (ret)
		return ret;

	pdev = platform_device_register_simple(RISCV_PMU_LEGACY_PDEV_NAME, -1, NULL, 0);
	if (IS_ERR(pdev)) {
		platform_driver_unregister(&pmu_legacy_driver);
		return PTR_ERR(pdev);
	}

	return ret;
}
late_initcall(riscv_pmu_legacy_devinit);

void riscv_pmu_legacy_skip_init(void)
{
	pmu_init_done = true;
}
