// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2016-2020 Arm Limited
// CMN-600 Coherent Mesh Network PMU driver
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/perf_event.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sort.h>
/* Common register stuff */
#define CMN_NODE_INFO 0x0000
#define CMN_NI_NODE_TYPE GENMASK_ULL(15, 0)
#define CMN_NI_NODE_ID GENMASK_ULL(31, 16)
#define CMN_NI_LOGICAL_ID GENMASK_ULL(47, 32)
#define CMN_NODEID_DEVID(reg) ((reg) & 3)
#define CMN_NODEID_PID(reg) (((reg) >> 2) & 1)
#define CMN_NODEID_X(reg, bits) ((reg) >> (3 + (bits)))
#define CMN_NODEID_Y(reg, bits) (((reg) >> 3) & ((1U << (bits)) - 1))
#define CMN_CHILD_INFO 0x0080
#define CMN_CI_CHILD_COUNT GENMASK_ULL(15, 0)
#define CMN_CI_CHILD_PTR_OFFSET GENMASK_ULL(31, 16)
#define CMN_CHILD_NODE_ADDR GENMASK(27, 0)
#define CMN_CHILD_NODE_EXTERNAL BIT(31)
#define CMN_ADDR_NODE_PTR GENMASK(27, 14)
#define CMN_NODE_PTR_DEVID(ptr) (((ptr) >> 2) & 3)
#define CMN_NODE_PTR_PID(ptr) ((ptr) & 1)
#define CMN_NODE_PTR_X(ptr, bits) ((ptr) >> (6 + (bits)))
#define CMN_NODE_PTR_Y(ptr, bits) (((ptr) >> 6) & ((1U << (bits)) - 1))
#define CMN_MAX_XPS (8 * 8)
/* The CFG node has one other useful purpose */
#define CMN_CFGM_PERIPH_ID_2 0x0010
#define CMN_CFGM_PID2_REVISION GENMASK(7, 4)
/* PMU registers occupy the 3rd 4KB page of each node's 16KB space */
#define CMN_PMU_OFFSET 0x2000
/* For most nodes, this is all there is */
#define CMN_PMU_EVENT_SEL 0x000
#define CMN_PMU_EVENTn_ID_SHIFT(n) ((n) * 8)
/* DTMs live in the PMU space of XP registers */
#define CMN_DTM_WPn(n) (0x1A0 + (n) * 0x18)
#define CMN_DTM_WPn_CONFIG(n) (CMN_DTM_WPn(n) + 0x00)
#define CMN_DTM_WPn_CONFIG_WP_COMBINE BIT(6)
#define CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE BIT(5)
#define CMN_DTM_WPn_CONFIG_WP_GRP BIT(4)
#define CMN_DTM_WPn_CONFIG_WP_CHN_SEL GENMASK_ULL(3, 1)
#define CMN_DTM_WPn_CONFIG_WP_DEV_SEL BIT(0)
#define CMN_DTM_WPn_VAL(n) (CMN_DTM_WPn(n) + 0x08)
#define CMN_DTM_WPn_MASK(n) (CMN_DTM_WPn(n) + 0x10)
#define CMN_DTM_PMU_CONFIG 0x210
#define CMN__PMEVCNT0_INPUT_SEL GENMASK_ULL(37, 32)
#define CMN__PMEVCNT0_INPUT_SEL_WP 0x00
#define CMN__PMEVCNT0_INPUT_SEL_XP 0x04
#define CMN__PMEVCNT0_INPUT_SEL_DEV 0x10
#define CMN__PMEVCNT0_GLOBAL_NUM GENMASK_ULL(18, 16)
#define CMN__PMEVCNTn_GLOBAL_NUM_SHIFT(n) ((n) * 4)
#define CMN__PMEVCNT_PAIRED(n) BIT(4 + (n))
#define CMN__PMEVCNT23_COMBINED BIT(2)
#define CMN__PMEVCNT01_COMBINED BIT(1)
#define CMN_DTM_PMU_CONFIG_PMU_EN BIT(0)
#define CMN_DTM_PMEVCNT 0x220
#define CMN_DTM_PMEVCNTSR 0x240
#define CMN_DTM_NUM_COUNTERS 4
/* The DTC node is where the magic happens */
#define CMN_DT_DTC_CTL 0x0a00
#define CMN_DT_DTC_CTL_DT_EN BIT(0)
/* DTC counters are paired in 64-bit registers on a 16-byte stride. Yuck */
#define _CMN_DT_CNT_REG(n) ((((n) / 2) * 4 + (n) % 2) * 4)
#define CMN_DT_PMEVCNT(n) (CMN_PMU_OFFSET + _CMN_DT_CNT_REG(n))
#define CMN_DT_PMCCNTR (CMN_PMU_OFFSET + 0x40)
#define CMN_DT_PMEVCNTSR(n) (CMN_PMU_OFFSET + 0x50 + _CMN_DT_CNT_REG(n))
#define CMN_DT_PMCCNTRSR (CMN_PMU_OFFSET + 0x90)
#define CMN_DT_PMCR (CMN_PMU_OFFSET + 0x100)
#define CMN_DT_PMCR_PMU_EN BIT(0)
#define CMN_DT_PMCR_CNTR_RST BIT(5)
#define CMN_DT_PMCR_OVFL_INTR_EN BIT(6)
#define CMN_DT_PMOVSR (CMN_PMU_OFFSET + 0x118)
#define CMN_DT_PMOVSR_CLR (CMN_PMU_OFFSET + 0x120)
#define CMN_DT_PMSSR (CMN_PMU_OFFSET + 0x128)
#define CMN_DT_PMSSR_SS_STATUS(n) BIT(n)
#define
|