perf_event_xscale.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * ARMv5 [xscale] Performance counter handling code.
  4. *
  5. * Copyright (C) 2010, ARM Ltd., Will Deacon <will.deacon@arm.com>
  6. *
  7. * Based on the previous xscale OProfile code.
  8. *
  9. * There are two variants of the xscale PMU that we support:
  10. * - xscale1pmu: 2 event counters and a cycle counter
  11. * - xscale2pmu: 4 event counters and a cycle counter
  12. * The two variants share event definitions, but have different
  13. * PMU structures.
  14. */
  15. #ifdef CONFIG_CPU_XSCALE
  16. #include <asm/cputype.h>
  17. #include <asm/irq_regs.h>
  18. #include <linux/of.h>
  19. #include <linux/perf/arm_pmu.h>
  20. #include <linux/platform_device.h>
  21. enum xscale_perf_types {
  22. XSCALE_PERFCTR_ICACHE_MISS = 0x00,
  23. XSCALE_PERFCTR_ICACHE_NO_DELIVER = 0x01,
  24. XSCALE_PERFCTR_DATA_STALL = 0x02,
  25. XSCALE_PERFCTR_ITLB_MISS = 0x03,
  26. XSCALE_PERFCTR_DTLB_MISS = 0x04,
  27. XSCALE_PERFCTR_BRANCH = 0x05,
  28. XSCALE_PERFCTR_BRANCH_MISS = 0x06,
  29. XSCALE_PERFCTR_INSTRUCTION = 0x07,
  30. XSCALE_PERFCTR_DCACHE_FULL_STALL = 0x08,
  31. XSCALE_PERFCTR_DCACHE_FULL_STALL_CONTIG = 0x09,
  32. XSCALE_PERFCTR_DCACHE_ACCESS = 0x0A,
  33. XSCALE_PERFCTR_DCACHE_MISS = 0x0B,
  34. XSCALE_PERFCTR_DCACHE_WRITE_BACK = 0x0C,
  35. XSCALE_PERFCTR_PC_CHANGED = 0x0D,
  36. XSCALE_PERFCTR_BCU_REQUEST = 0x10,
  37. XSCALE_PERFCTR_BCU_FULL = 0x11,
  38. XSCALE_PERFCTR_BCU_DRAIN = 0x12,
  39. XSCALE_PERFCTR_BCU_ECC_NO_ELOG = 0x14,
  40. XSCALE_PERFCTR_BCU_1_BIT_ERR = 0x15,
  41. XSCALE_PERFCTR_RMW = 0x16,
  42. /* XSCALE_PERFCTR_CCNT is not hardware defined */
  43. XSCALE_PERFCTR_CCNT = 0xFE,
  44. XSCALE_PERFCTR_UNUSED = 0xFF,
  45. };
  46. enum xscale_counters {
  47. XSCALE_CYCLE_COUNTER = 0,
  48. XSCALE_COUNTER0,
  49. XSCALE_COUNTER1,
  50. XSCALE_COUNTER2,
  51. XSCALE_COUNTER3,
  52. };
  53. static const unsigned xscale_perf_map[PERF_COUNT_HW_MAX] = {
  54. PERF_MAP_ALL_UNSUPPORTED,
  55. [PERF_COUNT_HW_CPU_CYCLES] = XSCALE_PERFCTR_CCNT,
  56. [PERF_COUNT_HW_INSTRUCTIONS] = XSCALE_PERFCTR_INSTRUCTION,
  57. [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XSCALE_PERFCTR_BRANCH,
  58. [PERF_COUNT_HW_BRANCH_MISSES] = XSCALE_PERFCTR_BRANCH_MISS,
  59. [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = XSCALE_PERFCTR_ICACHE_NO_DELIVER,
  60. };
  61. static const unsigned xscale_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
  62. [PERF_COUNT_HW_CACHE_OP_MAX]
  63. [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
  64. PERF_CACHE_MAP_ALL_UNSUPPORTED,
  65. [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
  66. [C(L1D)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
  67. [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = XSCALE_PERFCTR_DCACHE_ACCESS,
  68. [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)] = XSCALE_PERFCTR_DCACHE_MISS,
  69. [C(L1I)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_ICACHE_MISS,
  70. [C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
  71. [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)] = XSCALE_PERFCTR_DTLB_MISS,
  72. [C(ITLB)][C(OP_READ)][C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
  73. [C(ITLB)][C(OP_WRITE)][C(RESULT_MISS)] = XSCALE_PERFCTR_ITLB_MISS,
  74. };
  75. #define XSCALE_PMU_ENABLE 0x001
  76. #define XSCALE_PMN_RESET 0x002
  77. #define XSCALE_CCNT_RESET 0x004
  78. #define XSCALE_PMU_RESET (CCNT_RESET | PMN_RESET)
  79. #define XSCALE_PMU_CNT64 0x008
  80. #define XSCALE1_OVERFLOWED_MASK 0x700
  81. #define XSCALE1_CCOUNT_OVERFLOW 0x400
  82. #define XSCALE1_COUNT0_OVERFLOW 0x100
  83. #define XSCALE1_COUNT1_OVERFLOW 0x200
  84. #define XSCALE1_CCOUNT_INT_EN 0x040
  85. #define XSCALE1_COUNT0_INT_EN 0x010
  86. #define XSCALE1_COUNT1_INT_EN 0x020
  87. #define XSCALE1_COUNT0_EVT_SHFT 12
  88. #define XSCALE1_COUNT0_EVT_MASK (0xff << XSCALE1_COUNT0_EVT_SHFT)
  89. #define XSCALE1_COUNT1_EVT_SHFT 20
  90. #define XSCALE1_COUNT1_EVT_MASK (0xff << XSCALE1_COUNT1_EVT_SHFT)
  91. static inline u32
  92. xscale1pmu_read_pmnc(void)
  93. {
  94. u32 val;
  95. asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r" (val));
  96. return val;
  97. }
  98. static inline void
  99. xscale1pmu_write_pmnc(u32 val)
  100. {
  101. /* upper 4bits and 7, 11 are write-as-0 */
  102. val &= 0xffff77f;
  103. asm volatile("mcr p14, 0, %0, c0, c0, 0" : : "r" (val));
  104. }
  105. static inline int
  106. xscale1_pmnc_counter_has_overflowed(unsigned long pmnc,
  107. enum xscale_counters counter)
  108. {
  109. int ret = 0;
  110. switch (counter) {
  111. case XSCALE_CYCLE_COUNTER:
  112. ret = pmnc & XSCALE1_CCOUNT_OVERFLOW;
  113. break;
  114. case XSCALE_COUNTER0:
  115. ret = pmnc & XSCALE1_COUNT0_OVERFLOW;
  116. break;
  117. case XSCALE_COUNTER1:
  118. ret = pmnc & XSCALE1_COUNT1_OVERFLOW;
  119. break;
  120. default:
  121. WARN_ONCE(1, "invalid counter number (%d)\n", counter);
  122. }
  123. return ret;
  124. }
  125. static irqreturn_t
  126. xscale1pmu_handle_irq(struct arm_pmu *cpu_pmu)
  127. {
  128. unsigned long pmnc;
  129. struct perf_sample_data data;
  130. struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
  131. struct pt_regs *regs;
  132. int idx;
  133. /*
  134. * NOTE: there's an A stepping erratum that states if an overflow
  135. * bit already exists and another occurs, the previous
  136. * Overflow bit gets cleared. There's no workaround.
  137. * Fixed in B stepping or later.
  138. */
  139. pmnc = xscale1pmu_read_pmnc();
  140. /*
  141. * Write the value back to clear the overflow flags. Overflow
  142. * flags remain in pmnc for use below. We also disable the PMU
  143. * while we process the interrupt.
  144. */
  145. xscale1pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
  146. if (!(pmnc & XSCALE1_OVERFLOWED_MASK))
  147. return IRQ_NONE;
  148. regs = get_irq_regs();
  149. for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
  150. struct perf_event *event = cpuc->events[idx];
  151. struct hw_perf_event *hwc;
  152. if (!event)
  153. continue;
  154. if (!xscale1_pmnc_counter_has_overflowed(pmnc, idx))
  155. continue;
  156. hwc = &event->hw;
  157. armpmu_event_update(event);
  158. perf_sample_data_init(&data, 0, hwc->last_period);
  159. if (!armpmu_event_set_period(event))
  160. continue;
  161. if (perf_event_overflow(event, &data, regs))
  162. cpu_pmu->disable(event);
  163. }
  164. irq_work_run();
  165. /*
  166. * Re-enable the PMU.
  167. */
  168. pmnc = xscale1pmu_read_pmnc() | XSCALE_PMU_ENABLE;
  169. xscale1pmu_write_pmnc(pmnc);
  170. return IRQ_HANDLED;
  171. }
  172. static void xscale1pmu_enable_event(struct perf_event *event)
  173. {
  174. unsigned long val, mask, evt, flags;
  175. struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
  176. struct hw_perf_event *hwc = &event->hw;
  177. struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
  178. int idx = hwc->idx;
  179. switch (idx) {
  180. case XSCALE_CYCLE_COUNTER:
  181. mask = 0;
  182. evt = XSCALE1_CCOUNT_INT_EN;
  183. break;
  184. case XSCALE_COUNTER0:
  185. mask = XSCALE1_COUNT0_EVT_MASK;
  186. evt = (hwc->config_base << XSCALE1_COUNT0_EVT_SHFT) |
  187. XSCALE1_COUNT0_INT_EN;
  188. break;
  189. case XSCALE_COUNTER1:
  190. mask = XSCALE1_COUNT1_EVT_MASK;
  191. evt = (hwc->config_base << XSCALE1_COUNT1_EVT_SHFT) |
  192. XSCALE1_COUNT1_INT_EN;
  193. break;
  194. default:
  195. WARN_ONCE(1, "invalid counter number (%d)\n", idx);
  196. return;
  197. }
  198. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  199. val = xscale1pmu_read_pmnc();
  200. val &= ~mask;
  201. val |= evt;
  202. xscale1pmu_write_pmnc(val);
  203. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  204. }
  205. static void xscale1pmu_disable_event(struct perf_event *event)
  206. {
  207. unsigned long val, mask, evt, flags;
  208. struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
  209. struct hw_perf_event *hwc = &event->hw;
  210. struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
  211. int idx = hwc->idx;
  212. switch (idx) {
  213. case XSCALE_CYCLE_COUNTER:
  214. mask = XSCALE1_CCOUNT_INT_EN;
  215. evt = 0;
  216. break;
  217. case XSCALE_COUNTER0:
  218. mask = XSCALE1_COUNT0_INT_EN | XSCALE1_COUNT0_EVT_MASK;
  219. evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT0_EVT_SHFT;
  220. break;
  221. case XSCALE_COUNTER1:
  222. mask = XSCALE1_COUNT1_INT_EN | XSCALE1_COUNT1_EVT_MASK;
  223. evt = XSCALE_PERFCTR_UNUSED << XSCALE1_COUNT1_EVT_SHFT;
  224. break;
  225. default:
  226. WARN_ONCE(1, "invalid counter number (%d)\n", idx);
  227. return;
  228. }
  229. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  230. val = xscale1pmu_read_pmnc();
  231. val &= ~mask;
  232. val |= evt;
  233. xscale1pmu_write_pmnc(val);
  234. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  235. }
  236. static int
  237. xscale1pmu_get_event_idx(struct pmu_hw_events *cpuc,
  238. struct perf_event *event)
  239. {
  240. struct hw_perf_event *hwc = &event->hw;
  241. if (XSCALE_PERFCTR_CCNT == hwc->config_base) {
  242. if (test_and_set_bit(XSCALE_CYCLE_COUNTER, cpuc->used_mask))
  243. return -EAGAIN;
  244. return XSCALE_CYCLE_COUNTER;
  245. } else {
  246. if (!test_and_set_bit(XSCALE_COUNTER1, cpuc->used_mask))
  247. return XSCALE_COUNTER1;
  248. if (!test_and_set_bit(XSCALE_COUNTER0, cpuc->used_mask))
  249. return XSCALE_COUNTER0;
  250. return -EAGAIN;
  251. }
  252. }
  253. static void xscalepmu_clear_event_idx(struct pmu_hw_events *cpuc,
  254. struct perf_event *event)
  255. {
  256. clear_bit(event->hw.idx, cpuc->used_mask);
  257. }
  258. static void xscale1pmu_start(struct arm_pmu *cpu_pmu)
  259. {
  260. unsigned long flags, val;
  261. struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
  262. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  263. val = xscale1pmu_read_pmnc();
  264. val |= XSCALE_PMU_ENABLE;
  265. xscale1pmu_write_pmnc(val);
  266. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  267. }
  268. static void xscale1pmu_stop(struct arm_pmu *cpu_pmu)
  269. {
  270. unsigned long flags, val;
  271. struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
  272. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  273. val = xscale1pmu_read_pmnc();
  274. val &= ~XSCALE_PMU_ENABLE;
  275. xscale1pmu_write_pmnc(val);
  276. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  277. }
  278. static inline u64 xscale1pmu_read_counter(struct perf_event *event)
  279. {
  280. struct hw_perf_event *hwc = &event->hw;
  281. int counter = hwc->idx;
  282. u32 val = 0;
  283. switch (counter) {
  284. case XSCALE_CYCLE_COUNTER:
  285. asm volatile("mrc p14, 0, %0, c1, c0, 0" : "=r" (val));
  286. break;
  287. case XSCALE_COUNTER0:
  288. asm volatile("mrc p14, 0, %0, c2, c0, 0" : "=r" (val));
  289. break;
  290. case XSCALE_COUNTER1:
  291. asm volatile("mrc p14, 0, %0, c3, c0, 0" : "=r" (val));
  292. break;
  293. }
  294. return val;
  295. }
  296. static inline void xscale1pmu_write_counter(struct perf_event *event, u64 val)
  297. {
  298. struct hw_perf_event *hwc = &event->hw;
  299. int counter = hwc->idx;
  300. switch (counter) {
  301. case XSCALE_CYCLE_COUNTER:
  302. asm volatile("mcr p14, 0, %0, c1, c0, 0" : : "r" (val));
  303. break;
  304. case XSCALE_COUNTER0:
  305. asm volatile("mcr p14, 0, %0, c2, c0, 0" : : "r" (val));
  306. break;
  307. case XSCALE_COUNTER1:
  308. asm volatile("mcr p14, 0, %0, c3, c0, 0" : : "r" (val));
  309. break;
  310. }
  311. }
  312. static int xscale_map_event(struct perf_event *event)
  313. {
  314. return armpmu_map_event(event, &xscale_perf_map,
  315. &xscale_perf_cache_map, 0xFF);
  316. }
  317. static int xscale1pmu_init(struct arm_pmu *cpu_pmu)
  318. {
  319. cpu_pmu->name = "armv5_xscale1";
  320. cpu_pmu->handle_irq = xscale1pmu_handle_irq;
  321. cpu_pmu->enable = xscale1pmu_enable_event;
  322. cpu_pmu->disable = xscale1pmu_disable_event;
  323. cpu_pmu->read_counter = xscale1pmu_read_counter;
  324. cpu_pmu->write_counter = xscale1pmu_write_counter;
  325. cpu_pmu->get_event_idx = xscale1pmu_get_event_idx;
  326. cpu_pmu->clear_event_idx = xscalepmu_clear_event_idx;
  327. cpu_pmu->start = xscale1pmu_start;
  328. cpu_pmu->stop = xscale1pmu_stop;
  329. cpu_pmu->map_event = xscale_map_event;
  330. cpu_pmu->num_events = 3;
  331. return 0;
  332. }
  333. #define XSCALE2_OVERFLOWED_MASK 0x01f
  334. #define XSCALE2_CCOUNT_OVERFLOW 0x001
  335. #define XSCALE2_COUNT0_OVERFLOW 0x002
  336. #define XSCALE2_COUNT1_OVERFLOW 0x004
  337. #define XSCALE2_COUNT2_OVERFLOW 0x008
  338. #define XSCALE2_COUNT3_OVERFLOW 0x010
  339. #define XSCALE2_CCOUNT_INT_EN 0x001
  340. #define XSCALE2_COUNT0_INT_EN 0x002
  341. #define XSCALE2_COUNT1_INT_EN 0x004
  342. #define XSCALE2_COUNT2_INT_EN 0x008
  343. #define XSCALE2_COUNT3_INT_EN 0x010
  344. #define XSCALE2_COUNT0_EVT_SHFT 0
  345. #define XSCALE2_COUNT0_EVT_MASK (0xff << XSCALE2_COUNT0_EVT_SHFT)
  346. #define XSCALE2_COUNT1_EVT_SHFT 8
  347. #define XSCALE2_COUNT1_EVT_MASK (0xff << XSCALE2_COUNT1_EVT_SHFT)
  348. #define XSCALE2_COUNT2_EVT_SHFT 16
  349. #define XSCALE2_COUNT2_EVT_MASK (0xff << XSCALE2_COUNT2_EVT_SHFT)
  350. #define XSCALE2_COUNT3_EVT_SHFT 24
  351. #define XSCALE2_COUNT3_EVT_MASK (0xff << XSCALE2_COUNT3_EVT_SHFT)
  352. static inline u32
  353. xscale2pmu_read_pmnc(void)
  354. {
  355. u32 val;
  356. asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (val));
  357. /* bits 1-2 and 4-23 are read-unpredictable */
  358. return val & 0xff000009;
  359. }
  360. static inline void
  361. xscale2pmu_write_pmnc(u32 val)
  362. {
  363. /* bits 4-23 are write-as-0, 24-31 are write ignored */
  364. val &= 0xf;
  365. asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (val));
  366. }
  367. static inline u32
  368. xscale2pmu_read_overflow_flags(void)
  369. {
  370. u32 val;
  371. asm volatile("mrc p14, 0, %0, c5, c1, 0" : "=r" (val));
  372. return val;
  373. }
  374. static inline void
  375. xscale2pmu_write_overflow_flags(u32 val)
  376. {
  377. asm volatile("mcr p14, 0, %0, c5, c1, 0" : : "r" (val));
  378. }
  379. static inline u32
  380. xscale2pmu_read_event_select(void)
  381. {
  382. u32 val;
  383. asm volatile("mrc p14, 0, %0, c8, c1, 0" : "=r" (val));
  384. return val;
  385. }
  386. static inline void
  387. xscale2pmu_write_event_select(u32 val)
  388. {
  389. asm volatile("mcr p14, 0, %0, c8, c1, 0" : : "r"(val));
  390. }
  391. static inline u32
  392. xscale2pmu_read_int_enable(void)
  393. {
  394. u32 val;
  395. asm volatile("mrc p14, 0, %0, c4, c1, 0" : "=r" (val));
  396. return val;
  397. }
  398. static void
  399. xscale2pmu_write_int_enable(u32 val)
  400. {
  401. asm volatile("mcr p14, 0, %0, c4, c1, 0" : : "r" (val));
  402. }
  403. static inline int
  404. xscale2_pmnc_counter_has_overflowed(unsigned long of_flags,
  405. enum xscale_counters counter)
  406. {
  407. int ret = 0;
  408. switch (counter) {
  409. case XSCALE_CYCLE_COUNTER:
  410. ret = of_flags & XSCALE2_CCOUNT_OVERFLOW;
  411. break;
  412. case XSCALE_COUNTER0:
  413. ret = of_flags & XSCALE2_COUNT0_OVERFLOW;
  414. break;
  415. case XSCALE_COUNTER1:
  416. ret = of_flags & XSCALE2_COUNT1_OVERFLOW;
  417. break;
  418. case XSCALE_COUNTER2:
  419. ret = of_flags & XSCALE2_COUNT2_OVERFLOW;
  420. break;
  421. case XSCALE_COUNTER3:
  422. ret = of_flags & XSCALE2_COUNT3_OVERFLOW;
  423. break;
  424. default:
  425. WARN_ONCE(1, "invalid counter number (%d)\n", counter);
  426. }
  427. return ret;
  428. }
  429. static irqreturn_t
  430. xscale2pmu_handle_irq(struct arm_pmu *cpu_pmu)
  431. {
  432. unsigned long pmnc, of_flags;
  433. struct perf_sample_data data;
  434. struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events);
  435. struct pt_regs *regs;
  436. int idx;
  437. /* Disable the PMU. */
  438. pmnc = xscale2pmu_read_pmnc();
  439. xscale2pmu_write_pmnc(pmnc & ~XSCALE_PMU_ENABLE);
  440. /* Check the overflow flag register. */
  441. of_flags = xscale2pmu_read_overflow_flags();
  442. if (!(of_flags & XSCALE2_OVERFLOWED_MASK))
  443. return IRQ_NONE;
  444. /* Clear the overflow bits. */
  445. xscale2pmu_write_overflow_flags(of_flags);
  446. regs = get_irq_regs();
  447. for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
  448. struct perf_event *event = cpuc->events[idx];
  449. struct hw_perf_event *hwc;
  450. if (!event)
  451. continue;
  452. if (!xscale2_pmnc_counter_has_overflowed(of_flags, idx))
  453. continue;
  454. hwc = &event->hw;
  455. armpmu_event_update(event);
  456. perf_sample_data_init(&data, 0, hwc->last_period);
  457. if (!armpmu_event_set_period(event))
  458. continue;
  459. if (perf_event_overflow(event, &data, regs))
  460. cpu_pmu->disable(event);
  461. }
  462. irq_work_run();
  463. /*
  464. * Re-enable the PMU.
  465. */
  466. pmnc = xscale2pmu_read_pmnc() | XSCALE_PMU_ENABLE;
  467. xscale2pmu_write_pmnc(pmnc);
  468. return IRQ_HANDLED;
  469. }
  470. static void xscale2pmu_enable_event(struct perf_event *event)
  471. {
  472. unsigned long flags, ien, evtsel;
  473. struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
  474. struct hw_perf_event *hwc = &event->hw;
  475. struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
  476. int idx = hwc->idx;
  477. ien = xscale2pmu_read_int_enable();
  478. evtsel = xscale2pmu_read_event_select();
  479. switch (idx) {
  480. case XSCALE_CYCLE_COUNTER:
  481. ien |= XSCALE2_CCOUNT_INT_EN;
  482. break;
  483. case XSCALE_COUNTER0:
  484. ien |= XSCALE2_COUNT0_INT_EN;
  485. evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
  486. evtsel |= hwc->config_base << XSCALE2_COUNT0_EVT_SHFT;
  487. break;
  488. case XSCALE_COUNTER1:
  489. ien |= XSCALE2_COUNT1_INT_EN;
  490. evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
  491. evtsel |= hwc->config_base << XSCALE2_COUNT1_EVT_SHFT;
  492. break;
  493. case XSCALE_COUNTER2:
  494. ien |= XSCALE2_COUNT2_INT_EN;
  495. evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
  496. evtsel |= hwc->config_base << XSCALE2_COUNT2_EVT_SHFT;
  497. break;
  498. case XSCALE_COUNTER3:
  499. ien |= XSCALE2_COUNT3_INT_EN;
  500. evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
  501. evtsel |= hwc->config_base << XSCALE2_COUNT3_EVT_SHFT;
  502. break;
  503. default:
  504. WARN_ONCE(1, "invalid counter number (%d)\n", idx);
  505. return;
  506. }
  507. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  508. xscale2pmu_write_event_select(evtsel);
  509. xscale2pmu_write_int_enable(ien);
  510. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  511. }
  512. static void xscale2pmu_disable_event(struct perf_event *event)
  513. {
  514. unsigned long flags, ien, evtsel, of_flags;
  515. struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
  516. struct hw_perf_event *hwc = &event->hw;
  517. struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
  518. int idx = hwc->idx;
  519. ien = xscale2pmu_read_int_enable();
  520. evtsel = xscale2pmu_read_event_select();
  521. switch (idx) {
  522. case XSCALE_CYCLE_COUNTER:
  523. ien &= ~XSCALE2_CCOUNT_INT_EN;
  524. of_flags = XSCALE2_CCOUNT_OVERFLOW;
  525. break;
  526. case XSCALE_COUNTER0:
  527. ien &= ~XSCALE2_COUNT0_INT_EN;
  528. evtsel &= ~XSCALE2_COUNT0_EVT_MASK;
  529. evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT0_EVT_SHFT;
  530. of_flags = XSCALE2_COUNT0_OVERFLOW;
  531. break;
  532. case XSCALE_COUNTER1:
  533. ien &= ~XSCALE2_COUNT1_INT_EN;
  534. evtsel &= ~XSCALE2_COUNT1_EVT_MASK;
  535. evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT1_EVT_SHFT;
  536. of_flags = XSCALE2_COUNT1_OVERFLOW;
  537. break;
  538. case XSCALE_COUNTER2:
  539. ien &= ~XSCALE2_COUNT2_INT_EN;
  540. evtsel &= ~XSCALE2_COUNT2_EVT_MASK;
  541. evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT2_EVT_SHFT;
  542. of_flags = XSCALE2_COUNT2_OVERFLOW;
  543. break;
  544. case XSCALE_COUNTER3:
  545. ien &= ~XSCALE2_COUNT3_INT_EN;
  546. evtsel &= ~XSCALE2_COUNT3_EVT_MASK;
  547. evtsel |= XSCALE_PERFCTR_UNUSED << XSCALE2_COUNT3_EVT_SHFT;
  548. of_flags = XSCALE2_COUNT3_OVERFLOW;
  549. break;
  550. default:
  551. WARN_ONCE(1, "invalid counter number (%d)\n", idx);
  552. return;
  553. }
  554. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  555. xscale2pmu_write_event_select(evtsel);
  556. xscale2pmu_write_int_enable(ien);
  557. xscale2pmu_write_overflow_flags(of_flags);
  558. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  559. }
  560. static int
  561. xscale2pmu_get_event_idx(struct pmu_hw_events *cpuc,
  562. struct perf_event *event)
  563. {
  564. int idx = xscale1pmu_get_event_idx(cpuc, event);
  565. if (idx >= 0)
  566. goto out;
  567. if (!test_and_set_bit(XSCALE_COUNTER3, cpuc->used_mask))
  568. idx = XSCALE_COUNTER3;
  569. else if (!test_and_set_bit(XSCALE_COUNTER2, cpuc->used_mask))
  570. idx = XSCALE_COUNTER2;
  571. out:
  572. return idx;
  573. }
  574. static void xscale2pmu_start(struct arm_pmu *cpu_pmu)
  575. {
  576. unsigned long flags, val;
  577. struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
  578. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  579. val = xscale2pmu_read_pmnc() & ~XSCALE_PMU_CNT64;
  580. val |= XSCALE_PMU_ENABLE;
  581. xscale2pmu_write_pmnc(val);
  582. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  583. }
  584. static void xscale2pmu_stop(struct arm_pmu *cpu_pmu)
  585. {
  586. unsigned long flags, val;
  587. struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
  588. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  589. val = xscale2pmu_read_pmnc();
  590. val &= ~XSCALE_PMU_ENABLE;
  591. xscale2pmu_write_pmnc(val);
  592. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  593. }
  594. static inline u64 xscale2pmu_read_counter(struct perf_event *event)
  595. {
  596. struct hw_perf_event *hwc = &event->hw;
  597. int counter = hwc->idx;
  598. u32 val = 0;
  599. switch (counter) {
  600. case XSCALE_CYCLE_COUNTER:
  601. asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (val));
  602. break;
  603. case XSCALE_COUNTER0:
  604. asm volatile("mrc p14, 0, %0, c0, c2, 0" : "=r" (val));
  605. break;
  606. case XSCALE_COUNTER1:
  607. asm volatile("mrc p14, 0, %0, c1, c2, 0" : "=r" (val));
  608. break;
  609. case XSCALE_COUNTER2:
  610. asm volatile("mrc p14, 0, %0, c2, c2, 0" : "=r" (val));
  611. break;
  612. case XSCALE_COUNTER3:
  613. asm volatile("mrc p14, 0, %0, c3, c2, 0" : "=r" (val));
  614. break;
  615. }
  616. return val;
  617. }
  618. static inline void xscale2pmu_write_counter(struct perf_event *event, u64 val)
  619. {
  620. struct hw_perf_event *hwc = &event->hw;
  621. int counter = hwc->idx;
  622. switch (counter) {
  623. case XSCALE_CYCLE_COUNTER:
  624. asm volatile("mcr p14, 0, %0, c1, c1, 0" : : "r" (val));
  625. break;
  626. case XSCALE_COUNTER0:
  627. asm volatile("mcr p14, 0, %0, c0, c2, 0" : : "r" (val));
  628. break;
  629. case XSCALE_COUNTER1:
  630. asm volatile("mcr p14, 0, %0, c1, c2, 0" : : "r" (val));
  631. break;
  632. case XSCALE_COUNTER2:
  633. asm volatile("mcr p14, 0, %0, c2, c2, 0" : : "r" (val));
  634. break;
  635. case XSCALE_COUNTER3:
  636. asm volatile("mcr p14, 0, %0, c3, c2, 0" : : "r" (val));
  637. break;
  638. }
  639. }
  640. static int xscale2pmu_init(struct arm_pmu *cpu_pmu)
  641. {
  642. cpu_pmu->name = "armv5_xscale2";
  643. cpu_pmu->handle_irq = xscale2pmu_handle_irq;
  644. cpu_pmu->enable = xscale2pmu_enable_event;
  645. cpu_pmu->disable = xscale2pmu_disable_event;
  646. cpu_pmu->read_counter = xscale2pmu_read_counter;
  647. cpu_pmu->write_counter = xscale2pmu_write_counter;
  648. cpu_pmu->get_event_idx = xscale2pmu_get_event_idx;
  649. cpu_pmu->clear_event_idx = xscalepmu_clear_event_idx;
  650. cpu_pmu->start = xscale2pmu_start;
  651. cpu_pmu->stop = xscale2pmu_stop;
  652. cpu_pmu->map_event = xscale_map_event;
  653. cpu_pmu->num_events = 5;
  654. return 0;
  655. }
  656. static const struct pmu_probe_info xscale_pmu_probe_table[] = {
  657. XSCALE_PMU_PROBE(ARM_CPU_XSCALE_ARCH_V1, xscale1pmu_init),
  658. XSCALE_PMU_PROBE(ARM_CPU_XSCALE_ARCH_V2, xscale2pmu_init),
  659. { /* sentinel value */ }
  660. };
  661. static int xscale_pmu_device_probe(struct platform_device *pdev)
  662. {
  663. return arm_pmu_device_probe(pdev, NULL, xscale_pmu_probe_table);
  664. }
  665. static struct platform_driver xscale_pmu_driver = {
  666. .driver = {
  667. .name = "xscale-pmu",
  668. },
  669. .probe = xscale_pmu_device_probe,
  670. };
  671. builtin_platform_driver(xscale_pmu_driver);
  672. #endif /* CONFIG_CPU_XSCALE */