/*
* APM X-Gene SoC PMU (Performance Monitor Unit)
*
* Copyright (c) 2016, Applied Micro Circuits Corporation
* Author: Hoan Tran <hotran@apm.com>
* Tai Nguyen <ttnguyen@apm.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/cpumask.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_fdt.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/perf_event.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#define CSW_CSWCR 0x0000
#define CSW_CSWCR_DUALMCB_MASK BIT(0)
#define MCBADDRMR 0x0000
#define MCBADDRMR_DUALMCU_MODE_MASK BIT(2)
#define PCPPMU_INTSTATUS_REG 0x000
#define PCPPMU_INTMASK_REG 0x004
#define PCPPMU_INTMASK 0x0000000F
#define PCPPMU_INTENMASK 0xFFFFFFFF
#define PCPPMU_INTCLRMASK 0xFFFFFFF0
#define PCPPMU_INT_MCU BIT(0)
#define PCPPMU_INT_MCB BIT(1)
#define PCPPMU_INT_L3C BIT(2)
#define PCPPMU_INT_IOB BIT(3)
#define PMU_MAX_COUNTERS 4
#define PMU_CNT_MAX_PERIOD 0x100000000ULL
#define PMU_OVERFLOW_MASK 0xF
#define PMU_PMCR_E BIT(0)
#define PMU_PMCR_P BIT(1)
#define PMU_PMEVCNTR0 0x000
#define PMU_PMEVCNTR1 0x004
#define PMU_PMEVCNTR2 0x008
#define PMU_PMEVCNTR3 0x00C
#define PMU_PMEVTYPER0 0x400
#define PMU_PMEVTYPER1 0x404
#define PMU_PMEVTYPER2 0x408
#define PMU_PMEVTYPER3 0x40C
#define PMU_PMAMR0 0xA00
#define PMU_PMAMR1 0xA04
#define PMU_PMCNTENSET 0xC00
#define PMU_PMCNTENCLR 0xC20
#define PMU_PMINTENSET 0xC40
#define PMU_PMINTENCLR 0xC60
#define PMU_PMOVSR 0xC80
#define PMU_PMCR 0xE04
#define to_pmu_dev(p) container_of(p, struct xgene_pmu_dev, pmu)
#define GET_CNTR(ev) (ev->hw.idx)
#define GET_EVENTID(ev) (ev->hw.config & 0xFFULL)
#define GET_AGENTID(ev) (ev->hw.config_base & 0xFFFFFFFFUL)
#define GET_AGENT1ID(ev) ((ev->hw.config_base >> 32) & 0xFFFFFFFFUL)
struct hw_pmu_info {
u32 type;
u32 enable_mask;
void __iomem *csr;
};
struct xgene_pmu_dev {
struct hw_pmu_info *inf;
struct xgene_pmu *parent;
struct pmu pmu;
u8 max_counters;
DECLARE_BITMAP(cntr_assign_mask, PMU_MAX_COUNTERS);
u64 max_period;
const struct attribute_group **attr_groups;
struct perf_event *pmu_counter_event[PMU_MAX_COUNTERS];
};
struct xgene_pmu {
struct device *dev;
int version;
void __iomem *pcppmu_csr;
u32 mcb_active_mask;
u32