376c972f5f372377b7672928763c2a35e2ebbde8
[sfrench/cifs-2.6.git] / arch / csky / kernel / perf_event.c
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3
4 #include <linux/errno.h>
5 #include <linux/interrupt.h>
6 #include <linux/module.h>
7 #include <linux/of.h>
8 #include <linux/perf_event.h>
9 #include <linux/platform_device.h>
10
11 #define CSKY_PMU_MAX_EVENTS 32
12
13 #define HPCR            "<0, 0x0>"      /* PMU Control reg */
14 #define HPCNTENR        "<0, 0x4>"      /* Count Enable reg */
15
16 static uint64_t (*hw_raw_read_mapping[CSKY_PMU_MAX_EVENTS])(void);
17 static void (*hw_raw_write_mapping[CSKY_PMU_MAX_EVENTS])(uint64_t val);
18
19 struct csky_pmu_t {
20         struct pmu      pmu;
21         uint32_t        hpcr;
22 } csky_pmu;
23
24 #define cprgr(reg)                              \
25 ({                                              \
26         unsigned int tmp;                       \
27         asm volatile("cprgr %0, "reg"\n"        \
28                      : "=r"(tmp)                \
29                      :                          \
30                      : "memory");               \
31         tmp;                                    \
32 })
33
34 #define cpwgr(reg, val)         \
35 ({                              \
36         asm volatile(           \
37         "cpwgr %0, "reg"\n"     \
38         :                       \
39         : "r"(val)              \
40         : "memory");            \
41 })
42
43 #define cprcr(reg)                              \
44 ({                                              \
45         unsigned int tmp;                       \
46         asm volatile("cprcr %0, "reg"\n"        \
47                      : "=r"(tmp)                \
48                      :                          \
49                      : "memory");               \
50         tmp;                                    \
51 })
52
53 #define cpwcr(reg, val)         \
54 ({                              \
55         asm volatile(           \
56         "cpwcr %0, "reg"\n"     \
57         :                       \
58         : "r"(val)              \
59         : "memory");            \
60 })
61
62 /* cycle counter */
63 static uint64_t csky_pmu_read_cc(void)
64 {
65         uint32_t lo, hi, tmp;
66         uint64_t result;
67
68         do {
69                 tmp = cprgr("<0, 0x3>");
70                 lo  = cprgr("<0, 0x2>");
71                 hi  = cprgr("<0, 0x3>");
72         } while (hi != tmp);
73
74         result = (uint64_t) (hi) << 32;
75         result |= lo;
76
77         return result;
78 }
79
80 static void csky_pmu_write_cc(uint64_t val)
81 {
82         cpwgr("<0, 0x2>", (uint32_t)  val);
83         cpwgr("<0, 0x3>", (uint32_t) (val >> 32));
84 }
85
86 /* instruction counter */
87 static uint64_t csky_pmu_read_ic(void)
88 {
89         uint32_t lo, hi, tmp;
90         uint64_t result;
91
92         do {
93                 tmp = cprgr("<0, 0x5>");
94                 lo  = cprgr("<0, 0x4>");
95                 hi  = cprgr("<0, 0x5>");
96         } while (hi != tmp);
97
98         result = (uint64_t) (hi) << 32;
99         result |= lo;
100
101         return result;
102 }
103
104 static void csky_pmu_write_ic(uint64_t val)
105 {
106         cpwgr("<0, 0x4>", (uint32_t)  val);
107         cpwgr("<0, 0x5>", (uint32_t) (val >> 32));
108 }
109
110 /* l1 icache access counter */
111 static uint64_t csky_pmu_read_icac(void)
112 {
113         uint32_t lo, hi, tmp;
114         uint64_t result;
115
116         do {
117                 tmp = cprgr("<0, 0x7>");
118                 lo  = cprgr("<0, 0x6>");
119                 hi  = cprgr("<0, 0x7>");
120         } while (hi != tmp);
121
122         result = (uint64_t) (hi) << 32;
123         result |= lo;
124
125         return result;
126 }
127
128 static void csky_pmu_write_icac(uint64_t val)
129 {
130         cpwgr("<0, 0x6>", (uint32_t)  val);
131         cpwgr("<0, 0x7>", (uint32_t) (val >> 32));
132 }
133
134 /* l1 icache miss counter */
135 static uint64_t csky_pmu_read_icmc(void)
136 {
137         uint32_t lo, hi, tmp;
138         uint64_t result;
139
140         do {
141                 tmp = cprgr("<0, 0x9>");
142                 lo  = cprgr("<0, 0x8>");
143                 hi  = cprgr("<0, 0x9>");
144         } while (hi != tmp);
145
146         result = (uint64_t) (hi) << 32;
147         result |= lo;
148
149         return result;
150 }
151
152 static void csky_pmu_write_icmc(uint64_t val)
153 {
154         cpwgr("<0, 0x8>", (uint32_t)  val);
155         cpwgr("<0, 0x9>", (uint32_t) (val >> 32));
156 }
157
158 /* l1 dcache access counter */
159 static uint64_t csky_pmu_read_dcac(void)
160 {
161         uint32_t lo, hi, tmp;
162         uint64_t result;
163
164         do {
165                 tmp = cprgr("<0, 0xb>");
166                 lo  = cprgr("<0, 0xa>");
167                 hi  = cprgr("<0, 0xb>");
168         } while (hi != tmp);
169
170         result = (uint64_t) (hi) << 32;
171         result |= lo;
172
173         return result;
174 }
175
176 static void csky_pmu_write_dcac(uint64_t val)
177 {
178         cpwgr("<0, 0xa>", (uint32_t)  val);
179         cpwgr("<0, 0xb>", (uint32_t) (val >> 32));
180 }
181
182 /* l1 dcache miss counter */
183 static uint64_t csky_pmu_read_dcmc(void)
184 {
185         uint32_t lo, hi, tmp;
186         uint64_t result;
187
188         do {
189                 tmp = cprgr("<0, 0xd>");
190                 lo  = cprgr("<0, 0xc>");
191                 hi  = cprgr("<0, 0xd>");
192         } while (hi != tmp);
193
194         result = (uint64_t) (hi) << 32;
195         result |= lo;
196
197         return result;
198 }
199
200 static void csky_pmu_write_dcmc(uint64_t val)
201 {
202         cpwgr("<0, 0xc>", (uint32_t)  val);
203         cpwgr("<0, 0xd>", (uint32_t) (val >> 32));
204 }
205
206 /* l2 cache access counter */
207 static uint64_t csky_pmu_read_l2ac(void)
208 {
209         uint32_t lo, hi, tmp;
210         uint64_t result;
211
212         do {
213                 tmp = cprgr("<0, 0xf>");
214                 lo  = cprgr("<0, 0xe>");
215                 hi  = cprgr("<0, 0xf>");
216         } while (hi != tmp);
217
218         result = (uint64_t) (hi) << 32;
219         result |= lo;
220
221         return result;
222 }
223
224 static void csky_pmu_write_l2ac(uint64_t val)
225 {
226         cpwgr("<0, 0xe>", (uint32_t)  val);
227         cpwgr("<0, 0xf>", (uint32_t) (val >> 32));
228 }
229
230 /* l2 cache miss counter */
231 static uint64_t csky_pmu_read_l2mc(void)
232 {
233         uint32_t lo, hi, tmp;
234         uint64_t result;
235
236         do {
237                 tmp = cprgr("<0, 0x11>");
238                 lo  = cprgr("<0, 0x10>");
239                 hi  = cprgr("<0, 0x11>");
240         } while (hi != tmp);
241
242         result = (uint64_t) (hi) << 32;
243         result |= lo;
244
245         return result;
246 }
247
248 static void csky_pmu_write_l2mc(uint64_t val)
249 {
250         cpwgr("<0, 0x10>", (uint32_t)  val);
251         cpwgr("<0, 0x11>", (uint32_t) (val >> 32));
252 }
253
254 /* I-UTLB miss counter */
255 static uint64_t csky_pmu_read_iutlbmc(void)
256 {
257         uint32_t lo, hi, tmp;
258         uint64_t result;
259
260         do {
261                 tmp = cprgr("<0, 0x15>");
262                 lo  = cprgr("<0, 0x14>");
263                 hi  = cprgr("<0, 0x15>");
264         } while (hi != tmp);
265
266         result = (uint64_t) (hi) << 32;
267         result |= lo;
268
269         return result;
270 }
271
272 static void csky_pmu_write_iutlbmc(uint64_t val)
273 {
274         cpwgr("<0, 0x14>", (uint32_t)  val);
275         cpwgr("<0, 0x15>", (uint32_t) (val >> 32));
276 }
277
278 /* D-UTLB miss counter */
279 static uint64_t csky_pmu_read_dutlbmc(void)
280 {
281         uint32_t lo, hi, tmp;
282         uint64_t result;
283
284         do {
285                 tmp = cprgr("<0, 0x17>");
286                 lo  = cprgr("<0, 0x16>");
287                 hi  = cprgr("<0, 0x17>");
288         } while (hi != tmp);
289
290         result = (uint64_t) (hi) << 32;
291         result |= lo;
292
293         return result;
294 }
295
296 static void csky_pmu_write_dutlbmc(uint64_t val)
297 {
298         cpwgr("<0, 0x16>", (uint32_t)  val);
299         cpwgr("<0, 0x17>", (uint32_t) (val >> 32));
300 }
301
302 /* JTLB miss counter */
303 static uint64_t csky_pmu_read_jtlbmc(void)
304 {
305         uint32_t lo, hi, tmp;
306         uint64_t result;
307
308         do {
309                 tmp = cprgr("<0, 0x19>");
310                 lo  = cprgr("<0, 0x18>");
311                 hi  = cprgr("<0, 0x19>");
312         } while (hi != tmp);
313
314         result = (uint64_t) (hi) << 32;
315         result |= lo;
316
317         return result;
318 }
319
320 static void csky_pmu_write_jtlbmc(uint64_t val)
321 {
322         cpwgr("<0, 0x18>", (uint32_t)  val);
323         cpwgr("<0, 0x19>", (uint32_t) (val >> 32));
324 }
325
326 /* software counter */
327 static uint64_t csky_pmu_read_softc(void)
328 {
329         uint32_t lo, hi, tmp;
330         uint64_t result;
331
332         do {
333                 tmp = cprgr("<0, 0x1b>");
334                 lo  = cprgr("<0, 0x1a>");
335                 hi  = cprgr("<0, 0x1b>");
336         } while (hi != tmp);
337
338         result = (uint64_t) (hi) << 32;
339         result |= lo;
340
341         return result;
342 }
343
344 static void csky_pmu_write_softc(uint64_t val)
345 {
346         cpwgr("<0, 0x1a>", (uint32_t)  val);
347         cpwgr("<0, 0x1b>", (uint32_t) (val >> 32));
348 }
349
350 /* conditional branch mispredict counter */
351 static uint64_t csky_pmu_read_cbmc(void)
352 {
353         uint32_t lo, hi, tmp;
354         uint64_t result;
355
356         do {
357                 tmp = cprgr("<0, 0x1d>");
358                 lo  = cprgr("<0, 0x1c>");
359                 hi  = cprgr("<0, 0x1d>");
360         } while (hi != tmp);
361
362         result = (uint64_t) (hi) << 32;
363         result |= lo;
364
365         return result;
366 }
367
368 static void csky_pmu_write_cbmc(uint64_t val)
369 {
370         cpwgr("<0, 0x1c>", (uint32_t)  val);
371         cpwgr("<0, 0x1d>", (uint32_t) (val >> 32));
372 }
373
374 /* conditional branch instruction counter */
375 static uint64_t csky_pmu_read_cbic(void)
376 {
377         uint32_t lo, hi, tmp;
378         uint64_t result;
379
380         do {
381                 tmp = cprgr("<0, 0x1f>");
382                 lo  = cprgr("<0, 0x1e>");
383                 hi  = cprgr("<0, 0x1f>");
384         } while (hi != tmp);
385
386         result = (uint64_t) (hi) << 32;
387         result |= lo;
388
389         return result;
390 }
391
392 static void csky_pmu_write_cbic(uint64_t val)
393 {
394         cpwgr("<0, 0x1e>", (uint32_t)  val);
395         cpwgr("<0, 0x1f>", (uint32_t) (val >> 32));
396 }
397
398 /* indirect branch mispredict counter */
399 static uint64_t csky_pmu_read_ibmc(void)
400 {
401         uint32_t lo, hi, tmp;
402         uint64_t result;
403
404         do {
405                 tmp = cprgr("<0, 0x21>");
406                 lo  = cprgr("<0, 0x20>");
407                 hi  = cprgr("<0, 0x21>");
408         } while (hi != tmp);
409
410         result = (uint64_t) (hi) << 32;
411         result |= lo;
412
413         return result;
414 }
415
416 static void csky_pmu_write_ibmc(uint64_t val)
417 {
418         cpwgr("<0, 0x20>", (uint32_t)  val);
419         cpwgr("<0, 0x21>", (uint32_t) (val >> 32));
420 }
421
422 /* indirect branch instruction counter */
423 static uint64_t csky_pmu_read_ibic(void)
424 {
425         uint32_t lo, hi, tmp;
426         uint64_t result;
427
428         do {
429                 tmp = cprgr("<0, 0x23>");
430                 lo  = cprgr("<0, 0x22>");
431                 hi  = cprgr("<0, 0x23>");
432         } while (hi != tmp);
433
434         result = (uint64_t) (hi) << 32;
435         result |= lo;
436
437         return result;
438 }
439
440 static void csky_pmu_write_ibic(uint64_t val)
441 {
442         cpwgr("<0, 0x22>", (uint32_t)  val);
443         cpwgr("<0, 0x23>", (uint32_t) (val >> 32));
444 }
445
446 /* LSU spec fail counter */
447 static uint64_t csky_pmu_read_lsfc(void)
448 {
449         uint32_t lo, hi, tmp;
450         uint64_t result;
451
452         do {
453                 tmp = cprgr("<0, 0x25>");
454                 lo  = cprgr("<0, 0x24>");
455                 hi  = cprgr("<0, 0x25>");
456         } while (hi != tmp);
457
458         result = (uint64_t) (hi) << 32;
459         result |= lo;
460
461         return result;
462 }
463
464 static void csky_pmu_write_lsfc(uint64_t val)
465 {
466         cpwgr("<0, 0x24>", (uint32_t)  val);
467         cpwgr("<0, 0x25>", (uint32_t) (val >> 32));
468 }
469
470 /* store instruction counter */
471 static uint64_t csky_pmu_read_sic(void)
472 {
473         uint32_t lo, hi, tmp;
474         uint64_t result;
475
476         do {
477                 tmp = cprgr("<0, 0x27>");
478                 lo  = cprgr("<0, 0x26>");
479                 hi  = cprgr("<0, 0x27>");
480         } while (hi != tmp);
481
482         result = (uint64_t) (hi) << 32;
483         result |= lo;
484
485         return result;
486 }
487
488 static void csky_pmu_write_sic(uint64_t val)
489 {
490         cpwgr("<0, 0x26>", (uint32_t)  val);
491         cpwgr("<0, 0x27>", (uint32_t) (val >> 32));
492 }
493
494 /* dcache read access counter */
495 static uint64_t csky_pmu_read_dcrac(void)
496 {
497         uint32_t lo, hi, tmp;
498         uint64_t result;
499
500         do {
501                 tmp = cprgr("<0, 0x29>");
502                 lo  = cprgr("<0, 0x28>");
503                 hi  = cprgr("<0, 0x29>");
504         } while (hi != tmp);
505
506         result = (uint64_t) (hi) << 32;
507         result |= lo;
508
509         return result;
510 }
511
512 static void csky_pmu_write_dcrac(uint64_t val)
513 {
514         cpwgr("<0, 0x28>", (uint32_t)  val);
515         cpwgr("<0, 0x29>", (uint32_t) (val >> 32));
516 }
517
518 /* dcache read miss counter */
519 static uint64_t csky_pmu_read_dcrmc(void)
520 {
521         uint32_t lo, hi, tmp;
522         uint64_t result;
523
524         do {
525                 tmp = cprgr("<0, 0x2b>");
526                 lo  = cprgr("<0, 0x2a>");
527                 hi  = cprgr("<0, 0x2b>");
528         } while (hi != tmp);
529
530         result = (uint64_t) (hi) << 32;
531         result |= lo;
532
533         return result;
534 }
535
536 static void csky_pmu_write_dcrmc(uint64_t val)
537 {
538         cpwgr("<0, 0x2a>", (uint32_t)  val);
539         cpwgr("<0, 0x2b>", (uint32_t) (val >> 32));
540 }
541
542 /* dcache write access counter */
543 static uint64_t csky_pmu_read_dcwac(void)
544 {
545         uint32_t lo, hi, tmp;
546         uint64_t result;
547
548         do {
549                 tmp = cprgr("<0, 0x2d>");
550                 lo  = cprgr("<0, 0x2c>");
551                 hi  = cprgr("<0, 0x2d>");
552         } while (hi != tmp);
553
554         result = (uint64_t) (hi) << 32;
555         result |= lo;
556
557         return result;
558 }
559
560 static void csky_pmu_write_dcwac(uint64_t val)
561 {
562         cpwgr("<0, 0x2c>", (uint32_t)  val);
563         cpwgr("<0, 0x2d>", (uint32_t) (val >> 32));
564 }
565
566 /* dcache write miss counter */
567 static uint64_t csky_pmu_read_dcwmc(void)
568 {
569         uint32_t lo, hi, tmp;
570         uint64_t result;
571
572         do {
573                 tmp = cprgr("<0, 0x2f>");
574                 lo  = cprgr("<0, 0x2e>");
575                 hi  = cprgr("<0, 0x2f>");
576         } while (hi != tmp);
577
578         result = (uint64_t) (hi) << 32;
579         result |= lo;
580
581         return result;
582 }
583
584 static void csky_pmu_write_dcwmc(uint64_t val)
585 {
586         cpwgr("<0, 0x2e>", (uint32_t)  val);
587         cpwgr("<0, 0x2f>", (uint32_t) (val >> 32));
588 }
589
590 /* l2cache read access counter */
591 static uint64_t csky_pmu_read_l2rac(void)
592 {
593         uint32_t lo, hi, tmp;
594         uint64_t result;
595
596         do {
597                 tmp = cprgr("<0, 0x31>");
598                 lo  = cprgr("<0, 0x30>");
599                 hi  = cprgr("<0, 0x31>");
600         } while (hi != tmp);
601
602         result = (uint64_t) (hi) << 32;
603         result |= lo;
604
605         return result;
606 }
607
608 static void csky_pmu_write_l2rac(uint64_t val)
609 {
610         cpwgr("<0, 0x30>", (uint32_t)  val);
611         cpwgr("<0, 0x31>", (uint32_t) (val >> 32));
612 }
613
614 /* l2cache read miss counter */
615 static uint64_t csky_pmu_read_l2rmc(void)
616 {
617         uint32_t lo, hi, tmp;
618         uint64_t result;
619
620         do {
621                 tmp = cprgr("<0, 0x33>");
622                 lo  = cprgr("<0, 0x32>");
623                 hi  = cprgr("<0, 0x33>");
624         } while (hi != tmp);
625
626         result = (uint64_t) (hi) << 32;
627         result |= lo;
628
629         return result;
630 }
631
632 static void csky_pmu_write_l2rmc(uint64_t val)
633 {
634         cpwgr("<0, 0x32>", (uint32_t)  val);
635         cpwgr("<0, 0x33>", (uint32_t) (val >> 32));
636 }
637
638 /* l2cache write access counter */
639 static uint64_t csky_pmu_read_l2wac(void)
640 {
641         uint32_t lo, hi, tmp;
642         uint64_t result;
643
644         do {
645                 tmp = cprgr("<0, 0x35>");
646                 lo  = cprgr("<0, 0x34>");
647                 hi  = cprgr("<0, 0x35>");
648         } while (hi != tmp);
649
650         result = (uint64_t) (hi) << 32;
651         result |= lo;
652
653         return result;
654 }
655
656 static void csky_pmu_write_l2wac(uint64_t val)
657 {
658         cpwgr("<0, 0x34>", (uint32_t)  val);
659         cpwgr("<0, 0x35>", (uint32_t) (val >> 32));
660 }
661
662 /* l2cache write miss counter */
663 static uint64_t csky_pmu_read_l2wmc(void)
664 {
665         uint32_t lo, hi, tmp;
666         uint64_t result;
667
668         do {
669                 tmp = cprgr("<0, 0x37>");
670                 lo  = cprgr("<0, 0x36>");
671                 hi  = cprgr("<0, 0x37>");
672         } while (hi != tmp);
673
674         result = (uint64_t) (hi) << 32;
675         result |= lo;
676
677         return result;
678 }
679
680 static void csky_pmu_write_l2wmc(uint64_t val)
681 {
682         cpwgr("<0, 0x36>", (uint32_t)  val);
683         cpwgr("<0, 0x37>", (uint32_t) (val >> 32));
684 }
685
686 #define HW_OP_UNSUPPORTED       0xffff
687 static const int csky_pmu_hw_map[PERF_COUNT_HW_MAX] = {
688         [PERF_COUNT_HW_CPU_CYCLES]              = 0x1,
689         [PERF_COUNT_HW_INSTRUCTIONS]            = 0x2,
690         [PERF_COUNT_HW_CACHE_REFERENCES]        = HW_OP_UNSUPPORTED,
691         [PERF_COUNT_HW_CACHE_MISSES]            = HW_OP_UNSUPPORTED,
692         [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = 0xf,
693         [PERF_COUNT_HW_BRANCH_MISSES]           = 0xe,
694         [PERF_COUNT_HW_BUS_CYCLES]              = HW_OP_UNSUPPORTED,
695         [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
696         [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]  = HW_OP_UNSUPPORTED,
697         [PERF_COUNT_HW_REF_CPU_CYCLES]          = HW_OP_UNSUPPORTED,
698 };
699
700 #define C(_x)                   PERF_COUNT_HW_CACHE_##_x
701 #define CACHE_OP_UNSUPPORTED    0xffff
702 static const int csky_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
703         [C(L1D)] = {
704                 [C(OP_READ)] = {
705                         [C(RESULT_ACCESS)]      = 0x14,
706                         [C(RESULT_MISS)]        = 0x15,
707                 },
708                 [C(OP_WRITE)] = {
709                         [C(RESULT_ACCESS)]      = 0x16,
710                         [C(RESULT_MISS)]        = 0x17,
711                 },
712                 [C(OP_PREFETCH)] = {
713                         [C(RESULT_ACCESS)]      = 0x5,
714                         [C(RESULT_MISS)]        = 0x6,
715                 },
716         },
717         [C(L1I)] = {
718                 [C(OP_READ)] = {
719                         [C(RESULT_ACCESS)]      = 0x3,
720                         [C(RESULT_MISS)]        = 0x4,
721                 },
722                 [C(OP_WRITE)] = {
723                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
724                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
725                 },
726                 [C(OP_PREFETCH)] = {
727                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
728                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
729                 },
730         },
731         [C(LL)] = {
732                 [C(OP_READ)] = {
733                         [C(RESULT_ACCESS)]      = 0x18,
734                         [C(RESULT_MISS)]        = 0x19,
735                 },
736                 [C(OP_WRITE)] = {
737                         [C(RESULT_ACCESS)]      = 0x1a,
738                         [C(RESULT_MISS)]        = 0x1b,
739                 },
740                 [C(OP_PREFETCH)] = {
741                         [C(RESULT_ACCESS)]      = 0x7,
742                         [C(RESULT_MISS)]        = 0x8,
743                 },
744         },
745         [C(DTLB)] = {
746                 [C(OP_READ)] = {
747                         [C(RESULT_ACCESS)]      = 0x5,
748                         [C(RESULT_MISS)]        = 0xb,
749                 },
750                 [C(OP_WRITE)] = {
751                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
752                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
753                 },
754                 [C(OP_PREFETCH)] = {
755                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
756                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
757                 },
758         },
759         [C(ITLB)] = {
760                 [C(OP_READ)] = {
761                         [C(RESULT_ACCESS)]      = 0x3,
762                         [C(RESULT_MISS)]        = 0xa,
763                 },
764                 [C(OP_WRITE)] = {
765                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
766                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
767                 },
768                 [C(OP_PREFETCH)] = {
769                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
770                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
771                 },
772         },
773         [C(BPU)] = {
774                 [C(OP_READ)] = {
775                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
776                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
777                 },
778                 [C(OP_WRITE)] = {
779                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
780                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
781                 },
782                 [C(OP_PREFETCH)] = {
783                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
784                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
785                 },
786         },
787         [C(NODE)] = {
788                 [C(OP_READ)] = {
789                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
790                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
791                 },
792                 [C(OP_WRITE)] = {
793                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
794                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
795                 },
796                 [C(OP_PREFETCH)] = {
797                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
798                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
799                 },
800         },
801 };
802
803 static void csky_perf_event_update(struct perf_event *event,
804                                    struct hw_perf_event *hwc)
805 {
806         uint64_t prev_raw_count = local64_read(&hwc->prev_count);
807         uint64_t new_raw_count = hw_raw_read_mapping[hwc->idx]();
808         int64_t delta = new_raw_count - prev_raw_count;
809
810         /*
811          * We aren't afraid of hwc->prev_count changing beneath our feet
812          * because there's no way for us to re-enter this function anytime.
813          */
814         local64_set(&hwc->prev_count, new_raw_count);
815         local64_add(delta, &event->count);
816         local64_sub(delta, &hwc->period_left);
817 }
818
819 static void csky_pmu_read(struct perf_event *event)
820 {
821         csky_perf_event_update(event, &event->hw);
822 }
823
824 static int csky_pmu_cache_event(u64 config)
825 {
826         unsigned int cache_type, cache_op, cache_result;
827
828         cache_type      = (config >>  0) & 0xff;
829         cache_op        = (config >>  8) & 0xff;
830         cache_result    = (config >> 16) & 0xff;
831
832         if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
833                 return -EINVAL;
834         if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
835                 return -EINVAL;
836         if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
837                 return -EINVAL;
838
839         return csky_pmu_cache_map[cache_type][cache_op][cache_result];
840 }
841
842 static int csky_pmu_event_init(struct perf_event *event)
843 {
844         struct hw_perf_event *hwc = &event->hw;
845         int ret;
846
847         if (event->attr.exclude_user)
848                 csky_pmu.hpcr = BIT(2);
849         else if (event->attr.exclude_kernel)
850                 csky_pmu.hpcr = BIT(3);
851         else
852                 csky_pmu.hpcr = BIT(2) | BIT(3);
853
854         csky_pmu.hpcr |= BIT(1) | BIT(0);
855
856         switch (event->attr.type) {
857         case PERF_TYPE_HARDWARE:
858                 if (event->attr.config >= PERF_COUNT_HW_MAX)
859                         return -ENOENT;
860                 ret = csky_pmu_hw_map[event->attr.config];
861                 if (ret == HW_OP_UNSUPPORTED)
862                         return -ENOENT;
863                 hwc->idx = ret;
864                 return 0;
865         case PERF_TYPE_HW_CACHE:
866                 ret = csky_pmu_cache_event(event->attr.config);
867                 if (ret == CACHE_OP_UNSUPPORTED)
868                         return -ENOENT;
869                 hwc->idx = ret;
870                 return 0;
871         case PERF_TYPE_RAW:
872                 if (hw_raw_read_mapping[event->attr.config] == NULL)
873                         return -ENOENT;
874                 hwc->idx = event->attr.config;
875                 return 0;
876         default:
877                 return -ENOENT;
878         }
879 }
880
881 /* starts all counters */
882 static void csky_pmu_enable(struct pmu *pmu)
883 {
884         cpwcr(HPCR, csky_pmu.hpcr);
885 }
886
887 /* stops all counters */
888 static void csky_pmu_disable(struct pmu *pmu)
889 {
890         cpwcr(HPCR, BIT(1));
891 }
892
893 static void csky_pmu_start(struct perf_event *event, int flags)
894 {
895         struct hw_perf_event *hwc = &event->hw;
896         int idx = hwc->idx;
897
898         if (WARN_ON_ONCE(idx == -1))
899                 return;
900
901         if (flags & PERF_EF_RELOAD)
902                 WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
903
904         hwc->state = 0;
905
906         cpwcr(HPCNTENR, BIT(idx) | cprcr(HPCNTENR));
907 }
908
909 static void csky_pmu_stop(struct perf_event *event, int flags)
910 {
911         struct hw_perf_event *hwc = &event->hw;
912         int idx = hwc->idx;
913
914         if (!(event->hw.state & PERF_HES_STOPPED)) {
915                 cpwcr(HPCNTENR, ~BIT(idx) & cprcr(HPCNTENR));
916                 event->hw.state |= PERF_HES_STOPPED;
917         }
918
919         if ((flags & PERF_EF_UPDATE) &&
920             !(event->hw.state & PERF_HES_UPTODATE)) {
921                 csky_perf_event_update(event, &event->hw);
922                 event->hw.state |= PERF_HES_UPTODATE;
923         }
924 }
925
926 static void csky_pmu_del(struct perf_event *event, int flags)
927 {
928         csky_pmu_stop(event, PERF_EF_UPDATE);
929
930         perf_event_update_userpage(event);
931 }
932
933 /* allocate hardware counter and optionally start counting */
934 static int csky_pmu_add(struct perf_event *event, int flags)
935 {
936         struct hw_perf_event *hwc = &event->hw;
937
938         local64_set(&hwc->prev_count, 0);
939
940         if (hw_raw_write_mapping[hwc->idx] != NULL)
941                 hw_raw_write_mapping[hwc->idx](0);
942
943         hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
944         if (flags & PERF_EF_START)
945                 csky_pmu_start(event, PERF_EF_RELOAD);
946
947         perf_event_update_userpage(event);
948
949         return 0;
950 }
951
952 int __init init_hw_perf_events(void)
953 {
954         csky_pmu.pmu = (struct pmu) {
955                 .pmu_enable     = csky_pmu_enable,
956                 .pmu_disable    = csky_pmu_disable,
957                 .event_init     = csky_pmu_event_init,
958                 .add            = csky_pmu_add,
959                 .del            = csky_pmu_del,
960                 .start          = csky_pmu_start,
961                 .stop           = csky_pmu_stop,
962                 .read           = csky_pmu_read,
963         };
964
965         memset((void *)hw_raw_read_mapping, 0,
966                 sizeof(hw_raw_read_mapping[CSKY_PMU_MAX_EVENTS]));
967
968         hw_raw_read_mapping[0x1]  = csky_pmu_read_cc;
969         hw_raw_read_mapping[0x2]  = csky_pmu_read_ic;
970         hw_raw_read_mapping[0x3]  = csky_pmu_read_icac;
971         hw_raw_read_mapping[0x4]  = csky_pmu_read_icmc;
972         hw_raw_read_mapping[0x5]  = csky_pmu_read_dcac;
973         hw_raw_read_mapping[0x6]  = csky_pmu_read_dcmc;
974         hw_raw_read_mapping[0x7]  = csky_pmu_read_l2ac;
975         hw_raw_read_mapping[0x8]  = csky_pmu_read_l2mc;
976         hw_raw_read_mapping[0xa]  = csky_pmu_read_iutlbmc;
977         hw_raw_read_mapping[0xb]  = csky_pmu_read_dutlbmc;
978         hw_raw_read_mapping[0xc]  = csky_pmu_read_jtlbmc;
979         hw_raw_read_mapping[0xd]  = csky_pmu_read_softc;
980         hw_raw_read_mapping[0xe]  = csky_pmu_read_cbmc;
981         hw_raw_read_mapping[0xf]  = csky_pmu_read_cbic;
982         hw_raw_read_mapping[0x10] = csky_pmu_read_ibmc;
983         hw_raw_read_mapping[0x11] = csky_pmu_read_ibic;
984         hw_raw_read_mapping[0x12] = csky_pmu_read_lsfc;
985         hw_raw_read_mapping[0x13] = csky_pmu_read_sic;
986         hw_raw_read_mapping[0x14] = csky_pmu_read_dcrac;
987         hw_raw_read_mapping[0x15] = csky_pmu_read_dcrmc;
988         hw_raw_read_mapping[0x16] = csky_pmu_read_dcwac;
989         hw_raw_read_mapping[0x17] = csky_pmu_read_dcwmc;
990         hw_raw_read_mapping[0x18] = csky_pmu_read_l2rac;
991         hw_raw_read_mapping[0x19] = csky_pmu_read_l2rmc;
992         hw_raw_read_mapping[0x1a] = csky_pmu_read_l2wac;
993         hw_raw_read_mapping[0x1b] = csky_pmu_read_l2wmc;
994
995         memset((void *)hw_raw_write_mapping, 0,
996                 sizeof(hw_raw_write_mapping[CSKY_PMU_MAX_EVENTS]));
997
998         hw_raw_write_mapping[0x1]  = csky_pmu_write_cc;
999         hw_raw_write_mapping[0x2]  = csky_pmu_write_ic;
1000         hw_raw_write_mapping[0x3]  = csky_pmu_write_icac;
1001         hw_raw_write_mapping[0x4]  = csky_pmu_write_icmc;
1002         hw_raw_write_mapping[0x5]  = csky_pmu_write_dcac;
1003         hw_raw_write_mapping[0x6]  = csky_pmu_write_dcmc;
1004         hw_raw_write_mapping[0x7]  = csky_pmu_write_l2ac;
1005         hw_raw_write_mapping[0x8]  = csky_pmu_write_l2mc;
1006         hw_raw_write_mapping[0xa]  = csky_pmu_write_iutlbmc;
1007         hw_raw_write_mapping[0xb]  = csky_pmu_write_dutlbmc;
1008         hw_raw_write_mapping[0xc]  = csky_pmu_write_jtlbmc;
1009         hw_raw_write_mapping[0xd]  = csky_pmu_write_softc;
1010         hw_raw_write_mapping[0xe]  = csky_pmu_write_cbmc;
1011         hw_raw_write_mapping[0xf]  = csky_pmu_write_cbic;
1012         hw_raw_write_mapping[0x10] = csky_pmu_write_ibmc;
1013         hw_raw_write_mapping[0x11] = csky_pmu_write_ibic;
1014         hw_raw_write_mapping[0x12] = csky_pmu_write_lsfc;
1015         hw_raw_write_mapping[0x13] = csky_pmu_write_sic;
1016         hw_raw_write_mapping[0x14] = csky_pmu_write_dcrac;
1017         hw_raw_write_mapping[0x15] = csky_pmu_write_dcrmc;
1018         hw_raw_write_mapping[0x16] = csky_pmu_write_dcwac;
1019         hw_raw_write_mapping[0x17] = csky_pmu_write_dcwmc;
1020         hw_raw_write_mapping[0x18] = csky_pmu_write_l2rac;
1021         hw_raw_write_mapping[0x19] = csky_pmu_write_l2rmc;
1022         hw_raw_write_mapping[0x1a] = csky_pmu_write_l2wac;
1023         hw_raw_write_mapping[0x1b] = csky_pmu_write_l2wmc;
1024
1025         csky_pmu.pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
1026
1027         cpwcr(HPCR, BIT(31) | BIT(30) | BIT(1));
1028
1029         return perf_pmu_register(&csky_pmu.pmu, "cpu", PERF_TYPE_RAW);
1030 }
1031 arch_initcall(init_hw_perf_events);