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/cpumask.h> 15 #include <linux/device.h> 16 #include <linux/kernel.h> 17 #include <linux/perf_event.h> 18 #include <linux/types.h> 19 20 #undef pr_fmt 21 #define pr_fmt(fmt) "hisi_pmu: " fmt 22 23 #define HISI_MAX_COUNTERS 0x10 24 #define to_hisi_pmu(p) (container_of(p, struct hisi_pmu, pmu)) 25 26 #define HISI_PMU_ATTR(_name, _func, _config) \ 27 (&((struct dev_ext_attribute[]) { \ 28 { __ATTR(_name, 0444, _func, NULL), (void *)_config } \ 29 })[0].attr.attr) 30 31 #define HISI_PMU_FORMAT_ATTR(_name, _config) \ 32 HISI_PMU_ATTR(_name, hisi_format_sysfs_show, (void *)_config) 33 #define HISI_PMU_EVENT_ATTR(_name, _config) \ 34 HISI_PMU_ATTR(_name, hisi_event_sysfs_show, (unsigned long)_config) 35 36 struct hisi_pmu; 37 38 struct hisi_uncore_ops { 39 void (*write_evtype)(struct hisi_pmu *, int, u32); 40 int (*get_event_idx)(struct perf_event *); 41 u64 (*read_counter)(struct hisi_pmu *, struct hw_perf_event *); 42 void (*write_counter)(struct hisi_pmu *, struct hw_perf_event *, u64); 43 void (*enable_counter)(struct hisi_pmu *, struct hw_perf_event *); 44 void (*disable_counter)(struct hisi_pmu *, struct hw_perf_event *); 45 void (*enable_counter_int)(struct hisi_pmu *, struct hw_perf_event *); 46 void (*disable_counter_int)(struct hisi_pmu *, struct hw_perf_event *); 47 void (*start_counters)(struct hisi_pmu *); 48 void (*stop_counters)(struct hisi_pmu *); 49 }; 50 51 struct hisi_pmu_hwevents { 52 struct perf_event *hw_events[HISI_MAX_COUNTERS]; 53 DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS); 54 }; 55 56 /* Generic pmu struct for different pmu types */ 57 struct hisi_pmu { 58 struct pmu pmu; 59 const struct hisi_uncore_ops *ops; 60 struct hisi_pmu_hwevents pmu_events; 61 /* associated_cpus: All CPUs associated with the PMU */ 62 cpumask_t associated_cpus; 63 /* CPU used for counting */ 64 int on_cpu; 65 int irq; 66 struct device *dev; 67 struct hlist_node node; 68 int sccl_id; 69 int ccl_id; 70 void __iomem *base; 71 /* the ID of the PMU modules */ 72 u32 index_id; 73 int num_counters; 74 int counter_bits; 75 /* check event code range */ 76 int check_event; 77 }; 78 79 int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx); 80 int hisi_uncore_pmu_get_event_idx(struct perf_event *event); 81 void hisi_uncore_pmu_read(struct perf_event *event); 82 int hisi_uncore_pmu_add(struct perf_event *event, int flags); 83 void hisi_uncore_pmu_del(struct perf_event *event, int flags); 84 void hisi_uncore_pmu_start(struct perf_event *event, int flags); 85 void hisi_uncore_pmu_stop(struct perf_event *event, int flags); 86 void hisi_uncore_pmu_set_event_period(struct perf_event *event); 87 void hisi_uncore_pmu_event_update(struct perf_event *event); 88 int hisi_uncore_pmu_event_init(struct perf_event *event); 89 void hisi_uncore_pmu_enable(struct pmu *pmu); 90 void hisi_uncore_pmu_disable(struct pmu *pmu); 91 ssize_t hisi_event_sysfs_show(struct device *dev, 92 struct device_attribute *attr, char *buf); 93 ssize_t hisi_format_sysfs_show(struct device *dev, 94 struct device_attribute *attr, char *buf); 95 ssize_t hisi_cpumask_sysfs_show(struct device *dev, 96 struct device_attribute *attr, char *buf); 97 int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node); 98 int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node); 99 #endif /* __HISI_UNCORE_PMU_H__ */ 100