perf_event_xscale.c 20 KB

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