1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // CCI Cache Coherent Interconnect PMU driver
3*4882a593Smuzhiyun // Copyright (C) 2013-2018 Arm Ltd.
4*4882a593Smuzhiyun // Author: Punit Agrawal <punit.agrawal@arm.com>, Suzuki Poulose <suzuki.poulose@arm.com>
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/arm-cci.h>
7*4882a593Smuzhiyun #include <linux/io.h>
8*4882a593Smuzhiyun #include <linux/interrupt.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/of_address.h>
11*4882a593Smuzhiyun #include <linux/of_device.h>
12*4882a593Smuzhiyun #include <linux/of_irq.h>
13*4882a593Smuzhiyun #include <linux/of_platform.h>
14*4882a593Smuzhiyun #include <linux/perf_event.h>
15*4882a593Smuzhiyun #include <linux/platform_device.h>
16*4882a593Smuzhiyun #include <linux/slab.h>
17*4882a593Smuzhiyun #include <linux/spinlock.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define DRIVER_NAME "ARM-CCI PMU"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #define CCI_PMCR 0x0100
22*4882a593Smuzhiyun #define CCI_PID2 0x0fe8
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define CCI_PMCR_CEN 0x00000001
25*4882a593Smuzhiyun #define CCI_PMCR_NCNT_MASK 0x0000f800
26*4882a593Smuzhiyun #define CCI_PMCR_NCNT_SHIFT 11
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define CCI_PID2_REV_MASK 0xf0
29*4882a593Smuzhiyun #define CCI_PID2_REV_SHIFT 4
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #define CCI_PMU_EVT_SEL 0x000
32*4882a593Smuzhiyun #define CCI_PMU_CNTR 0x004
33*4882a593Smuzhiyun #define CCI_PMU_CNTR_CTRL 0x008
34*4882a593Smuzhiyun #define CCI_PMU_OVRFLW 0x00c
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define CCI_PMU_OVRFLW_FLAG 1
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define CCI_PMU_CNTR_SIZE(model) ((model)->cntr_size)
39*4882a593Smuzhiyun #define CCI_PMU_CNTR_BASE(model, idx) ((idx) * CCI_PMU_CNTR_SIZE(model))
40*4882a593Smuzhiyun #define CCI_PMU_CNTR_MASK ((1ULL << 32) -1)
41*4882a593Smuzhiyun #define CCI_PMU_CNTR_LAST(cci_pmu) (cci_pmu->num_cntrs - 1)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define CCI_PMU_MAX_HW_CNTRS(model) \
44*4882a593Smuzhiyun ((model)->num_hw_cntrs + (model)->fixed_hw_cntrs)
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* Types of interfaces that can generate events */
47*4882a593Smuzhiyun enum {
48*4882a593Smuzhiyun CCI_IF_SLAVE,
49*4882a593Smuzhiyun CCI_IF_MASTER,
50*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI5xx_PMU
51*4882a593Smuzhiyun CCI_IF_GLOBAL,
52*4882a593Smuzhiyun #endif
53*4882a593Smuzhiyun CCI_IF_MAX,
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define NUM_HW_CNTRS_CII_4XX 4
57*4882a593Smuzhiyun #define NUM_HW_CNTRS_CII_5XX 8
58*4882a593Smuzhiyun #define NUM_HW_CNTRS_MAX NUM_HW_CNTRS_CII_5XX
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun #define FIXED_HW_CNTRS_CII_4XX 1
61*4882a593Smuzhiyun #define FIXED_HW_CNTRS_CII_5XX 0
62*4882a593Smuzhiyun #define FIXED_HW_CNTRS_MAX FIXED_HW_CNTRS_CII_4XX
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun #define HW_CNTRS_MAX (NUM_HW_CNTRS_MAX + FIXED_HW_CNTRS_MAX)
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun struct event_range {
67*4882a593Smuzhiyun u32 min;
68*4882a593Smuzhiyun u32 max;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun struct cci_pmu_hw_events {
72*4882a593Smuzhiyun struct perf_event **events;
73*4882a593Smuzhiyun unsigned long *used_mask;
74*4882a593Smuzhiyun raw_spinlock_t pmu_lock;
75*4882a593Smuzhiyun };
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun struct cci_pmu;
78*4882a593Smuzhiyun /*
79*4882a593Smuzhiyun * struct cci_pmu_model:
80*4882a593Smuzhiyun * @fixed_hw_cntrs - Number of fixed event counters
81*4882a593Smuzhiyun * @num_hw_cntrs - Maximum number of programmable event counters
82*4882a593Smuzhiyun * @cntr_size - Size of an event counter mapping
83*4882a593Smuzhiyun */
84*4882a593Smuzhiyun struct cci_pmu_model {
85*4882a593Smuzhiyun char *name;
86*4882a593Smuzhiyun u32 fixed_hw_cntrs;
87*4882a593Smuzhiyun u32 num_hw_cntrs;
88*4882a593Smuzhiyun u32 cntr_size;
89*4882a593Smuzhiyun struct attribute **format_attrs;
90*4882a593Smuzhiyun struct attribute **event_attrs;
91*4882a593Smuzhiyun struct event_range event_ranges[CCI_IF_MAX];
92*4882a593Smuzhiyun int (*validate_hw_event)(struct cci_pmu *, unsigned long);
93*4882a593Smuzhiyun int (*get_event_idx)(struct cci_pmu *, struct cci_pmu_hw_events *, unsigned long);
94*4882a593Smuzhiyun void (*write_counters)(struct cci_pmu *, unsigned long *);
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun static struct cci_pmu_model cci_pmu_models[];
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun struct cci_pmu {
100*4882a593Smuzhiyun void __iomem *base;
101*4882a593Smuzhiyun void __iomem *ctrl_base;
102*4882a593Smuzhiyun struct pmu pmu;
103*4882a593Smuzhiyun int cpu;
104*4882a593Smuzhiyun int nr_irqs;
105*4882a593Smuzhiyun int *irqs;
106*4882a593Smuzhiyun unsigned long active_irqs;
107*4882a593Smuzhiyun const struct cci_pmu_model *model;
108*4882a593Smuzhiyun struct cci_pmu_hw_events hw_events;
109*4882a593Smuzhiyun struct platform_device *plat_device;
110*4882a593Smuzhiyun int num_cntrs;
111*4882a593Smuzhiyun atomic_t active_events;
112*4882a593Smuzhiyun struct mutex reserve_mutex;
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun #define to_cci_pmu(c) (container_of(c, struct cci_pmu, pmu))
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun static struct cci_pmu *g_cci_pmu;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun enum cci_models {
120*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI400_PMU
121*4882a593Smuzhiyun CCI400_R0,
122*4882a593Smuzhiyun CCI400_R1,
123*4882a593Smuzhiyun #endif
124*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI5xx_PMU
125*4882a593Smuzhiyun CCI500_R0,
126*4882a593Smuzhiyun CCI550_R0,
127*4882a593Smuzhiyun #endif
128*4882a593Smuzhiyun CCI_MODEL_MAX
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun static void pmu_write_counters(struct cci_pmu *cci_pmu,
132*4882a593Smuzhiyun unsigned long *mask);
133*4882a593Smuzhiyun static ssize_t __maybe_unused cci_pmu_format_show(struct device *dev,
134*4882a593Smuzhiyun struct device_attribute *attr, char *buf);
135*4882a593Smuzhiyun static ssize_t __maybe_unused cci_pmu_event_show(struct device *dev,
136*4882a593Smuzhiyun struct device_attribute *attr, char *buf);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun #define CCI_EXT_ATTR_ENTRY(_name, _func, _config) \
139*4882a593Smuzhiyun &((struct dev_ext_attribute[]) { \
140*4882a593Smuzhiyun { __ATTR(_name, S_IRUGO, _func, NULL), (void *)_config } \
141*4882a593Smuzhiyun })[0].attr.attr
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun #define CCI_FORMAT_EXT_ATTR_ENTRY(_name, _config) \
144*4882a593Smuzhiyun CCI_EXT_ATTR_ENTRY(_name, cci_pmu_format_show, (char *)_config)
145*4882a593Smuzhiyun #define CCI_EVENT_EXT_ATTR_ENTRY(_name, _config) \
146*4882a593Smuzhiyun CCI_EXT_ATTR_ENTRY(_name, cci_pmu_event_show, (unsigned long)_config)
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun /* CCI400 PMU Specific definitions */
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI400_PMU
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun /* Port ids */
153*4882a593Smuzhiyun #define CCI400_PORT_S0 0
154*4882a593Smuzhiyun #define CCI400_PORT_S1 1
155*4882a593Smuzhiyun #define CCI400_PORT_S2 2
156*4882a593Smuzhiyun #define CCI400_PORT_S3 3
157*4882a593Smuzhiyun #define CCI400_PORT_S4 4
158*4882a593Smuzhiyun #define CCI400_PORT_M0 5
159*4882a593Smuzhiyun #define CCI400_PORT_M1 6
160*4882a593Smuzhiyun #define CCI400_PORT_M2 7
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun #define CCI400_R1_PX 5
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /*
165*4882a593Smuzhiyun * Instead of an event id to monitor CCI cycles, a dedicated counter is
166*4882a593Smuzhiyun * provided. Use 0xff to represent CCI cycles and hope that no future revisions
167*4882a593Smuzhiyun * make use of this event in hardware.
168*4882a593Smuzhiyun */
169*4882a593Smuzhiyun enum cci400_perf_events {
170*4882a593Smuzhiyun CCI400_PMU_CYCLES = 0xff
171*4882a593Smuzhiyun };
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun #define CCI400_PMU_CYCLE_CNTR_IDX 0
174*4882a593Smuzhiyun #define CCI400_PMU_CNTR0_IDX 1
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /*
177*4882a593Smuzhiyun * CCI PMU event id is an 8-bit value made of two parts - bits 7:5 for one of 8
178*4882a593Smuzhiyun * ports and bits 4:0 are event codes. There are different event codes
179*4882a593Smuzhiyun * associated with each port type.
180*4882a593Smuzhiyun *
181*4882a593Smuzhiyun * Additionally, the range of events associated with the port types changed
182*4882a593Smuzhiyun * between Rev0 and Rev1.
183*4882a593Smuzhiyun *
184*4882a593Smuzhiyun * The constants below define the range of valid codes for each port type for
185*4882a593Smuzhiyun * the different revisions and are used to validate the event to be monitored.
186*4882a593Smuzhiyun */
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun #define CCI400_PMU_EVENT_MASK 0xffUL
189*4882a593Smuzhiyun #define CCI400_PMU_EVENT_SOURCE_SHIFT 5
190*4882a593Smuzhiyun #define CCI400_PMU_EVENT_SOURCE_MASK 0x7
191*4882a593Smuzhiyun #define CCI400_PMU_EVENT_CODE_SHIFT 0
192*4882a593Smuzhiyun #define CCI400_PMU_EVENT_CODE_MASK 0x1f
193*4882a593Smuzhiyun #define CCI400_PMU_EVENT_SOURCE(event) \
194*4882a593Smuzhiyun ((event >> CCI400_PMU_EVENT_SOURCE_SHIFT) & \
195*4882a593Smuzhiyun CCI400_PMU_EVENT_SOURCE_MASK)
196*4882a593Smuzhiyun #define CCI400_PMU_EVENT_CODE(event) \
197*4882a593Smuzhiyun ((event >> CCI400_PMU_EVENT_CODE_SHIFT) & CCI400_PMU_EVENT_CODE_MASK)
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun #define CCI400_R0_SLAVE_PORT_MIN_EV 0x00
200*4882a593Smuzhiyun #define CCI400_R0_SLAVE_PORT_MAX_EV 0x13
201*4882a593Smuzhiyun #define CCI400_R0_MASTER_PORT_MIN_EV 0x14
202*4882a593Smuzhiyun #define CCI400_R0_MASTER_PORT_MAX_EV 0x1a
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun #define CCI400_R1_SLAVE_PORT_MIN_EV 0x00
205*4882a593Smuzhiyun #define CCI400_R1_SLAVE_PORT_MAX_EV 0x14
206*4882a593Smuzhiyun #define CCI400_R1_MASTER_PORT_MIN_EV 0x00
207*4882a593Smuzhiyun #define CCI400_R1_MASTER_PORT_MAX_EV 0x11
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun #define CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(_name, _config) \
210*4882a593Smuzhiyun CCI_EXT_ATTR_ENTRY(_name, cci400_pmu_cycle_event_show, \
211*4882a593Smuzhiyun (unsigned long)_config)
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun static ssize_t cci400_pmu_cycle_event_show(struct device *dev,
214*4882a593Smuzhiyun struct device_attribute *attr, char *buf);
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun static struct attribute *cci400_pmu_format_attrs[] = {
217*4882a593Smuzhiyun CCI_FORMAT_EXT_ATTR_ENTRY(event, "config:0-4"),
218*4882a593Smuzhiyun CCI_FORMAT_EXT_ATTR_ENTRY(source, "config:5-7"),
219*4882a593Smuzhiyun NULL
220*4882a593Smuzhiyun };
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun static struct attribute *cci400_r0_pmu_event_attrs[] = {
223*4882a593Smuzhiyun /* Slave events */
224*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_any, 0x0),
225*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_device, 0x01),
226*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_normal_or_nonshareable, 0x2),
227*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_inner_or_outershareable, 0x3),
228*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_cache_maintenance, 0x4),
229*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_mem_barrier, 0x5),
230*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_sync_barrier, 0x6),
231*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg, 0x7),
232*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg_sync, 0x8),
233*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_stall_tt_full, 0x9),
234*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_last_hs_snoop, 0xA),
235*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_stall_rvalids_h_rready_l, 0xB),
236*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_any, 0xC),
237*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_device, 0xD),
238*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_normal_or_nonshareable, 0xE),
239*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_inner_or_outershare_wback_wclean, 0xF),
240*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_write_unique, 0x10),
241*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_write_line_unique, 0x11),
242*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_evict, 0x12),
243*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_stall_tt_full, 0x13),
244*4882a593Smuzhiyun /* Master events */
245*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_retry_speculative_fetch, 0x14),
246*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_addr_hazard, 0x15),
247*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_id_hazard, 0x16),
248*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_tt_full, 0x17),
249*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_barrier_hazard, 0x18),
250*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_barrier_hazard, 0x19),
251*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_tt_full, 0x1A),
252*4882a593Smuzhiyun /* Special event for cycles counter */
253*4882a593Smuzhiyun CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(cycles, 0xff),
254*4882a593Smuzhiyun NULL
255*4882a593Smuzhiyun };
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun static struct attribute *cci400_r1_pmu_event_attrs[] = {
258*4882a593Smuzhiyun /* Slave events */
259*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_any, 0x0),
260*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_device, 0x01),
261*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_normal_or_nonshareable, 0x2),
262*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_inner_or_outershareable, 0x3),
263*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_cache_maintenance, 0x4),
264*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_mem_barrier, 0x5),
265*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_sync_barrier, 0x6),
266*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg, 0x7),
267*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg_sync, 0x8),
268*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_stall_tt_full, 0x9),
269*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_last_hs_snoop, 0xA),
270*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_stall_rvalids_h_rready_l, 0xB),
271*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_any, 0xC),
272*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_device, 0xD),
273*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_normal_or_nonshareable, 0xE),
274*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_inner_or_outershare_wback_wclean, 0xF),
275*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_write_unique, 0x10),
276*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_write_line_unique, 0x11),
277*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_evict, 0x12),
278*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_stall_tt_full, 0x13),
279*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_stall_slave_id_hazard, 0x14),
280*4882a593Smuzhiyun /* Master events */
281*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_retry_speculative_fetch, 0x0),
282*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_stall_cycle_addr_hazard, 0x1),
283*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_master_id_hazard, 0x2),
284*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_hi_prio_rtq_full, 0x3),
285*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_barrier_hazard, 0x4),
286*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_barrier_hazard, 0x5),
287*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_wtq_full, 0x6),
288*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_low_prio_rtq_full, 0x7),
289*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_mid_prio_rtq_full, 0x8),
290*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_qvn_vn0, 0x9),
291*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_qvn_vn1, 0xA),
292*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_qvn_vn2, 0xB),
293*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall_qvn_vn3, 0xC),
294*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_qvn_vn0, 0xD),
295*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_qvn_vn1, 0xE),
296*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_qvn_vn2, 0xF),
297*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall_qvn_vn3, 0x10),
298*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_unique_or_line_unique_addr_hazard, 0x11),
299*4882a593Smuzhiyun /* Special event for cycles counter */
300*4882a593Smuzhiyun CCI400_CYCLE_EVENT_EXT_ATTR_ENTRY(cycles, 0xff),
301*4882a593Smuzhiyun NULL
302*4882a593Smuzhiyun };
303*4882a593Smuzhiyun
cci400_pmu_cycle_event_show(struct device * dev,struct device_attribute * attr,char * buf)304*4882a593Smuzhiyun static ssize_t cci400_pmu_cycle_event_show(struct device *dev,
305*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun struct dev_ext_attribute *eattr = container_of(attr,
308*4882a593Smuzhiyun struct dev_ext_attribute, attr);
309*4882a593Smuzhiyun return snprintf(buf, PAGE_SIZE, "config=0x%lx\n", (unsigned long)eattr->var);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
cci400_get_event_idx(struct cci_pmu * cci_pmu,struct cci_pmu_hw_events * hw,unsigned long cci_event)312*4882a593Smuzhiyun static int cci400_get_event_idx(struct cci_pmu *cci_pmu,
313*4882a593Smuzhiyun struct cci_pmu_hw_events *hw,
314*4882a593Smuzhiyun unsigned long cci_event)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun int idx;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun /* cycles event idx is fixed */
319*4882a593Smuzhiyun if (cci_event == CCI400_PMU_CYCLES) {
320*4882a593Smuzhiyun if (test_and_set_bit(CCI400_PMU_CYCLE_CNTR_IDX, hw->used_mask))
321*4882a593Smuzhiyun return -EAGAIN;
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun return CCI400_PMU_CYCLE_CNTR_IDX;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun for (idx = CCI400_PMU_CNTR0_IDX; idx <= CCI_PMU_CNTR_LAST(cci_pmu); ++idx)
327*4882a593Smuzhiyun if (!test_and_set_bit(idx, hw->used_mask))
328*4882a593Smuzhiyun return idx;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun /* No counters available */
331*4882a593Smuzhiyun return -EAGAIN;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
cci400_validate_hw_event(struct cci_pmu * cci_pmu,unsigned long hw_event)334*4882a593Smuzhiyun static int cci400_validate_hw_event(struct cci_pmu *cci_pmu, unsigned long hw_event)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun u8 ev_source = CCI400_PMU_EVENT_SOURCE(hw_event);
337*4882a593Smuzhiyun u8 ev_code = CCI400_PMU_EVENT_CODE(hw_event);
338*4882a593Smuzhiyun int if_type;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun if (hw_event & ~CCI400_PMU_EVENT_MASK)
341*4882a593Smuzhiyun return -ENOENT;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun if (hw_event == CCI400_PMU_CYCLES)
344*4882a593Smuzhiyun return hw_event;
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun switch (ev_source) {
347*4882a593Smuzhiyun case CCI400_PORT_S0:
348*4882a593Smuzhiyun case CCI400_PORT_S1:
349*4882a593Smuzhiyun case CCI400_PORT_S2:
350*4882a593Smuzhiyun case CCI400_PORT_S3:
351*4882a593Smuzhiyun case CCI400_PORT_S4:
352*4882a593Smuzhiyun /* Slave Interface */
353*4882a593Smuzhiyun if_type = CCI_IF_SLAVE;
354*4882a593Smuzhiyun break;
355*4882a593Smuzhiyun case CCI400_PORT_M0:
356*4882a593Smuzhiyun case CCI400_PORT_M1:
357*4882a593Smuzhiyun case CCI400_PORT_M2:
358*4882a593Smuzhiyun /* Master Interface */
359*4882a593Smuzhiyun if_type = CCI_IF_MASTER;
360*4882a593Smuzhiyun break;
361*4882a593Smuzhiyun default:
362*4882a593Smuzhiyun return -ENOENT;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun if (ev_code >= cci_pmu->model->event_ranges[if_type].min &&
366*4882a593Smuzhiyun ev_code <= cci_pmu->model->event_ranges[if_type].max)
367*4882a593Smuzhiyun return hw_event;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun return -ENOENT;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
probe_cci400_revision(struct cci_pmu * cci_pmu)372*4882a593Smuzhiyun static int probe_cci400_revision(struct cci_pmu *cci_pmu)
373*4882a593Smuzhiyun {
374*4882a593Smuzhiyun int rev;
375*4882a593Smuzhiyun rev = readl_relaxed(cci_pmu->ctrl_base + CCI_PID2) & CCI_PID2_REV_MASK;
376*4882a593Smuzhiyun rev >>= CCI_PID2_REV_SHIFT;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun if (rev < CCI400_R1_PX)
379*4882a593Smuzhiyun return CCI400_R0;
380*4882a593Smuzhiyun else
381*4882a593Smuzhiyun return CCI400_R1;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
probe_cci_model(struct cci_pmu * cci_pmu)384*4882a593Smuzhiyun static const struct cci_pmu_model *probe_cci_model(struct cci_pmu *cci_pmu)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun if (platform_has_secure_cci_access())
387*4882a593Smuzhiyun return &cci_pmu_models[probe_cci400_revision(cci_pmu)];
388*4882a593Smuzhiyun return NULL;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun #else /* !CONFIG_ARM_CCI400_PMU */
probe_cci_model(struct cci_pmu * cci_pmu)391*4882a593Smuzhiyun static inline struct cci_pmu_model *probe_cci_model(struct cci_pmu *cci_pmu)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun return NULL;
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun #endif /* CONFIG_ARM_CCI400_PMU */
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI5xx_PMU
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /*
400*4882a593Smuzhiyun * CCI5xx PMU event id is an 9-bit value made of two parts.
401*4882a593Smuzhiyun * bits [8:5] - Source for the event
402*4882a593Smuzhiyun * bits [4:0] - Event code (specific to type of interface)
403*4882a593Smuzhiyun *
404*4882a593Smuzhiyun *
405*4882a593Smuzhiyun */
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /* Port ids */
408*4882a593Smuzhiyun #define CCI5xx_PORT_S0 0x0
409*4882a593Smuzhiyun #define CCI5xx_PORT_S1 0x1
410*4882a593Smuzhiyun #define CCI5xx_PORT_S2 0x2
411*4882a593Smuzhiyun #define CCI5xx_PORT_S3 0x3
412*4882a593Smuzhiyun #define CCI5xx_PORT_S4 0x4
413*4882a593Smuzhiyun #define CCI5xx_PORT_S5 0x5
414*4882a593Smuzhiyun #define CCI5xx_PORT_S6 0x6
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun #define CCI5xx_PORT_M0 0x8
417*4882a593Smuzhiyun #define CCI5xx_PORT_M1 0x9
418*4882a593Smuzhiyun #define CCI5xx_PORT_M2 0xa
419*4882a593Smuzhiyun #define CCI5xx_PORT_M3 0xb
420*4882a593Smuzhiyun #define CCI5xx_PORT_M4 0xc
421*4882a593Smuzhiyun #define CCI5xx_PORT_M5 0xd
422*4882a593Smuzhiyun #define CCI5xx_PORT_M6 0xe
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun #define CCI5xx_PORT_GLOBAL 0xf
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun #define CCI5xx_PMU_EVENT_MASK 0x1ffUL
427*4882a593Smuzhiyun #define CCI5xx_PMU_EVENT_SOURCE_SHIFT 0x5
428*4882a593Smuzhiyun #define CCI5xx_PMU_EVENT_SOURCE_MASK 0xf
429*4882a593Smuzhiyun #define CCI5xx_PMU_EVENT_CODE_SHIFT 0x0
430*4882a593Smuzhiyun #define CCI5xx_PMU_EVENT_CODE_MASK 0x1f
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun #define CCI5xx_PMU_EVENT_SOURCE(event) \
433*4882a593Smuzhiyun ((event >> CCI5xx_PMU_EVENT_SOURCE_SHIFT) & CCI5xx_PMU_EVENT_SOURCE_MASK)
434*4882a593Smuzhiyun #define CCI5xx_PMU_EVENT_CODE(event) \
435*4882a593Smuzhiyun ((event >> CCI5xx_PMU_EVENT_CODE_SHIFT) & CCI5xx_PMU_EVENT_CODE_MASK)
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun #define CCI5xx_SLAVE_PORT_MIN_EV 0x00
438*4882a593Smuzhiyun #define CCI5xx_SLAVE_PORT_MAX_EV 0x1f
439*4882a593Smuzhiyun #define CCI5xx_MASTER_PORT_MIN_EV 0x00
440*4882a593Smuzhiyun #define CCI5xx_MASTER_PORT_MAX_EV 0x06
441*4882a593Smuzhiyun #define CCI5xx_GLOBAL_PORT_MIN_EV 0x00
442*4882a593Smuzhiyun #define CCI5xx_GLOBAL_PORT_MAX_EV 0x0f
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun #define CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(_name, _config) \
446*4882a593Smuzhiyun CCI_EXT_ATTR_ENTRY(_name, cci5xx_pmu_global_event_show, \
447*4882a593Smuzhiyun (unsigned long) _config)
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun static ssize_t cci5xx_pmu_global_event_show(struct device *dev,
450*4882a593Smuzhiyun struct device_attribute *attr, char *buf);
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun static struct attribute *cci5xx_pmu_format_attrs[] = {
453*4882a593Smuzhiyun CCI_FORMAT_EXT_ATTR_ENTRY(event, "config:0-4"),
454*4882a593Smuzhiyun CCI_FORMAT_EXT_ATTR_ENTRY(source, "config:5-8"),
455*4882a593Smuzhiyun NULL,
456*4882a593Smuzhiyun };
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun static struct attribute *cci5xx_pmu_event_attrs[] = {
459*4882a593Smuzhiyun /* Slave events */
460*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_arvalid, 0x0),
461*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_dev, 0x1),
462*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_nonshareable, 0x2),
463*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_shareable_non_alloc, 0x3),
464*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_shareable_alloc, 0x4),
465*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_invalidate, 0x5),
466*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_cache_maint, 0x6),
467*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_dvm_msg, 0x7),
468*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_rval, 0x8),
469*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_hs_rlast_snoop, 0x9),
470*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_hs_awalid, 0xA),
471*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_dev, 0xB),
472*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_non_shareable, 0xC),
473*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_share_wb, 0xD),
474*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_share_wlu, 0xE),
475*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_share_wunique, 0xF),
476*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_evict, 0x10),
477*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_wrevict, 0x11),
478*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_w_data_beat, 0x12),
479*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_srq_acvalid, 0x13),
480*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_srq_read, 0x14),
481*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_srq_clean, 0x15),
482*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_srq_data_transfer_low, 0x16),
483*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rrq_stall_arvalid, 0x17),
484*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_r_data_stall, 0x18),
485*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_wrq_stall, 0x19),
486*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_w_data_stall, 0x1A),
487*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_w_resp_stall, 0x1B),
488*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_srq_stall, 0x1C),
489*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_s_data_stall, 0x1D),
490*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_rq_stall_ot_limit, 0x1E),
491*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(si_r_stall_arbit, 0x1F),
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun /* Master events */
494*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_r_data_beat_any, 0x0),
495*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_w_data_beat_any, 0x1),
496*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_rrq_stall, 0x2),
497*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_r_data_stall, 0x3),
498*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_wrq_stall, 0x4),
499*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_w_data_stall, 0x5),
500*4882a593Smuzhiyun CCI_EVENT_EXT_ATTR_ENTRY(mi_w_resp_stall, 0x6),
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun /* Global events */
503*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_0_1, 0x0),
504*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_2_3, 0x1),
505*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_4_5, 0x2),
506*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_filter_bank_6_7, 0x3),
507*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_0_1, 0x4),
508*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_2_3, 0x5),
509*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_4_5, 0x6),
510*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_access_miss_filter_bank_6_7, 0x7),
511*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_back_invalidation, 0x8),
512*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_stall_alloc_busy, 0x9),
513*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_stall_tt_full, 0xA),
514*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_wrq, 0xB),
515*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_cd_hs, 0xC),
516*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_rq_stall_addr_hazard, 0xD),
517*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_rq_stall_tt_full, 0xE),
518*4882a593Smuzhiyun CCI5xx_GLOBAL_EVENT_EXT_ATTR_ENTRY(cci_snoop_rq_tzmp1_prot, 0xF),
519*4882a593Smuzhiyun NULL
520*4882a593Smuzhiyun };
521*4882a593Smuzhiyun
cci5xx_pmu_global_event_show(struct device * dev,struct device_attribute * attr,char * buf)522*4882a593Smuzhiyun static ssize_t cci5xx_pmu_global_event_show(struct device *dev,
523*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun struct dev_ext_attribute *eattr = container_of(attr,
526*4882a593Smuzhiyun struct dev_ext_attribute, attr);
527*4882a593Smuzhiyun /* Global events have single fixed source code */
528*4882a593Smuzhiyun return snprintf(buf, PAGE_SIZE, "event=0x%lx,source=0x%x\n",
529*4882a593Smuzhiyun (unsigned long)eattr->var, CCI5xx_PORT_GLOBAL);
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun /*
533*4882a593Smuzhiyun * CCI500 provides 8 independent event counters that can count
534*4882a593Smuzhiyun * any of the events available.
535*4882a593Smuzhiyun * CCI500 PMU event source ids
536*4882a593Smuzhiyun * 0x0-0x6 - Slave interfaces
537*4882a593Smuzhiyun * 0x8-0xD - Master interfaces
538*4882a593Smuzhiyun * 0xf - Global Events
539*4882a593Smuzhiyun * 0x7,0xe - Reserved
540*4882a593Smuzhiyun */
cci500_validate_hw_event(struct cci_pmu * cci_pmu,unsigned long hw_event)541*4882a593Smuzhiyun static int cci500_validate_hw_event(struct cci_pmu *cci_pmu,
542*4882a593Smuzhiyun unsigned long hw_event)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun u32 ev_source = CCI5xx_PMU_EVENT_SOURCE(hw_event);
545*4882a593Smuzhiyun u32 ev_code = CCI5xx_PMU_EVENT_CODE(hw_event);
546*4882a593Smuzhiyun int if_type;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun if (hw_event & ~CCI5xx_PMU_EVENT_MASK)
549*4882a593Smuzhiyun return -ENOENT;
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun switch (ev_source) {
552*4882a593Smuzhiyun case CCI5xx_PORT_S0:
553*4882a593Smuzhiyun case CCI5xx_PORT_S1:
554*4882a593Smuzhiyun case CCI5xx_PORT_S2:
555*4882a593Smuzhiyun case CCI5xx_PORT_S3:
556*4882a593Smuzhiyun case CCI5xx_PORT_S4:
557*4882a593Smuzhiyun case CCI5xx_PORT_S5:
558*4882a593Smuzhiyun case CCI5xx_PORT_S6:
559*4882a593Smuzhiyun if_type = CCI_IF_SLAVE;
560*4882a593Smuzhiyun break;
561*4882a593Smuzhiyun case CCI5xx_PORT_M0:
562*4882a593Smuzhiyun case CCI5xx_PORT_M1:
563*4882a593Smuzhiyun case CCI5xx_PORT_M2:
564*4882a593Smuzhiyun case CCI5xx_PORT_M3:
565*4882a593Smuzhiyun case CCI5xx_PORT_M4:
566*4882a593Smuzhiyun case CCI5xx_PORT_M5:
567*4882a593Smuzhiyun if_type = CCI_IF_MASTER;
568*4882a593Smuzhiyun break;
569*4882a593Smuzhiyun case CCI5xx_PORT_GLOBAL:
570*4882a593Smuzhiyun if_type = CCI_IF_GLOBAL;
571*4882a593Smuzhiyun break;
572*4882a593Smuzhiyun default:
573*4882a593Smuzhiyun return -ENOENT;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun if (ev_code >= cci_pmu->model->event_ranges[if_type].min &&
577*4882a593Smuzhiyun ev_code <= cci_pmu->model->event_ranges[if_type].max)
578*4882a593Smuzhiyun return hw_event;
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun return -ENOENT;
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun /*
584*4882a593Smuzhiyun * CCI550 provides 8 independent event counters that can count
585*4882a593Smuzhiyun * any of the events available.
586*4882a593Smuzhiyun * CCI550 PMU event source ids
587*4882a593Smuzhiyun * 0x0-0x6 - Slave interfaces
588*4882a593Smuzhiyun * 0x8-0xe - Master interfaces
589*4882a593Smuzhiyun * 0xf - Global Events
590*4882a593Smuzhiyun * 0x7 - Reserved
591*4882a593Smuzhiyun */
cci550_validate_hw_event(struct cci_pmu * cci_pmu,unsigned long hw_event)592*4882a593Smuzhiyun static int cci550_validate_hw_event(struct cci_pmu *cci_pmu,
593*4882a593Smuzhiyun unsigned long hw_event)
594*4882a593Smuzhiyun {
595*4882a593Smuzhiyun u32 ev_source = CCI5xx_PMU_EVENT_SOURCE(hw_event);
596*4882a593Smuzhiyun u32 ev_code = CCI5xx_PMU_EVENT_CODE(hw_event);
597*4882a593Smuzhiyun int if_type;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun if (hw_event & ~CCI5xx_PMU_EVENT_MASK)
600*4882a593Smuzhiyun return -ENOENT;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun switch (ev_source) {
603*4882a593Smuzhiyun case CCI5xx_PORT_S0:
604*4882a593Smuzhiyun case CCI5xx_PORT_S1:
605*4882a593Smuzhiyun case CCI5xx_PORT_S2:
606*4882a593Smuzhiyun case CCI5xx_PORT_S3:
607*4882a593Smuzhiyun case CCI5xx_PORT_S4:
608*4882a593Smuzhiyun case CCI5xx_PORT_S5:
609*4882a593Smuzhiyun case CCI5xx_PORT_S6:
610*4882a593Smuzhiyun if_type = CCI_IF_SLAVE;
611*4882a593Smuzhiyun break;
612*4882a593Smuzhiyun case CCI5xx_PORT_M0:
613*4882a593Smuzhiyun case CCI5xx_PORT_M1:
614*4882a593Smuzhiyun case CCI5xx_PORT_M2:
615*4882a593Smuzhiyun case CCI5xx_PORT_M3:
616*4882a593Smuzhiyun case CCI5xx_PORT_M4:
617*4882a593Smuzhiyun case CCI5xx_PORT_M5:
618*4882a593Smuzhiyun case CCI5xx_PORT_M6:
619*4882a593Smuzhiyun if_type = CCI_IF_MASTER;
620*4882a593Smuzhiyun break;
621*4882a593Smuzhiyun case CCI5xx_PORT_GLOBAL:
622*4882a593Smuzhiyun if_type = CCI_IF_GLOBAL;
623*4882a593Smuzhiyun break;
624*4882a593Smuzhiyun default:
625*4882a593Smuzhiyun return -ENOENT;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun
628*4882a593Smuzhiyun if (ev_code >= cci_pmu->model->event_ranges[if_type].min &&
629*4882a593Smuzhiyun ev_code <= cci_pmu->model->event_ranges[if_type].max)
630*4882a593Smuzhiyun return hw_event;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun return -ENOENT;
633*4882a593Smuzhiyun }
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun #endif /* CONFIG_ARM_CCI5xx_PMU */
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun /*
638*4882a593Smuzhiyun * Program the CCI PMU counters which have PERF_HES_ARCH set
639*4882a593Smuzhiyun * with the event period and mark them ready before we enable
640*4882a593Smuzhiyun * PMU.
641*4882a593Smuzhiyun */
cci_pmu_sync_counters(struct cci_pmu * cci_pmu)642*4882a593Smuzhiyun static void cci_pmu_sync_counters(struct cci_pmu *cci_pmu)
643*4882a593Smuzhiyun {
644*4882a593Smuzhiyun int i;
645*4882a593Smuzhiyun struct cci_pmu_hw_events *cci_hw = &cci_pmu->hw_events;
646*4882a593Smuzhiyun DECLARE_BITMAP(mask, HW_CNTRS_MAX);
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun bitmap_zero(mask, cci_pmu->num_cntrs);
649*4882a593Smuzhiyun for_each_set_bit(i, cci_pmu->hw_events.used_mask, cci_pmu->num_cntrs) {
650*4882a593Smuzhiyun struct perf_event *event = cci_hw->events[i];
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun if (WARN_ON(!event))
653*4882a593Smuzhiyun continue;
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun /* Leave the events which are not counting */
656*4882a593Smuzhiyun if (event->hw.state & PERF_HES_STOPPED)
657*4882a593Smuzhiyun continue;
658*4882a593Smuzhiyun if (event->hw.state & PERF_HES_ARCH) {
659*4882a593Smuzhiyun set_bit(i, mask);
660*4882a593Smuzhiyun event->hw.state &= ~PERF_HES_ARCH;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun pmu_write_counters(cci_pmu, mask);
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun /* Should be called with cci_pmu->hw_events->pmu_lock held */
__cci_pmu_enable_nosync(struct cci_pmu * cci_pmu)668*4882a593Smuzhiyun static void __cci_pmu_enable_nosync(struct cci_pmu *cci_pmu)
669*4882a593Smuzhiyun {
670*4882a593Smuzhiyun u32 val;
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun /* Enable all the PMU counters. */
673*4882a593Smuzhiyun val = readl_relaxed(cci_pmu->ctrl_base + CCI_PMCR) | CCI_PMCR_CEN;
674*4882a593Smuzhiyun writel(val, cci_pmu->ctrl_base + CCI_PMCR);
675*4882a593Smuzhiyun }
676*4882a593Smuzhiyun
677*4882a593Smuzhiyun /* Should be called with cci_pmu->hw_events->pmu_lock held */
__cci_pmu_enable_sync(struct cci_pmu * cci_pmu)678*4882a593Smuzhiyun static void __cci_pmu_enable_sync(struct cci_pmu *cci_pmu)
679*4882a593Smuzhiyun {
680*4882a593Smuzhiyun cci_pmu_sync_counters(cci_pmu);
681*4882a593Smuzhiyun __cci_pmu_enable_nosync(cci_pmu);
682*4882a593Smuzhiyun }
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun /* Should be called with cci_pmu->hw_events->pmu_lock held */
__cci_pmu_disable(struct cci_pmu * cci_pmu)685*4882a593Smuzhiyun static void __cci_pmu_disable(struct cci_pmu *cci_pmu)
686*4882a593Smuzhiyun {
687*4882a593Smuzhiyun u32 val;
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun /* Disable all the PMU counters. */
690*4882a593Smuzhiyun val = readl_relaxed(cci_pmu->ctrl_base + CCI_PMCR) & ~CCI_PMCR_CEN;
691*4882a593Smuzhiyun writel(val, cci_pmu->ctrl_base + CCI_PMCR);
692*4882a593Smuzhiyun }
693*4882a593Smuzhiyun
cci_pmu_format_show(struct device * dev,struct device_attribute * attr,char * buf)694*4882a593Smuzhiyun static ssize_t cci_pmu_format_show(struct device *dev,
695*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun struct dev_ext_attribute *eattr = container_of(attr,
698*4882a593Smuzhiyun struct dev_ext_attribute, attr);
699*4882a593Smuzhiyun return snprintf(buf, PAGE_SIZE, "%s\n", (char *)eattr->var);
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun
cci_pmu_event_show(struct device * dev,struct device_attribute * attr,char * buf)702*4882a593Smuzhiyun static ssize_t cci_pmu_event_show(struct device *dev,
703*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
704*4882a593Smuzhiyun {
705*4882a593Smuzhiyun struct dev_ext_attribute *eattr = container_of(attr,
706*4882a593Smuzhiyun struct dev_ext_attribute, attr);
707*4882a593Smuzhiyun /* source parameter is mandatory for normal PMU events */
708*4882a593Smuzhiyun return snprintf(buf, PAGE_SIZE, "source=?,event=0x%lx\n",
709*4882a593Smuzhiyun (unsigned long)eattr->var);
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun
pmu_is_valid_counter(struct cci_pmu * cci_pmu,int idx)712*4882a593Smuzhiyun static int pmu_is_valid_counter(struct cci_pmu *cci_pmu, int idx)
713*4882a593Smuzhiyun {
714*4882a593Smuzhiyun return 0 <= idx && idx <= CCI_PMU_CNTR_LAST(cci_pmu);
715*4882a593Smuzhiyun }
716*4882a593Smuzhiyun
pmu_read_register(struct cci_pmu * cci_pmu,int idx,unsigned int offset)717*4882a593Smuzhiyun static u32 pmu_read_register(struct cci_pmu *cci_pmu, int idx, unsigned int offset)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun return readl_relaxed(cci_pmu->base +
720*4882a593Smuzhiyun CCI_PMU_CNTR_BASE(cci_pmu->model, idx) + offset);
721*4882a593Smuzhiyun }
722*4882a593Smuzhiyun
pmu_write_register(struct cci_pmu * cci_pmu,u32 value,int idx,unsigned int offset)723*4882a593Smuzhiyun static void pmu_write_register(struct cci_pmu *cci_pmu, u32 value,
724*4882a593Smuzhiyun int idx, unsigned int offset)
725*4882a593Smuzhiyun {
726*4882a593Smuzhiyun writel_relaxed(value, cci_pmu->base +
727*4882a593Smuzhiyun CCI_PMU_CNTR_BASE(cci_pmu->model, idx) + offset);
728*4882a593Smuzhiyun }
729*4882a593Smuzhiyun
pmu_disable_counter(struct cci_pmu * cci_pmu,int idx)730*4882a593Smuzhiyun static void pmu_disable_counter(struct cci_pmu *cci_pmu, int idx)
731*4882a593Smuzhiyun {
732*4882a593Smuzhiyun pmu_write_register(cci_pmu, 0, idx, CCI_PMU_CNTR_CTRL);
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun
pmu_enable_counter(struct cci_pmu * cci_pmu,int idx)735*4882a593Smuzhiyun static void pmu_enable_counter(struct cci_pmu *cci_pmu, int idx)
736*4882a593Smuzhiyun {
737*4882a593Smuzhiyun pmu_write_register(cci_pmu, 1, idx, CCI_PMU_CNTR_CTRL);
738*4882a593Smuzhiyun }
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun static bool __maybe_unused
pmu_counter_is_enabled(struct cci_pmu * cci_pmu,int idx)741*4882a593Smuzhiyun pmu_counter_is_enabled(struct cci_pmu *cci_pmu, int idx)
742*4882a593Smuzhiyun {
743*4882a593Smuzhiyun return (pmu_read_register(cci_pmu, idx, CCI_PMU_CNTR_CTRL) & 0x1) != 0;
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
pmu_set_event(struct cci_pmu * cci_pmu,int idx,unsigned long event)746*4882a593Smuzhiyun static void pmu_set_event(struct cci_pmu *cci_pmu, int idx, unsigned long event)
747*4882a593Smuzhiyun {
748*4882a593Smuzhiyun pmu_write_register(cci_pmu, event, idx, CCI_PMU_EVT_SEL);
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun /*
752*4882a593Smuzhiyun * For all counters on the CCI-PMU, disable any 'enabled' counters,
753*4882a593Smuzhiyun * saving the changed counters in the mask, so that we can restore
754*4882a593Smuzhiyun * it later using pmu_restore_counters. The mask is private to the
755*4882a593Smuzhiyun * caller. We cannot rely on the used_mask maintained by the CCI_PMU
756*4882a593Smuzhiyun * as it only tells us if the counter is assigned to perf_event or not.
757*4882a593Smuzhiyun * The state of the perf_event cannot be locked by the PMU layer, hence
758*4882a593Smuzhiyun * we check the individual counter status (which can be locked by
759*4882a593Smuzhiyun * cci_pm->hw_events->pmu_lock).
760*4882a593Smuzhiyun *
761*4882a593Smuzhiyun * @mask should be initialised to empty by the caller.
762*4882a593Smuzhiyun */
763*4882a593Smuzhiyun static void __maybe_unused
pmu_save_counters(struct cci_pmu * cci_pmu,unsigned long * mask)764*4882a593Smuzhiyun pmu_save_counters(struct cci_pmu *cci_pmu, unsigned long *mask)
765*4882a593Smuzhiyun {
766*4882a593Smuzhiyun int i;
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun for (i = 0; i < cci_pmu->num_cntrs; i++) {
769*4882a593Smuzhiyun if (pmu_counter_is_enabled(cci_pmu, i)) {
770*4882a593Smuzhiyun set_bit(i, mask);
771*4882a593Smuzhiyun pmu_disable_counter(cci_pmu, i);
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun }
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun /*
777*4882a593Smuzhiyun * Restore the status of the counters. Reversal of the pmu_save_counters().
778*4882a593Smuzhiyun * For each counter set in the mask, enable the counter back.
779*4882a593Smuzhiyun */
780*4882a593Smuzhiyun static void __maybe_unused
pmu_restore_counters(struct cci_pmu * cci_pmu,unsigned long * mask)781*4882a593Smuzhiyun pmu_restore_counters(struct cci_pmu *cci_pmu, unsigned long *mask)
782*4882a593Smuzhiyun {
783*4882a593Smuzhiyun int i;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun for_each_set_bit(i, mask, cci_pmu->num_cntrs)
786*4882a593Smuzhiyun pmu_enable_counter(cci_pmu, i);
787*4882a593Smuzhiyun }
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun /*
790*4882a593Smuzhiyun * Returns the number of programmable counters actually implemented
791*4882a593Smuzhiyun * by the cci
792*4882a593Smuzhiyun */
pmu_get_max_counters(struct cci_pmu * cci_pmu)793*4882a593Smuzhiyun static u32 pmu_get_max_counters(struct cci_pmu *cci_pmu)
794*4882a593Smuzhiyun {
795*4882a593Smuzhiyun return (readl_relaxed(cci_pmu->ctrl_base + CCI_PMCR) &
796*4882a593Smuzhiyun CCI_PMCR_NCNT_MASK) >> CCI_PMCR_NCNT_SHIFT;
797*4882a593Smuzhiyun }
798*4882a593Smuzhiyun
pmu_get_event_idx(struct cci_pmu_hw_events * hw,struct perf_event * event)799*4882a593Smuzhiyun static int pmu_get_event_idx(struct cci_pmu_hw_events *hw, struct perf_event *event)
800*4882a593Smuzhiyun {
801*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
802*4882a593Smuzhiyun unsigned long cci_event = event->hw.config_base;
803*4882a593Smuzhiyun int idx;
804*4882a593Smuzhiyun
805*4882a593Smuzhiyun if (cci_pmu->model->get_event_idx)
806*4882a593Smuzhiyun return cci_pmu->model->get_event_idx(cci_pmu, hw, cci_event);
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun /* Generic code to find an unused idx from the mask */
809*4882a593Smuzhiyun for(idx = 0; idx <= CCI_PMU_CNTR_LAST(cci_pmu); idx++)
810*4882a593Smuzhiyun if (!test_and_set_bit(idx, hw->used_mask))
811*4882a593Smuzhiyun return idx;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun /* No counters available */
814*4882a593Smuzhiyun return -EAGAIN;
815*4882a593Smuzhiyun }
816*4882a593Smuzhiyun
pmu_map_event(struct perf_event * event)817*4882a593Smuzhiyun static int pmu_map_event(struct perf_event *event)
818*4882a593Smuzhiyun {
819*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
820*4882a593Smuzhiyun
821*4882a593Smuzhiyun if (event->attr.type < PERF_TYPE_MAX ||
822*4882a593Smuzhiyun !cci_pmu->model->validate_hw_event)
823*4882a593Smuzhiyun return -ENOENT;
824*4882a593Smuzhiyun
825*4882a593Smuzhiyun return cci_pmu->model->validate_hw_event(cci_pmu, event->attr.config);
826*4882a593Smuzhiyun }
827*4882a593Smuzhiyun
pmu_request_irq(struct cci_pmu * cci_pmu,irq_handler_t handler)828*4882a593Smuzhiyun static int pmu_request_irq(struct cci_pmu *cci_pmu, irq_handler_t handler)
829*4882a593Smuzhiyun {
830*4882a593Smuzhiyun int i;
831*4882a593Smuzhiyun struct platform_device *pmu_device = cci_pmu->plat_device;
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun if (unlikely(!pmu_device))
834*4882a593Smuzhiyun return -ENODEV;
835*4882a593Smuzhiyun
836*4882a593Smuzhiyun if (cci_pmu->nr_irqs < 1) {
837*4882a593Smuzhiyun dev_err(&pmu_device->dev, "no irqs for CCI PMUs defined\n");
838*4882a593Smuzhiyun return -ENODEV;
839*4882a593Smuzhiyun }
840*4882a593Smuzhiyun
841*4882a593Smuzhiyun /*
842*4882a593Smuzhiyun * Register all available CCI PMU interrupts. In the interrupt handler
843*4882a593Smuzhiyun * we iterate over the counters checking for interrupt source (the
844*4882a593Smuzhiyun * overflowing counter) and clear it.
845*4882a593Smuzhiyun *
846*4882a593Smuzhiyun * This should allow handling of non-unique interrupt for the counters.
847*4882a593Smuzhiyun */
848*4882a593Smuzhiyun for (i = 0; i < cci_pmu->nr_irqs; i++) {
849*4882a593Smuzhiyun int err = request_irq(cci_pmu->irqs[i], handler, IRQF_SHARED,
850*4882a593Smuzhiyun "arm-cci-pmu", cci_pmu);
851*4882a593Smuzhiyun if (err) {
852*4882a593Smuzhiyun dev_err(&pmu_device->dev, "unable to request IRQ%d for ARM CCI PMU counters\n",
853*4882a593Smuzhiyun cci_pmu->irqs[i]);
854*4882a593Smuzhiyun return err;
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun
857*4882a593Smuzhiyun set_bit(i, &cci_pmu->active_irqs);
858*4882a593Smuzhiyun }
859*4882a593Smuzhiyun
860*4882a593Smuzhiyun return 0;
861*4882a593Smuzhiyun }
862*4882a593Smuzhiyun
pmu_free_irq(struct cci_pmu * cci_pmu)863*4882a593Smuzhiyun static void pmu_free_irq(struct cci_pmu *cci_pmu)
864*4882a593Smuzhiyun {
865*4882a593Smuzhiyun int i;
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun for (i = 0; i < cci_pmu->nr_irqs; i++) {
868*4882a593Smuzhiyun if (!test_and_clear_bit(i, &cci_pmu->active_irqs))
869*4882a593Smuzhiyun continue;
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun free_irq(cci_pmu->irqs[i], cci_pmu);
872*4882a593Smuzhiyun }
873*4882a593Smuzhiyun }
874*4882a593Smuzhiyun
pmu_read_counter(struct perf_event * event)875*4882a593Smuzhiyun static u32 pmu_read_counter(struct perf_event *event)
876*4882a593Smuzhiyun {
877*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
878*4882a593Smuzhiyun struct hw_perf_event *hw_counter = &event->hw;
879*4882a593Smuzhiyun int idx = hw_counter->idx;
880*4882a593Smuzhiyun u32 value;
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
883*4882a593Smuzhiyun dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
884*4882a593Smuzhiyun return 0;
885*4882a593Smuzhiyun }
886*4882a593Smuzhiyun value = pmu_read_register(cci_pmu, idx, CCI_PMU_CNTR);
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun return value;
889*4882a593Smuzhiyun }
890*4882a593Smuzhiyun
pmu_write_counter(struct cci_pmu * cci_pmu,u32 value,int idx)891*4882a593Smuzhiyun static void pmu_write_counter(struct cci_pmu *cci_pmu, u32 value, int idx)
892*4882a593Smuzhiyun {
893*4882a593Smuzhiyun pmu_write_register(cci_pmu, value, idx, CCI_PMU_CNTR);
894*4882a593Smuzhiyun }
895*4882a593Smuzhiyun
__pmu_write_counters(struct cci_pmu * cci_pmu,unsigned long * mask)896*4882a593Smuzhiyun static void __pmu_write_counters(struct cci_pmu *cci_pmu, unsigned long *mask)
897*4882a593Smuzhiyun {
898*4882a593Smuzhiyun int i;
899*4882a593Smuzhiyun struct cci_pmu_hw_events *cci_hw = &cci_pmu->hw_events;
900*4882a593Smuzhiyun
901*4882a593Smuzhiyun for_each_set_bit(i, mask, cci_pmu->num_cntrs) {
902*4882a593Smuzhiyun struct perf_event *event = cci_hw->events[i];
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun if (WARN_ON(!event))
905*4882a593Smuzhiyun continue;
906*4882a593Smuzhiyun pmu_write_counter(cci_pmu, local64_read(&event->hw.prev_count), i);
907*4882a593Smuzhiyun }
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun
pmu_write_counters(struct cci_pmu * cci_pmu,unsigned long * mask)910*4882a593Smuzhiyun static void pmu_write_counters(struct cci_pmu *cci_pmu, unsigned long *mask)
911*4882a593Smuzhiyun {
912*4882a593Smuzhiyun if (cci_pmu->model->write_counters)
913*4882a593Smuzhiyun cci_pmu->model->write_counters(cci_pmu, mask);
914*4882a593Smuzhiyun else
915*4882a593Smuzhiyun __pmu_write_counters(cci_pmu, mask);
916*4882a593Smuzhiyun }
917*4882a593Smuzhiyun
918*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI5xx_PMU
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun /*
921*4882a593Smuzhiyun * CCI-500/CCI-550 has advanced power saving policies, which could gate the
922*4882a593Smuzhiyun * clocks to the PMU counters, which makes the writes to them ineffective.
923*4882a593Smuzhiyun * The only way to write to those counters is when the global counters
924*4882a593Smuzhiyun * are enabled and the particular counter is enabled.
925*4882a593Smuzhiyun *
926*4882a593Smuzhiyun * So we do the following :
927*4882a593Smuzhiyun *
928*4882a593Smuzhiyun * 1) Disable all the PMU counters, saving their current state
929*4882a593Smuzhiyun * 2) Enable the global PMU profiling, now that all counters are
930*4882a593Smuzhiyun * disabled.
931*4882a593Smuzhiyun *
932*4882a593Smuzhiyun * For each counter to be programmed, repeat steps 3-7:
933*4882a593Smuzhiyun *
934*4882a593Smuzhiyun * 3) Write an invalid event code to the event control register for the
935*4882a593Smuzhiyun counter, so that the counters are not modified.
936*4882a593Smuzhiyun * 4) Enable the counter control for the counter.
937*4882a593Smuzhiyun * 5) Set the counter value
938*4882a593Smuzhiyun * 6) Disable the counter
939*4882a593Smuzhiyun * 7) Restore the event in the target counter
940*4882a593Smuzhiyun *
941*4882a593Smuzhiyun * 8) Disable the global PMU.
942*4882a593Smuzhiyun * 9) Restore the status of the rest of the counters.
943*4882a593Smuzhiyun *
944*4882a593Smuzhiyun * We choose an event which for CCI-5xx is guaranteed not to count.
945*4882a593Smuzhiyun * We use the highest possible event code (0x1f) for the master interface 0.
946*4882a593Smuzhiyun */
947*4882a593Smuzhiyun #define CCI5xx_INVALID_EVENT ((CCI5xx_PORT_M0 << CCI5xx_PMU_EVENT_SOURCE_SHIFT) | \
948*4882a593Smuzhiyun (CCI5xx_PMU_EVENT_CODE_MASK << CCI5xx_PMU_EVENT_CODE_SHIFT))
cci5xx_pmu_write_counters(struct cci_pmu * cci_pmu,unsigned long * mask)949*4882a593Smuzhiyun static void cci5xx_pmu_write_counters(struct cci_pmu *cci_pmu, unsigned long *mask)
950*4882a593Smuzhiyun {
951*4882a593Smuzhiyun int i;
952*4882a593Smuzhiyun DECLARE_BITMAP(saved_mask, HW_CNTRS_MAX);
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun bitmap_zero(saved_mask, cci_pmu->num_cntrs);
955*4882a593Smuzhiyun pmu_save_counters(cci_pmu, saved_mask);
956*4882a593Smuzhiyun
957*4882a593Smuzhiyun /*
958*4882a593Smuzhiyun * Now that all the counters are disabled, we can safely turn the PMU on,
959*4882a593Smuzhiyun * without syncing the status of the counters
960*4882a593Smuzhiyun */
961*4882a593Smuzhiyun __cci_pmu_enable_nosync(cci_pmu);
962*4882a593Smuzhiyun
963*4882a593Smuzhiyun for_each_set_bit(i, mask, cci_pmu->num_cntrs) {
964*4882a593Smuzhiyun struct perf_event *event = cci_pmu->hw_events.events[i];
965*4882a593Smuzhiyun
966*4882a593Smuzhiyun if (WARN_ON(!event))
967*4882a593Smuzhiyun continue;
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun pmu_set_event(cci_pmu, i, CCI5xx_INVALID_EVENT);
970*4882a593Smuzhiyun pmu_enable_counter(cci_pmu, i);
971*4882a593Smuzhiyun pmu_write_counter(cci_pmu, local64_read(&event->hw.prev_count), i);
972*4882a593Smuzhiyun pmu_disable_counter(cci_pmu, i);
973*4882a593Smuzhiyun pmu_set_event(cci_pmu, i, event->hw.config_base);
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun
976*4882a593Smuzhiyun __cci_pmu_disable(cci_pmu);
977*4882a593Smuzhiyun
978*4882a593Smuzhiyun pmu_restore_counters(cci_pmu, saved_mask);
979*4882a593Smuzhiyun }
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun #endif /* CONFIG_ARM_CCI5xx_PMU */
982*4882a593Smuzhiyun
pmu_event_update(struct perf_event * event)983*4882a593Smuzhiyun static u64 pmu_event_update(struct perf_event *event)
984*4882a593Smuzhiyun {
985*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
986*4882a593Smuzhiyun u64 delta, prev_raw_count, new_raw_count;
987*4882a593Smuzhiyun
988*4882a593Smuzhiyun do {
989*4882a593Smuzhiyun prev_raw_count = local64_read(&hwc->prev_count);
990*4882a593Smuzhiyun new_raw_count = pmu_read_counter(event);
991*4882a593Smuzhiyun } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
992*4882a593Smuzhiyun new_raw_count) != prev_raw_count);
993*4882a593Smuzhiyun
994*4882a593Smuzhiyun delta = (new_raw_count - prev_raw_count) & CCI_PMU_CNTR_MASK;
995*4882a593Smuzhiyun
996*4882a593Smuzhiyun local64_add(delta, &event->count);
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun return new_raw_count;
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun
pmu_read(struct perf_event * event)1001*4882a593Smuzhiyun static void pmu_read(struct perf_event *event)
1002*4882a593Smuzhiyun {
1003*4882a593Smuzhiyun pmu_event_update(event);
1004*4882a593Smuzhiyun }
1005*4882a593Smuzhiyun
pmu_event_set_period(struct perf_event * event)1006*4882a593Smuzhiyun static void pmu_event_set_period(struct perf_event *event)
1007*4882a593Smuzhiyun {
1008*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
1009*4882a593Smuzhiyun /*
1010*4882a593Smuzhiyun * The CCI PMU counters have a period of 2^32. To account for the
1011*4882a593Smuzhiyun * possiblity of extreme interrupt latency we program for a period of
1012*4882a593Smuzhiyun * half that. Hopefully we can handle the interrupt before another 2^31
1013*4882a593Smuzhiyun * events occur and the counter overtakes its previous value.
1014*4882a593Smuzhiyun */
1015*4882a593Smuzhiyun u64 val = 1ULL << 31;
1016*4882a593Smuzhiyun local64_set(&hwc->prev_count, val);
1017*4882a593Smuzhiyun
1018*4882a593Smuzhiyun /*
1019*4882a593Smuzhiyun * CCI PMU uses PERF_HES_ARCH to keep track of the counters, whose
1020*4882a593Smuzhiyun * values needs to be sync-ed with the s/w state before the PMU is
1021*4882a593Smuzhiyun * enabled.
1022*4882a593Smuzhiyun * Mark this counter for sync.
1023*4882a593Smuzhiyun */
1024*4882a593Smuzhiyun hwc->state |= PERF_HES_ARCH;
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun
pmu_handle_irq(int irq_num,void * dev)1027*4882a593Smuzhiyun static irqreturn_t pmu_handle_irq(int irq_num, void *dev)
1028*4882a593Smuzhiyun {
1029*4882a593Smuzhiyun unsigned long flags;
1030*4882a593Smuzhiyun struct cci_pmu *cci_pmu = dev;
1031*4882a593Smuzhiyun struct cci_pmu_hw_events *events = &cci_pmu->hw_events;
1032*4882a593Smuzhiyun int idx, handled = IRQ_NONE;
1033*4882a593Smuzhiyun
1034*4882a593Smuzhiyun raw_spin_lock_irqsave(&events->pmu_lock, flags);
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun /* Disable the PMU while we walk through the counters */
1037*4882a593Smuzhiyun __cci_pmu_disable(cci_pmu);
1038*4882a593Smuzhiyun /*
1039*4882a593Smuzhiyun * Iterate over counters and update the corresponding perf events.
1040*4882a593Smuzhiyun * This should work regardless of whether we have per-counter overflow
1041*4882a593Smuzhiyun * interrupt or a combined overflow interrupt.
1042*4882a593Smuzhiyun */
1043*4882a593Smuzhiyun for (idx = 0; idx <= CCI_PMU_CNTR_LAST(cci_pmu); idx++) {
1044*4882a593Smuzhiyun struct perf_event *event = events->events[idx];
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun if (!event)
1047*4882a593Smuzhiyun continue;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun /* Did this counter overflow? */
1050*4882a593Smuzhiyun if (!(pmu_read_register(cci_pmu, idx, CCI_PMU_OVRFLW) &
1051*4882a593Smuzhiyun CCI_PMU_OVRFLW_FLAG))
1052*4882a593Smuzhiyun continue;
1053*4882a593Smuzhiyun
1054*4882a593Smuzhiyun pmu_write_register(cci_pmu, CCI_PMU_OVRFLW_FLAG, idx,
1055*4882a593Smuzhiyun CCI_PMU_OVRFLW);
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun pmu_event_update(event);
1058*4882a593Smuzhiyun pmu_event_set_period(event);
1059*4882a593Smuzhiyun handled = IRQ_HANDLED;
1060*4882a593Smuzhiyun }
1061*4882a593Smuzhiyun
1062*4882a593Smuzhiyun /* Enable the PMU and sync possibly overflowed counters */
1063*4882a593Smuzhiyun __cci_pmu_enable_sync(cci_pmu);
1064*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun return IRQ_RETVAL(handled);
1067*4882a593Smuzhiyun }
1068*4882a593Smuzhiyun
cci_pmu_get_hw(struct cci_pmu * cci_pmu)1069*4882a593Smuzhiyun static int cci_pmu_get_hw(struct cci_pmu *cci_pmu)
1070*4882a593Smuzhiyun {
1071*4882a593Smuzhiyun int ret = pmu_request_irq(cci_pmu, pmu_handle_irq);
1072*4882a593Smuzhiyun if (ret) {
1073*4882a593Smuzhiyun pmu_free_irq(cci_pmu);
1074*4882a593Smuzhiyun return ret;
1075*4882a593Smuzhiyun }
1076*4882a593Smuzhiyun return 0;
1077*4882a593Smuzhiyun }
1078*4882a593Smuzhiyun
cci_pmu_put_hw(struct cci_pmu * cci_pmu)1079*4882a593Smuzhiyun static void cci_pmu_put_hw(struct cci_pmu *cci_pmu)
1080*4882a593Smuzhiyun {
1081*4882a593Smuzhiyun pmu_free_irq(cci_pmu);
1082*4882a593Smuzhiyun }
1083*4882a593Smuzhiyun
hw_perf_event_destroy(struct perf_event * event)1084*4882a593Smuzhiyun static void hw_perf_event_destroy(struct perf_event *event)
1085*4882a593Smuzhiyun {
1086*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
1087*4882a593Smuzhiyun atomic_t *active_events = &cci_pmu->active_events;
1088*4882a593Smuzhiyun struct mutex *reserve_mutex = &cci_pmu->reserve_mutex;
1089*4882a593Smuzhiyun
1090*4882a593Smuzhiyun if (atomic_dec_and_mutex_lock(active_events, reserve_mutex)) {
1091*4882a593Smuzhiyun cci_pmu_put_hw(cci_pmu);
1092*4882a593Smuzhiyun mutex_unlock(reserve_mutex);
1093*4882a593Smuzhiyun }
1094*4882a593Smuzhiyun }
1095*4882a593Smuzhiyun
cci_pmu_enable(struct pmu * pmu)1096*4882a593Smuzhiyun static void cci_pmu_enable(struct pmu *pmu)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
1099*4882a593Smuzhiyun struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
1100*4882a593Smuzhiyun int enabled = bitmap_weight(hw_events->used_mask, cci_pmu->num_cntrs);
1101*4882a593Smuzhiyun unsigned long flags;
1102*4882a593Smuzhiyun
1103*4882a593Smuzhiyun if (!enabled)
1104*4882a593Smuzhiyun return;
1105*4882a593Smuzhiyun
1106*4882a593Smuzhiyun raw_spin_lock_irqsave(&hw_events->pmu_lock, flags);
1107*4882a593Smuzhiyun __cci_pmu_enable_sync(cci_pmu);
1108*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags);
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun }
1111*4882a593Smuzhiyun
cci_pmu_disable(struct pmu * pmu)1112*4882a593Smuzhiyun static void cci_pmu_disable(struct pmu *pmu)
1113*4882a593Smuzhiyun {
1114*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
1115*4882a593Smuzhiyun struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
1116*4882a593Smuzhiyun unsigned long flags;
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun raw_spin_lock_irqsave(&hw_events->pmu_lock, flags);
1119*4882a593Smuzhiyun __cci_pmu_disable(cci_pmu);
1120*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags);
1121*4882a593Smuzhiyun }
1122*4882a593Smuzhiyun
1123*4882a593Smuzhiyun /*
1124*4882a593Smuzhiyun * Check if the idx represents a non-programmable counter.
1125*4882a593Smuzhiyun * All the fixed event counters are mapped before the programmable
1126*4882a593Smuzhiyun * counters.
1127*4882a593Smuzhiyun */
pmu_fixed_hw_idx(struct cci_pmu * cci_pmu,int idx)1128*4882a593Smuzhiyun static bool pmu_fixed_hw_idx(struct cci_pmu *cci_pmu, int idx)
1129*4882a593Smuzhiyun {
1130*4882a593Smuzhiyun return (idx >= 0) && (idx < cci_pmu->model->fixed_hw_cntrs);
1131*4882a593Smuzhiyun }
1132*4882a593Smuzhiyun
cci_pmu_start(struct perf_event * event,int pmu_flags)1133*4882a593Smuzhiyun static void cci_pmu_start(struct perf_event *event, int pmu_flags)
1134*4882a593Smuzhiyun {
1135*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
1136*4882a593Smuzhiyun struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
1137*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
1138*4882a593Smuzhiyun int idx = hwc->idx;
1139*4882a593Smuzhiyun unsigned long flags;
1140*4882a593Smuzhiyun
1141*4882a593Smuzhiyun /*
1142*4882a593Smuzhiyun * To handle interrupt latency, we always reprogram the period
1143*4882a593Smuzhiyun * regardlesss of PERF_EF_RELOAD.
1144*4882a593Smuzhiyun */
1145*4882a593Smuzhiyun if (pmu_flags & PERF_EF_RELOAD)
1146*4882a593Smuzhiyun WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun hwc->state = 0;
1149*4882a593Smuzhiyun
1150*4882a593Smuzhiyun if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
1151*4882a593Smuzhiyun dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
1152*4882a593Smuzhiyun return;
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun raw_spin_lock_irqsave(&hw_events->pmu_lock, flags);
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun /* Configure the counter unless you are counting a fixed event */
1158*4882a593Smuzhiyun if (!pmu_fixed_hw_idx(cci_pmu, idx))
1159*4882a593Smuzhiyun pmu_set_event(cci_pmu, idx, hwc->config_base);
1160*4882a593Smuzhiyun
1161*4882a593Smuzhiyun pmu_event_set_period(event);
1162*4882a593Smuzhiyun pmu_enable_counter(cci_pmu, idx);
1163*4882a593Smuzhiyun
1164*4882a593Smuzhiyun raw_spin_unlock_irqrestore(&hw_events->pmu_lock, flags);
1165*4882a593Smuzhiyun }
1166*4882a593Smuzhiyun
cci_pmu_stop(struct perf_event * event,int pmu_flags)1167*4882a593Smuzhiyun static void cci_pmu_stop(struct perf_event *event, int pmu_flags)
1168*4882a593Smuzhiyun {
1169*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
1170*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
1171*4882a593Smuzhiyun int idx = hwc->idx;
1172*4882a593Smuzhiyun
1173*4882a593Smuzhiyun if (hwc->state & PERF_HES_STOPPED)
1174*4882a593Smuzhiyun return;
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun if (unlikely(!pmu_is_valid_counter(cci_pmu, idx))) {
1177*4882a593Smuzhiyun dev_err(&cci_pmu->plat_device->dev, "Invalid CCI PMU counter %d\n", idx);
1178*4882a593Smuzhiyun return;
1179*4882a593Smuzhiyun }
1180*4882a593Smuzhiyun
1181*4882a593Smuzhiyun /*
1182*4882a593Smuzhiyun * We always reprogram the counter, so ignore PERF_EF_UPDATE. See
1183*4882a593Smuzhiyun * cci_pmu_start()
1184*4882a593Smuzhiyun */
1185*4882a593Smuzhiyun pmu_disable_counter(cci_pmu, idx);
1186*4882a593Smuzhiyun pmu_event_update(event);
1187*4882a593Smuzhiyun hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
1188*4882a593Smuzhiyun }
1189*4882a593Smuzhiyun
cci_pmu_add(struct perf_event * event,int flags)1190*4882a593Smuzhiyun static int cci_pmu_add(struct perf_event *event, int flags)
1191*4882a593Smuzhiyun {
1192*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
1193*4882a593Smuzhiyun struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
1194*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
1195*4882a593Smuzhiyun int idx;
1196*4882a593Smuzhiyun
1197*4882a593Smuzhiyun /* If we don't have a space for the counter then finish early. */
1198*4882a593Smuzhiyun idx = pmu_get_event_idx(hw_events, event);
1199*4882a593Smuzhiyun if (idx < 0)
1200*4882a593Smuzhiyun return idx;
1201*4882a593Smuzhiyun
1202*4882a593Smuzhiyun event->hw.idx = idx;
1203*4882a593Smuzhiyun hw_events->events[idx] = event;
1204*4882a593Smuzhiyun
1205*4882a593Smuzhiyun hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
1206*4882a593Smuzhiyun if (flags & PERF_EF_START)
1207*4882a593Smuzhiyun cci_pmu_start(event, PERF_EF_RELOAD);
1208*4882a593Smuzhiyun
1209*4882a593Smuzhiyun /* Propagate our changes to the userspace mapping. */
1210*4882a593Smuzhiyun perf_event_update_userpage(event);
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun return 0;
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun
cci_pmu_del(struct perf_event * event,int flags)1215*4882a593Smuzhiyun static void cci_pmu_del(struct perf_event *event, int flags)
1216*4882a593Smuzhiyun {
1217*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
1218*4882a593Smuzhiyun struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events;
1219*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
1220*4882a593Smuzhiyun int idx = hwc->idx;
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun cci_pmu_stop(event, PERF_EF_UPDATE);
1223*4882a593Smuzhiyun hw_events->events[idx] = NULL;
1224*4882a593Smuzhiyun clear_bit(idx, hw_events->used_mask);
1225*4882a593Smuzhiyun
1226*4882a593Smuzhiyun perf_event_update_userpage(event);
1227*4882a593Smuzhiyun }
1228*4882a593Smuzhiyun
validate_event(struct pmu * cci_pmu,struct cci_pmu_hw_events * hw_events,struct perf_event * event)1229*4882a593Smuzhiyun static int validate_event(struct pmu *cci_pmu,
1230*4882a593Smuzhiyun struct cci_pmu_hw_events *hw_events,
1231*4882a593Smuzhiyun struct perf_event *event)
1232*4882a593Smuzhiyun {
1233*4882a593Smuzhiyun if (is_software_event(event))
1234*4882a593Smuzhiyun return 1;
1235*4882a593Smuzhiyun
1236*4882a593Smuzhiyun /*
1237*4882a593Smuzhiyun * Reject groups spanning multiple HW PMUs (e.g. CPU + CCI). The
1238*4882a593Smuzhiyun * core perf code won't check that the pmu->ctx == leader->ctx
1239*4882a593Smuzhiyun * until after pmu->event_init(event).
1240*4882a593Smuzhiyun */
1241*4882a593Smuzhiyun if (event->pmu != cci_pmu)
1242*4882a593Smuzhiyun return 0;
1243*4882a593Smuzhiyun
1244*4882a593Smuzhiyun if (event->state < PERF_EVENT_STATE_OFF)
1245*4882a593Smuzhiyun return 1;
1246*4882a593Smuzhiyun
1247*4882a593Smuzhiyun if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec)
1248*4882a593Smuzhiyun return 1;
1249*4882a593Smuzhiyun
1250*4882a593Smuzhiyun return pmu_get_event_idx(hw_events, event) >= 0;
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun
validate_group(struct perf_event * event)1253*4882a593Smuzhiyun static int validate_group(struct perf_event *event)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun struct perf_event *sibling, *leader = event->group_leader;
1256*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
1257*4882a593Smuzhiyun unsigned long mask[BITS_TO_LONGS(HW_CNTRS_MAX)];
1258*4882a593Smuzhiyun struct cci_pmu_hw_events fake_pmu = {
1259*4882a593Smuzhiyun /*
1260*4882a593Smuzhiyun * Initialise the fake PMU. We only need to populate the
1261*4882a593Smuzhiyun * used_mask for the purposes of validation.
1262*4882a593Smuzhiyun */
1263*4882a593Smuzhiyun .used_mask = mask,
1264*4882a593Smuzhiyun };
1265*4882a593Smuzhiyun memset(mask, 0, BITS_TO_LONGS(cci_pmu->num_cntrs) * sizeof(unsigned long));
1266*4882a593Smuzhiyun
1267*4882a593Smuzhiyun if (!validate_event(event->pmu, &fake_pmu, leader))
1268*4882a593Smuzhiyun return -EINVAL;
1269*4882a593Smuzhiyun
1270*4882a593Smuzhiyun for_each_sibling_event(sibling, leader) {
1271*4882a593Smuzhiyun if (!validate_event(event->pmu, &fake_pmu, sibling))
1272*4882a593Smuzhiyun return -EINVAL;
1273*4882a593Smuzhiyun }
1274*4882a593Smuzhiyun
1275*4882a593Smuzhiyun if (!validate_event(event->pmu, &fake_pmu, event))
1276*4882a593Smuzhiyun return -EINVAL;
1277*4882a593Smuzhiyun
1278*4882a593Smuzhiyun return 0;
1279*4882a593Smuzhiyun }
1280*4882a593Smuzhiyun
__hw_perf_event_init(struct perf_event * event)1281*4882a593Smuzhiyun static int __hw_perf_event_init(struct perf_event *event)
1282*4882a593Smuzhiyun {
1283*4882a593Smuzhiyun struct hw_perf_event *hwc = &event->hw;
1284*4882a593Smuzhiyun int mapping;
1285*4882a593Smuzhiyun
1286*4882a593Smuzhiyun mapping = pmu_map_event(event);
1287*4882a593Smuzhiyun
1288*4882a593Smuzhiyun if (mapping < 0) {
1289*4882a593Smuzhiyun pr_debug("event %x:%llx not supported\n", event->attr.type,
1290*4882a593Smuzhiyun event->attr.config);
1291*4882a593Smuzhiyun return mapping;
1292*4882a593Smuzhiyun }
1293*4882a593Smuzhiyun
1294*4882a593Smuzhiyun /*
1295*4882a593Smuzhiyun * We don't assign an index until we actually place the event onto
1296*4882a593Smuzhiyun * hardware. Use -1 to signify that we haven't decided where to put it
1297*4882a593Smuzhiyun * yet.
1298*4882a593Smuzhiyun */
1299*4882a593Smuzhiyun hwc->idx = -1;
1300*4882a593Smuzhiyun hwc->config_base = 0;
1301*4882a593Smuzhiyun hwc->config = 0;
1302*4882a593Smuzhiyun hwc->event_base = 0;
1303*4882a593Smuzhiyun
1304*4882a593Smuzhiyun /*
1305*4882a593Smuzhiyun * Store the event encoding into the config_base field.
1306*4882a593Smuzhiyun */
1307*4882a593Smuzhiyun hwc->config_base |= (unsigned long)mapping;
1308*4882a593Smuzhiyun
1309*4882a593Smuzhiyun if (event->group_leader != event) {
1310*4882a593Smuzhiyun if (validate_group(event) != 0)
1311*4882a593Smuzhiyun return -EINVAL;
1312*4882a593Smuzhiyun }
1313*4882a593Smuzhiyun
1314*4882a593Smuzhiyun return 0;
1315*4882a593Smuzhiyun }
1316*4882a593Smuzhiyun
cci_pmu_event_init(struct perf_event * event)1317*4882a593Smuzhiyun static int cci_pmu_event_init(struct perf_event *event)
1318*4882a593Smuzhiyun {
1319*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(event->pmu);
1320*4882a593Smuzhiyun atomic_t *active_events = &cci_pmu->active_events;
1321*4882a593Smuzhiyun int err = 0;
1322*4882a593Smuzhiyun
1323*4882a593Smuzhiyun if (event->attr.type != event->pmu->type)
1324*4882a593Smuzhiyun return -ENOENT;
1325*4882a593Smuzhiyun
1326*4882a593Smuzhiyun /* Shared by all CPUs, no meaningful state to sample */
1327*4882a593Smuzhiyun if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
1328*4882a593Smuzhiyun return -EOPNOTSUPP;
1329*4882a593Smuzhiyun
1330*4882a593Smuzhiyun /*
1331*4882a593Smuzhiyun * Following the example set by other "uncore" PMUs, we accept any CPU
1332*4882a593Smuzhiyun * and rewrite its affinity dynamically rather than having perf core
1333*4882a593Smuzhiyun * handle cpu == -1 and pid == -1 for this case.
1334*4882a593Smuzhiyun *
1335*4882a593Smuzhiyun * The perf core will pin online CPUs for the duration of this call and
1336*4882a593Smuzhiyun * the event being installed into its context, so the PMU's CPU can't
1337*4882a593Smuzhiyun * change under our feet.
1338*4882a593Smuzhiyun */
1339*4882a593Smuzhiyun if (event->cpu < 0)
1340*4882a593Smuzhiyun return -EINVAL;
1341*4882a593Smuzhiyun event->cpu = cci_pmu->cpu;
1342*4882a593Smuzhiyun
1343*4882a593Smuzhiyun event->destroy = hw_perf_event_destroy;
1344*4882a593Smuzhiyun if (!atomic_inc_not_zero(active_events)) {
1345*4882a593Smuzhiyun mutex_lock(&cci_pmu->reserve_mutex);
1346*4882a593Smuzhiyun if (atomic_read(active_events) == 0)
1347*4882a593Smuzhiyun err = cci_pmu_get_hw(cci_pmu);
1348*4882a593Smuzhiyun if (!err)
1349*4882a593Smuzhiyun atomic_inc(active_events);
1350*4882a593Smuzhiyun mutex_unlock(&cci_pmu->reserve_mutex);
1351*4882a593Smuzhiyun }
1352*4882a593Smuzhiyun if (err)
1353*4882a593Smuzhiyun return err;
1354*4882a593Smuzhiyun
1355*4882a593Smuzhiyun err = __hw_perf_event_init(event);
1356*4882a593Smuzhiyun if (err)
1357*4882a593Smuzhiyun hw_perf_event_destroy(event);
1358*4882a593Smuzhiyun
1359*4882a593Smuzhiyun return err;
1360*4882a593Smuzhiyun }
1361*4882a593Smuzhiyun
pmu_cpumask_attr_show(struct device * dev,struct device_attribute * attr,char * buf)1362*4882a593Smuzhiyun static ssize_t pmu_cpumask_attr_show(struct device *dev,
1363*4882a593Smuzhiyun struct device_attribute *attr, char *buf)
1364*4882a593Smuzhiyun {
1365*4882a593Smuzhiyun struct pmu *pmu = dev_get_drvdata(dev);
1366*4882a593Smuzhiyun struct cci_pmu *cci_pmu = to_cci_pmu(pmu);
1367*4882a593Smuzhiyun
1368*4882a593Smuzhiyun return cpumap_print_to_pagebuf(true, buf, cpumask_of(cci_pmu->cpu));
1369*4882a593Smuzhiyun }
1370*4882a593Smuzhiyun
1371*4882a593Smuzhiyun static struct device_attribute pmu_cpumask_attr =
1372*4882a593Smuzhiyun __ATTR(cpumask, S_IRUGO, pmu_cpumask_attr_show, NULL);
1373*4882a593Smuzhiyun
1374*4882a593Smuzhiyun static struct attribute *pmu_attrs[] = {
1375*4882a593Smuzhiyun &pmu_cpumask_attr.attr,
1376*4882a593Smuzhiyun NULL,
1377*4882a593Smuzhiyun };
1378*4882a593Smuzhiyun
1379*4882a593Smuzhiyun static struct attribute_group pmu_attr_group = {
1380*4882a593Smuzhiyun .attrs = pmu_attrs,
1381*4882a593Smuzhiyun };
1382*4882a593Smuzhiyun
1383*4882a593Smuzhiyun static struct attribute_group pmu_format_attr_group = {
1384*4882a593Smuzhiyun .name = "format",
1385*4882a593Smuzhiyun .attrs = NULL, /* Filled in cci_pmu_init_attrs */
1386*4882a593Smuzhiyun };
1387*4882a593Smuzhiyun
1388*4882a593Smuzhiyun static struct attribute_group pmu_event_attr_group = {
1389*4882a593Smuzhiyun .name = "events",
1390*4882a593Smuzhiyun .attrs = NULL, /* Filled in cci_pmu_init_attrs */
1391*4882a593Smuzhiyun };
1392*4882a593Smuzhiyun
1393*4882a593Smuzhiyun static const struct attribute_group *pmu_attr_groups[] = {
1394*4882a593Smuzhiyun &pmu_attr_group,
1395*4882a593Smuzhiyun &pmu_format_attr_group,
1396*4882a593Smuzhiyun &pmu_event_attr_group,
1397*4882a593Smuzhiyun NULL
1398*4882a593Smuzhiyun };
1399*4882a593Smuzhiyun
cci_pmu_init(struct cci_pmu * cci_pmu,struct platform_device * pdev)1400*4882a593Smuzhiyun static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev)
1401*4882a593Smuzhiyun {
1402*4882a593Smuzhiyun const struct cci_pmu_model *model = cci_pmu->model;
1403*4882a593Smuzhiyun char *name = model->name;
1404*4882a593Smuzhiyun u32 num_cntrs;
1405*4882a593Smuzhiyun
1406*4882a593Smuzhiyun if (WARN_ON(model->num_hw_cntrs > NUM_HW_CNTRS_MAX))
1407*4882a593Smuzhiyun return -EINVAL;
1408*4882a593Smuzhiyun if (WARN_ON(model->fixed_hw_cntrs > FIXED_HW_CNTRS_MAX))
1409*4882a593Smuzhiyun return -EINVAL;
1410*4882a593Smuzhiyun
1411*4882a593Smuzhiyun pmu_event_attr_group.attrs = model->event_attrs;
1412*4882a593Smuzhiyun pmu_format_attr_group.attrs = model->format_attrs;
1413*4882a593Smuzhiyun
1414*4882a593Smuzhiyun cci_pmu->pmu = (struct pmu) {
1415*4882a593Smuzhiyun .module = THIS_MODULE,
1416*4882a593Smuzhiyun .name = cci_pmu->model->name,
1417*4882a593Smuzhiyun .task_ctx_nr = perf_invalid_context,
1418*4882a593Smuzhiyun .pmu_enable = cci_pmu_enable,
1419*4882a593Smuzhiyun .pmu_disable = cci_pmu_disable,
1420*4882a593Smuzhiyun .event_init = cci_pmu_event_init,
1421*4882a593Smuzhiyun .add = cci_pmu_add,
1422*4882a593Smuzhiyun .del = cci_pmu_del,
1423*4882a593Smuzhiyun .start = cci_pmu_start,
1424*4882a593Smuzhiyun .stop = cci_pmu_stop,
1425*4882a593Smuzhiyun .read = pmu_read,
1426*4882a593Smuzhiyun .attr_groups = pmu_attr_groups,
1427*4882a593Smuzhiyun .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
1428*4882a593Smuzhiyun };
1429*4882a593Smuzhiyun
1430*4882a593Smuzhiyun cci_pmu->plat_device = pdev;
1431*4882a593Smuzhiyun num_cntrs = pmu_get_max_counters(cci_pmu);
1432*4882a593Smuzhiyun if (num_cntrs > cci_pmu->model->num_hw_cntrs) {
1433*4882a593Smuzhiyun dev_warn(&pdev->dev,
1434*4882a593Smuzhiyun "PMU implements more counters(%d) than supported by"
1435*4882a593Smuzhiyun " the model(%d), truncated.",
1436*4882a593Smuzhiyun num_cntrs, cci_pmu->model->num_hw_cntrs);
1437*4882a593Smuzhiyun num_cntrs = cci_pmu->model->num_hw_cntrs;
1438*4882a593Smuzhiyun }
1439*4882a593Smuzhiyun cci_pmu->num_cntrs = num_cntrs + cci_pmu->model->fixed_hw_cntrs;
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun return perf_pmu_register(&cci_pmu->pmu, name, -1);
1442*4882a593Smuzhiyun }
1443*4882a593Smuzhiyun
cci_pmu_offline_cpu(unsigned int cpu)1444*4882a593Smuzhiyun static int cci_pmu_offline_cpu(unsigned int cpu)
1445*4882a593Smuzhiyun {
1446*4882a593Smuzhiyun int target;
1447*4882a593Smuzhiyun
1448*4882a593Smuzhiyun if (!g_cci_pmu || cpu != g_cci_pmu->cpu)
1449*4882a593Smuzhiyun return 0;
1450*4882a593Smuzhiyun
1451*4882a593Smuzhiyun target = cpumask_any_but(cpu_online_mask, cpu);
1452*4882a593Smuzhiyun if (target >= nr_cpu_ids)
1453*4882a593Smuzhiyun return 0;
1454*4882a593Smuzhiyun
1455*4882a593Smuzhiyun perf_pmu_migrate_context(&g_cci_pmu->pmu, cpu, target);
1456*4882a593Smuzhiyun g_cci_pmu->cpu = target;
1457*4882a593Smuzhiyun return 0;
1458*4882a593Smuzhiyun }
1459*4882a593Smuzhiyun
1460*4882a593Smuzhiyun static __maybe_unused struct cci_pmu_model cci_pmu_models[] = {
1461*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI400_PMU
1462*4882a593Smuzhiyun [CCI400_R0] = {
1463*4882a593Smuzhiyun .name = "CCI_400",
1464*4882a593Smuzhiyun .fixed_hw_cntrs = FIXED_HW_CNTRS_CII_4XX, /* Cycle counter */
1465*4882a593Smuzhiyun .num_hw_cntrs = NUM_HW_CNTRS_CII_4XX,
1466*4882a593Smuzhiyun .cntr_size = SZ_4K,
1467*4882a593Smuzhiyun .format_attrs = cci400_pmu_format_attrs,
1468*4882a593Smuzhiyun .event_attrs = cci400_r0_pmu_event_attrs,
1469*4882a593Smuzhiyun .event_ranges = {
1470*4882a593Smuzhiyun [CCI_IF_SLAVE] = {
1471*4882a593Smuzhiyun CCI400_R0_SLAVE_PORT_MIN_EV,
1472*4882a593Smuzhiyun CCI400_R0_SLAVE_PORT_MAX_EV,
1473*4882a593Smuzhiyun },
1474*4882a593Smuzhiyun [CCI_IF_MASTER] = {
1475*4882a593Smuzhiyun CCI400_R0_MASTER_PORT_MIN_EV,
1476*4882a593Smuzhiyun CCI400_R0_MASTER_PORT_MAX_EV,
1477*4882a593Smuzhiyun },
1478*4882a593Smuzhiyun },
1479*4882a593Smuzhiyun .validate_hw_event = cci400_validate_hw_event,
1480*4882a593Smuzhiyun .get_event_idx = cci400_get_event_idx,
1481*4882a593Smuzhiyun },
1482*4882a593Smuzhiyun [CCI400_R1] = {
1483*4882a593Smuzhiyun .name = "CCI_400_r1",
1484*4882a593Smuzhiyun .fixed_hw_cntrs = FIXED_HW_CNTRS_CII_4XX, /* Cycle counter */
1485*4882a593Smuzhiyun .num_hw_cntrs = NUM_HW_CNTRS_CII_4XX,
1486*4882a593Smuzhiyun .cntr_size = SZ_4K,
1487*4882a593Smuzhiyun .format_attrs = cci400_pmu_format_attrs,
1488*4882a593Smuzhiyun .event_attrs = cci400_r1_pmu_event_attrs,
1489*4882a593Smuzhiyun .event_ranges = {
1490*4882a593Smuzhiyun [CCI_IF_SLAVE] = {
1491*4882a593Smuzhiyun CCI400_R1_SLAVE_PORT_MIN_EV,
1492*4882a593Smuzhiyun CCI400_R1_SLAVE_PORT_MAX_EV,
1493*4882a593Smuzhiyun },
1494*4882a593Smuzhiyun [CCI_IF_MASTER] = {
1495*4882a593Smuzhiyun CCI400_R1_MASTER_PORT_MIN_EV,
1496*4882a593Smuzhiyun CCI400_R1_MASTER_PORT_MAX_EV,
1497*4882a593Smuzhiyun },
1498*4882a593Smuzhiyun },
1499*4882a593Smuzhiyun .validate_hw_event = cci400_validate_hw_event,
1500*4882a593Smuzhiyun .get_event_idx = cci400_get_event_idx,
1501*4882a593Smuzhiyun },
1502*4882a593Smuzhiyun #endif
1503*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI5xx_PMU
1504*4882a593Smuzhiyun [CCI500_R0] = {
1505*4882a593Smuzhiyun .name = "CCI_500",
1506*4882a593Smuzhiyun .fixed_hw_cntrs = FIXED_HW_CNTRS_CII_5XX,
1507*4882a593Smuzhiyun .num_hw_cntrs = NUM_HW_CNTRS_CII_5XX,
1508*4882a593Smuzhiyun .cntr_size = SZ_64K,
1509*4882a593Smuzhiyun .format_attrs = cci5xx_pmu_format_attrs,
1510*4882a593Smuzhiyun .event_attrs = cci5xx_pmu_event_attrs,
1511*4882a593Smuzhiyun .event_ranges = {
1512*4882a593Smuzhiyun [CCI_IF_SLAVE] = {
1513*4882a593Smuzhiyun CCI5xx_SLAVE_PORT_MIN_EV,
1514*4882a593Smuzhiyun CCI5xx_SLAVE_PORT_MAX_EV,
1515*4882a593Smuzhiyun },
1516*4882a593Smuzhiyun [CCI_IF_MASTER] = {
1517*4882a593Smuzhiyun CCI5xx_MASTER_PORT_MIN_EV,
1518*4882a593Smuzhiyun CCI5xx_MASTER_PORT_MAX_EV,
1519*4882a593Smuzhiyun },
1520*4882a593Smuzhiyun [CCI_IF_GLOBAL] = {
1521*4882a593Smuzhiyun CCI5xx_GLOBAL_PORT_MIN_EV,
1522*4882a593Smuzhiyun CCI5xx_GLOBAL_PORT_MAX_EV,
1523*4882a593Smuzhiyun },
1524*4882a593Smuzhiyun },
1525*4882a593Smuzhiyun .validate_hw_event = cci500_validate_hw_event,
1526*4882a593Smuzhiyun .write_counters = cci5xx_pmu_write_counters,
1527*4882a593Smuzhiyun },
1528*4882a593Smuzhiyun [CCI550_R0] = {
1529*4882a593Smuzhiyun .name = "CCI_550",
1530*4882a593Smuzhiyun .fixed_hw_cntrs = FIXED_HW_CNTRS_CII_5XX,
1531*4882a593Smuzhiyun .num_hw_cntrs = NUM_HW_CNTRS_CII_5XX,
1532*4882a593Smuzhiyun .cntr_size = SZ_64K,
1533*4882a593Smuzhiyun .format_attrs = cci5xx_pmu_format_attrs,
1534*4882a593Smuzhiyun .event_attrs = cci5xx_pmu_event_attrs,
1535*4882a593Smuzhiyun .event_ranges = {
1536*4882a593Smuzhiyun [CCI_IF_SLAVE] = {
1537*4882a593Smuzhiyun CCI5xx_SLAVE_PORT_MIN_EV,
1538*4882a593Smuzhiyun CCI5xx_SLAVE_PORT_MAX_EV,
1539*4882a593Smuzhiyun },
1540*4882a593Smuzhiyun [CCI_IF_MASTER] = {
1541*4882a593Smuzhiyun CCI5xx_MASTER_PORT_MIN_EV,
1542*4882a593Smuzhiyun CCI5xx_MASTER_PORT_MAX_EV,
1543*4882a593Smuzhiyun },
1544*4882a593Smuzhiyun [CCI_IF_GLOBAL] = {
1545*4882a593Smuzhiyun CCI5xx_GLOBAL_PORT_MIN_EV,
1546*4882a593Smuzhiyun CCI5xx_GLOBAL_PORT_MAX_EV,
1547*4882a593Smuzhiyun },
1548*4882a593Smuzhiyun },
1549*4882a593Smuzhiyun .validate_hw_event = cci550_validate_hw_event,
1550*4882a593Smuzhiyun .write_counters = cci5xx_pmu_write_counters,
1551*4882a593Smuzhiyun },
1552*4882a593Smuzhiyun #endif
1553*4882a593Smuzhiyun };
1554*4882a593Smuzhiyun
1555*4882a593Smuzhiyun static const struct of_device_id arm_cci_pmu_matches[] = {
1556*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI400_PMU
1557*4882a593Smuzhiyun {
1558*4882a593Smuzhiyun .compatible = "arm,cci-400-pmu",
1559*4882a593Smuzhiyun .data = NULL,
1560*4882a593Smuzhiyun },
1561*4882a593Smuzhiyun {
1562*4882a593Smuzhiyun .compatible = "arm,cci-400-pmu,r0",
1563*4882a593Smuzhiyun .data = &cci_pmu_models[CCI400_R0],
1564*4882a593Smuzhiyun },
1565*4882a593Smuzhiyun {
1566*4882a593Smuzhiyun .compatible = "arm,cci-400-pmu,r1",
1567*4882a593Smuzhiyun .data = &cci_pmu_models[CCI400_R1],
1568*4882a593Smuzhiyun },
1569*4882a593Smuzhiyun #endif
1570*4882a593Smuzhiyun #ifdef CONFIG_ARM_CCI5xx_PMU
1571*4882a593Smuzhiyun {
1572*4882a593Smuzhiyun .compatible = "arm,cci-500-pmu,r0",
1573*4882a593Smuzhiyun .data = &cci_pmu_models[CCI500_R0],
1574*4882a593Smuzhiyun },
1575*4882a593Smuzhiyun {
1576*4882a593Smuzhiyun .compatible = "arm,cci-550-pmu,r0",
1577*4882a593Smuzhiyun .data = &cci_pmu_models[CCI550_R0],
1578*4882a593Smuzhiyun },
1579*4882a593Smuzhiyun #endif
1580*4882a593Smuzhiyun {},
1581*4882a593Smuzhiyun };
1582*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, arm_cci_pmu_matches);
1583*4882a593Smuzhiyun
is_duplicate_irq(int irq,int * irqs,int nr_irqs)1584*4882a593Smuzhiyun static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs)
1585*4882a593Smuzhiyun {
1586*4882a593Smuzhiyun int i;
1587*4882a593Smuzhiyun
1588*4882a593Smuzhiyun for (i = 0; i < nr_irqs; i++)
1589*4882a593Smuzhiyun if (irq == irqs[i])
1590*4882a593Smuzhiyun return true;
1591*4882a593Smuzhiyun
1592*4882a593Smuzhiyun return false;
1593*4882a593Smuzhiyun }
1594*4882a593Smuzhiyun
cci_pmu_alloc(struct device * dev)1595*4882a593Smuzhiyun static struct cci_pmu *cci_pmu_alloc(struct device *dev)
1596*4882a593Smuzhiyun {
1597*4882a593Smuzhiyun struct cci_pmu *cci_pmu;
1598*4882a593Smuzhiyun const struct cci_pmu_model *model;
1599*4882a593Smuzhiyun
1600*4882a593Smuzhiyun /*
1601*4882a593Smuzhiyun * All allocations are devm_* hence we don't have to free
1602*4882a593Smuzhiyun * them explicitly on an error, as it would end up in driver
1603*4882a593Smuzhiyun * detach.
1604*4882a593Smuzhiyun */
1605*4882a593Smuzhiyun cci_pmu = devm_kzalloc(dev, sizeof(*cci_pmu), GFP_KERNEL);
1606*4882a593Smuzhiyun if (!cci_pmu)
1607*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1608*4882a593Smuzhiyun
1609*4882a593Smuzhiyun cci_pmu->ctrl_base = *(void __iomem **)dev->platform_data;
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun model = of_device_get_match_data(dev);
1612*4882a593Smuzhiyun if (!model) {
1613*4882a593Smuzhiyun dev_warn(dev,
1614*4882a593Smuzhiyun "DEPRECATED compatible property, requires secure access to CCI registers");
1615*4882a593Smuzhiyun model = probe_cci_model(cci_pmu);
1616*4882a593Smuzhiyun }
1617*4882a593Smuzhiyun if (!model) {
1618*4882a593Smuzhiyun dev_warn(dev, "CCI PMU version not supported\n");
1619*4882a593Smuzhiyun return ERR_PTR(-ENODEV);
1620*4882a593Smuzhiyun }
1621*4882a593Smuzhiyun
1622*4882a593Smuzhiyun cci_pmu->model = model;
1623*4882a593Smuzhiyun cci_pmu->irqs = devm_kcalloc(dev, CCI_PMU_MAX_HW_CNTRS(model),
1624*4882a593Smuzhiyun sizeof(*cci_pmu->irqs), GFP_KERNEL);
1625*4882a593Smuzhiyun if (!cci_pmu->irqs)
1626*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1627*4882a593Smuzhiyun cci_pmu->hw_events.events = devm_kcalloc(dev,
1628*4882a593Smuzhiyun CCI_PMU_MAX_HW_CNTRS(model),
1629*4882a593Smuzhiyun sizeof(*cci_pmu->hw_events.events),
1630*4882a593Smuzhiyun GFP_KERNEL);
1631*4882a593Smuzhiyun if (!cci_pmu->hw_events.events)
1632*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1633*4882a593Smuzhiyun cci_pmu->hw_events.used_mask = devm_kcalloc(dev,
1634*4882a593Smuzhiyun BITS_TO_LONGS(CCI_PMU_MAX_HW_CNTRS(model)),
1635*4882a593Smuzhiyun sizeof(*cci_pmu->hw_events.used_mask),
1636*4882a593Smuzhiyun GFP_KERNEL);
1637*4882a593Smuzhiyun if (!cci_pmu->hw_events.used_mask)
1638*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1639*4882a593Smuzhiyun
1640*4882a593Smuzhiyun return cci_pmu;
1641*4882a593Smuzhiyun }
1642*4882a593Smuzhiyun
cci_pmu_probe(struct platform_device * pdev)1643*4882a593Smuzhiyun static int cci_pmu_probe(struct platform_device *pdev)
1644*4882a593Smuzhiyun {
1645*4882a593Smuzhiyun struct cci_pmu *cci_pmu;
1646*4882a593Smuzhiyun int i, ret, irq;
1647*4882a593Smuzhiyun
1648*4882a593Smuzhiyun cci_pmu = cci_pmu_alloc(&pdev->dev);
1649*4882a593Smuzhiyun if (IS_ERR(cci_pmu))
1650*4882a593Smuzhiyun return PTR_ERR(cci_pmu);
1651*4882a593Smuzhiyun
1652*4882a593Smuzhiyun cci_pmu->base = devm_platform_ioremap_resource(pdev, 0);
1653*4882a593Smuzhiyun if (IS_ERR(cci_pmu->base))
1654*4882a593Smuzhiyun return -ENOMEM;
1655*4882a593Smuzhiyun
1656*4882a593Smuzhiyun /*
1657*4882a593Smuzhiyun * CCI PMU has one overflow interrupt per counter; but some may be tied
1658*4882a593Smuzhiyun * together to a common interrupt.
1659*4882a593Smuzhiyun */
1660*4882a593Smuzhiyun cci_pmu->nr_irqs = 0;
1661*4882a593Smuzhiyun for (i = 0; i < CCI_PMU_MAX_HW_CNTRS(cci_pmu->model); i++) {
1662*4882a593Smuzhiyun irq = platform_get_irq(pdev, i);
1663*4882a593Smuzhiyun if (irq < 0)
1664*4882a593Smuzhiyun break;
1665*4882a593Smuzhiyun
1666*4882a593Smuzhiyun if (is_duplicate_irq(irq, cci_pmu->irqs, cci_pmu->nr_irqs))
1667*4882a593Smuzhiyun continue;
1668*4882a593Smuzhiyun
1669*4882a593Smuzhiyun cci_pmu->irqs[cci_pmu->nr_irqs++] = irq;
1670*4882a593Smuzhiyun }
1671*4882a593Smuzhiyun
1672*4882a593Smuzhiyun /*
1673*4882a593Smuzhiyun * Ensure that the device tree has as many interrupts as the number
1674*4882a593Smuzhiyun * of counters.
1675*4882a593Smuzhiyun */
1676*4882a593Smuzhiyun if (i < CCI_PMU_MAX_HW_CNTRS(cci_pmu->model)) {
1677*4882a593Smuzhiyun dev_warn(&pdev->dev, "In-correct number of interrupts: %d, should be %d\n",
1678*4882a593Smuzhiyun i, CCI_PMU_MAX_HW_CNTRS(cci_pmu->model));
1679*4882a593Smuzhiyun return -EINVAL;
1680*4882a593Smuzhiyun }
1681*4882a593Smuzhiyun
1682*4882a593Smuzhiyun raw_spin_lock_init(&cci_pmu->hw_events.pmu_lock);
1683*4882a593Smuzhiyun mutex_init(&cci_pmu->reserve_mutex);
1684*4882a593Smuzhiyun atomic_set(&cci_pmu->active_events, 0);
1685*4882a593Smuzhiyun
1686*4882a593Smuzhiyun cci_pmu->cpu = raw_smp_processor_id();
1687*4882a593Smuzhiyun g_cci_pmu = cci_pmu;
1688*4882a593Smuzhiyun cpuhp_setup_state_nocalls(CPUHP_AP_PERF_ARM_CCI_ONLINE,
1689*4882a593Smuzhiyun "perf/arm/cci:online", NULL,
1690*4882a593Smuzhiyun cci_pmu_offline_cpu);
1691*4882a593Smuzhiyun
1692*4882a593Smuzhiyun ret = cci_pmu_init(cci_pmu, pdev);
1693*4882a593Smuzhiyun if (ret)
1694*4882a593Smuzhiyun goto error_pmu_init;
1695*4882a593Smuzhiyun
1696*4882a593Smuzhiyun pr_info("ARM %s PMU driver probed", cci_pmu->model->name);
1697*4882a593Smuzhiyun return 0;
1698*4882a593Smuzhiyun
1699*4882a593Smuzhiyun error_pmu_init:
1700*4882a593Smuzhiyun cpuhp_remove_state(CPUHP_AP_PERF_ARM_CCI_ONLINE);
1701*4882a593Smuzhiyun g_cci_pmu = NULL;
1702*4882a593Smuzhiyun return ret;
1703*4882a593Smuzhiyun }
1704*4882a593Smuzhiyun
cci_pmu_remove(struct platform_device * pdev)1705*4882a593Smuzhiyun static int cci_pmu_remove(struct platform_device *pdev)
1706*4882a593Smuzhiyun {
1707*4882a593Smuzhiyun if (!g_cci_pmu)
1708*4882a593Smuzhiyun return 0;
1709*4882a593Smuzhiyun
1710*4882a593Smuzhiyun cpuhp_remove_state(CPUHP_AP_PERF_ARM_CCI_ONLINE);
1711*4882a593Smuzhiyun perf_pmu_unregister(&g_cci_pmu->pmu);
1712*4882a593Smuzhiyun g_cci_pmu = NULL;
1713*4882a593Smuzhiyun
1714*4882a593Smuzhiyun return 0;
1715*4882a593Smuzhiyun }
1716*4882a593Smuzhiyun
1717*4882a593Smuzhiyun static struct platform_driver cci_pmu_driver = {
1718*4882a593Smuzhiyun .driver = {
1719*4882a593Smuzhiyun .name = DRIVER_NAME,
1720*4882a593Smuzhiyun .of_match_table = arm_cci_pmu_matches,
1721*4882a593Smuzhiyun .suppress_bind_attrs = true,
1722*4882a593Smuzhiyun },
1723*4882a593Smuzhiyun .probe = cci_pmu_probe,
1724*4882a593Smuzhiyun .remove = cci_pmu_remove,
1725*4882a593Smuzhiyun };
1726*4882a593Smuzhiyun
1727*4882a593Smuzhiyun module_platform_driver(cci_pmu_driver);
1728*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
1729*4882a593Smuzhiyun MODULE_DESCRIPTION("ARM CCI PMU support");
1730