linux/drivers/perf/hisilicon/hisi_uncore_pmu.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * HiSilicon SoC Hardware event counters support
   4 *
   5 * Copyright (C) 2017 HiSilicon Limited
   6 * Author: Anurup M <anurup.m@huawei.com>
   7 *         Shaokun Zhang <zhangshaokun@hisilicon.com>
   8 *
   9 * This code is based on the uncore PMUs like arm-cci and arm-ccn.
  10 */
  11#ifndef __HISI_UNCORE_PMU_H__
  12#define __HISI_UNCORE_PMU_H__
  13
  14#include <linux/bitfield.h>
  15#include <linux/cpumask.h>
  16#include <linux/device.h>
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/perf_event.h>
  20#include <linux/platform_device.h>
  21#include <linux/types.h>
  22
  23#undef pr_fmt
  24#define pr_fmt(fmt)     "hisi_pmu: " fmt
  25
  26#define HISI_PMU_V2             0x30
  27#define HISI_MAX_COUNTERS 0x10
  28#define to_hisi_pmu(p)  (container_of(p, struct hisi_pmu, pmu))
  29
  30#define HISI_PMU_ATTR(_name, _func, _config)                            \
  31        (&((struct dev_ext_attribute[]) {                               \
  32                { __ATTR(_name, 0444, _func, NULL), (void *)_config }   \
  33        })[0].attr.attr)
  34
  35#define HISI_PMU_FORMAT_ATTR(_name, _config)            \
  36        HISI_PMU_ATTR(_name, hisi_format_sysfs_show, (void *)_config)
  37#define HISI_PMU_EVENT_ATTR(_name, _config)             \
  38        HISI_PMU_ATTR(_name, hisi_event_sysfs_show, (unsigned long)_config)
  39
  40#define HISI_PMU_EVENT_ATTR_EXTRACTOR(name, config, hi, lo)        \
  41        static inline u32 hisi_get_##name(struct perf_event *event)            \
  42        {                                                                  \
  43                return FIELD_GET(GENMASK_ULL(hi, lo), event->attr.config);  \
  44        }
  45
  46struct hisi_pmu;
  47
  48struct hisi_uncore_ops {
  49        void (*write_evtype)(struct hisi_pmu *, int, u32);
  50        int (*get_event_idx)(struct perf_event *);
  51        u64 (*read_counter)(struct hisi_pmu *, struct hw_perf_event *);
  52        void (*write_counter)(struct hisi_pmu *, struct hw_perf_event *, u64);
  53        void (*enable_counter)(struct hisi_pmu *, struct hw_perf_event *);
  54        void (*disable_counter)(struct hisi_pmu *, struct hw_perf_event *);
  55        void (*enable_counter_int)(struct hisi_pmu *, struct hw_perf_event *);
  56        void (*disable_counter_int)(struct hisi_pmu *, struct hw_perf_event *);
  57        void (*start_counters)(struct hisi_pmu *);
  58        void (*stop_counters)(struct hisi_pmu *);
  59        u32 (*get_int_status)(struct hisi_pmu *hisi_pmu);
  60        void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx);
  61        void (*enable_filter)(struct perf_event *event);
  62        void (*disable_filter)(struct perf_event *event);
  63};
  64
  65struct hisi_pmu_hwevents {
  66        struct perf_event *hw_events[HISI_MAX_COUNTERS];
  67        DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS);
  68        const struct attribute_group **attr_groups;
  69};
  70
  71/* Generic pmu struct for different pmu types */
  72struct hisi_pmu {
  73        struct pmu pmu;
  74        const struct hisi_uncore_ops *ops;
  75        struct hisi_pmu_hwevents pmu_events;
  76        /* associated_cpus: All CPUs associated with the PMU */
  77        cpumask_t associated_cpus;
  78        /* CPU used for counting */
  79        int on_cpu;
  80        int irq;
  81        struct device *dev;
  82        struct hlist_node node;
  83        int sccl_id;
  84        int ccl_id;
  85        void __iomem *base;
  86        /* the ID of the PMU modules */
  87        u32 index_id;
  88        /* For DDRC PMU v2: each DDRC has more than one DMC */
  89        u32 sub_id;
  90        int num_counters;
  91        int counter_bits;
  92        /* check event code range */
  93        int check_event;
  94        u32 identifier;
  95};
  96
  97int hisi_uncore_pmu_get_event_idx(struct perf_event *event);
  98void hisi_uncore_pmu_read(struct perf_event *event);
  99int hisi_uncore_pmu_add(struct perf_event *event, int flags);
 100void hisi_uncore_pmu_del(struct perf_event *event, int flags);
 101void hisi_uncore_pmu_start(struct perf_event *event, int flags);
 102void hisi_uncore_pmu_stop(struct perf_event *event, int flags);
 103void hisi_uncore_pmu_set_event_period(struct perf_event *event);
 104void hisi_uncore_pmu_event_update(struct perf_event *event);
 105int hisi_uncore_pmu_event_init(struct perf_event *event);
 106void hisi_uncore_pmu_enable(struct pmu *pmu);
 107void hisi_uncore_pmu_disable(struct pmu *pmu);
 108ssize_t hisi_event_sysfs_show(struct device *dev,
 109                              struct device_attribute *attr, char *buf);
 110ssize_t hisi_format_sysfs_show(struct device *dev,
 111                               struct device_attribute *attr, char *buf);
 112ssize_t hisi_cpumask_sysfs_show(struct device *dev,
 113                                struct device_attribute *attr, char *buf);
 114int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node);
 115int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node);
 116
 117ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
 118                                             struct device_attribute *attr,
 119                                             char *page);
 120int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
 121                             struct platform_device *pdev);
 122
 123#endif /* __HISI_UNCORE_PMU_H__ */
 124