cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

perf_event.c (30117B)


      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. */
     23struct 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
     36static uint64_t (*hw_raw_read_mapping[CSKY_PMU_MAX_EVENTS])(void);
     37static void (*hw_raw_write_mapping[CSKY_PMU_MAX_EVENTS])(uint64_t val);
     38
     39static 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;
     47static 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 */
     90uint64_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
    107static 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 */
    114static 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
    131static 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 */
    138static 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
    155static 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 */
    162static 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
    179static 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 */
    186static 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
    203static 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 */
    210static 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
    227static 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 */
    234static 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
    251static 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 */
    258static 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
    275static 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 */
    282static 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
    299static 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 */
    306static 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
    323static 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 */
    330static 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
    347static 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 */
    354static 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
    371static 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 */
    378static 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
    395static 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 */
    402static 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
    419static 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 */
    426static 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
    443static 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 */
    450static 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
    467static 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 */
    474static 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
    491static 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 */
    498static 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
    515static 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 */
    522static 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
    539static 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 */
    546static 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
    563static 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 */
    570static 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
    587static 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 */
    594static 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
    611static 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 */
    618static 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
    635static 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 */
    642static 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
    659static 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 */
    666static 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
    683static 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 */
    690static 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
    707static 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
    714static 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
    729static 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
    878int  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
    919static 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
    940static void csky_pmu_reset(void *info)
    941{
    942	cpwcr(HPCR, BIT(31) | BIT(30) | BIT(1));
    943}
    944
    945static void csky_pmu_read(struct perf_event *event)
    946{
    947	csky_perf_event_update(event, &event->hw);
    948}
    949
    950static 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
    968static 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 */
   1010static void csky_pmu_enable(struct pmu *pmu)
   1011{
   1012	cpwcr(HPCR, csky_pmu.hpcr);
   1013}
   1014
   1015/* stops all counters */
   1016static void csky_pmu_disable(struct pmu *pmu)
   1017{
   1018	cpwcr(HPCR, BIT(1));
   1019}
   1020
   1021static 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
   1045static 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
   1059static 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
   1073static 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 */
   1086static 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
   1103static 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
   1160static 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
   1188static 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
   1198int 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
   1281static int csky_pmu_starting_cpu(unsigned int cpu)
   1282{
   1283	enable_percpu_irq(csky_pmu_irq, 0);
   1284	return 0;
   1285}
   1286
   1287static int csky_pmu_dying_cpu(unsigned int cpu)
   1288{
   1289	disable_percpu_irq(csky_pmu_irq);
   1290	return 0;
   1291}
   1292
   1293int 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
   1340static const struct of_device_id csky_pmu_of_device_ids[] = {
   1341	{.compatible = "csky,csky-pmu"},
   1342	{},
   1343};
   1344
   1345static int csky_pmu_dev_probe(struct platform_device *pdev)
   1346{
   1347	return csky_pmu_device_probe(pdev, csky_pmu_of_device_ids);
   1348}
   1349
   1350static 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
   1358static 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
   1371device_initcall(csky_pmu_probe);