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