1 /* 2 * HiSilicon SoC Hardware event counters support 3 * 4 * Copyright (C) 2017 Hisilicon Limited 5 * Author: Anurup M <anurup.m@huawei.com> 6 * Shaokun Zhang <zhangshaokun@hisilicon.com> 7 * 8 * This code is based on the uncore PMUs like arm-cci and arm-ccn. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 #ifndef __HISI_UNCORE_PMU_H__ 15 #define __HISI_UNCORE_PMU_H__ 16 17 #include <linux/cpumask.h> 18 #include <linux/device.h> 19 #include <linux/kernel.h> 20 #include <linux/perf_event.h> 21 #include <linux/types.h> 22 23 #undef pr_fmt 24 #define pr_fmt(fmt) "hisi_pmu: " fmt 25 26 #define HISI_MAX_COUNTERS 0x10 27 #define to_hisi_pmu(p) (container_of(p, struct hisi_pmu, pmu)) 28 29 #define HISI_PMU_ATTR(_name, _func, _config) \ 30 (&((struct dev_ext_attribute[]) { \ 31 { __ATTR(_name, 0444, _func, NULL), (void *)_config } \ 32 })[0].attr.attr) 33 34 #define HISI_PMU_FORMAT_ATTR(_name, _config) \ 35 HISI_PMU_ATTR(_name, hisi_format_sysfs_show, (void *)_config) 36 #define HISI_PMU_EVENT_ATTR(_name, _config) \ 37 HISI_PMU_ATTR(_name, hisi_event_sysfs_show, (unsigned long)_config) 38 39 struct hisi_pmu; 40 41 struct hisi_uncore_ops { 42 void (*write_evtype)(struct hisi_pmu *, int, u32); 43 int (*get_event_idx)(struct perf_event *); 44 u64 (*read_counter)(struct hisi_pmu *, struct hw_perf_event *); 45 void (*write_counter)(struct hisi_pmu *, struct hw_perf_event *, u64); 46 void (*enable_counter)(struct hisi_pmu *, struct hw_perf_event *); 47 void (*disable_counter)(struct hisi_pmu *, struct hw_perf_event *); 48 void (*enable_counter_int)(struct hisi_pmu *, struct hw_perf_event *); 49 void (*disable_counter_int)(struct hisi_pmu *, struct hw_perf_event *); 50 void (*start_counters)(struct hisi_pmu *); 51 void (*stop_counters)(struct hisi_pmu *); 52 }; 53 54 struct hisi_pmu_hwevents { 55 struct perf_event *hw_events[HISI_MAX_COUNTERS]; 56 DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS); 57 }; 58 59 /* Generic pmu struct for different pmu types */ 60 struct hisi_pmu { 61 struct pmu pmu; 62 const struct hisi_uncore_ops *ops; 63 struct hisi_pmu_hwevents pmu_events; 64 /* associated_cpus: All CPUs associated with the PMU */ 65 cpumask_t associated_cpus; 66 /* CPU used for counting */ 67 int on_cpu; 68 int irq; 69 struct device *dev; 70 struct hlist_node node; 71 int sccl_id; 72 int ccl_id; 73 void __iomem *base; 74 /* the ID of the PMU modules */ 75 u32 index_id; 76 int num_counters; 77 int counter_bits; 78 /* check event code range */ 79 int check_event; 80 }; 81 82 int hisi_uncore_pmu_counter_valid(struct hisi_pmu *hisi_pmu, int idx); 83 int hisi_uncore_pmu_get_event_idx(struct perf_event *event); 84 void hisi_uncore_pmu_read(struct perf_event *event); 85 int hisi_uncore_pmu_add(struct perf_event *event, int flags); 86 void hisi_uncore_pmu_del(struct perf_event *event, int flags); 87 void hisi_uncore_pmu_start(struct perf_event *event, int flags); 88 void hisi_uncore_pmu_stop(struct perf_event *event, int flags); 89 void hisi_uncore_pmu_set_event_period(struct perf_event *event); 90 void hisi_uncore_pmu_event_update(struct perf_event *event); 91 int hisi_uncore_pmu_event_init(struct perf_event *event); 92 void hisi_uncore_pmu_enable(struct pmu *pmu); 93 void hisi_uncore_pmu_disable(struct pmu *pmu); 94 ssize_t hisi_event_sysfs_show(struct device *dev, 95 struct device_attribute *attr, char *buf); 96 ssize_t hisi_format_sysfs_show(struct device *dev, 97 struct device_attribute *attr, char *buf); 98 ssize_t hisi_cpumask_sysfs_show(struct device *dev, 99 struct device_attribute *attr, char *buf); 100 int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node); 101 int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node); 102 #endif /* __HISI_UNCORE_PMU_H__ */ 103