Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
0003 
0004 #include <linux/errno.h>
0005 #include <linux/interrupt.h>
0006 #include <linux/module.h>
0007 #include <linux/of.h>
0008 #include <linux/perf_event.h>
0009 #include <linux/platform_device.h>
0010 
0011 #define CSKY_PMU_MAX_EVENTS 32
0012 #define DEFAULT_COUNT_WIDTH 48
0013 
0014 #define HPCR        "<0, 0x0>"      /* PMU Control reg */
0015 #define HPSPR       "<0, 0x1>"      /* Start PC reg */
0016 #define HPEPR       "<0, 0x2>"      /* End PC reg */
0017 #define HPSIR       "<0, 0x3>"      /* Soft Counter reg */
0018 #define HPCNTENR    "<0, 0x4>"      /* Count Enable reg */
0019 #define HPINTENR    "<0, 0x5>"      /* Interrupt Enable reg */
0020 #define HPOFSR      "<0, 0x6>"      /* Interrupt Status reg */
0021 
0022 /* The events for a given PMU register set. */
0023 struct pmu_hw_events {
0024     /*
0025      * The events that are active on the PMU for the given index.
0026      */
0027     struct perf_event *events[CSKY_PMU_MAX_EVENTS];
0028 
0029     /*
0030      * A 1 bit for an index indicates that the counter is being used for
0031      * an event. A 0 means that the counter can be used.
0032      */
0033     unsigned long used_mask[BITS_TO_LONGS(CSKY_PMU_MAX_EVENTS)];
0034 };
0035 
0036 static uint64_t (*hw_raw_read_mapping[CSKY_PMU_MAX_EVENTS])(void);
0037 static void (*hw_raw_write_mapping[CSKY_PMU_MAX_EVENTS])(uint64_t val);
0038 
0039 static struct csky_pmu_t {
0040     struct pmu          pmu;
0041     struct pmu_hw_events __percpu   *hw_events;
0042     struct platform_device      *plat_device;
0043     uint32_t            count_width;
0044     uint32_t            hpcr;
0045     u64             max_period;
0046 } csky_pmu;
0047 static int csky_pmu_irq;
0048 
0049 #define to_csky_pmu(p)  (container_of(p, struct csky_pmu, pmu))
0050 
0051 #define cprgr(reg)              \
0052 ({                      \
0053     unsigned int tmp;           \
0054     asm volatile("cprgr %0, "reg"\n"    \
0055              : "=r"(tmp)        \
0056              :              \
0057              : "memory");       \
0058     tmp;                    \
0059 })
0060 
0061 #define cpwgr(reg, val)     \
0062 ({              \
0063     asm volatile(       \
0064     "cpwgr %0, "reg"\n" \
0065     :           \
0066     : "r"(val)      \
0067     : "memory");        \
0068 })
0069 
0070 #define cprcr(reg)              \
0071 ({                      \
0072     unsigned int tmp;           \
0073     asm volatile("cprcr %0, "reg"\n"    \
0074              : "=r"(tmp)        \
0075              :              \
0076              : "memory");       \
0077     tmp;                    \
0078 })
0079 
0080 #define cpwcr(reg, val)     \
0081 ({              \
0082     asm volatile(       \
0083     "cpwcr %0, "reg"\n" \
0084     :           \
0085     : "r"(val)      \
0086     : "memory");        \
0087 })
0088 
0089 /* cycle counter */
0090 uint64_t csky_pmu_read_cc(void)
0091 {
0092     uint32_t lo, hi, tmp;
0093     uint64_t result;
0094 
0095     do {
0096         tmp = cprgr("<0, 0x3>");
0097         lo  = cprgr("<0, 0x2>");
0098         hi  = cprgr("<0, 0x3>");
0099     } while (hi != tmp);
0100 
0101     result = (uint64_t) (hi) << 32;
0102     result |= lo;
0103 
0104     return result;
0105 }
0106 
0107 static void csky_pmu_write_cc(uint64_t val)
0108 {
0109     cpwgr("<0, 0x2>", (uint32_t)  val);
0110     cpwgr("<0, 0x3>", (uint32_t) (val >> 32));
0111 }
0112 
0113 /* instruction counter */
0114 static uint64_t csky_pmu_read_ic(void)
0115 {
0116     uint32_t lo, hi, tmp;
0117     uint64_t result;
0118 
0119     do {
0120         tmp = cprgr("<0, 0x5>");
0121         lo  = cprgr("<0, 0x4>");
0122         hi  = cprgr("<0, 0x5>");
0123     } while (hi != tmp);
0124 
0125     result = (uint64_t) (hi) << 32;
0126     result |= lo;
0127 
0128     return result;
0129 }
0130 
0131 static void csky_pmu_write_ic(uint64_t val)
0132 {
0133     cpwgr("<0, 0x4>", (uint32_t)  val);
0134     cpwgr("<0, 0x5>", (uint32_t) (val >> 32));
0135 }
0136 
0137 /* l1 icache access counter */
0138 static uint64_t csky_pmu_read_icac(void)
0139 {
0140     uint32_t lo, hi, tmp;
0141     uint64_t result;
0142 
0143     do {
0144         tmp = cprgr("<0, 0x7>");
0145         lo  = cprgr("<0, 0x6>");
0146         hi  = cprgr("<0, 0x7>");
0147     } while (hi != tmp);
0148 
0149     result = (uint64_t) (hi) << 32;
0150     result |= lo;
0151 
0152     return result;
0153 }
0154 
0155 static void csky_pmu_write_icac(uint64_t val)
0156 {
0157     cpwgr("<0, 0x6>", (uint32_t)  val);
0158     cpwgr("<0, 0x7>", (uint32_t) (val >> 32));
0159 }
0160 
0161 /* l1 icache miss counter */
0162 static uint64_t csky_pmu_read_icmc(void)
0163 {
0164     uint32_t lo, hi, tmp;
0165     uint64_t result;
0166 
0167     do {
0168         tmp = cprgr("<0, 0x9>");
0169         lo  = cprgr("<0, 0x8>");
0170         hi  = cprgr("<0, 0x9>");
0171     } while (hi != tmp);
0172 
0173     result = (uint64_t) (hi) << 32;
0174     result |= lo;
0175 
0176     return result;
0177 }
0178 
0179 static void csky_pmu_write_icmc(uint64_t val)
0180 {
0181     cpwgr("<0, 0x8>", (uint32_t)  val);
0182     cpwgr("<0, 0x9>", (uint32_t) (val >> 32));
0183 }
0184 
0185 /* l1 dcache access counter */
0186 static uint64_t csky_pmu_read_dcac(void)
0187 {
0188     uint32_t lo, hi, tmp;
0189     uint64_t result;
0190 
0191     do {
0192         tmp = cprgr("<0, 0xb>");
0193         lo  = cprgr("<0, 0xa>");
0194         hi  = cprgr("<0, 0xb>");
0195     } while (hi != tmp);
0196 
0197     result = (uint64_t) (hi) << 32;
0198     result |= lo;
0199 
0200     return result;
0201 }
0202 
0203 static void csky_pmu_write_dcac(uint64_t val)
0204 {
0205     cpwgr("<0, 0xa>", (uint32_t)  val);
0206     cpwgr("<0, 0xb>", (uint32_t) (val >> 32));
0207 }
0208 
0209 /* l1 dcache miss counter */
0210 static uint64_t csky_pmu_read_dcmc(void)
0211 {
0212     uint32_t lo, hi, tmp;
0213     uint64_t result;
0214 
0215     do {
0216         tmp = cprgr("<0, 0xd>");
0217         lo  = cprgr("<0, 0xc>");
0218         hi  = cprgr("<0, 0xd>");
0219     } while (hi != tmp);
0220 
0221     result = (uint64_t) (hi) << 32;
0222     result |= lo;
0223 
0224     return result;
0225 }
0226 
0227 static void csky_pmu_write_dcmc(uint64_t val)
0228 {
0229     cpwgr("<0, 0xc>", (uint32_t)  val);
0230     cpwgr("<0, 0xd>", (uint32_t) (val >> 32));
0231 }
0232 
0233 /* l2 cache access counter */
0234 static uint64_t csky_pmu_read_l2ac(void)
0235 {
0236     uint32_t lo, hi, tmp;
0237     uint64_t result;
0238 
0239     do {
0240         tmp = cprgr("<0, 0xf>");
0241         lo  = cprgr("<0, 0xe>");
0242         hi  = cprgr("<0, 0xf>");
0243     } while (hi != tmp);
0244 
0245     result = (uint64_t) (hi) << 32;
0246     result |= lo;
0247 
0248     return result;
0249 }
0250 
0251 static void csky_pmu_write_l2ac(uint64_t val)
0252 {
0253     cpwgr("<0, 0xe>", (uint32_t)  val);
0254     cpwgr("<0, 0xf>", (uint32_t) (val >> 32));
0255 }
0256 
0257 /* l2 cache miss counter */
0258 static uint64_t csky_pmu_read_l2mc(void)
0259 {
0260     uint32_t lo, hi, tmp;
0261     uint64_t result;
0262 
0263     do {
0264         tmp = cprgr("<0, 0x11>");
0265         lo  = cprgr("<0, 0x10>");
0266         hi  = cprgr("<0, 0x11>");
0267     } while (hi != tmp);
0268 
0269     result = (uint64_t) (hi) << 32;
0270     result |= lo;
0271 
0272     return result;
0273 }
0274 
0275 static void csky_pmu_write_l2mc(uint64_t val)
0276 {
0277     cpwgr("<0, 0x10>", (uint32_t)  val);
0278     cpwgr("<0, 0x11>", (uint32_t) (val >> 32));
0279 }
0280 
0281 /* I-UTLB miss counter */
0282 static uint64_t csky_pmu_read_iutlbmc(void)
0283 {
0284     uint32_t lo, hi, tmp;
0285     uint64_t result;
0286 
0287     do {
0288         tmp = cprgr("<0, 0x15>");
0289         lo  = cprgr("<0, 0x14>");
0290         hi  = cprgr("<0, 0x15>");
0291     } while (hi != tmp);
0292 
0293     result = (uint64_t) (hi) << 32;
0294     result |= lo;
0295 
0296     return result;
0297 }
0298 
0299 static void csky_pmu_write_iutlbmc(uint64_t val)
0300 {
0301     cpwgr("<0, 0x14>", (uint32_t)  val);
0302     cpwgr("<0, 0x15>", (uint32_t) (val >> 32));
0303 }
0304 
0305 /* D-UTLB miss counter */
0306 static uint64_t csky_pmu_read_dutlbmc(void)
0307 {
0308     uint32_t lo, hi, tmp;
0309     uint64_t result;
0310 
0311     do {
0312         tmp = cprgr("<0, 0x17>");
0313         lo  = cprgr("<0, 0x16>");
0314         hi  = cprgr("<0, 0x17>");
0315     } while (hi != tmp);
0316 
0317     result = (uint64_t) (hi) << 32;
0318     result |= lo;
0319 
0320     return result;
0321 }
0322 
0323 static void csky_pmu_write_dutlbmc(uint64_t val)
0324 {
0325     cpwgr("<0, 0x16>", (uint32_t)  val);
0326     cpwgr("<0, 0x17>", (uint32_t) (val >> 32));
0327 }
0328 
0329 /* JTLB miss counter */
0330 static uint64_t csky_pmu_read_jtlbmc(void)
0331 {
0332     uint32_t lo, hi, tmp;
0333     uint64_t result;
0334 
0335     do {
0336         tmp = cprgr("<0, 0x19>");
0337         lo  = cprgr("<0, 0x18>");
0338         hi  = cprgr("<0, 0x19>");
0339     } while (hi != tmp);
0340 
0341     result = (uint64_t) (hi) << 32;
0342     result |= lo;
0343 
0344     return result;
0345 }
0346 
0347 static void csky_pmu_write_jtlbmc(uint64_t val)
0348 {
0349     cpwgr("<0, 0x18>", (uint32_t)  val);
0350     cpwgr("<0, 0x19>", (uint32_t) (val >> 32));
0351 }
0352 
0353 /* software counter */
0354 static uint64_t csky_pmu_read_softc(void)
0355 {
0356     uint32_t lo, hi, tmp;
0357     uint64_t result;
0358 
0359     do {
0360         tmp = cprgr("<0, 0x1b>");
0361         lo  = cprgr("<0, 0x1a>");
0362         hi  = cprgr("<0, 0x1b>");
0363     } while (hi != tmp);
0364 
0365     result = (uint64_t) (hi) << 32;
0366     result |= lo;
0367 
0368     return result;
0369 }
0370 
0371 static void csky_pmu_write_softc(uint64_t val)
0372 {
0373     cpwgr("<0, 0x1a>", (uint32_t)  val);
0374     cpwgr("<0, 0x1b>", (uint32_t) (val >> 32));
0375 }
0376 
0377 /* conditional branch mispredict counter */
0378 static uint64_t csky_pmu_read_cbmc(void)
0379 {
0380     uint32_t lo, hi, tmp;
0381     uint64_t result;
0382 
0383     do {
0384         tmp = cprgr("<0, 0x1d>");
0385         lo  = cprgr("<0, 0x1c>");
0386         hi  = cprgr("<0, 0x1d>");
0387     } while (hi != tmp);
0388 
0389     result = (uint64_t) (hi) << 32;
0390     result |= lo;
0391 
0392     return result;
0393 }
0394 
0395 static void csky_pmu_write_cbmc(uint64_t val)
0396 {
0397     cpwgr("<0, 0x1c>", (uint32_t)  val);
0398     cpwgr("<0, 0x1d>", (uint32_t) (val >> 32));
0399 }
0400 
0401 /* conditional branch instruction counter */
0402 static uint64_t csky_pmu_read_cbic(void)
0403 {
0404     uint32_t lo, hi, tmp;
0405     uint64_t result;
0406 
0407     do {
0408         tmp = cprgr("<0, 0x1f>");
0409         lo  = cprgr("<0, 0x1e>");
0410         hi  = cprgr("<0, 0x1f>");
0411     } while (hi != tmp);
0412 
0413     result = (uint64_t) (hi) << 32;
0414     result |= lo;
0415 
0416     return result;
0417 }
0418 
0419 static void csky_pmu_write_cbic(uint64_t val)
0420 {
0421     cpwgr("<0, 0x1e>", (uint32_t)  val);
0422     cpwgr("<0, 0x1f>", (uint32_t) (val >> 32));
0423 }
0424 
0425 /* indirect branch mispredict counter */
0426 static uint64_t csky_pmu_read_ibmc(void)
0427 {
0428     uint32_t lo, hi, tmp;
0429     uint64_t result;
0430 
0431     do {
0432         tmp = cprgr("<0, 0x21>");
0433         lo  = cprgr("<0, 0x20>");
0434         hi  = cprgr("<0, 0x21>");
0435     } while (hi != tmp);
0436 
0437     result = (uint64_t) (hi) << 32;
0438     result |= lo;
0439 
0440     return result;
0441 }
0442 
0443 static void csky_pmu_write_ibmc(uint64_t val)
0444 {
0445     cpwgr("<0, 0x20>", (uint32_t)  val);
0446     cpwgr("<0, 0x21>", (uint32_t) (val >> 32));
0447 }
0448 
0449 /* indirect branch instruction counter */
0450 static uint64_t csky_pmu_read_ibic(void)
0451 {
0452     uint32_t lo, hi, tmp;
0453     uint64_t result;
0454 
0455     do {
0456         tmp = cprgr("<0, 0x23>");
0457         lo  = cprgr("<0, 0x22>");
0458         hi  = cprgr("<0, 0x23>");
0459     } while (hi != tmp);
0460 
0461     result = (uint64_t) (hi) << 32;
0462     result |= lo;
0463 
0464     return result;
0465 }
0466 
0467 static void csky_pmu_write_ibic(uint64_t val)
0468 {
0469     cpwgr("<0, 0x22>", (uint32_t)  val);
0470     cpwgr("<0, 0x23>", (uint32_t) (val >> 32));
0471 }
0472 
0473 /* LSU spec fail counter */
0474 static uint64_t csky_pmu_read_lsfc(void)
0475 {
0476     uint32_t lo, hi, tmp;
0477     uint64_t result;
0478 
0479     do {
0480         tmp = cprgr("<0, 0x25>");
0481         lo  = cprgr("<0, 0x24>");
0482         hi  = cprgr("<0, 0x25>");
0483     } while (hi != tmp);
0484 
0485     result = (uint64_t) (hi) << 32;
0486     result |= lo;
0487 
0488     return result;
0489 }
0490 
0491 static void csky_pmu_write_lsfc(uint64_t val)
0492 {
0493     cpwgr("<0, 0x24>", (uint32_t)  val);
0494     cpwgr("<0, 0x25>", (uint32_t) (val >> 32));
0495 }
0496 
0497 /* store instruction counter */
0498 static uint64_t csky_pmu_read_sic(void)
0499 {
0500     uint32_t lo, hi, tmp;
0501     uint64_t result;
0502 
0503     do {
0504         tmp = cprgr("<0, 0x27>");
0505         lo  = cprgr("<0, 0x26>");
0506         hi  = cprgr("<0, 0x27>");
0507     } while (hi != tmp);
0508 
0509     result = (uint64_t) (hi) << 32;
0510     result |= lo;
0511 
0512     return result;
0513 }
0514 
0515 static void csky_pmu_write_sic(uint64_t val)
0516 {
0517     cpwgr("<0, 0x26>", (uint32_t)  val);
0518     cpwgr("<0, 0x27>", (uint32_t) (val >> 32));
0519 }
0520 
0521 /* dcache read access counter */
0522 static uint64_t csky_pmu_read_dcrac(void)
0523 {
0524     uint32_t lo, hi, tmp;
0525     uint64_t result;
0526 
0527     do {
0528         tmp = cprgr("<0, 0x29>");
0529         lo  = cprgr("<0, 0x28>");
0530         hi  = cprgr("<0, 0x29>");
0531     } while (hi != tmp);
0532 
0533     result = (uint64_t) (hi) << 32;
0534     result |= lo;
0535 
0536     return result;
0537 }
0538 
0539 static void csky_pmu_write_dcrac(uint64_t val)
0540 {
0541     cpwgr("<0, 0x28>", (uint32_t)  val);
0542     cpwgr("<0, 0x29>", (uint32_t) (val >> 32));
0543 }
0544 
0545 /* dcache read miss counter */
0546 static uint64_t csky_pmu_read_dcrmc(void)
0547 {
0548     uint32_t lo, hi, tmp;
0549     uint64_t result;
0550 
0551     do {
0552         tmp = cprgr("<0, 0x2b>");
0553         lo  = cprgr("<0, 0x2a>");
0554         hi  = cprgr("<0, 0x2b>");
0555     } while (hi != tmp);
0556 
0557     result = (uint64_t) (hi) << 32;
0558     result |= lo;
0559 
0560     return result;
0561 }
0562 
0563 static void csky_pmu_write_dcrmc(uint64_t val)
0564 {
0565     cpwgr("<0, 0x2a>", (uint32_t)  val);
0566     cpwgr("<0, 0x2b>", (uint32_t) (val >> 32));
0567 }
0568 
0569 /* dcache write access counter */
0570 static uint64_t csky_pmu_read_dcwac(void)
0571 {
0572     uint32_t lo, hi, tmp;
0573     uint64_t result;
0574 
0575     do {
0576         tmp = cprgr("<0, 0x2d>");
0577         lo  = cprgr("<0, 0x2c>");
0578         hi  = cprgr("<0, 0x2d>");
0579     } while (hi != tmp);
0580 
0581     result = (uint64_t) (hi) << 32;
0582     result |= lo;
0583 
0584     return result;
0585 }
0586 
0587 static void csky_pmu_write_dcwac(uint64_t val)
0588 {
0589     cpwgr("<0, 0x2c>", (uint32_t)  val);
0590     cpwgr("<0, 0x2d>", (uint32_t) (val >> 32));
0591 }
0592 
0593 /* dcache write miss counter */
0594 static uint64_t csky_pmu_read_dcwmc(void)
0595 {
0596     uint32_t lo, hi, tmp;
0597     uint64_t result;
0598 
0599     do {
0600         tmp = cprgr("<0, 0x2f>");
0601         lo  = cprgr("<0, 0x2e>");
0602         hi  = cprgr("<0, 0x2f>");
0603     } while (hi != tmp);
0604 
0605     result = (uint64_t) (hi) << 32;
0606     result |= lo;
0607 
0608     return result;
0609 }
0610 
0611 static void csky_pmu_write_dcwmc(uint64_t val)
0612 {
0613     cpwgr("<0, 0x2e>", (uint32_t)  val);
0614     cpwgr("<0, 0x2f>", (uint32_t) (val >> 32));
0615 }
0616 
0617 /* l2cache read access counter */
0618 static uint64_t csky_pmu_read_l2rac(void)
0619 {
0620     uint32_t lo, hi, tmp;
0621     uint64_t result;
0622 
0623     do {
0624         tmp = cprgr("<0, 0x31>");
0625         lo  = cprgr("<0, 0x30>");
0626         hi  = cprgr("<0, 0x31>");
0627     } while (hi != tmp);
0628 
0629     result = (uint64_t) (hi) << 32;
0630     result |= lo;
0631 
0632     return result;
0633 }
0634 
0635 static void csky_pmu_write_l2rac(uint64_t val)
0636 {
0637     cpwgr("<0, 0x30>", (uint32_t)  val);
0638     cpwgr("<0, 0x31>", (uint32_t) (val >> 32));
0639 }
0640 
0641 /* l2cache read miss counter */
0642 static uint64_t csky_pmu_read_l2rmc(void)
0643 {
0644     uint32_t lo, hi, tmp;
0645     uint64_t result;
0646 
0647     do {
0648         tmp = cprgr("<0, 0x33>");
0649         lo  = cprgr("<0, 0x32>");
0650         hi  = cprgr("<0, 0x33>");
0651     } while (hi != tmp);
0652 
0653     result = (uint64_t) (hi) << 32;
0654     result |= lo;
0655 
0656     return result;
0657 }
0658 
0659 static void csky_pmu_write_l2rmc(uint64_t val)
0660 {
0661     cpwgr("<0, 0x32>", (uint32_t)  val);
0662     cpwgr("<0, 0x33>", (uint32_t) (val >> 32));
0663 }
0664 
0665 /* l2cache write access counter */
0666 static uint64_t csky_pmu_read_l2wac(void)
0667 {
0668     uint32_t lo, hi, tmp;
0669     uint64_t result;
0670 
0671     do {
0672         tmp = cprgr("<0, 0x35>");
0673         lo  = cprgr("<0, 0x34>");
0674         hi  = cprgr("<0, 0x35>");
0675     } while (hi != tmp);
0676 
0677     result = (uint64_t) (hi) << 32;
0678     result |= lo;
0679 
0680     return result;
0681 }
0682 
0683 static void csky_pmu_write_l2wac(uint64_t val)
0684 {
0685     cpwgr("<0, 0x34>", (uint32_t)  val);
0686     cpwgr("<0, 0x35>", (uint32_t) (val >> 32));
0687 }
0688 
0689 /* l2cache write miss counter */
0690 static uint64_t csky_pmu_read_l2wmc(void)
0691 {
0692     uint32_t lo, hi, tmp;
0693     uint64_t result;
0694 
0695     do {
0696         tmp = cprgr("<0, 0x37>");
0697         lo  = cprgr("<0, 0x36>");
0698         hi  = cprgr("<0, 0x37>");
0699     } while (hi != tmp);
0700 
0701     result = (uint64_t) (hi) << 32;
0702     result |= lo;
0703 
0704     return result;
0705 }
0706 
0707 static void csky_pmu_write_l2wmc(uint64_t val)
0708 {
0709     cpwgr("<0, 0x36>", (uint32_t)  val);
0710     cpwgr("<0, 0x37>", (uint32_t) (val >> 32));
0711 }
0712 
0713 #define HW_OP_UNSUPPORTED   0xffff
0714 static const int csky_pmu_hw_map[PERF_COUNT_HW_MAX] = {
0715     [PERF_COUNT_HW_CPU_CYCLES]      = 0x1,
0716     [PERF_COUNT_HW_INSTRUCTIONS]        = 0x2,
0717     [PERF_COUNT_HW_CACHE_REFERENCES]    = HW_OP_UNSUPPORTED,
0718     [PERF_COUNT_HW_CACHE_MISSES]        = HW_OP_UNSUPPORTED,
0719     [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0xf,
0720     [PERF_COUNT_HW_BRANCH_MISSES]       = 0xe,
0721     [PERF_COUNT_HW_BUS_CYCLES]      = HW_OP_UNSUPPORTED,
0722     [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = HW_OP_UNSUPPORTED,
0723     [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]  = HW_OP_UNSUPPORTED,
0724     [PERF_COUNT_HW_REF_CPU_CYCLES]      = HW_OP_UNSUPPORTED,
0725 };
0726 
0727 #define C(_x)           PERF_COUNT_HW_CACHE_##_x
0728 #define CACHE_OP_UNSUPPORTED    0xffff
0729 static const int csky_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
0730     [C(L1D)] = {
0731 #ifdef CONFIG_CPU_CK810
0732         [C(OP_READ)] = {
0733             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0734             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0735         },
0736         [C(OP_WRITE)] = {
0737             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0738             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0739         },
0740         [C(OP_PREFETCH)] = {
0741             [C(RESULT_ACCESS)]  = 0x5,
0742             [C(RESULT_MISS)]    = 0x6,
0743         },
0744 #else
0745         [C(OP_READ)] = {
0746             [C(RESULT_ACCESS)]  = 0x14,
0747             [C(RESULT_MISS)]    = 0x15,
0748         },
0749         [C(OP_WRITE)] = {
0750             [C(RESULT_ACCESS)]  = 0x16,
0751             [C(RESULT_MISS)]    = 0x17,
0752         },
0753         [C(OP_PREFETCH)] = {
0754             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0755             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0756         },
0757 #endif
0758     },
0759     [C(L1I)] = {
0760         [C(OP_READ)] = {
0761             [C(RESULT_ACCESS)]  = 0x3,
0762             [C(RESULT_MISS)]    = 0x4,
0763         },
0764         [C(OP_WRITE)] = {
0765             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0766             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0767         },
0768         [C(OP_PREFETCH)] = {
0769             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0770             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0771         },
0772     },
0773     [C(LL)] = {
0774 #ifdef CONFIG_CPU_CK810
0775         [C(OP_READ)] = {
0776             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0777             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0778         },
0779         [C(OP_WRITE)] = {
0780             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0781             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0782         },
0783         [C(OP_PREFETCH)] = {
0784             [C(RESULT_ACCESS)]  = 0x7,
0785             [C(RESULT_MISS)]    = 0x8,
0786         },
0787 #else
0788         [C(OP_READ)] = {
0789             [C(RESULT_ACCESS)]  = 0x18,
0790             [C(RESULT_MISS)]    = 0x19,
0791         },
0792         [C(OP_WRITE)] = {
0793             [C(RESULT_ACCESS)]  = 0x1a,
0794             [C(RESULT_MISS)]    = 0x1b,
0795         },
0796         [C(OP_PREFETCH)] = {
0797             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0798             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0799         },
0800 #endif
0801     },
0802     [C(DTLB)] = {
0803 #ifdef CONFIG_CPU_CK810
0804         [C(OP_READ)] = {
0805             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0806             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0807         },
0808         [C(OP_WRITE)] = {
0809             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0810             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0811         },
0812 #else
0813         [C(OP_READ)] = {
0814             [C(RESULT_ACCESS)]  = 0x14,
0815             [C(RESULT_MISS)]    = 0xb,
0816         },
0817         [C(OP_WRITE)] = {
0818             [C(RESULT_ACCESS)]  = 0x16,
0819             [C(RESULT_MISS)]    = 0xb,
0820         },
0821 #endif
0822         [C(OP_PREFETCH)] = {
0823             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0824             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0825         },
0826     },
0827     [C(ITLB)] = {
0828 #ifdef CONFIG_CPU_CK810
0829         [C(OP_READ)] = {
0830             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0831             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0832         },
0833 #else
0834         [C(OP_READ)] = {
0835             [C(RESULT_ACCESS)]  = 0x3,
0836             [C(RESULT_MISS)]    = 0xa,
0837         },
0838 #endif
0839         [C(OP_WRITE)] = {
0840             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0841             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0842         },
0843         [C(OP_PREFETCH)] = {
0844             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0845             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0846         },
0847     },
0848     [C(BPU)] = {
0849         [C(OP_READ)] = {
0850             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0851             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0852         },
0853         [C(OP_WRITE)] = {
0854             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0855             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0856         },
0857         [C(OP_PREFETCH)] = {
0858             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0859             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0860         },
0861     },
0862     [C(NODE)] = {
0863         [C(OP_READ)] = {
0864             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0865             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0866         },
0867         [C(OP_WRITE)] = {
0868             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0869             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0870         },
0871         [C(OP_PREFETCH)] = {
0872             [C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
0873             [C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
0874         },
0875     },
0876 };
0877 
0878 int  csky_pmu_event_set_period(struct perf_event *event)
0879 {
0880     struct hw_perf_event *hwc = &event->hw;
0881     s64 left = local64_read(&hwc->period_left);
0882     s64 period = hwc->sample_period;
0883     int ret = 0;
0884 
0885     if (unlikely(left <= -period)) {
0886         left = period;
0887         local64_set(&hwc->period_left, left);
0888         hwc->last_period = period;
0889         ret = 1;
0890     }
0891 
0892     if (unlikely(left <= 0)) {
0893         left += period;
0894         local64_set(&hwc->period_left, left);
0895         hwc->last_period = period;
0896         ret = 1;
0897     }
0898 
0899     if (left > (s64)csky_pmu.max_period)
0900         left = csky_pmu.max_period;
0901 
0902     /*
0903      * The hw event starts counting from this event offset,
0904      * mark it to be able to extract future "deltas":
0905      */
0906     local64_set(&hwc->prev_count, (u64)(-left));
0907 
0908     if (hw_raw_write_mapping[hwc->idx] != NULL)
0909         hw_raw_write_mapping[hwc->idx]((u64)(-left) &
0910                         csky_pmu.max_period);
0911 
0912     cpwcr(HPOFSR, ~BIT(hwc->idx) & cprcr(HPOFSR));
0913 
0914     perf_event_update_userpage(event);
0915 
0916     return ret;
0917 }
0918 
0919 static void csky_perf_event_update(struct perf_event *event,
0920                    struct hw_perf_event *hwc)
0921 {
0922     uint64_t prev_raw_count = local64_read(&hwc->prev_count);
0923     /*
0924      * Sign extend count value to 64bit, otherwise delta calculation
0925      * would be incorrect when overflow occurs.
0926      */
0927     uint64_t new_raw_count = sign_extend64(
0928         hw_raw_read_mapping[hwc->idx](), csky_pmu.count_width - 1);
0929     int64_t delta = new_raw_count - prev_raw_count;
0930 
0931     /*
0932      * We aren't afraid of hwc->prev_count changing beneath our feet
0933      * because there's no way for us to re-enter this function anytime.
0934      */
0935     local64_set(&hwc->prev_count, new_raw_count);
0936     local64_add(delta, &event->count);
0937     local64_sub(delta, &hwc->period_left);
0938 }
0939 
0940 static void csky_pmu_reset(void *info)
0941 {
0942     cpwcr(HPCR, BIT(31) | BIT(30) | BIT(1));
0943 }
0944 
0945 static void csky_pmu_read(struct perf_event *event)
0946 {
0947     csky_perf_event_update(event, &event->hw);
0948 }
0949 
0950 static int csky_pmu_cache_event(u64 config)
0951 {
0952     unsigned int cache_type, cache_op, cache_result;
0953 
0954     cache_type  = (config >>  0) & 0xff;
0955     cache_op    = (config >>  8) & 0xff;
0956     cache_result    = (config >> 16) & 0xff;
0957 
0958     if (cache_type >= PERF_COUNT_HW_CACHE_MAX)
0959         return -EINVAL;
0960     if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX)
0961         return -EINVAL;
0962     if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
0963         return -EINVAL;
0964 
0965     return csky_pmu_cache_map[cache_type][cache_op][cache_result];
0966 }
0967 
0968 static int csky_pmu_event_init(struct perf_event *event)
0969 {
0970     struct hw_perf_event *hwc = &event->hw;
0971     int ret;
0972 
0973     switch (event->attr.type) {
0974     case PERF_TYPE_HARDWARE:
0975         if (event->attr.config >= PERF_COUNT_HW_MAX)
0976             return -ENOENT;
0977         ret = csky_pmu_hw_map[event->attr.config];
0978         if (ret == HW_OP_UNSUPPORTED)
0979             return -ENOENT;
0980         hwc->idx = ret;
0981         break;
0982     case PERF_TYPE_HW_CACHE:
0983         ret = csky_pmu_cache_event(event->attr.config);
0984         if (ret == CACHE_OP_UNSUPPORTED)
0985             return -ENOENT;
0986         hwc->idx = ret;
0987         break;
0988     case PERF_TYPE_RAW:
0989         if (hw_raw_read_mapping[event->attr.config] == NULL)
0990             return -ENOENT;
0991         hwc->idx = event->attr.config;
0992         break;
0993     default:
0994         return -ENOENT;
0995     }
0996 
0997     if (event->attr.exclude_user)
0998         csky_pmu.hpcr = BIT(2);
0999     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);