blob: 53e9e31053d6d5511c88f75155c3c3f36dfd2b55 [file] [log] [blame]
Tai Nguyen832c9272016-07-15 10:38:04 -07001/*
2 * APM X-Gene SoC PMU (Performance Monitor Unit)
3 *
4 * Copyright (c) 2016, Applied Micro Circuits Corporation
5 * Author: Hoan Tran <hotran@apm.com>
6 * Tai Nguyen <ttnguyen@apm.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <linux/acpi.h>
23#include <linux/clk.h>
24#include <linux/cpumask.h>
25#include <linux/interrupt.h>
26#include <linux/io.h>
27#include <linux/mfd/syscon.h>
Stephen Boydc0bfc542017-01-25 15:46:58 -080028#include <linux/module.h>
Tai Nguyen832c9272016-07-15 10:38:04 -070029#include <linux/of_address.h>
30#include <linux/of_fdt.h>
31#include <linux/of_irq.h>
32#include <linux/of_platform.h>
33#include <linux/perf_event.h>
34#include <linux/platform_device.h>
35#include <linux/regmap.h>
36#include <linux/slab.h>
37
38#define CSW_CSWCR 0x0000
39#define CSW_CSWCR_DUALMCB_MASK BIT(0)
40#define MCBADDRMR 0x0000
41#define MCBADDRMR_DUALMCU_MODE_MASK BIT(2)
42
43#define PCPPMU_INTSTATUS_REG 0x000
44#define PCPPMU_INTMASK_REG 0x004
45#define PCPPMU_INTMASK 0x0000000F
46#define PCPPMU_INTENMASK 0xFFFFFFFF
47#define PCPPMU_INTCLRMASK 0xFFFFFFF0
48#define PCPPMU_INT_MCU BIT(0)
49#define PCPPMU_INT_MCB BIT(1)
50#define PCPPMU_INT_L3C BIT(2)
51#define PCPPMU_INT_IOB BIT(3)
52
53#define PMU_MAX_COUNTERS 4
54#define PMU_CNT_MAX_PERIOD 0x100000000ULL
55#define PMU_OVERFLOW_MASK 0xF
56#define PMU_PMCR_E BIT(0)
57#define PMU_PMCR_P BIT(1)
58
59#define PMU_PMEVCNTR0 0x000
60#define PMU_PMEVCNTR1 0x004
61#define PMU_PMEVCNTR2 0x008
62#define PMU_PMEVCNTR3 0x00C
63#define PMU_PMEVTYPER0 0x400
64#define PMU_PMEVTYPER1 0x404
65#define PMU_PMEVTYPER2 0x408
66#define PMU_PMEVTYPER3 0x40C
67#define PMU_PMAMR0 0xA00
68#define PMU_PMAMR1 0xA04
69#define PMU_PMCNTENSET 0xC00
70#define PMU_PMCNTENCLR 0xC20
71#define PMU_PMINTENSET 0xC40
72#define PMU_PMINTENCLR 0xC60
73#define PMU_PMOVSR 0xC80
74#define PMU_PMCR 0xE04
75
76#define to_pmu_dev(p) container_of(p, struct xgene_pmu_dev, pmu)
77#define GET_CNTR(ev) (ev->hw.idx)
78#define GET_EVENTID(ev) (ev->hw.config & 0xFFULL)
79#define GET_AGENTID(ev) (ev->hw.config_base & 0xFFFFFFFFUL)
80#define GET_AGENT1ID(ev) ((ev->hw.config_base >> 32) & 0xFFFFFFFFUL)
81
82struct hw_pmu_info {
83 u32 type;
84 u32 enable_mask;
85 void __iomem *csr;
86};
87
88struct xgene_pmu_dev {
89 struct hw_pmu_info *inf;
90 struct xgene_pmu *parent;
91 struct pmu pmu;
92 u8 max_counters;
93 DECLARE_BITMAP(cntr_assign_mask, PMU_MAX_COUNTERS);
94 u64 max_period;
95 const struct attribute_group **attr_groups;
96 struct perf_event *pmu_counter_event[PMU_MAX_COUNTERS];
97};
98
Hoan Trane35e0a02017-06-22 19:26:04 +010099struct xgene_pmu_ops {
100 void (*mask_int)(struct xgene_pmu *pmu);
101 void (*unmask_int)(struct xgene_pmu *pmu);
102 u64 (*read_counter)(struct xgene_pmu_dev *pmu, int idx);
103 void (*write_counter)(struct xgene_pmu_dev *pmu, int idx, u64 val);
104 void (*write_evttype)(struct xgene_pmu_dev *pmu_dev, int idx, u32 val);
105 void (*write_agentmsk)(struct xgene_pmu_dev *pmu_dev, u32 val);
106 void (*write_agent1msk)(struct xgene_pmu_dev *pmu_dev, u32 val);
107 void (*enable_counter)(struct xgene_pmu_dev *pmu_dev, int idx);
108 void (*disable_counter)(struct xgene_pmu_dev *pmu_dev, int idx);
109 void (*enable_counter_int)(struct xgene_pmu_dev *pmu_dev, int idx);
110 void (*disable_counter_int)(struct xgene_pmu_dev *pmu_dev, int idx);
111 void (*reset_counters)(struct xgene_pmu_dev *pmu_dev);
112 void (*start_counters)(struct xgene_pmu_dev *pmu_dev);
113 void (*stop_counters)(struct xgene_pmu_dev *pmu_dev);
114};
115
Tai Nguyen832c9272016-07-15 10:38:04 -0700116struct xgene_pmu {
117 struct device *dev;
118 int version;
119 void __iomem *pcppmu_csr;
120 u32 mcb_active_mask;
121 u32 mc_active_mask;
122 cpumask_t cpu;
123 raw_spinlock_t lock;
Hoan Trane35e0a02017-06-22 19:26:04 +0100124 const struct xgene_pmu_ops *ops;
Tai Nguyen832c9272016-07-15 10:38:04 -0700125 struct list_head l3cpmus;
126 struct list_head iobpmus;
127 struct list_head mcbpmus;
128 struct list_head mcpmus;
129};
130
131struct xgene_pmu_dev_ctx {
132 char *name;
133 struct list_head next;
134 struct xgene_pmu_dev *pmu_dev;
135 struct hw_pmu_info inf;
136};
137
138struct xgene_pmu_data {
139 int id;
140 u32 data;
141};
142
143enum xgene_pmu_version {
144 PCP_PMU_V1 = 1,
145 PCP_PMU_V2,
146};
147
148enum xgene_pmu_dev_type {
149 PMU_TYPE_L3C = 0,
150 PMU_TYPE_IOB,
151 PMU_TYPE_MCB,
152 PMU_TYPE_MC,
153};
154
155/*
156 * sysfs format attributes
157 */
158static ssize_t xgene_pmu_format_show(struct device *dev,
159 struct device_attribute *attr, char *buf)
160{
161 struct dev_ext_attribute *eattr;
162
163 eattr = container_of(attr, struct dev_ext_attribute, attr);
164 return sprintf(buf, "%s\n", (char *) eattr->var);
165}
166
167#define XGENE_PMU_FORMAT_ATTR(_name, _config) \
168 (&((struct dev_ext_attribute[]) { \
169 { .attr = __ATTR(_name, S_IRUGO, xgene_pmu_format_show, NULL), \
170 .var = (void *) _config, } \
171 })[0].attr.attr)
172
173static struct attribute *l3c_pmu_format_attrs[] = {
174 XGENE_PMU_FORMAT_ATTR(l3c_eventid, "config:0-7"),
175 XGENE_PMU_FORMAT_ATTR(l3c_agentid, "config1:0-9"),
176 NULL,
177};
178
179static struct attribute *iob_pmu_format_attrs[] = {
180 XGENE_PMU_FORMAT_ATTR(iob_eventid, "config:0-7"),
181 XGENE_PMU_FORMAT_ATTR(iob_agentid, "config1:0-63"),
182 NULL,
183};
184
185static struct attribute *mcb_pmu_format_attrs[] = {
186 XGENE_PMU_FORMAT_ATTR(mcb_eventid, "config:0-5"),
187 XGENE_PMU_FORMAT_ATTR(mcb_agentid, "config1:0-9"),
188 NULL,
189};
190
191static struct attribute *mc_pmu_format_attrs[] = {
192 XGENE_PMU_FORMAT_ATTR(mc_eventid, "config:0-28"),
193 NULL,
194};
195
196static const struct attribute_group l3c_pmu_format_attr_group = {
197 .name = "format",
198 .attrs = l3c_pmu_format_attrs,
199};
200
201static const struct attribute_group iob_pmu_format_attr_group = {
202 .name = "format",
203 .attrs = iob_pmu_format_attrs,
204};
205
206static const struct attribute_group mcb_pmu_format_attr_group = {
207 .name = "format",
208 .attrs = mcb_pmu_format_attrs,
209};
210
211static const struct attribute_group mc_pmu_format_attr_group = {
212 .name = "format",
213 .attrs = mc_pmu_format_attrs,
214};
215
216/*
217 * sysfs event attributes
218 */
219static ssize_t xgene_pmu_event_show(struct device *dev,
220 struct device_attribute *attr, char *buf)
221{
222 struct dev_ext_attribute *eattr;
223
224 eattr = container_of(attr, struct dev_ext_attribute, attr);
225 return sprintf(buf, "config=0x%lx\n", (unsigned long) eattr->var);
226}
227
228#define XGENE_PMU_EVENT_ATTR(_name, _config) \
229 (&((struct dev_ext_attribute[]) { \
230 { .attr = __ATTR(_name, S_IRUGO, xgene_pmu_event_show, NULL), \
231 .var = (void *) _config, } \
232 })[0].attr.attr)
233
234static struct attribute *l3c_pmu_events_attrs[] = {
235 XGENE_PMU_EVENT_ATTR(cycle-count, 0x00),
236 XGENE_PMU_EVENT_ATTR(cycle-count-div-64, 0x01),
237 XGENE_PMU_EVENT_ATTR(read-hit, 0x02),
238 XGENE_PMU_EVENT_ATTR(read-miss, 0x03),
239 XGENE_PMU_EVENT_ATTR(write-need-replacement, 0x06),
240 XGENE_PMU_EVENT_ATTR(write-not-need-replacement, 0x07),
241 XGENE_PMU_EVENT_ATTR(tq-full, 0x08),
242 XGENE_PMU_EVENT_ATTR(ackq-full, 0x09),
243 XGENE_PMU_EVENT_ATTR(wdb-full, 0x0a),
244 XGENE_PMU_EVENT_ATTR(bank-fifo-full, 0x0b),
245 XGENE_PMU_EVENT_ATTR(odb-full, 0x0c),
246 XGENE_PMU_EVENT_ATTR(wbq-full, 0x0d),
247 XGENE_PMU_EVENT_ATTR(bank-conflict-fifo-issue, 0x0e),
248 XGENE_PMU_EVENT_ATTR(bank-fifo-issue, 0x0f),
249 NULL,
250};
251
252static struct attribute *iob_pmu_events_attrs[] = {
253 XGENE_PMU_EVENT_ATTR(cycle-count, 0x00),
254 XGENE_PMU_EVENT_ATTR(cycle-count-div-64, 0x01),
255 XGENE_PMU_EVENT_ATTR(axi0-read, 0x02),
256 XGENE_PMU_EVENT_ATTR(axi0-read-partial, 0x03),
257 XGENE_PMU_EVENT_ATTR(axi1-read, 0x04),
258 XGENE_PMU_EVENT_ATTR(axi1-read-partial, 0x05),
259 XGENE_PMU_EVENT_ATTR(csw-read-block, 0x06),
260 XGENE_PMU_EVENT_ATTR(csw-read-partial, 0x07),
261 XGENE_PMU_EVENT_ATTR(axi0-write, 0x10),
262 XGENE_PMU_EVENT_ATTR(axi0-write-partial, 0x11),
263 XGENE_PMU_EVENT_ATTR(axi1-write, 0x13),
264 XGENE_PMU_EVENT_ATTR(axi1-write-partial, 0x14),
265 XGENE_PMU_EVENT_ATTR(csw-inbound-dirty, 0x16),
266 NULL,
267};
268
269static struct attribute *mcb_pmu_events_attrs[] = {
270 XGENE_PMU_EVENT_ATTR(cycle-count, 0x00),
271 XGENE_PMU_EVENT_ATTR(cycle-count-div-64, 0x01),
272 XGENE_PMU_EVENT_ATTR(csw-read, 0x02),
273 XGENE_PMU_EVENT_ATTR(csw-write-request, 0x03),
274 XGENE_PMU_EVENT_ATTR(mcb-csw-stall, 0x04),
275 XGENE_PMU_EVENT_ATTR(cancel-read-gack, 0x05),
276 NULL,
277};
278
279static struct attribute *mc_pmu_events_attrs[] = {
280 XGENE_PMU_EVENT_ATTR(cycle-count, 0x00),
281 XGENE_PMU_EVENT_ATTR(cycle-count-div-64, 0x01),
282 XGENE_PMU_EVENT_ATTR(act-cmd-sent, 0x02),
283 XGENE_PMU_EVENT_ATTR(pre-cmd-sent, 0x03),
284 XGENE_PMU_EVENT_ATTR(rd-cmd-sent, 0x04),
285 XGENE_PMU_EVENT_ATTR(rda-cmd-sent, 0x05),
286 XGENE_PMU_EVENT_ATTR(wr-cmd-sent, 0x06),
287 XGENE_PMU_EVENT_ATTR(wra-cmd-sent, 0x07),
288 XGENE_PMU_EVENT_ATTR(pde-cmd-sent, 0x08),
289 XGENE_PMU_EVENT_ATTR(sre-cmd-sent, 0x09),
290 XGENE_PMU_EVENT_ATTR(prea-cmd-sent, 0x0a),
291 XGENE_PMU_EVENT_ATTR(ref-cmd-sent, 0x0b),
292 XGENE_PMU_EVENT_ATTR(rd-rda-cmd-sent, 0x0c),
293 XGENE_PMU_EVENT_ATTR(wr-wra-cmd-sent, 0x0d),
294 XGENE_PMU_EVENT_ATTR(in-rd-collision, 0x0e),
295 XGENE_PMU_EVENT_ATTR(in-wr-collision, 0x0f),
296 XGENE_PMU_EVENT_ATTR(collision-queue-not-empty, 0x10),
297 XGENE_PMU_EVENT_ATTR(collision-queue-full, 0x11),
298 XGENE_PMU_EVENT_ATTR(mcu-request, 0x12),
299 XGENE_PMU_EVENT_ATTR(mcu-rd-request, 0x13),
300 XGENE_PMU_EVENT_ATTR(mcu-hp-rd-request, 0x14),
301 XGENE_PMU_EVENT_ATTR(mcu-wr-request, 0x15),
302 XGENE_PMU_EVENT_ATTR(mcu-rd-proceed-all, 0x16),
303 XGENE_PMU_EVENT_ATTR(mcu-rd-proceed-cancel, 0x17),
304 XGENE_PMU_EVENT_ATTR(mcu-rd-response, 0x18),
305 XGENE_PMU_EVENT_ATTR(mcu-rd-proceed-speculative-all, 0x19),
306 XGENE_PMU_EVENT_ATTR(mcu-rd-proceed-speculative-cancel, 0x1a),
307 XGENE_PMU_EVENT_ATTR(mcu-wr-proceed-all, 0x1b),
308 XGENE_PMU_EVENT_ATTR(mcu-wr-proceed-cancel, 0x1c),
309 NULL,
310};
311
312static const struct attribute_group l3c_pmu_events_attr_group = {
313 .name = "events",
314 .attrs = l3c_pmu_events_attrs,
315};
316
317static const struct attribute_group iob_pmu_events_attr_group = {
318 .name = "events",
319 .attrs = iob_pmu_events_attrs,
320};
321
322static const struct attribute_group mcb_pmu_events_attr_group = {
323 .name = "events",
324 .attrs = mcb_pmu_events_attrs,
325};
326
327static const struct attribute_group mc_pmu_events_attr_group = {
328 .name = "events",
329 .attrs = mc_pmu_events_attrs,
330};
331
332/*
333 * sysfs cpumask attributes
334 */
335static ssize_t xgene_pmu_cpumask_show(struct device *dev,
336 struct device_attribute *attr, char *buf)
337{
338 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(dev_get_drvdata(dev));
339
340 return cpumap_print_to_pagebuf(true, buf, &pmu_dev->parent->cpu);
341}
342
343static DEVICE_ATTR(cpumask, S_IRUGO, xgene_pmu_cpumask_show, NULL);
344
345static struct attribute *xgene_pmu_cpumask_attrs[] = {
346 &dev_attr_cpumask.attr,
347 NULL,
348};
349
350static const struct attribute_group pmu_cpumask_attr_group = {
351 .attrs = xgene_pmu_cpumask_attrs,
352};
353
354/*
355 * Per PMU device attribute groups
356 */
357static const struct attribute_group *l3c_pmu_attr_groups[] = {
358 &l3c_pmu_format_attr_group,
359 &pmu_cpumask_attr_group,
360 &l3c_pmu_events_attr_group,
361 NULL
362};
363
364static const struct attribute_group *iob_pmu_attr_groups[] = {
365 &iob_pmu_format_attr_group,
366 &pmu_cpumask_attr_group,
367 &iob_pmu_events_attr_group,
368 NULL
369};
370
371static const struct attribute_group *mcb_pmu_attr_groups[] = {
372 &mcb_pmu_format_attr_group,
373 &pmu_cpumask_attr_group,
374 &mcb_pmu_events_attr_group,
375 NULL
376};
377
378static const struct attribute_group *mc_pmu_attr_groups[] = {
379 &mc_pmu_format_attr_group,
380 &pmu_cpumask_attr_group,
381 &mc_pmu_events_attr_group,
382 NULL
383};
384
385static int get_next_avail_cntr(struct xgene_pmu_dev *pmu_dev)
386{
387 int cntr;
388
389 cntr = find_first_zero_bit(pmu_dev->cntr_assign_mask,
390 pmu_dev->max_counters);
391 if (cntr == pmu_dev->max_counters)
392 return -ENOSPC;
393 set_bit(cntr, pmu_dev->cntr_assign_mask);
394
395 return cntr;
396}
397
398static void clear_avail_cntr(struct xgene_pmu_dev *pmu_dev, int cntr)
399{
400 clear_bit(cntr, pmu_dev->cntr_assign_mask);
401}
402
403static inline void xgene_pmu_mask_int(struct xgene_pmu *xgene_pmu)
404{
405 writel(PCPPMU_INTENMASK, xgene_pmu->pcppmu_csr + PCPPMU_INTMASK_REG);
406}
407
408static inline void xgene_pmu_unmask_int(struct xgene_pmu *xgene_pmu)
409{
410 writel(PCPPMU_INTCLRMASK, xgene_pmu->pcppmu_csr + PCPPMU_INTMASK_REG);
411}
412
Hoan Trane35e0a02017-06-22 19:26:04 +0100413static inline u64 xgene_pmu_read_counter32(struct xgene_pmu_dev *pmu_dev,
414 int idx)
Tai Nguyen832c9272016-07-15 10:38:04 -0700415{
416 return readl(pmu_dev->inf->csr + PMU_PMEVCNTR0 + (4 * idx));
417}
418
419static inline void
Hoan Trane35e0a02017-06-22 19:26:04 +0100420xgene_pmu_write_counter32(struct xgene_pmu_dev *pmu_dev, int idx, u64 val)
Tai Nguyen832c9272016-07-15 10:38:04 -0700421{
422 writel(val, pmu_dev->inf->csr + PMU_PMEVCNTR0 + (4 * idx));
423}
424
425static inline void
426xgene_pmu_write_evttype(struct xgene_pmu_dev *pmu_dev, int idx, u32 val)
427{
428 writel(val, pmu_dev->inf->csr + PMU_PMEVTYPER0 + (4 * idx));
429}
430
431static inline void
432xgene_pmu_write_agentmsk(struct xgene_pmu_dev *pmu_dev, u32 val)
433{
434 writel(val, pmu_dev->inf->csr + PMU_PMAMR0);
435}
436
437static inline void
438xgene_pmu_write_agent1msk(struct xgene_pmu_dev *pmu_dev, u32 val)
439{
440 writel(val, pmu_dev->inf->csr + PMU_PMAMR1);
441}
442
443static inline void
444xgene_pmu_enable_counter(struct xgene_pmu_dev *pmu_dev, int idx)
445{
446 u32 val;
447
448 val = readl(pmu_dev->inf->csr + PMU_PMCNTENSET);
449 val |= 1 << idx;
450 writel(val, pmu_dev->inf->csr + PMU_PMCNTENSET);
451}
452
453static inline void
454xgene_pmu_disable_counter(struct xgene_pmu_dev *pmu_dev, int idx)
455{
456 u32 val;
457
458 val = readl(pmu_dev->inf->csr + PMU_PMCNTENCLR);
459 val |= 1 << idx;
460 writel(val, pmu_dev->inf->csr + PMU_PMCNTENCLR);
461}
462
463static inline void
464xgene_pmu_enable_counter_int(struct xgene_pmu_dev *pmu_dev, int idx)
465{
466 u32 val;
467
468 val = readl(pmu_dev->inf->csr + PMU_PMINTENSET);
469 val |= 1 << idx;
470 writel(val, pmu_dev->inf->csr + PMU_PMINTENSET);
471}
472
473static inline void
474xgene_pmu_disable_counter_int(struct xgene_pmu_dev *pmu_dev, int idx)
475{
476 u32 val;
477
478 val = readl(pmu_dev->inf->csr + PMU_PMINTENCLR);
479 val |= 1 << idx;
480 writel(val, pmu_dev->inf->csr + PMU_PMINTENCLR);
481}
482
483static inline void xgene_pmu_reset_counters(struct xgene_pmu_dev *pmu_dev)
484{
485 u32 val;
486
487 val = readl(pmu_dev->inf->csr + PMU_PMCR);
488 val |= PMU_PMCR_P;
489 writel(val, pmu_dev->inf->csr + PMU_PMCR);
490}
491
492static inline void xgene_pmu_start_counters(struct xgene_pmu_dev *pmu_dev)
493{
494 u32 val;
495
496 val = readl(pmu_dev->inf->csr + PMU_PMCR);
497 val |= PMU_PMCR_E;
498 writel(val, pmu_dev->inf->csr + PMU_PMCR);
499}
500
501static inline void xgene_pmu_stop_counters(struct xgene_pmu_dev *pmu_dev)
502{
503 u32 val;
504
505 val = readl(pmu_dev->inf->csr + PMU_PMCR);
506 val &= ~PMU_PMCR_E;
507 writel(val, pmu_dev->inf->csr + PMU_PMCR);
508}
509
510static void xgene_perf_pmu_enable(struct pmu *pmu)
511{
512 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(pmu);
Hoan Trane35e0a02017-06-22 19:26:04 +0100513 struct xgene_pmu *xgene_pmu = pmu_dev->parent;
Tai Nguyen832c9272016-07-15 10:38:04 -0700514 int enabled = bitmap_weight(pmu_dev->cntr_assign_mask,
515 pmu_dev->max_counters);
516
517 if (!enabled)
518 return;
519
Hoan Trane35e0a02017-06-22 19:26:04 +0100520 xgene_pmu->ops->start_counters(pmu_dev);
Tai Nguyen832c9272016-07-15 10:38:04 -0700521}
522
523static void xgene_perf_pmu_disable(struct pmu *pmu)
524{
525 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(pmu);
Hoan Trane35e0a02017-06-22 19:26:04 +0100526 struct xgene_pmu *xgene_pmu = pmu_dev->parent;
Tai Nguyen832c9272016-07-15 10:38:04 -0700527
Hoan Trane35e0a02017-06-22 19:26:04 +0100528 xgene_pmu->ops->stop_counters(pmu_dev);
Tai Nguyen832c9272016-07-15 10:38:04 -0700529}
530
531static int xgene_perf_event_init(struct perf_event *event)
532{
533 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
534 struct hw_perf_event *hw = &event->hw;
535 struct perf_event *sibling;
536
537 /* Test the event attr type check for PMU enumeration */
538 if (event->attr.type != event->pmu->type)
539 return -ENOENT;
540
541 /*
542 * SOC PMU counters are shared across all cores.
543 * Therefore, it does not support per-process mode.
544 * Also, it does not support event sampling mode.
545 */
546 if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
547 return -EINVAL;
548
549 /* SOC counters do not have usr/os/guest/host bits */
550 if (event->attr.exclude_user || event->attr.exclude_kernel ||
551 event->attr.exclude_host || event->attr.exclude_guest)
552 return -EINVAL;
553
554 if (event->cpu < 0)
555 return -EINVAL;
556 /*
557 * Many perf core operations (eg. events rotation) operate on a
558 * single CPU context. This is obvious for CPU PMUs, where one
559 * expects the same sets of events being observed on all CPUs,
560 * but can lead to issues for off-core PMUs, where each
561 * event could be theoretically assigned to a different CPU. To
562 * mitigate this, we enforce CPU assignment to one, selected
563 * processor (the one described in the "cpumask" attribute).
564 */
565 event->cpu = cpumask_first(&pmu_dev->parent->cpu);
566
567 hw->config = event->attr.config;
568 /*
569 * Each bit of the config1 field represents an agent from which the
570 * request of the event come. The event is counted only if it's caused
571 * by a request of an agent has the bit cleared.
572 * By default, the event is counted for all agents.
573 */
574 hw->config_base = event->attr.config1;
575
576 /*
577 * We must NOT create groups containing mixed PMUs, although software
578 * events are acceptable
579 */
580 if (event->group_leader->pmu != event->pmu &&
581 !is_software_event(event->group_leader))
582 return -EINVAL;
583
584 list_for_each_entry(sibling, &event->group_leader->sibling_list,
585 group_entry)
586 if (sibling->pmu != event->pmu &&
587 !is_software_event(sibling))
588 return -EINVAL;
589
590 return 0;
591}
592
593static void xgene_perf_enable_event(struct perf_event *event)
594{
595 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
Hoan Trane35e0a02017-06-22 19:26:04 +0100596 struct xgene_pmu *xgene_pmu = pmu_dev->parent;
Tai Nguyen832c9272016-07-15 10:38:04 -0700597
Hoan Trane35e0a02017-06-22 19:26:04 +0100598 xgene_pmu->ops->write_evttype(pmu_dev, GET_CNTR(event),
599 GET_EVENTID(event));
600 xgene_pmu->ops->write_agentmsk(pmu_dev, ~((u32)GET_AGENTID(event)));
Tai Nguyen832c9272016-07-15 10:38:04 -0700601 if (pmu_dev->inf->type == PMU_TYPE_IOB)
Hoan Trane35e0a02017-06-22 19:26:04 +0100602 xgene_pmu->ops->write_agent1msk(pmu_dev,
603 ~((u32)GET_AGENT1ID(event)));
Tai Nguyen832c9272016-07-15 10:38:04 -0700604
Hoan Trane35e0a02017-06-22 19:26:04 +0100605 xgene_pmu->ops->enable_counter(pmu_dev, GET_CNTR(event));
606 xgene_pmu->ops->enable_counter_int(pmu_dev, GET_CNTR(event));
Tai Nguyen832c9272016-07-15 10:38:04 -0700607}
608
609static void xgene_perf_disable_event(struct perf_event *event)
610{
611 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
Hoan Trane35e0a02017-06-22 19:26:04 +0100612 struct xgene_pmu *xgene_pmu = pmu_dev->parent;
Tai Nguyen832c9272016-07-15 10:38:04 -0700613
Hoan Trane35e0a02017-06-22 19:26:04 +0100614 xgene_pmu->ops->disable_counter(pmu_dev, GET_CNTR(event));
615 xgene_pmu->ops->disable_counter_int(pmu_dev, GET_CNTR(event));
Tai Nguyen832c9272016-07-15 10:38:04 -0700616}
617
618static void xgene_perf_event_set_period(struct perf_event *event)
619{
620 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
Hoan Trane35e0a02017-06-22 19:26:04 +0100621 struct xgene_pmu *xgene_pmu = pmu_dev->parent;
Tai Nguyen832c9272016-07-15 10:38:04 -0700622 struct hw_perf_event *hw = &event->hw;
623 /*
624 * The X-Gene PMU counters have a period of 2^32. To account for the
625 * possiblity of extreme interrupt latency we program for a period of
626 * half that. Hopefully we can handle the interrupt before another 2^31
627 * events occur and the counter overtakes its previous value.
628 */
629 u64 val = 1ULL << 31;
630
631 local64_set(&hw->prev_count, val);
Hoan Trane35e0a02017-06-22 19:26:04 +0100632 xgene_pmu->ops->write_counter(pmu_dev, hw->idx, val);
Tai Nguyen832c9272016-07-15 10:38:04 -0700633}
634
635static void xgene_perf_event_update(struct perf_event *event)
636{
637 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
Hoan Trane35e0a02017-06-22 19:26:04 +0100638 struct xgene_pmu *xgene_pmu = pmu_dev->parent;
Tai Nguyen832c9272016-07-15 10:38:04 -0700639 struct hw_perf_event *hw = &event->hw;
640 u64 delta, prev_raw_count, new_raw_count;
641
642again:
643 prev_raw_count = local64_read(&hw->prev_count);
Hoan Trane35e0a02017-06-22 19:26:04 +0100644 new_raw_count = xgene_pmu->ops->read_counter(pmu_dev, GET_CNTR(event));
Tai Nguyen832c9272016-07-15 10:38:04 -0700645
646 if (local64_cmpxchg(&hw->prev_count, prev_raw_count,
647 new_raw_count) != prev_raw_count)
648 goto again;
649
650 delta = (new_raw_count - prev_raw_count) & pmu_dev->max_period;
651
652 local64_add(delta, &event->count);
653}
654
655static void xgene_perf_read(struct perf_event *event)
656{
657 xgene_perf_event_update(event);
658}
659
660static void xgene_perf_start(struct perf_event *event, int flags)
661{
662 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
Hoan Trane35e0a02017-06-22 19:26:04 +0100663 struct xgene_pmu *xgene_pmu = pmu_dev->parent;
Tai Nguyen832c9272016-07-15 10:38:04 -0700664 struct hw_perf_event *hw = &event->hw;
665
666 if (WARN_ON_ONCE(!(hw->state & PERF_HES_STOPPED)))
667 return;
668
669 WARN_ON_ONCE(!(hw->state & PERF_HES_UPTODATE));
670 hw->state = 0;
671
672 xgene_perf_event_set_period(event);
673
674 if (flags & PERF_EF_RELOAD) {
675 u64 prev_raw_count = local64_read(&hw->prev_count);
676
Hoan Trane35e0a02017-06-22 19:26:04 +0100677 xgene_pmu->ops->write_counter(pmu_dev, GET_CNTR(event),
678 prev_raw_count);
Tai Nguyen832c9272016-07-15 10:38:04 -0700679 }
680
681 xgene_perf_enable_event(event);
682 perf_event_update_userpage(event);
683}
684
685static void xgene_perf_stop(struct perf_event *event, int flags)
686{
687 struct hw_perf_event *hw = &event->hw;
688 u64 config;
689
690 if (hw->state & PERF_HES_UPTODATE)
691 return;
692
693 xgene_perf_disable_event(event);
694 WARN_ON_ONCE(hw->state & PERF_HES_STOPPED);
695 hw->state |= PERF_HES_STOPPED;
696
697 if (hw->state & PERF_HES_UPTODATE)
698 return;
699
700 config = hw->config;
701 xgene_perf_read(event);
702 hw->state |= PERF_HES_UPTODATE;
703}
704
705static int xgene_perf_add(struct perf_event *event, int flags)
706{
707 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
708 struct hw_perf_event *hw = &event->hw;
709
710 hw->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
711
712 /* Allocate an event counter */
713 hw->idx = get_next_avail_cntr(pmu_dev);
714 if (hw->idx < 0)
715 return -EAGAIN;
716
717 /* Update counter event pointer for Interrupt handler */
718 pmu_dev->pmu_counter_event[hw->idx] = event;
719
720 if (flags & PERF_EF_START)
721 xgene_perf_start(event, PERF_EF_RELOAD);
722
723 return 0;
724}
725
726static void xgene_perf_del(struct perf_event *event, int flags)
727{
728 struct xgene_pmu_dev *pmu_dev = to_pmu_dev(event->pmu);
729 struct hw_perf_event *hw = &event->hw;
730
731 xgene_perf_stop(event, PERF_EF_UPDATE);
732
733 /* clear the assigned counter */
734 clear_avail_cntr(pmu_dev, GET_CNTR(event));
735
736 perf_event_update_userpage(event);
737 pmu_dev->pmu_counter_event[hw->idx] = NULL;
738}
739
740static int xgene_init_perf(struct xgene_pmu_dev *pmu_dev, char *name)
741{
742 struct xgene_pmu *xgene_pmu;
743
744 pmu_dev->max_period = PMU_CNT_MAX_PERIOD - 1;
745 /* First version PMU supports only single event counter */
746 xgene_pmu = pmu_dev->parent;
747 if (xgene_pmu->version == PCP_PMU_V1)
748 pmu_dev->max_counters = 1;
749 else
750 pmu_dev->max_counters = PMU_MAX_COUNTERS;
751
752 /* Perf driver registration */
753 pmu_dev->pmu = (struct pmu) {
754 .attr_groups = pmu_dev->attr_groups,
755 .task_ctx_nr = perf_invalid_context,
756 .pmu_enable = xgene_perf_pmu_enable,
757 .pmu_disable = xgene_perf_pmu_disable,
758 .event_init = xgene_perf_event_init,
759 .add = xgene_perf_add,
760 .del = xgene_perf_del,
761 .start = xgene_perf_start,
762 .stop = xgene_perf_stop,
763 .read = xgene_perf_read,
764 };
765
766 /* Hardware counter init */
Hoan Trane35e0a02017-06-22 19:26:04 +0100767 xgene_pmu->ops->stop_counters(pmu_dev);
768 xgene_pmu->ops->reset_counters(pmu_dev);
Tai Nguyen832c9272016-07-15 10:38:04 -0700769
770 return perf_pmu_register(&pmu_dev->pmu, name, -1);
771}
772
773static int
774xgene_pmu_dev_add(struct xgene_pmu *xgene_pmu, struct xgene_pmu_dev_ctx *ctx)
775{
776 struct device *dev = xgene_pmu->dev;
777 struct xgene_pmu_dev *pmu;
778 int rc;
779
780 pmu = devm_kzalloc(dev, sizeof(*pmu), GFP_KERNEL);
781 if (!pmu)
782 return -ENOMEM;
783 pmu->parent = xgene_pmu;
784 pmu->inf = &ctx->inf;
785 ctx->pmu_dev = pmu;
786
787 switch (pmu->inf->type) {
788 case PMU_TYPE_L3C:
789 pmu->attr_groups = l3c_pmu_attr_groups;
790 break;
791 case PMU_TYPE_IOB:
792 pmu->attr_groups = iob_pmu_attr_groups;
793 break;
794 case PMU_TYPE_MCB:
795 if (!(xgene_pmu->mcb_active_mask & pmu->inf->enable_mask))
796 goto dev_err;
797 pmu->attr_groups = mcb_pmu_attr_groups;
798 break;
799 case PMU_TYPE_MC:
800 if (!(xgene_pmu->mc_active_mask & pmu->inf->enable_mask))
801 goto dev_err;
802 pmu->attr_groups = mc_pmu_attr_groups;
803 break;
804 default:
805 return -EINVAL;
806 }
807
808 rc = xgene_init_perf(pmu, ctx->name);
809 if (rc) {
810 dev_err(dev, "%s PMU: Failed to init perf driver\n", ctx->name);
811 goto dev_err;
812 }
813
814 dev_info(dev, "%s PMU registered\n", ctx->name);
815
816 return rc;
817
818dev_err:
819 devm_kfree(dev, pmu);
820 return -ENODEV;
821}
822
823static void _xgene_pmu_isr(int irq, struct xgene_pmu_dev *pmu_dev)
824{
825 struct xgene_pmu *xgene_pmu = pmu_dev->parent;
826 u32 pmovsr;
827 int idx;
828
829 pmovsr = readl(pmu_dev->inf->csr + PMU_PMOVSR) & PMU_OVERFLOW_MASK;
830 if (!pmovsr)
831 return;
832
833 /* Clear interrupt flag */
834 if (xgene_pmu->version == PCP_PMU_V1)
835 writel(0x0, pmu_dev->inf->csr + PMU_PMOVSR);
836 else
837 writel(pmovsr, pmu_dev->inf->csr + PMU_PMOVSR);
838
839 for (idx = 0; idx < PMU_MAX_COUNTERS; idx++) {
840 struct perf_event *event = pmu_dev->pmu_counter_event[idx];
841 int overflowed = pmovsr & BIT(idx);
842
843 /* Ignore if we don't have an event. */
844 if (!event || !overflowed)
845 continue;
846 xgene_perf_event_update(event);
847 xgene_perf_event_set_period(event);
848 }
849}
850
851static irqreturn_t xgene_pmu_isr(int irq, void *dev_id)
852{
853 struct xgene_pmu_dev_ctx *ctx;
854 struct xgene_pmu *xgene_pmu = dev_id;
855 unsigned long flags;
856 u32 val;
857
858 raw_spin_lock_irqsave(&xgene_pmu->lock, flags);
859
860 /* Get Interrupt PMU source */
861 val = readl(xgene_pmu->pcppmu_csr + PCPPMU_INTSTATUS_REG);
862 if (val & PCPPMU_INT_MCU) {
863 list_for_each_entry(ctx, &xgene_pmu->mcpmus, next) {
864 _xgene_pmu_isr(irq, ctx->pmu_dev);
865 }
866 }
867 if (val & PCPPMU_INT_MCB) {
868 list_for_each_entry(ctx, &xgene_pmu->mcbpmus, next) {
869 _xgene_pmu_isr(irq, ctx->pmu_dev);
870 }
871 }
872 if (val & PCPPMU_INT_L3C) {
873 list_for_each_entry(ctx, &xgene_pmu->l3cpmus, next) {
874 _xgene_pmu_isr(irq, ctx->pmu_dev);
875 }
876 }
877 if (val & PCPPMU_INT_IOB) {
878 list_for_each_entry(ctx, &xgene_pmu->iobpmus, next) {
879 _xgene_pmu_isr(irq, ctx->pmu_dev);
880 }
881 }
882
883 raw_spin_unlock_irqrestore(&xgene_pmu->lock, flags);
884
885 return IRQ_HANDLED;
886}
887
888static int acpi_pmu_probe_active_mcb_mcu(struct xgene_pmu *xgene_pmu,
889 struct platform_device *pdev)
890{
891 void __iomem *csw_csr, *mcba_csr, *mcbb_csr;
892 struct resource *res;
893 unsigned int reg;
894
895 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
896 csw_csr = devm_ioremap_resource(&pdev->dev, res);
897 if (IS_ERR(csw_csr)) {
898 dev_err(&pdev->dev, "ioremap failed for CSW CSR resource\n");
899 return PTR_ERR(csw_csr);
900 }
901
902 res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
903 mcba_csr = devm_ioremap_resource(&pdev->dev, res);
904 if (IS_ERR(mcba_csr)) {
905 dev_err(&pdev->dev, "ioremap failed for MCBA CSR resource\n");
906 return PTR_ERR(mcba_csr);
907 }
908
909 res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
910 mcbb_csr = devm_ioremap_resource(&pdev->dev, res);
911 if (IS_ERR(mcbb_csr)) {
912 dev_err(&pdev->dev, "ioremap failed for MCBB CSR resource\n");
913 return PTR_ERR(mcbb_csr);
914 }
915
916 reg = readl(csw_csr + CSW_CSWCR);
917 if (reg & CSW_CSWCR_DUALMCB_MASK) {
918 /* Dual MCB active */
919 xgene_pmu->mcb_active_mask = 0x3;
920 /* Probe all active MC(s) */
921 reg = readl(mcbb_csr + CSW_CSWCR);
922 xgene_pmu->mc_active_mask =
923 (reg & MCBADDRMR_DUALMCU_MODE_MASK) ? 0xF : 0x5;
924 } else {
925 /* Single MCB active */
926 xgene_pmu->mcb_active_mask = 0x1;
927 /* Probe all active MC(s) */
928 reg = readl(mcba_csr + CSW_CSWCR);
929 xgene_pmu->mc_active_mask =
930 (reg & MCBADDRMR_DUALMCU_MODE_MASK) ? 0x3 : 0x1;
931 }
932
933 return 0;
934}
935
936static int fdt_pmu_probe_active_mcb_mcu(struct xgene_pmu *xgene_pmu,
937 struct platform_device *pdev)
938{
939 struct regmap *csw_map, *mcba_map, *mcbb_map;
940 struct device_node *np = pdev->dev.of_node;
941 unsigned int reg;
942
943 csw_map = syscon_regmap_lookup_by_phandle(np, "regmap-csw");
944 if (IS_ERR(csw_map)) {
945 dev_err(&pdev->dev, "unable to get syscon regmap csw\n");
946 return PTR_ERR(csw_map);
947 }
948
949 mcba_map = syscon_regmap_lookup_by_phandle(np, "regmap-mcba");
950 if (IS_ERR(mcba_map)) {
951 dev_err(&pdev->dev, "unable to get syscon regmap mcba\n");
952 return PTR_ERR(mcba_map);
953 }
954
955 mcbb_map = syscon_regmap_lookup_by_phandle(np, "regmap-mcbb");
956 if (IS_ERR(mcbb_map)) {
957 dev_err(&pdev->dev, "unable to get syscon regmap mcbb\n");
958 return PTR_ERR(mcbb_map);
959 }
960
961 if (regmap_read(csw_map, CSW_CSWCR, &reg))
962 return -EINVAL;
963
964 if (reg & CSW_CSWCR_DUALMCB_MASK) {
965 /* Dual MCB active */
966 xgene_pmu->mcb_active_mask = 0x3;
967 /* Probe all active MC(s) */
968 if (regmap_read(mcbb_map, MCBADDRMR, &reg))
969 return 0;
970 xgene_pmu->mc_active_mask =
971 (reg & MCBADDRMR_DUALMCU_MODE_MASK) ? 0xF : 0x5;
972 } else {
973 /* Single MCB active */
974 xgene_pmu->mcb_active_mask = 0x1;
975 /* Probe all active MC(s) */
976 if (regmap_read(mcba_map, MCBADDRMR, &reg))
977 return 0;
978 xgene_pmu->mc_active_mask =
979 (reg & MCBADDRMR_DUALMCU_MODE_MASK) ? 0x3 : 0x1;
980 }
981
982 return 0;
983}
984
985static int xgene_pmu_probe_active_mcb_mcu(struct xgene_pmu *xgene_pmu,
986 struct platform_device *pdev)
987{
988 if (has_acpi_companion(&pdev->dev))
989 return acpi_pmu_probe_active_mcb_mcu(xgene_pmu, pdev);
990 return fdt_pmu_probe_active_mcb_mcu(xgene_pmu, pdev);
991}
992
993static char *xgene_pmu_dev_name(struct device *dev, u32 type, int id)
994{
995 switch (type) {
996 case PMU_TYPE_L3C:
997 return devm_kasprintf(dev, GFP_KERNEL, "l3c%d", id);
998 case PMU_TYPE_IOB:
999 return devm_kasprintf(dev, GFP_KERNEL, "iob%d", id);
1000 case PMU_TYPE_MCB:
1001 return devm_kasprintf(dev, GFP_KERNEL, "mcb%d", id);
1002 case PMU_TYPE_MC:
1003 return devm_kasprintf(dev, GFP_KERNEL, "mc%d", id);
1004 default:
1005 return devm_kasprintf(dev, GFP_KERNEL, "unknown");
1006 }
1007}
1008
1009#if defined(CONFIG_ACPI)
1010static int acpi_pmu_dev_add_resource(struct acpi_resource *ares, void *data)
1011{
1012 struct resource *res = data;
1013
1014 if (ares->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32)
1015 acpi_dev_resource_memory(ares, res);
1016
1017 /* Always tell the ACPI core to skip this resource */
1018 return 1;
1019}
1020
1021static struct
1022xgene_pmu_dev_ctx *acpi_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
1023 struct acpi_device *adev, u32 type)
1024{
1025 struct device *dev = xgene_pmu->dev;
1026 struct list_head resource_list;
1027 struct xgene_pmu_dev_ctx *ctx;
1028 const union acpi_object *obj;
1029 struct hw_pmu_info *inf;
1030 void __iomem *dev_csr;
1031 struct resource res;
1032 int enable_bit;
1033 int rc;
1034
1035 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1036 if (!ctx)
1037 return NULL;
1038
1039 INIT_LIST_HEAD(&resource_list);
1040 rc = acpi_dev_get_resources(adev, &resource_list,
1041 acpi_pmu_dev_add_resource, &res);
1042 acpi_dev_free_resource_list(&resource_list);
Tai Nguyen9a1a1f42016-10-13 11:09:16 -07001043 if (rc < 0) {
Tai Nguyen832c9272016-07-15 10:38:04 -07001044 dev_err(dev, "PMU type %d: No resource address found\n", type);
1045 goto err;
1046 }
1047
1048 dev_csr = devm_ioremap_resource(dev, &res);
1049 if (IS_ERR(dev_csr)) {
1050 dev_err(dev, "PMU type %d: Fail to map resource\n", type);
1051 goto err;
1052 }
1053
1054 /* A PMU device node without enable-bit-index is always enabled */
1055 rc = acpi_dev_get_property(adev, "enable-bit-index",
1056 ACPI_TYPE_INTEGER, &obj);
1057 if (rc < 0)
1058 enable_bit = 0;
1059 else
1060 enable_bit = (int) obj->integer.value;
1061
1062 ctx->name = xgene_pmu_dev_name(dev, type, enable_bit);
1063 if (!ctx->name) {
1064 dev_err(dev, "PMU type %d: Fail to get device name\n", type);
1065 goto err;
1066 }
1067 inf = &ctx->inf;
1068 inf->type = type;
1069 inf->csr = dev_csr;
1070 inf->enable_mask = 1 << enable_bit;
1071
1072 return ctx;
1073err:
1074 devm_kfree(dev, ctx);
1075 return NULL;
1076}
1077
Hoan Tran838955e2017-06-22 19:26:03 +01001078static const struct acpi_device_id xgene_pmu_acpi_type_match[] = {
1079 {"APMC0D5D", PMU_TYPE_L3C},
1080 {"APMC0D5E", PMU_TYPE_IOB},
1081 {"APMC0D5F", PMU_TYPE_MCB},
1082 {"APMC0D60", PMU_TYPE_MC},
1083 {},
1084};
1085
1086static const struct acpi_device_id *xgene_pmu_acpi_match_type(
1087 const struct acpi_device_id *ids,
1088 struct acpi_device *adev)
1089{
1090 const struct acpi_device_id *match_id = NULL;
1091 const struct acpi_device_id *id;
1092
1093 for (id = ids; id->id[0] || id->cls; id++) {
1094 if (!acpi_match_device_ids(adev, id))
1095 match_id = id;
1096 else if (match_id)
1097 break;
1098 }
1099
1100 return match_id;
1101}
1102
Tai Nguyen832c9272016-07-15 10:38:04 -07001103static acpi_status acpi_pmu_dev_add(acpi_handle handle, u32 level,
1104 void *data, void **return_value)
1105{
Hoan Tran838955e2017-06-22 19:26:03 +01001106 const struct acpi_device_id *acpi_id;
Tai Nguyen832c9272016-07-15 10:38:04 -07001107 struct xgene_pmu *xgene_pmu = data;
1108 struct xgene_pmu_dev_ctx *ctx;
1109 struct acpi_device *adev;
1110
1111 if (acpi_bus_get_device(handle, &adev))
1112 return AE_OK;
1113 if (acpi_bus_get_status(adev) || !adev->status.present)
1114 return AE_OK;
1115
Hoan Tran838955e2017-06-22 19:26:03 +01001116 acpi_id = xgene_pmu_acpi_match_type(xgene_pmu_acpi_type_match, adev);
1117 if (!acpi_id)
1118 return AE_OK;
Tai Nguyen832c9272016-07-15 10:38:04 -07001119
Hoan Tran838955e2017-06-22 19:26:03 +01001120 ctx = acpi_get_pmu_hw_inf(xgene_pmu, adev, (u32)acpi_id->driver_data);
Tai Nguyen832c9272016-07-15 10:38:04 -07001121 if (!ctx)
1122 return AE_OK;
1123
1124 if (xgene_pmu_dev_add(xgene_pmu, ctx)) {
1125 /* Can't add the PMU device, skip it */
1126 devm_kfree(xgene_pmu->dev, ctx);
1127 return AE_OK;
1128 }
1129
1130 switch (ctx->inf.type) {
1131 case PMU_TYPE_L3C:
1132 list_add(&ctx->next, &xgene_pmu->l3cpmus);
1133 break;
1134 case PMU_TYPE_IOB:
1135 list_add(&ctx->next, &xgene_pmu->iobpmus);
1136 break;
1137 case PMU_TYPE_MCB:
1138 list_add(&ctx->next, &xgene_pmu->mcbpmus);
1139 break;
1140 case PMU_TYPE_MC:
1141 list_add(&ctx->next, &xgene_pmu->mcpmus);
1142 break;
1143 }
1144 return AE_OK;
1145}
1146
1147static int acpi_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
1148 struct platform_device *pdev)
1149{
1150 struct device *dev = xgene_pmu->dev;
1151 acpi_handle handle;
1152 acpi_status status;
1153
1154 handle = ACPI_HANDLE(dev);
1155 if (!handle)
1156 return -EINVAL;
1157
1158 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
1159 acpi_pmu_dev_add, NULL, xgene_pmu, NULL);
1160 if (ACPI_FAILURE(status)) {
1161 dev_err(dev, "failed to probe PMU devices\n");
1162 return -ENODEV;
1163 }
1164
1165 return 0;
1166}
1167#else
1168static int acpi_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
1169 struct platform_device *pdev)
1170{
1171 return 0;
1172}
1173#endif
1174
1175static struct
1176xgene_pmu_dev_ctx *fdt_get_pmu_hw_inf(struct xgene_pmu *xgene_pmu,
1177 struct device_node *np, u32 type)
1178{
1179 struct device *dev = xgene_pmu->dev;
1180 struct xgene_pmu_dev_ctx *ctx;
1181 struct hw_pmu_info *inf;
1182 void __iomem *dev_csr;
1183 struct resource res;
1184 int enable_bit;
1185 int rc;
1186
1187 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
1188 if (!ctx)
1189 return NULL;
1190 rc = of_address_to_resource(np, 0, &res);
1191 if (rc < 0) {
1192 dev_err(dev, "PMU type %d: No resource address found\n", type);
1193 goto err;
1194 }
1195 dev_csr = devm_ioremap_resource(dev, &res);
1196 if (IS_ERR(dev_csr)) {
1197 dev_err(dev, "PMU type %d: Fail to map resource\n", type);
1198 goto err;
1199 }
1200
1201 /* A PMU device node without enable-bit-index is always enabled */
1202 if (of_property_read_u32(np, "enable-bit-index", &enable_bit))
1203 enable_bit = 0;
1204
1205 ctx->name = xgene_pmu_dev_name(dev, type, enable_bit);
1206 if (!ctx->name) {
1207 dev_err(dev, "PMU type %d: Fail to get device name\n", type);
1208 goto err;
1209 }
1210 inf = &ctx->inf;
1211 inf->type = type;
1212 inf->csr = dev_csr;
1213 inf->enable_mask = 1 << enable_bit;
1214
1215 return ctx;
1216err:
1217 devm_kfree(dev, ctx);
1218 return NULL;
1219}
1220
1221static int fdt_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
1222 struct platform_device *pdev)
1223{
1224 struct xgene_pmu_dev_ctx *ctx;
1225 struct device_node *np;
1226
1227 for_each_child_of_node(pdev->dev.of_node, np) {
1228 if (!of_device_is_available(np))
1229 continue;
1230
1231 if (of_device_is_compatible(np, "apm,xgene-pmu-l3c"))
1232 ctx = fdt_get_pmu_hw_inf(xgene_pmu, np, PMU_TYPE_L3C);
1233 else if (of_device_is_compatible(np, "apm,xgene-pmu-iob"))
1234 ctx = fdt_get_pmu_hw_inf(xgene_pmu, np, PMU_TYPE_IOB);
1235 else if (of_device_is_compatible(np, "apm,xgene-pmu-mcb"))
1236 ctx = fdt_get_pmu_hw_inf(xgene_pmu, np, PMU_TYPE_MCB);
1237 else if (of_device_is_compatible(np, "apm,xgene-pmu-mc"))
1238 ctx = fdt_get_pmu_hw_inf(xgene_pmu, np, PMU_TYPE_MC);
1239 else
1240 ctx = NULL;
1241
1242 if (!ctx)
1243 continue;
1244
1245 if (xgene_pmu_dev_add(xgene_pmu, ctx)) {
1246 /* Can't add the PMU device, skip it */
1247 devm_kfree(xgene_pmu->dev, ctx);
1248 continue;
1249 }
1250
1251 switch (ctx->inf.type) {
1252 case PMU_TYPE_L3C:
1253 list_add(&ctx->next, &xgene_pmu->l3cpmus);
1254 break;
1255 case PMU_TYPE_IOB:
1256 list_add(&ctx->next, &xgene_pmu->iobpmus);
1257 break;
1258 case PMU_TYPE_MCB:
1259 list_add(&ctx->next, &xgene_pmu->mcbpmus);
1260 break;
1261 case PMU_TYPE_MC:
1262 list_add(&ctx->next, &xgene_pmu->mcpmus);
1263 break;
1264 }
1265 }
1266
1267 return 0;
1268}
1269
1270static int xgene_pmu_probe_pmu_dev(struct xgene_pmu *xgene_pmu,
1271 struct platform_device *pdev)
1272{
1273 if (has_acpi_companion(&pdev->dev))
1274 return acpi_pmu_probe_pmu_dev(xgene_pmu, pdev);
1275 return fdt_pmu_probe_pmu_dev(xgene_pmu, pdev);
1276}
1277
1278static const struct xgene_pmu_data xgene_pmu_data = {
1279 .id = PCP_PMU_V1,
1280};
1281
1282static const struct xgene_pmu_data xgene_pmu_v2_data = {
1283 .id = PCP_PMU_V2,
1284};
1285
Hoan Trane35e0a02017-06-22 19:26:04 +01001286static const struct xgene_pmu_ops xgene_pmu_ops = {
1287 .mask_int = xgene_pmu_mask_int,
1288 .unmask_int = xgene_pmu_unmask_int,
1289 .read_counter = xgene_pmu_read_counter32,
1290 .write_counter = xgene_pmu_write_counter32,
1291 .write_evttype = xgene_pmu_write_evttype,
1292 .write_agentmsk = xgene_pmu_write_agentmsk,
1293 .write_agent1msk = xgene_pmu_write_agent1msk,
1294 .enable_counter = xgene_pmu_enable_counter,
1295 .disable_counter = xgene_pmu_disable_counter,
1296 .enable_counter_int = xgene_pmu_enable_counter_int,
1297 .disable_counter_int = xgene_pmu_disable_counter_int,
1298 .reset_counters = xgene_pmu_reset_counters,
1299 .start_counters = xgene_pmu_start_counters,
1300 .stop_counters = xgene_pmu_stop_counters,
1301};
1302
Tai Nguyen832c9272016-07-15 10:38:04 -07001303static const struct of_device_id xgene_pmu_of_match[] = {
1304 { .compatible = "apm,xgene-pmu", .data = &xgene_pmu_data },
1305 { .compatible = "apm,xgene-pmu-v2", .data = &xgene_pmu_v2_data },
1306 {},
1307};
1308MODULE_DEVICE_TABLE(of, xgene_pmu_of_match);
1309#ifdef CONFIG_ACPI
1310static const struct acpi_device_id xgene_pmu_acpi_match[] = {
1311 {"APMC0D5B", PCP_PMU_V1},
1312 {"APMC0D5C", PCP_PMU_V2},
1313 {},
1314};
1315MODULE_DEVICE_TABLE(acpi, xgene_pmu_acpi_match);
1316#endif
1317
1318static int xgene_pmu_probe(struct platform_device *pdev)
1319{
1320 const struct xgene_pmu_data *dev_data;
1321 const struct of_device_id *of_id;
1322 struct xgene_pmu *xgene_pmu;
1323 struct resource *res;
1324 int irq, rc;
1325 int version;
1326
1327 xgene_pmu = devm_kzalloc(&pdev->dev, sizeof(*xgene_pmu), GFP_KERNEL);
1328 if (!xgene_pmu)
1329 return -ENOMEM;
1330 xgene_pmu->dev = &pdev->dev;
1331 platform_set_drvdata(pdev, xgene_pmu);
1332
1333 version = -EINVAL;
1334 of_id = of_match_device(xgene_pmu_of_match, &pdev->dev);
1335 if (of_id) {
1336 dev_data = (const struct xgene_pmu_data *) of_id->data;
1337 version = dev_data->id;
1338 }
1339
1340#ifdef CONFIG_ACPI
1341 if (ACPI_COMPANION(&pdev->dev)) {
1342 const struct acpi_device_id *acpi_id;
1343
1344 acpi_id = acpi_match_device(xgene_pmu_acpi_match, &pdev->dev);
1345 if (acpi_id)
1346 version = (int) acpi_id->driver_data;
1347 }
1348#endif
1349 if (version < 0)
1350 return -ENODEV;
1351
Hoan Trane35e0a02017-06-22 19:26:04 +01001352 xgene_pmu->ops = &xgene_pmu_ops;
1353
Tai Nguyen832c9272016-07-15 10:38:04 -07001354 INIT_LIST_HEAD(&xgene_pmu->l3cpmus);
1355 INIT_LIST_HEAD(&xgene_pmu->iobpmus);
1356 INIT_LIST_HEAD(&xgene_pmu->mcbpmus);
1357 INIT_LIST_HEAD(&xgene_pmu->mcpmus);
1358
1359 xgene_pmu->version = version;
1360 dev_info(&pdev->dev, "X-Gene PMU version %d\n", xgene_pmu->version);
1361
1362 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1363 xgene_pmu->pcppmu_csr = devm_ioremap_resource(&pdev->dev, res);
1364 if (IS_ERR(xgene_pmu->pcppmu_csr)) {
1365 dev_err(&pdev->dev, "ioremap failed for PCP PMU resource\n");
1366 rc = PTR_ERR(xgene_pmu->pcppmu_csr);
1367 goto err;
1368 }
1369
1370 irq = platform_get_irq(pdev, 0);
1371 if (irq < 0) {
1372 dev_err(&pdev->dev, "No IRQ resource\n");
1373 rc = -EINVAL;
1374 goto err;
1375 }
1376 rc = devm_request_irq(&pdev->dev, irq, xgene_pmu_isr,
1377 IRQF_NOBALANCING | IRQF_NO_THREAD,
1378 dev_name(&pdev->dev), xgene_pmu);
1379 if (rc) {
1380 dev_err(&pdev->dev, "Could not request IRQ %d\n", irq);
1381 goto err;
1382 }
1383
1384 raw_spin_lock_init(&xgene_pmu->lock);
1385
1386 /* Check for active MCBs and MCUs */
1387 rc = xgene_pmu_probe_active_mcb_mcu(xgene_pmu, pdev);
1388 if (rc) {
1389 dev_warn(&pdev->dev, "Unknown MCB/MCU active status\n");
1390 xgene_pmu->mcb_active_mask = 0x1;
1391 xgene_pmu->mc_active_mask = 0x1;
1392 }
1393
1394 /* Pick one core to use for cpumask attributes */
1395 cpumask_set_cpu(smp_processor_id(), &xgene_pmu->cpu);
1396
1397 /* Make sure that the overflow interrupt is handled by this CPU */
1398 rc = irq_set_affinity(irq, &xgene_pmu->cpu);
1399 if (rc) {
1400 dev_err(&pdev->dev, "Failed to set interrupt affinity!\n");
1401 goto err;
1402 }
1403
1404 /* Walk through the tree for all PMU perf devices */
1405 rc = xgene_pmu_probe_pmu_dev(xgene_pmu, pdev);
1406 if (rc) {
1407 dev_err(&pdev->dev, "No PMU perf devices found!\n");
1408 goto err;
1409 }
1410
1411 /* Enable interrupt */
Hoan Trane35e0a02017-06-22 19:26:04 +01001412 xgene_pmu->ops->unmask_int(xgene_pmu);
Tai Nguyen832c9272016-07-15 10:38:04 -07001413
1414 return 0;
1415
1416err:
1417 if (xgene_pmu->pcppmu_csr)
1418 devm_iounmap(&pdev->dev, xgene_pmu->pcppmu_csr);
1419 devm_kfree(&pdev->dev, xgene_pmu);
1420
1421 return rc;
1422}
1423
1424static void
1425xgene_pmu_dev_cleanup(struct xgene_pmu *xgene_pmu, struct list_head *pmus)
1426{
1427 struct xgene_pmu_dev_ctx *ctx;
1428 struct device *dev = xgene_pmu->dev;
1429 struct xgene_pmu_dev *pmu_dev;
1430
1431 list_for_each_entry(ctx, pmus, next) {
1432 pmu_dev = ctx->pmu_dev;
1433 if (pmu_dev->inf->csr)
1434 devm_iounmap(dev, pmu_dev->inf->csr);
1435 devm_kfree(dev, ctx);
1436 devm_kfree(dev, pmu_dev);
1437 }
1438}
1439
1440static int xgene_pmu_remove(struct platform_device *pdev)
1441{
1442 struct xgene_pmu *xgene_pmu = dev_get_drvdata(&pdev->dev);
1443
1444 xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->l3cpmus);
1445 xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->iobpmus);
1446 xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcbpmus);
1447 xgene_pmu_dev_cleanup(xgene_pmu, &xgene_pmu->mcpmus);
1448
1449 if (xgene_pmu->pcppmu_csr)
1450 devm_iounmap(&pdev->dev, xgene_pmu->pcppmu_csr);
1451 devm_kfree(&pdev->dev, xgene_pmu);
1452
1453 return 0;
1454}
1455
1456static struct platform_driver xgene_pmu_driver = {
1457 .probe = xgene_pmu_probe,
1458 .remove = xgene_pmu_remove,
1459 .driver = {
1460 .name = "xgene-pmu",
1461 .of_match_table = xgene_pmu_of_match,
1462 .acpi_match_table = ACPI_PTR(xgene_pmu_acpi_match),
1463 },
1464};
1465
1466builtin_platform_driver(xgene_pmu_driver);