Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * HiSilicon SoC Hardware event counters support
0004  *
0005  * Copyright (C) 2017 HiSilicon Limited
0006  * Author: Anurup M <anurup.m@huawei.com>
0007  *         Shaokun Zhang <zhangshaokun@hisilicon.com>
0008  *
0009  * This code is based on the uncore PMUs like arm-cci and arm-ccn.
0010  */
0011 #ifndef __HISI_UNCORE_PMU_H__
0012 #define __HISI_UNCORE_PMU_H__
0013 
0014 #include <linux/bitfield.h>
0015 #include <linux/cpumask.h>
0016 #include <linux/device.h>
0017 #include <linux/kernel.h>
0018 #include <linux/module.h>
0019 #include <linux/perf_event.h>
0020 #include <linux/platform_device.h>
0021 #include <linux/types.h>
0022 
0023 #undef pr_fmt
0024 #define pr_fmt(fmt)     "hisi_pmu: " fmt
0025 
0026 #define HISI_PMU_V2     0x30
0027 #define HISI_MAX_COUNTERS 0x10
0028 #define to_hisi_pmu(p)  (container_of(p, struct hisi_pmu, pmu))
0029 
0030 #define HISI_PMU_ATTR(_name, _func, _config)                \
0031     (&((struct dev_ext_attribute[]) {               \
0032         { __ATTR(_name, 0444, _func, NULL), (void *)_config }   \
0033     })[0].attr.attr)
0034 
0035 #define HISI_PMU_FORMAT_ATTR(_name, _config)        \
0036     HISI_PMU_ATTR(_name, hisi_format_sysfs_show, (void *)_config)
0037 #define HISI_PMU_EVENT_ATTR(_name, _config)     \
0038     HISI_PMU_ATTR(_name, hisi_event_sysfs_show, (unsigned long)_config)
0039 
0040 #define HISI_PMU_EVENT_ATTR_EXTRACTOR(name, config, hi, lo)        \
0041     static inline u32 hisi_get_##name(struct perf_event *event)            \
0042     {                                                                  \
0043         return FIELD_GET(GENMASK_ULL(hi, lo), event->attr.config);  \
0044     }
0045 
0046 struct hisi_pmu;
0047 
0048 struct hisi_uncore_ops {
0049     void (*write_evtype)(struct hisi_pmu *, int, u32);
0050     int (*get_event_idx)(struct perf_event *);
0051     u64 (*read_counter)(struct hisi_pmu *, struct hw_perf_event *);
0052     void (*write_counter)(struct hisi_pmu *, struct hw_perf_event *, u64);
0053     void (*enable_counter)(struct hisi_pmu *, struct hw_perf_event *);
0054     void (*disable_counter)(struct hisi_pmu *, struct hw_perf_event *);
0055     void (*enable_counter_int)(struct hisi_pmu *, struct hw_perf_event *);
0056     void (*disable_counter_int)(struct hisi_pmu *, struct hw_perf_event *);
0057     void (*start_counters)(struct hisi_pmu *);
0058     void (*stop_counters)(struct hisi_pmu *);
0059     u32 (*get_int_status)(struct hisi_pmu *hisi_pmu);
0060     void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx);
0061     void (*enable_filter)(struct perf_event *event);
0062     void (*disable_filter)(struct perf_event *event);
0063 };
0064 
0065 struct hisi_pmu_hwevents {
0066     struct perf_event *hw_events[HISI_MAX_COUNTERS];
0067     DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS);
0068     const struct attribute_group **attr_groups;
0069 };
0070 
0071 /* Generic pmu struct for different pmu types */
0072 struct hisi_pmu {
0073     struct pmu pmu;
0074     const struct hisi_uncore_ops *ops;
0075     struct hisi_pmu_hwevents pmu_events;
0076     /* associated_cpus: All CPUs associated with the PMU */
0077     cpumask_t associated_cpus;
0078     /* CPU used for counting */
0079     int on_cpu;
0080     int irq;
0081     struct device *dev;
0082     struct hlist_node node;
0083     int sccl_id;
0084     int sicl_id;
0085     int ccl_id;
0086     void __iomem *base;
0087     /* the ID of the PMU modules */
0088     u32 index_id;
0089     /* For DDRC PMU v2: each DDRC has more than one DMC */
0090     u32 sub_id;
0091     int num_counters;
0092     int counter_bits;
0093     /* check event code range */
0094     int check_event;
0095     u32 identifier;
0096 };
0097 
0098 int hisi_uncore_pmu_get_event_idx(struct perf_event *event);
0099 void hisi_uncore_pmu_read(struct perf_event *event);
0100 int hisi_uncore_pmu_add(struct perf_event *event, int flags);
0101 void hisi_uncore_pmu_del(struct perf_event *event, int flags);
0102 void hisi_uncore_pmu_start(struct perf_event *event, int flags);
0103 void hisi_uncore_pmu_stop(struct perf_event *event, int flags);
0104 void hisi_uncore_pmu_set_event_period(struct perf_event *event);
0105 void hisi_uncore_pmu_event_update(struct perf_event *event);
0106 int hisi_uncore_pmu_event_init(struct perf_event *event);
0107 void hisi_uncore_pmu_enable(struct pmu *pmu);
0108 void hisi_uncore_pmu_disable(struct pmu *pmu);
0109 ssize_t hisi_event_sysfs_show(struct device *dev,
0110                   struct device_attribute *attr, char *buf);
0111 ssize_t hisi_format_sysfs_show(struct device *dev,
0112                    struct device_attribute *attr, char *buf);
0113 ssize_t hisi_cpumask_sysfs_show(struct device *dev,
0114                 struct device_attribute *attr, char *buf);
0115 int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct hlist_node *node);
0116 int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node);
0117 
0118 ssize_t hisi_uncore_pmu_identifier_attr_show(struct device *dev,
0119                          struct device_attribute *attr,
0120                          char *page);
0121 int hisi_uncore_pmu_init_irq(struct hisi_pmu *hisi_pmu,
0122                  struct platform_device *pdev);
0123 
0124 void hisi_pmu_init(struct pmu *pmu, const char *name,
0125         const struct attribute_group **attr_groups, struct module *module);
0126 #endif /* __HISI_UNCORE_PMU_H__ */