~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/csky/kernel/perf_event.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 #define DEFAULT_COUNT_WIDTH 48
 13 
 14 #define HPCR            "<0, 0x0>"      /* PMU Control reg */
 15 #define HPSPR           "<0, 0x1>"      /* Start PC reg */
 16 #define HPEPR           "<0, 0x2>"      /* End PC reg */
 17 #define HPSIR           "<0, 0x3>"      /* Soft Counter reg */
 18 #define HPCNTENR        "<0, 0x4>"      /* Count Enable reg */
 19 #define HPINTENR        "<0, 0x5>"      /* Interrupt Enable reg */
 20 #define HPOFSR          "<0, 0x6>"      /* Interrupt Status reg */
 21 
 22 /* The events for a given PMU register set. */
 23 struct pmu_hw_events {
 24         /*
 25          * The events that are active on the PMU for the given index.
 26          */
 27         struct perf_event *events[CSKY_PMU_MAX_EVENTS];
 28 
 29         /*
 30          * A 1 bit for an index indicates that the counter is being used for
 31          * an event. A 0 means that the counter can be used.
 32          */
 33         unsigned long used_mask[BITS_TO_LONGS(CSKY_PMU_MAX_EVENTS)];
 34 };
 35 
 36 static uint64_t (*hw_raw_read_mapping[CSKY_PMU_MAX_EVENTS])(void);
 37 static void (*hw_raw_write_mapping[CSKY_PMU_MAX_EVENTS])(uint64_t val);
 38 
 39 static struct csky_pmu_t {
 40         struct pmu                      pmu;
 41         struct pmu_hw_events __percpu   *hw_events;
 42         struct platform_device          *plat_device;
 43         uint32_t                        count_width;
 44         uint32_t                        hpcr;
 45         u64                             max_period;
 46 } csky_pmu;
 47 static int csky_pmu_irq;
 48 
 49 #define to_csky_pmu(p)  (container_of(p, struct csky_pmu, pmu))
 50 
 51 #define cprgr(reg)                              \
 52 ({                                              \
 53         unsigned int tmp;                       \
 54         asm volatile("cprgr %0, "reg"\n"        \
 55                      : "=r"(tmp)                \
 56                      :                          \
 57                      : "memory");               \
 58         tmp;                                    \
 59 })
 60 
 61 #define cpwgr(reg, val)         \
 62 ({                              \
 63         asm volatile(           \
 64         "cpwgr %0, "reg"\n"     \
 65         :                       \
 66         : "r"(val)              \
 67         : "memory");            \
 68 })
 69 
 70 #define cprcr(reg)                              \
 71 ({                                              \
 72         unsigned int tmp;                       \
 73         asm volatile("cprcr %0, "reg"\n"        \
 74                      : "=r"(tmp)                \
 75                      :                          \
 76                      : "memory");               \
 77         tmp;                                    \
 78 })
 79 
 80 #define cpwcr(reg, val)         \
 81 ({                              \
 82         asm volatile(           \
 83         "cpwcr %0, "reg"\n"     \
 84         :                       \
 85         : "r"(val)              \
 86         : "memory");            \
 87 })
 88 
 89 /* cycle counter */
 90 uint64_t csky_pmu_read_cc(void)
 91 {
 92         uint32_t lo, hi, tmp;
 93         uint64_t result;
 94 
 95         do {
 96                 tmp = cprgr("<0, 0x3>");
 97                 lo  = cprgr("<0, 0x2>");
 98                 hi  = cprgr("<0, 0x3>");
 99         } while (hi != tmp);
100 
101         result = (uint64_t) (hi) << 32;
102         result |= lo;
103 
104         return result;
105 }
106 
107 static void csky_pmu_write_cc(uint64_t val)
108 {
109         cpwgr("<0, 0x2>", (uint32_t)  val);
110         cpwgr("<0, 0x3>", (uint32_t) (val >> 32));
111 }
112 
113 /* instruction counter */
114 static uint64_t csky_pmu_read_ic(void)
115 {
116         uint32_t lo, hi, tmp;
117         uint64_t result;
118 
119         do {
120                 tmp = cprgr("<0, 0x5>");
121                 lo  = cprgr("<0, 0x4>");
122                 hi  = cprgr("<0, 0x5>");
123         } while (hi != tmp);
124 
125         result = (uint64_t) (hi) << 32;
126         result |= lo;
127 
128         return result;
129 }
130 
131 static void csky_pmu_write_ic(uint64_t val)
132 {
133         cpwgr("<0, 0x4>", (uint32_t)  val);
134         cpwgr("<0, 0x5>", (uint32_t) (val >> 32));
135 }
136 
137 /* l1 icache access counter */
138 static uint64_t csky_pmu_read_icac(void)
139 {
140         uint32_t lo, hi, tmp;
141         uint64_t result;
142 
143         do {
144                 tmp = cprgr("<0, 0x7>");
145                 lo  = cprgr("<0, 0x6>");
146                 hi  = cprgr("<0, 0x7>");
147         } while (hi != tmp);
148 
149         result = (uint64_t) (hi) << 32;
150         result |= lo;
151 
152         return result;
153 }
154 
155 static void csky_pmu_write_icac(uint64_t val)
156 {
157         cpwgr("<0, 0x6>", (uint32_t)  val);
158         cpwgr("<0, 0x7>", (uint32_t) (val >> 32));
159 }
160 
161 /* l1 icache miss counter */
162 static uint64_t csky_pmu_read_icmc(void)
163 {
164         uint32_t lo, hi, tmp;
165         uint64_t result;
166 
167         do {
168                 tmp = cprgr("<0, 0x9>");
169                 lo  = cprgr("<0, 0x8>");
170                 hi  = cprgr("<0, 0x9>");
171         } while (hi != tmp);
172 
173         result = (uint64_t) (hi) << 32;
174         result |= lo;
175 
176         return result;
177 }
178 
179 static void csky_pmu_write_icmc(uint64_t val)
180 {
181         cpwgr("<0, 0x8>", (uint32_t)  val);
182         cpwgr("<0, 0x9>", (uint32_t) (val >> 32));
183 }
184 
185 /* l1 dcache access counter */
186 static uint64_t csky_pmu_read_dcac(void)
187 {
188         uint32_t lo, hi, tmp;
189         uint64_t result;
190 
191         do {
192                 tmp = cprgr("<0, 0xb>");
193                 lo  = cprgr("<0, 0xa>");
194                 hi  = cprgr("<0, 0xb>");
195         } while (hi != tmp);
196 
197         result = (uint64_t) (hi) << 32;
198         result |= lo;
199 
200         return result;
201 }
202 
203 static void csky_pmu_write_dcac(uint64_t val)
204 {
205         cpwgr("<0, 0xa>", (uint32_t)  val);
206         cpwgr("<0, 0xb>", (uint32_t) (val >> 32));
207 }
208 
209 /* l1 dcache miss counter */
210 static uint64_t csky_pmu_read_dcmc(void)
211 {
212         uint32_t lo, hi, tmp;
213         uint64_t result;
214 
215         do {
216                 tmp = cprgr("<0, 0xd>");
217                 lo  = cprgr("<0, 0xc>");
218                 hi  = cprgr("<0, 0xd>");
219         } while (hi != tmp);
220 
221         result = (uint64_t) (hi) << 32;
222         result |= lo;
223 
224         return result;
225 }
226 
227 static void csky_pmu_write_dcmc(uint64_t val)
228 {
229         cpwgr("<0, 0xc>", (uint32_t)  val);
230         cpwgr("<0, 0xd>", (uint32_t) (val >> 32));
231 }
232 
233 /* l2 cache access counter */
234 static uint64_t csky_pmu_read_l2ac(void)
235 {
236         uint32_t lo, hi, tmp;
237         uint64_t result;
238 
239         do {
240                 tmp = cprgr("<0, 0xf>");
241                 lo  = cprgr("<0, 0xe>");
242                 hi  = cprgr("<0, 0xf>");
243         } while (hi != tmp);
244 
245         result = (uint64_t) (hi) << 32;
246         result |= lo;
247 
248         return result;
249 }
250 
251 static void csky_pmu_write_l2ac(uint64_t val)
252 {
253         cpwgr("<0, 0xe>", (uint32_t)  val);
254         cpwgr("<0, 0xf>", (uint32_t) (val >> 32));
255 }
256 
257 /* l2 cache miss counter */
258 static uint64_t csky_pmu_read_l2mc(void)
259 {
260         uint32_t lo, hi, tmp;
261         uint64_t result;
262 
263         do {
264                 tmp = cprgr("<0, 0x11>");
265                 lo  = cprgr("<0, 0x10>");
266                 hi  = cprgr("<0, 0x11>");
267         } while (hi != tmp);
268 
269         result = (uint64_t) (hi) << 32;
270         result |= lo;
271 
272         return result;
273 }
274 
275 static void csky_pmu_write_l2mc(uint64_t val)
276 {
277         cpwgr("<0, 0x10>", (uint32_t)  val);
278         cpwgr("<0, 0x11>", (uint32_t) (val >> 32));
279 }
280 
281 /* I-UTLB miss counter */
282 static uint64_t csky_pmu_read_iutlbmc(void)
283 {
284         uint32_t lo, hi, tmp;
285         uint64_t result;
286 
287         do {
288                 tmp = cprgr("<0, 0x15>");
289                 lo  = cprgr("<0, 0x14>");
290                 hi  = cprgr("<0, 0x15>");
291         } while (hi != tmp);
292 
293         result = (uint64_t) (hi) << 32;
294         result |= lo;
295 
296         return result;
297 }
298 
299 static void csky_pmu_write_iutlbmc(uint64_t val)
300 {
301         cpwgr("<0, 0x14>", (uint32_t)  val);
302         cpwgr("<0, 0x15>", (uint32_t) (val >> 32));
303 }
304 
305 /* D-UTLB miss counter */
306 static uint64_t csky_pmu_read_dutlbmc(void)
307 {
308         uint32_t lo, hi, tmp;
309         uint64_t result;
310 
311         do {
312                 tmp = cprgr("<0, 0x17>");
313                 lo  = cprgr("<0, 0x16>");
314                 hi  = cprgr("<0, 0x17>");
315         } while (hi != tmp);
316 
317         result = (uint64_t) (hi) << 32;
318         result |= lo;
319 
320         return result;
321 }
322 
323 static void csky_pmu_write_dutlbmc(uint64_t val)
324 {
325         cpwgr("<0, 0x16>", (uint32_t)  val);
326         cpwgr("<0, 0x17>", (uint32_t) (val >> 32));
327 }
328 
329 /* JTLB miss counter */
330 static uint64_t csky_pmu_read_jtlbmc(void)
331 {
332         uint32_t lo, hi, tmp;
333         uint64_t result;
334 
335         do {
336                 tmp = cprgr("<0, 0x19>");
337                 lo  = cprgr("<0, 0x18>");
338                 hi  = cprgr("<0, 0x19>");
339         } while (hi != tmp);
340 
341         result = (uint64_t) (hi) << 32;
342         result |= lo;
343 
344         return result;
345 }
346 
347 static void csky_pmu_write_jtlbmc(uint64_t val)
348 {
349         cpwgr("<0, 0x18>", (uint32_t)  val);
350         cpwgr("<0, 0x19>", (uint32_t) (val >> 32));
351 }
352 
353 /* software counter */
354 static uint64_t csky_pmu_read_softc(void)
355 {
356         uint32_t lo, hi, tmp;
357         uint64_t result;
358 
359         do {
360                 tmp = cprgr("<0, 0x1b>");
361                 lo  = cprgr("<0, 0x1a>");
362                 hi  = cprgr("<0, 0x1b>");
363         } while (hi != tmp);
364 
365         result = (uint64_t) (hi) << 32;
366         result |= lo;
367 
368         return result;
369 }
370 
371 static void csky_pmu_write_softc(uint64_t val)
372 {
373         cpwgr("<0, 0x1a>", (uint32_t)  val);
374         cpwgr("<0, 0x1b>", (uint32_t) (val >> 32));
375 }
376 
377 /* conditional branch mispredict counter */
378 static uint64_t csky_pmu_read_cbmc(void)
379 {
380         uint32_t lo, hi, tmp;
381         uint64_t result;
382 
383         do {
384                 tmp = cprgr("<0, 0x1d>");
385                 lo  = cprgr("<0, 0x1c>");
386                 hi  = cprgr("<0, 0x1d>");
387         } while (hi != tmp);
388 
389         result = (uint64_t) (hi) << 32;
390         result |= lo;
391 
392         return result;
393 }
394 
395 static void csky_pmu_write_cbmc(uint64_t val)
396 {
397         cpwgr("<0, 0x1c>", (uint32_t)  val);
398         cpwgr("<0, 0x1d>", (uint32_t) (val >> 32));
399 }
400 
401 /* conditional branch instruction counter */
402 static uint64_t csky_pmu_read_cbic(void)
403 {
404         uint32_t lo, hi, tmp;
405         uint64_t result;
406 
407         do {
408                 tmp = cprgr("<0, 0x1f>");
409                 lo  = cprgr("<0, 0x1e>");
410                 hi  = cprgr("<0, 0x1f>");
411         } while (hi != tmp);
412 
413         result = (uint64_t) (hi) << 32;
414         result |= lo;
415 
416         return result;
417 }
418 
419 static void csky_pmu_write_cbic(uint64_t val)
420 {
421         cpwgr("<0, 0x1e>", (uint32_t)  val);
422         cpwgr("<0, 0x1f>", (uint32_t) (val >> 32));
423 }
424 
425 /* indirect branch mispredict counter */
426 static uint64_t csky_pmu_read_ibmc(void)
427 {
428         uint32_t lo, hi, tmp;
429         uint64_t result;
430 
431         do {
432                 tmp = cprgr("<0, 0x21>");
433                 lo  = cprgr("<0, 0x20>");
434                 hi  = cprgr("<0, 0x21>");
435         } while (hi != tmp);
436 
437         result = (uint64_t) (hi) << 32;
438         result |= lo;
439 
440         return result;
441 }
442 
443 static void csky_pmu_write_ibmc(uint64_t val)
444 {
445         cpwgr("<0, 0x20>", (uint32_t)  val);
446         cpwgr("<0, 0x21>", (uint32_t) (val >> 32));
447 }
448 
449 /* indirect branch instruction counter */
450 static uint64_t csky_pmu_read_ibic(void)
451 {
452         uint32_t lo, hi, tmp;
453         uint64_t result;
454 
455         do {
456                 tmp = cprgr("<0, 0x23>");
457                 lo  = cprgr("<0, 0x22>");
458                 hi  = cprgr("<0, 0x23>");
459         } while (hi != tmp);
460 
461         result = (uint64_t) (hi) << 32;
462         result |= lo;
463 
464         return result;
465 }
466 
467 static void csky_pmu_write_ibic(uint64_t val)
468 {
469         cpwgr("<0, 0x22>", (uint32_t)  val);
470         cpwgr("<0, 0x23>", (uint32_t) (val >> 32));
471 }
472 
473 /* LSU spec fail counter */
474 static uint64_t csky_pmu_read_lsfc(void)
475 {
476         uint32_t lo, hi, tmp;
477         uint64_t result;
478 
479         do {
480                 tmp = cprgr("<0, 0x25>");
481                 lo  = cprgr("<0, 0x24>");
482                 hi  = cprgr("<0, 0x25>");
483         } while (hi != tmp);
484 
485         result = (uint64_t) (hi) << 32;
486         result |= lo;
487 
488         return result;
489 }
490 
491 static void csky_pmu_write_lsfc(uint64_t val)
492 {
493         cpwgr("<0, 0x24>", (uint32_t)  val);
494         cpwgr("<0, 0x25>", (uint32_t) (val >> 32));
495 }
496 
497 /* store instruction counter */
498 static uint64_t csky_pmu_read_sic(void)
499 {
500         uint32_t lo, hi, tmp;
501         uint64_t result;
502 
503         do {
504                 tmp = cprgr("<0, 0x27>");
505                 lo  = cprgr("<0, 0x26>");
506                 hi  = cprgr("<0, 0x27>");
507         } while (hi != tmp);
508 
509         result = (uint64_t) (hi) << 32;
510         result |= lo;
511 
512         return result;
513 }
514 
515 static void csky_pmu_write_sic(uint64_t val)
516 {
517         cpwgr("<0, 0x26>", (uint32_t)  val);
518         cpwgr("<0, 0x27>", (uint32_t) (val >> 32));
519 }
520 
521 /* dcache read access counter */
522 static uint64_t csky_pmu_read_dcrac(void)
523 {
524         uint32_t lo, hi, tmp;
525         uint64_t result;
526 
527         do {
528                 tmp = cprgr("<0, 0x29>");
529                 lo  = cprgr("<0, 0x28>");
530                 hi  = cprgr("<0, 0x29>");
531         } while (hi != tmp);
532 
533         result = (uint64_t) (hi) << 32;
534         result |= lo;
535 
536         return result;
537 }
538 
539 static void csky_pmu_write_dcrac(uint64_t val)
540 {
541         cpwgr("<0, 0x28>", (uint32_t)  val);
542         cpwgr("<0, 0x29>", (uint32_t) (val >> 32));
543 }
544 
545 /* dcache read miss counter */
546 static uint64_t csky_pmu_read_dcrmc(void)
547 {
548         uint32_t lo, hi, tmp;
549         uint64_t result;
550 
551         do {
552                 tmp = cprgr("<0, 0x2b>");
553                 lo  = cprgr("<0, 0x2a>");
554                 hi  = cprgr("<0, 0x2b>");
555         } while (hi != tmp);
556 
557         result = (uint64_t) (hi) << 32;
558         result |= lo;
559 
560         return result;
561 }
562 
563 static void csky_pmu_write_dcrmc(uint64_t val)
564 {
565         cpwgr("<0, 0x2a>", (uint32_t)  val);
566         cpwgr("<0, 0x2b>", (uint32_t) (val >> 32));
567 }
568 
569 /* dcache write access counter */
570 static uint64_t csky_pmu_read_dcwac(void)
571 {
572         uint32_t lo, hi, tmp;
573         uint64_t result;
574 
575         do {
576                 tmp = cprgr("<0, 0x2d>");
577                 lo  = cprgr("<0, 0x2c>");
578                 hi  = cprgr("<0, 0x2d>");
579         } while (hi != tmp);
580 
581         result = (uint64_t) (hi) << 32;
582         result |= lo;
583 
584         return result;
585 }
586 
587 static void csky_pmu_write_dcwac(uint64_t val)
588 {
589         cpwgr("<0, 0x2c>", (uint32_t)  val);
590         cpwgr("<0, 0x2d>", (uint32_t) (val >> 32));
591 }
592 
593 /* dcache write miss counter */
594 static uint64_t csky_pmu_read_dcwmc(void)
595 {
596         uint32_t lo, hi, tmp;
597         uint64_t result;
598 
599         do {
600                 tmp = cprgr("<0, 0x2f>");
601                 lo  = cprgr("<0, 0x2e>");
602                 hi  = cprgr("<0, 0x2f>");
603         } while (hi != tmp);
604 
605         result = (uint64_t) (hi) << 32;
606         result |= lo;
607 
608         return result;
609 }
610 
611 static void csky_pmu_write_dcwmc(uint64_t val)
612 {
613         cpwgr("<0, 0x2e>", (uint32_t)  val);
614         cpwgr("<0, 0x2f>", (uint32_t) (val >> 32));
615 }
616 
617 /* l2cache read access counter */
618 static uint64_t csky_pmu_read_l2rac(void)
619 {
620         uint32_t lo, hi, tmp;
621         uint64_t result;
622 
623         do {
624                 tmp = cprgr("<0, 0x31>");
625                 lo  = cprgr("<0, 0x30>");
626                 hi  = cprgr("<0, 0x31>");
627         } while (hi != tmp);
628 
629         result = (uint64_t) (hi) << 32;
630         result |= lo;
631 
632         return result;
633 }
634 
635 static void csky_pmu_write_l2rac(uint64_t val)
636 {
637         cpwgr("<0, 0x30>", (uint32_t)  val);
638         cpwgr("<0, 0x31>", (uint32_t) (val >> 32));
639 }
640 
641 /* l2cache read miss counter */
642 static uint64_t csky_pmu_read_l2rmc(void)
643 {
644         uint32_t lo, hi, tmp;
645         uint64_t result;
646 
647         do {
648                 tmp = cprgr("<0, 0x33>");
649                 lo  = cprgr("<0, 0x32>");
650                 hi  = cprgr("<0, 0x33>");
651         } while (hi != tmp);
652 
653         result = (uint64_t) (hi) << 32;
654         result |= lo;
655 
656         return result;
657 }
658 
659 static void csky_pmu_write_l2rmc(uint64_t val)
660 {
661         cpwgr("<0, 0x32>", (uint32_t)  val);
662         cpwgr("<0, 0x33>", (uint32_t) (val >> 32));
663 }
664 
665 /* l2cache write access counter */
666 static uint64_t csky_pmu_read_l2wac(void)
667 {
668         uint32_t lo, hi, tmp;
669         uint64_t result;
670 
671         do {
672                 tmp = cprgr("<0, 0x35>");
673                 lo  = cprgr("<0, 0x34>");
674                 hi  = cprgr("<0, 0x35>");
675         } while (hi != tmp);
676 
677         result = (uint64_t) (hi) << 32;
678         result |= lo;
679 
680         return result;
681 }
682 
683 static void csky_pmu_write_l2wac(uint64_t val)
684 {
685         cpwgr("<0, 0x34>", (uint32_t)  val);
686         cpwgr("<0, 0x35>", (uint32_t) (val >> 32));
687 }
688 
689 /* l2cache write miss counter */
690 static uint64_t csky_pmu_read_l2wmc(void)
691 {
692         uint32_t lo, hi, tmp;
693         uint64_t result;
694 
695         do {
696                 tmp = cprgr("<0, 0x37>");
697                 lo  = cprgr("<0, 0x36>");
698                 hi  = cprgr("<0, 0x37>");
699         } while (hi != tmp);
700 
701         result = (uint64_t) (hi) << 32;
702         result |= lo;
703 
704         return result;
705 }
706 
707 static void csky_pmu_write_l2wmc(uint64_t val)
708 {
709         cpwgr("<0, 0x36>", (uint32_t)  val);
710         cpwgr("<0, 0x37>", (uint32_t) (val >> 32));
711 }
712 
713 #define HW_OP_UNSUPPORTED       0xffff
714 static const int csky_pmu_hw_map[PERF_COUNT_HW_MAX] = {
715         [PERF_COUNT_HW_CPU_CYCLES]              = 0x1,
716         [PERF_COUNT_HW_INSTRUCTIONS]            = 0x2,
717         [PERF_COUNT_HW_CACHE_REFERENCES]        = HW_OP_UNSUPPORTED,
718         [PERF_COUNT_HW_CACHE_MISSES]            = HW_OP_UNSUPPORTED,
719         [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = 0xf,
720         [PERF_COUNT_HW_BRANCH_MISSES]           = 0xe,
721         [PERF_COUNT_HW_BUS_CYCLES]              = HW_OP_UNSUPPORTED,
722         [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
723         [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]  = HW_OP_UNSUPPORTED,
724         [PERF_COUNT_HW_REF_CPU_CYCLES]          = HW_OP_UNSUPPORTED,
725 };
726 
727 #define C(_x)                   PERF_COUNT_HW_CACHE_##_x
728 #define CACHE_OP_UNSUPPORTED    0xffff
729 static const int csky_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
730         [C(L1D)] = {
731 #ifdef CONFIG_CPU_CK810
732                 [C(OP_READ)] = {
733                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
734                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
735                 },
736                 [C(OP_WRITE)] = {
737                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
738                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
739                 },
740                 [C(OP_PREFETCH)] = {
741                         [C(RESULT_ACCESS)]      = 0x5,
742                         [C(RESULT_MISS)]        = 0x6,
743                 },
744 #else
745                 [C(OP_READ)] = {
746                         [C(RESULT_ACCESS)]      = 0x14,
747                         [C(RESULT_MISS)]        = 0x15,
748                 },
749                 [C(OP_WRITE)] = {
750                         [C(RESULT_ACCESS)]      = 0x16,
751                         [C(RESULT_MISS)]        = 0x17,
752                 },
753                 [C(OP_PREFETCH)] = {
754                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
755                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
756                 },
757 #endif
758         },
759         [C(L1I)] = {
760                 [C(OP_READ)] = {
761                         [C(RESULT_ACCESS)]      = 0x3,
762                         [C(RESULT_MISS)]        = 0x4,
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(LL)] = {
774 #ifdef CONFIG_CPU_CK810
775                 [C(OP_READ)] = {
776                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
777                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
778                 },
779                 [C(OP_WRITE)] = {
780                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
781                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
782                 },
783                 [C(OP_PREFETCH)] = {
784                         [C(RESULT_ACCESS)]      = 0x7,
785                         [C(RESULT_MISS)]        = 0x8,
786                 },
787 #else
788                 [C(OP_READ)] = {
789                         [C(RESULT_ACCESS)]      = 0x18,
790                         [C(RESULT_MISS)]        = 0x19,
791                 },
792                 [C(OP_WRITE)] = {
793                         [C(RESULT_ACCESS)]      = 0x1a,
794                         [C(RESULT_MISS)]        = 0x1b,
795                 },
796                 [C(OP_PREFETCH)] = {
797                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
798                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
799                 },
800 #endif
801         },
802         [C(DTLB)] = {
803 #ifdef CONFIG_CPU_CK810
804                 [C(OP_READ)] = {
805                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
806                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
807                 },
808                 [C(OP_WRITE)] = {
809                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
810                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
811                 },
812 #else
813                 [C(OP_READ)] = {
814                         [C(RESULT_ACCESS)]      = 0x14,
815                         [C(RESULT_MISS)]        = 0xb,
816                 },
817                 [C(OP_WRITE)] = {
818                         [C(RESULT_ACCESS)]      = 0x16,
819                         [C(RESULT_MISS)]        = 0xb,
820                 },
821 #endif
822                 [C(OP_PREFETCH)] = {
823                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
824                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
825                 },
826         },
827         [C(ITLB)] = {
828 #ifdef CONFIG_CPU_CK810
829                 [C(OP_READ)] = {
830                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
831                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
832                 },
833 #else
834                 [C(OP_READ)] = {
835                         [C(RESULT_ACCESS)]      = 0x3,
836                         [C(RESULT_MISS)]        = 0xa,
837                 },
838 #endif
839                 [C(OP_WRITE)] = {
840                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
841                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
842                 },
843                 [C(OP_PREFETCH)] = {
844                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
845                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
846                 },
847         },
848         [C(BPU)] = {
849                 [C(OP_READ)] = {
850                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
851                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
852                 },
853                 [C(OP_WRITE)] = {
854                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
855                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
856                 },
857                 [C(OP_PREFETCH)] = {
858                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
859                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
860                 },
861         },
862         [C(NODE)] = {
863                 [C(OP_READ)] = {
864                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
865                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
866                 },
867                 [C(OP_WRITE)] = {
868                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
869                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
870                 },
871                 [C(OP_PREFETCH)] = {
872                         [C(RESULT_ACCESS)]      = CACHE_OP_UNSUPPORTED,
873                         [C(RESULT_MISS)]        = CACHE_OP_UNSUPPORTED,
874                 },
875         },
876 };
877 
878 int  csky_pmu_event_set_period(struct perf_event *event)
879 {
880         struct hw_perf_event *hwc = &event->hw;
881         s64 left = local64_read(&hwc->period_left);
882         s64 period = hwc->sample_period;
883         int ret = 0;
884 
885         if (unlikely(left <= -period)) {
886                 left = period;
887                 local64_set(&hwc->period_left, left);
888                 hwc->last_period = period;
889                 ret = 1;
890         }
891 
892         if (unlikely(left <= 0)) {
893                 left += period;
894                 local64_set(&hwc->period_left, left);
895                 hwc->last_period = period;
896                 ret = 1;
897         }
898 
899         if (left > (s64)csky_pmu.max_period)
900                 left = csky_pmu.max_period;
901 
902         /*
903          * The hw event starts counting from this event offset,
904          * mark it to be able to extract future "deltas":
905          */
906         local64_set(&hwc->prev_count, (u64)(-left));
907 
908         if (hw_raw_write_mapping[hwc->idx] != NULL)
909                 hw_raw_write_mapping[hwc->idx]((u64)(-left) &
910                                                 csky_pmu.max_period);
911 
912         cpwcr(HPOFSR, ~BIT(hwc->idx) & cprcr(HPOFSR));
913 
914         perf_event_update_userpage(event);
915 
916         return ret;
917 }
918 
919 static void csky_perf_event_update(struct perf_event *event,
920                                    struct hw_perf_event *hwc)
921 {
922         uint64_t prev_raw_count = local64_read(&hwc->prev_count);
923         /*
924          * Sign extend count value to 64bit, otherwise delta calculation
925          * would be incorrect when overflow occurs.
926          */
927         uint64_t new_raw_count = sign_extend64(
928                 hw_raw_read_mapping[hwc->idx](), csky_pmu.count_width - 1);
929         int64_t delta = new_raw_count - prev_raw_count;
930 
931         /*
932          * We aren't afraid of hwc->prev_count changing beneath our feet
933          * because there's no way for us to re-enter this function anytime.
934          */
935         local64_set(&hwc->prev_count, new_raw_count);
936         local64_add(delta, &event->count);
937         local64_sub(delta, &hwc->period_left);
938 }
939 
940 static void csky_pmu_reset(void *info)
941 {
942         cpwcr(HPCR, BIT(31) | BIT(30) | BIT(1));
943 }
944 
945 static void csky_pmu_read(struct perf_event *event)
946 {
947         csky_perf_event_update(event, &event->hw);
948 }
949 
950 static int csky_pmu_cache_event(u64 config)
951 {
952         unsigned int cache_type, cache_op, cache_result;
953 
954         cache_type      = (config >>  0) & 0xff;
955         cache_op        = (config >>  8) & 0xff;
956         cache_result    = (config >> 16) & 0xff;
957 
958         if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
959                 return -EINVAL;
960         if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
961                 return -EINVAL;
962         if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
963                 return -EINVAL;
964 
965         return csky_pmu_cache_map[cache_type][cache_op][cache_result];
966 }
967 
968 static int csky_pmu_event_init(struct perf_event *event)
969 {
970         struct hw_perf_event *hwc = &event->hw;
971         int ret;
972 
973         switch (event->attr.type) {
974         case PERF_TYPE_HARDWARE:
975                 if (event->attr.config >= PERF_COUNT_HW_MAX)
976                         return -ENOENT;
977                 ret = csky_pmu_hw_map[event->attr.config];
978                 if (ret == HW_OP_UNSUPPORTED)
979                         return -ENOENT;
980                 hwc->idx = ret;
981                 break;
982         case PERF_TYPE_HW_CACHE:
983                 ret = csky_pmu_cache_event(event->attr.config);
984                 if (ret == CACHE_OP_UNSUPPORTED)
985                         return -ENOENT;
986                 hwc->idx = ret;
987                 break;
988         case PERF_TYPE_RAW:
989                 if (hw_raw_read_mapping[event->attr.config] == NULL)
990                         return -ENOENT;
991                 hwc->idx = event->attr.config;
992                 break;
993         default:
994                 return -ENOENT;
995         }
996 
997         if (event->attr.exclude_user)
998                 csky_pmu.hpcr = BIT(2);
999         else if (event->attr.exclude_kernel)
1000                 csky_pmu.hpcr = BIT(3);
1001         else
1002                 csky_pmu.hpcr = BIT(2) | BIT(3);
1003 
1004         csky_pmu.hpcr |= BIT(1) | BIT(0);
1005 
1006         return 0;
1007 }
1008 
1009 /* starts all counters */
1010 static void csky_pmu_enable(struct pmu *pmu)
1011 {
1012         cpwcr(HPCR, csky_pmu.hpcr);
1013 }
1014 
1015 /* stops all counters */
1016 static void csky_pmu_disable(struct pmu *pmu)
1017 {
1018         cpwcr(HPCR, BIT(1));
1019 }
1020 
1021 static void csky_pmu_start(struct perf_event *event, int flags)
1022 {
1023         unsigned long flg;
1024         struct hw_perf_event *hwc = &event->hw;
1025         int idx = hwc->idx;
1026 
1027         if (WARN_ON_ONCE(idx == -1))
1028                 return;
1029 
1030         if (flags & PERF_EF_RELOAD)
1031                 WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
1032 
1033         hwc->state = 0;
1034 
1035         csky_pmu_event_set_period(event);
1036 
1037         local_irq_save(flg);
1038 
1039         cpwcr(HPINTENR, BIT(idx) | cprcr(HPINTENR));
1040         cpwcr(HPCNTENR, BIT(idx) | cprcr(HPCNTENR));
1041 
1042         local_irq_restore(flg);
1043 }
1044 
1045 static void csky_pmu_stop_event(struct perf_event *event)
1046 {
1047         unsigned long flg;
1048         struct hw_perf_event *hwc = &event->hw;
1049         int idx = hwc->idx;
1050 
1051         local_irq_save(flg);
1052 
1053         cpwcr(HPINTENR, ~BIT(idx) & cprcr(HPINTENR));
1054         cpwcr(HPCNTENR, ~BIT(idx) & cprcr(HPCNTENR));
1055 
1056         local_irq_restore(flg);
1057 }
1058 
1059 static void csky_pmu_stop(struct perf_event *event, int flags)
1060 {
1061         if (!(event->hw.state & PERF_HES_STOPPED)) {
1062                 csky_pmu_stop_event(event);
1063                 event->hw.state |= PERF_HES_STOPPED;
1064         }
1065 
1066         if ((flags & PERF_EF_UPDATE) &&
1067             !(event->hw.state & PERF_HES_UPTODATE)) {
1068                 csky_perf_event_update(event, &event->hw);
1069                 event->hw.state |= PERF_HES_UPTODATE;
1070         }
1071 }
1072 
1073 static void csky_pmu_del(struct perf_event *event, int flags)
1074 {
1075         struct pmu_hw_events *hw_events = this_cpu_ptr(csky_pmu.hw_events);
1076         struct hw_perf_event *hwc = &event->hw;
1077 
1078         csky_pmu_stop(event, PERF_EF_UPDATE);
1079 
1080         hw_events->events[hwc->idx] = NULL;
1081 
1082         perf_event_update_userpage(event);
1083 }
1084 
1085 /* allocate hardware counter and optionally start counting */
1086 static int csky_pmu_add(struct perf_event *event, int flags)
1087 {
1088         struct pmu_hw_events *hw_events = this_cpu_ptr(csky_pmu.hw_events);
1089         struct hw_perf_event *hwc = &event->hw;
1090 
1091         hw_events->events[hwc->idx] = event;
1092 
1093         hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
1094 
1095         if (flags & PERF_EF_START)
1096                 csky_pmu_start(event, PERF_EF_RELOAD);
1097 
1098         perf_event_update_userpage(event);
1099 
1100         return 0;
1101 }
1102 
1103 static irqreturn_t csky_pmu_handle_irq(int irq_num, void *dev)
1104 {
1105         struct perf_sample_data data;
1106         struct pmu_hw_events *cpuc = this_cpu_ptr(csky_pmu.hw_events);
1107         struct pt_regs *regs;
1108         int idx;
1109 
1110         /*
1111          * Did an overflow occur?
1112          */
1113         if (!cprcr(HPOFSR))
1114                 return IRQ_NONE;
1115 
1116         /*
1117          * Handle the counter(s) overflow(s)
1118          */
1119         regs = get_irq_regs();
1120 
1121         csky_pmu_disable(&csky_pmu.pmu);
1122 
1123         for (idx = 0; idx < CSKY_PMU_MAX_EVENTS; ++idx) {
1124                 struct perf_event *event = cpuc->events[idx];
1125                 struct hw_perf_event *hwc;
1126 
1127                 /* Ignore if we don't have an event. */
1128                 if (!event)
1129                         continue;
1130                 /*
1131                  * We have a single interrupt for all counters. Check that
1132                  * each counter has overflowed before we process it.
1133                  */
1134                 if (!(cprcr(HPOFSR) & BIT(idx)))
1135                         continue;
1136 
1137                 hwc = &event->hw;
1138                 csky_perf_event_update(event, &event->hw);
1139                 perf_sample_data_init(&data, 0, hwc->last_period);
1140                 csky_pmu_event_set_period(event);
1141 
1142                 if (perf_event_overflow(event, &data, regs))
1143                         csky_pmu_stop_event(event);
1144         }
1145 
1146         csky_pmu_enable(&csky_pmu.pmu);
1147 
1148         /*
1149          * Handle the pending perf events.
1150          *
1151          * Note: this call *must* be run with interrupts disabled. For
1152          * platforms that can have the PMU interrupts raised as an NMI, this
1153          * will not work.
1154          */
1155         irq_work_run();
1156 
1157         return IRQ_HANDLED;
1158 }
1159 
1160 static int csky_pmu_request_irq(irq_handler_t handler)
1161 {
1162         int err, irqs;
1163         struct platform_device *pmu_device = csky_pmu.plat_device;
1164 
1165         if (!pmu_device)
1166                 return -ENODEV;
1167 
1168         irqs = min(pmu_device->num_resources, num_possible_cpus());
1169         if (irqs < 1) {
1170                 pr_err("no irqs for PMUs defined\n");
1171                 return -ENODEV;
1172         }
1173 
1174         csky_pmu_irq = platform_get_irq(pmu_device, 0);
1175         if (csky_pmu_irq < 0)
1176                 return -ENODEV;
1177         err = request_percpu_irq(csky_pmu_irq, handler, "csky-pmu",
1178                                  this_cpu_ptr(csky_pmu.hw_events));
1179         if (err) {
1180                 pr_err("unable to request IRQ%d for CSKY PMU counters\n",
1181                        csky_pmu_irq);
1182                 return err;
1183         }
1184 
1185         return 0;
1186 }
1187 
1188 static void csky_pmu_free_irq(void)
1189 {
1190         int irq;
1191         struct platform_device *pmu_device = csky_pmu.plat_device;
1192 
1193         irq = platform_get_irq(pmu_device, 0);
1194         if (irq >= 0)
1195                 free_percpu_irq(irq, this_cpu_ptr(csky_pmu.hw_events));
1196 }
1197 
1198 int init_hw_perf_events(void)
1199 {
1200         csky_pmu.hw_events = alloc_percpu_gfp(struct pmu_hw_events,
1201                                               GFP_KERNEL);
1202         if (!csky_pmu.hw_events) {
1203                 pr_info("failed to allocate per-cpu PMU data.\n");
1204                 return -ENOMEM;
1205         }
1206 
1207         csky_pmu.pmu = (struct pmu) {
1208                 .pmu_enable     = csky_pmu_enable,
1209                 .pmu_disable    = csky_pmu_disable,
1210                 .event_init     = csky_pmu_event_init,
1211                 .add            = csky_pmu_add,
1212                 .del            = csky_pmu_del,
1213                 .start          = csky_pmu_start,
1214                 .stop           = csky_pmu_stop,
1215                 .read           = csky_pmu_read,
1216         };
1217 
1218         memset((void *)hw_raw_read_mapping, 0,
1219                 sizeof(hw_raw_read_mapping[CSKY_PMU_MAX_EVENTS]));
1220 
1221         hw_raw_read_mapping[0x1]  = csky_pmu_read_cc;
1222         hw_raw_read_mapping[0x2]  = csky_pmu_read_ic;
1223         hw_raw_read_mapping[0x3]  = csky_pmu_read_icac;
1224         hw_raw_read_mapping[0x4]  = csky_pmu_read_icmc;
1225         hw_raw_read_mapping[0x5]  = csky_pmu_read_dcac;
1226         hw_raw_read_mapping[0x6]  = csky_pmu_read_dcmc;
1227         hw_raw_read_mapping[0x7]  = csky_pmu_read_l2ac;
1228         hw_raw_read_mapping[0x8]  = csky_pmu_read_l2mc;
1229         hw_raw_read_mapping[0xa]  = csky_pmu_read_iutlbmc;
1230         hw_raw_read_mapping[0xb]  = csky_pmu_read_dutlbmc;
1231         hw_raw_read_mapping[0xc]  = csky_pmu_read_jtlbmc;
1232         hw_raw_read_mapping[0xd]  = csky_pmu_read_softc;
1233         hw_raw_read_mapping[0xe]  = csky_pmu_read_cbmc;
1234         hw_raw_read_mapping[0xf]  = csky_pmu_read_cbic;
1235         hw_raw_read_mapping[0x10] = csky_pmu_read_ibmc;
1236         hw_raw_read_mapping[0x11] = csky_pmu_read_ibic;
1237         hw_raw_read_mapping[0x12] = csky_pmu_read_lsfc;
1238         hw_raw_read_mapping[0x13] = csky_pmu_read_sic;
1239         hw_raw_read_mapping[0x14] = csky_pmu_read_dcrac;
1240         hw_raw_read_mapping[0x15] = csky_pmu_read_dcrmc;
1241         hw_raw_read_mapping[0x16] = csky_pmu_read_dcwac;
1242         hw_raw_read_mapping[0x17] = csky_pmu_read_dcwmc;
1243         hw_raw_read_mapping[0x18] = csky_pmu_read_l2rac;
1244         hw_raw_read_mapping[0x19] = csky_pmu_read_l2rmc;
1245         hw_raw_read_mapping[0x1a] = csky_pmu_read_l2wac;
1246         hw_raw_read_mapping[0x1b] = csky_pmu_read_l2wmc;
1247 
1248         memset((void *)hw_raw_write_mapping, 0,
1249                 sizeof(hw_raw_write_mapping[CSKY_PMU_MAX_EVENTS]));
1250 
1251         hw_raw_write_mapping[0x1]  = csky_pmu_write_cc;
1252         hw_raw_write_mapping[0x2]  = csky_pmu_write_ic;
1253         hw_raw_write_mapping[0x3]  = csky_pmu_write_icac;
1254         hw_raw_write_mapping[0x4]  = csky_pmu_write_icmc;
1255         hw_raw_write_mapping[0x5]  = csky_pmu_write_dcac;
1256         hw_raw_write_mapping[0x6]  = csky_pmu_write_dcmc;
1257         hw_raw_write_mapping[0x7]  = csky_pmu_write_l2ac;
1258         hw_raw_write_mapping[0x8]  = csky_pmu_write_l2mc;
1259         hw_raw_write_mapping[0xa]  = csky_pmu_write_iutlbmc;
1260         hw_raw_write_mapping[0xb]  = csky_pmu_write_dutlbmc;
1261         hw_raw_write_mapping[0xc]  = csky_pmu_write_jtlbmc;
1262         hw_raw_write_mapping[0xd]  = csky_pmu_write_softc;
1263         hw_raw_write_mapping[0xe]  = csky_pmu_write_cbmc;
1264         hw_raw_write_mapping[0xf]  = csky_pmu_write_cbic;
1265         hw_raw_write_mapping[0x10] = csky_pmu_write_ibmc;
1266         hw_raw_write_mapping[0x11] = csky_pmu_write_ibic;
1267         hw_raw_write_mapping[0x12] = csky_pmu_write_lsfc;
1268         hw_raw_write_mapping[0x13] = csky_pmu_write_sic;
1269         hw_raw_write_mapping[0x14] = csky_pmu_write_dcrac;
1270         hw_raw_write_mapping[0x15] = csky_pmu_write_dcrmc;
1271         hw_raw_write_mapping[0x16] = csky_pmu_write_dcwac;
1272         hw_raw_write_mapping[0x17] = csky_pmu_write_dcwmc;
1273         hw_raw_write_mapping[0x18] = csky_pmu_write_l2rac;
1274         hw_raw_write_mapping[0x19] = csky_pmu_write_l2rmc;
1275         hw_raw_write_mapping[0x1a] = csky_pmu_write_l2wac;
1276         hw_raw_write_mapping[0x1b] = csky_pmu_write_l2wmc;
1277 
1278         return 0;
1279 }
1280 
1281 static int csky_pmu_starting_cpu(unsigned int cpu)
1282 {
1283         enable_percpu_irq(csky_pmu_irq, 0);
1284         return 0;
1285 }
1286 
1287 static int csky_pmu_dying_cpu(unsigned int cpu)
1288 {
1289         disable_percpu_irq(csky_pmu_irq);
1290         return 0;
1291 }
1292 
1293 int csky_pmu_device_probe(struct platform_device *pdev,
1294                           const struct of_device_id *of_table)
1295 {
1296         struct device_node *node = pdev->dev.of_node;
1297         int ret;
1298 
1299         ret = init_hw_perf_events();
1300         if (ret) {
1301                 pr_notice("[perf] failed to probe PMU!\n");
1302                 return ret;
1303         }
1304 
1305         if (of_property_read_u32(node, "count-width",
1306                                  &csky_pmu.count_width)) {
1307                 csky_pmu.count_width = DEFAULT_COUNT_WIDTH;
1308         }
1309         csky_pmu.max_period = BIT_ULL(csky_pmu.count_width) - 1;
1310 
1311         csky_pmu.plat_device = pdev;
1312 
1313         /* Ensure the PMU has sane values out of reset. */
1314         on_each_cpu(csky_pmu_reset, &csky_pmu, 1);
1315 
1316         ret = csky_pmu_request_irq(csky_pmu_handle_irq);
1317         if (ret) {
1318                 csky_pmu.pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
1319                 pr_notice("[perf] PMU request irq fail!\n");
1320         }
1321 
1322         ret = cpuhp_setup_state(CPUHP_AP_PERF_CSKY_ONLINE, "AP_PERF_ONLINE",
1323                                 csky_pmu_starting_cpu,
1324                                 csky_pmu_dying_cpu);
1325         if (ret) {
1326                 csky_pmu_free_irq();
1327                 free_percpu(csky_pmu.hw_events);
1328                 return ret;
1329         }
1330 
1331         ret = perf_pmu_register(&csky_pmu.pmu, "cpu", PERF_TYPE_RAW);
1332         if (ret) {
1333                 csky_pmu_free_irq();
1334                 free_percpu(csky_pmu.hw_events);
1335         }
1336 
1337         return ret;
1338 }
1339 
1340 static const struct of_device_id csky_pmu_of_device_ids[] = {
1341         {.compatible = "csky,csky-pmu"},
1342         {},
1343 };
1344 
1345 static int csky_pmu_dev_probe(struct platform_device *pdev)
1346 {
1347         return csky_pmu_device_probe(pdev, csky_pmu_of_device_ids);
1348 }
1349 
1350 static struct platform_driver csky_pmu_driver = {
1351         .driver = {
1352                    .name = "csky-pmu",
1353                    .of_match_table = csky_pmu_of_device_ids,
1354                    },
1355         .probe = csky_pmu_dev_probe,
1356 };
1357 
1358 static int __init csky_pmu_probe(void)
1359 {
1360         int ret;
1361 
1362         ret = platform_driver_register(&csky_pmu_driver);
1363         if (ret)
1364                 pr_notice("[perf] PMU initialization failed\n");
1365         else
1366                 pr_notice("[perf] PMU initialization done\n");
1367 
1368         return ret;
1369 }
1370 
1371 device_initcall(csky_pmu_probe);
1372 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php