// SPDX-License-Identifier: GPL-2.0
/*
* ARM CoreSight Architecture PMU driver.
*
* This driver adds support for uncore PMU based on ARM CoreSight Performance
* Monitoring Unit Architecture. The PMU is accessible via MMIO registers and
* like other uncore PMUs, it does not support process specific events and
* cannot be used in sampling mode.
*
* This code is based on other uncore PMUs like ARM DSU PMU. It provides a
* generic implementation to operate the PMU according to CoreSight PMU
* architecture and ACPI ARM PMU table (APMT) documents below:
* - ARM CoreSight PMU architecture document number: ARM IHI 0091 A.a-00bet0.
* - APMT document number: ARM DEN0117.
*
* The user should refer to the vendor technical documentation to get details
* about the supported events.
*
* Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*
*/
#include <linux/acpi.h>
#include <linux/cacheinfo.h>
#include <linux/ctype.h>
#include <linux/interrupt.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/perf_event.h>
#include <linux/platform_device.h>
#include "arm_cspmu.h"
#define PMUNAME "arm_cspmu"
#define DRVNAME "arm-cs-arch-pmu"
#define ARM_CSPMU_CPUMASK_ATTR(_name, _config) \
ARM_CSPMU_EXT_ATTR(_name, arm_cspmu_cpumask_show, \
(unsigned long)_config)
/*
* CoreSight PMU Arch register offsets.
*/
#define PMEVCNTR_LO 0x0
#define PMEVCNTR_HI 0x4
#define PMEVTYPER 0x400
#define PMCCFILTR 0x47C
#define PMEVFILTR 0xA00
#define PMCNTENSET 0xC00
#define PMCNTENCLR 0xC20
#define PMINTENSET 0xC40
#define PMINTENCLR 0xC60
#define PMOVSCLR 0xC80
#define PMOVSSET 0xCC0
#define PMCFGR 0xE00
#define PMCR 0xE04
#define PMIIDR 0xE08
/* PMCFGR register field */
#define PMCFGR_NCG GENMASK(31, 28)
#define PMCFGR_HDBG BIT(24)
#define PMCFGR_TRO BIT(23)
#define PMCFGR_SS BIT(22)
#define PMCFGR_FZO BIT(21)
#define PMCFGR_MSI BIT(20)
#define PMCFGR_UEN BIT(19)
#define PMCFGR_NA BIT(17)
#define PMCFGR_EX BIT(16)
#define PMCFGR_CCD BIT(15)
#define PMCFGR_CC BIT(14)
#define PMCFGR_SIZE GENMASK(13, 8)
#define PMCFGR_N GENMASK(7, 0)
/* PMCR register field */
#define PMCR_TRO BIT(11)
#define PMCR_HDBG BIT(10)
#define PMCR_FZO BIT(9)
#define PMCR_NA BIT(8)
#define PMCR_DP BIT(5)
#define PMCR_X BIT(4)
#define PMCR_D BIT(3)
#define PMCR_C BIT(2)
#define PMCR_P BIT(1)
#define PMCR_E BIT(0)
/* Each SET/CLR register supports up to 32 counters. */
#define ARM_CSPMU_SET_CLR_COUNTER_SHIFT 5
#define ARM_CSPMU_SET_CLR_COUNTER_NUM \
(1 << ARM_CSPMU_SET_CLR_COUNTER_SHIFT)
/* Convert counter idx into SET/CLR register number. */
#define COUNTER_TO_SET_CLR_ID(idx) \
(idx >> ARM_CSPMU_SET_CLR_COUNTER_SHIFT)
/* Convert counter idx into SET/CLR register bit. */
#define COUNTER_TO_SET_CLR_BIT(idx) \
(idx & (ARM_CSPMU_SET_CLR_COUNTER_NUM - 1))
#define ARM_CSPMU_ACTIVE_CPU_MASK 0x0
#define ARM_CSPMU_ASSOCIATED_CPU_MASK 0x1
/* Check and use default if implementer doesn't provide attribute callback */
#define CHECK_DEFAULT_IMPL_OPS(ops, callback) \
do { \
if (!ops->callback) \
ops->callback = arm_cspmu_ ## callback; \
} while (0)
/*
* Maximum poll count for reading counter value using high-low-high sequence.
*/
#define HILOHI_MAX_POLL 1000
static unsigned long arm_cspmu_cpuhp_state;
static DEFINE_MUTEX(arm_cspmu_lock);
static void arm_cspmu_set_ev_filter(struct arm_cs