perf_event_msm.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. /*
  2. * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/cpumask.h>
  14. #include <asm/cp15.h>
  15. #include <asm/vfp.h>
  16. #include <asm/system.h>
  17. #include "../vfp/vfpinstr.h"
  18. #ifdef CONFIG_CPU_V7
  19. #define SCORPION_EVT_PREFIX 1
  20. #define SCORPION_MAX_L1_REG 4
  21. #define SCORPION_EVTYPE_EVENT 0xfffff
  22. static u32 scorpion_evt_type_base[] = {0x4c, 0x50, 0x54, 0x58, 0x5c};
  23. enum scorpion_perf_common {
  24. SCORPION_EVT_START_IDX = 0x4c,
  25. SCORPION_ICACHE_EXPL_INV = 0x4c,
  26. SCORPION_ICACHE_MISS = 0x4d,
  27. SCORPION_ICACHE_ACCESS = 0x4e,
  28. SCORPION_ICACHE_CACHEREQ_L2 = 0x4f,
  29. SCORPION_ICACHE_NOCACHE_L2 = 0x50,
  30. SCORPION_HIQUP_NOPED = 0x51,
  31. SCORPION_DATA_ABORT = 0x52,
  32. SCORPION_IRQ = 0x53,
  33. SCORPION_FIQ = 0x54,
  34. SCORPION_ALL_EXCPT = 0x55,
  35. SCORPION_UNDEF = 0x56,
  36. SCORPION_SVC = 0x57,
  37. SCORPION_SMC = 0x58,
  38. SCORPION_PREFETCH_ABORT = 0x59,
  39. SCORPION_INDEX_CHECK = 0x5a,
  40. SCORPION_NULL_CHECK = 0x5b,
  41. SCORPION_ICIMVAU_IMPL_ICIALLU = 0x5c,
  42. SCORPION_NONICIALLU_BTAC_INV = 0x5d,
  43. SCORPION_IMPL_ICIALLU = 0x5e,
  44. SCORPION_EXPL_ICIALLU = 0x5f,
  45. SCORPION_SPIPE_ONLY_CYCLES = 0x60,
  46. SCORPION_XPIPE_ONLY_CYCLES = 0x61,
  47. SCORPION_DUAL_CYCLES = 0x62,
  48. SCORPION_DISPATCH_ANY_CYCLES = 0x63,
  49. SCORPION_FIFO_FULLBLK_CMT = 0x64,
  50. SCORPION_FAIL_COND_INST = 0x65,
  51. SCORPION_PASS_COND_INST = 0x66,
  52. SCORPION_ALLOW_VU_CLK = 0x67,
  53. SCORPION_VU_IDLE = 0x68,
  54. SCORPION_ALLOW_L2_CLK = 0x69,
  55. SCORPION_L2_IDLE = 0x6a,
  56. SCORPION_DTLB_IMPL_INV_SCTLR_DACR = 0x6b,
  57. SCORPION_DTLB_EXPL_INV = 0x6c,
  58. SCORPION_DTLB_MISS = 0x6d,
  59. SCORPION_DTLB_ACCESS = 0x6e,
  60. SCORPION_ITLB_MISS = 0x6f,
  61. SCORPION_ITLB_IMPL_INV = 0x70,
  62. SCORPION_ITLB_EXPL_INV = 0x71,
  63. SCORPION_UTLB_D_MISS = 0x72,
  64. SCORPION_UTLB_D_ACCESS = 0x73,
  65. SCORPION_UTLB_I_MISS = 0x74,
  66. SCORPION_UTLB_I_ACCESS = 0x75,
  67. SCORPION_UTLB_INV_ASID = 0x76,
  68. SCORPION_UTLB_INV_MVA = 0x77,
  69. SCORPION_UTLB_INV_ALL = 0x78,
  70. SCORPION_S2_HOLD_RDQ_UNAVAIL = 0x79,
  71. SCORPION_S2_HOLD = 0x7a,
  72. SCORPION_S2_HOLD_DEV_OP = 0x7b,
  73. SCORPION_S2_HOLD_ORDER = 0x7c,
  74. SCORPION_S2_HOLD_BARRIER = 0x7d,
  75. SCORPION_VIU_DUAL_CYCLE = 0x7e,
  76. SCORPION_VIU_SINGLE_CYCLE = 0x7f,
  77. SCORPION_VX_PIPE_WAR_STALL_CYCLES = 0x80,
  78. SCORPION_VX_PIPE_WAW_STALL_CYCLES = 0x81,
  79. SCORPION_VX_PIPE_RAW_STALL_CYCLES = 0x82,
  80. SCORPION_VX_PIPE_LOAD_USE_STALL = 0x83,
  81. SCORPION_VS_PIPE_WAR_STALL_CYCLES = 0x84,
  82. SCORPION_VS_PIPE_WAW_STALL_CYCLES = 0x85,
  83. SCORPION_VS_PIPE_RAW_STALL_CYCLES = 0x86,
  84. SCORPION_EXCEPTIONS_INV_OPERATION = 0x87,
  85. SCORPION_EXCEPTIONS_DIV_BY_ZERO = 0x88,
  86. SCORPION_COND_INST_FAIL_VX_PIPE = 0x89,
  87. SCORPION_COND_INST_FAIL_VS_PIPE = 0x8a,
  88. SCORPION_EXCEPTIONS_OVERFLOW = 0x8b,
  89. SCORPION_EXCEPTIONS_UNDERFLOW = 0x8c,
  90. SCORPION_EXCEPTIONS_DENORM = 0x8d,
  91. };
  92. enum scorpion_perf_smp {
  93. SCORPIONMP_NUM_BARRIERS = 0x8e,
  94. SCORPIONMP_BARRIER_CYCLES = 0x8f,
  95. };
  96. enum scorpion_perf_up {
  97. SCORPION_BANK_AB_HIT = 0x8e,
  98. SCORPION_BANK_AB_ACCESS = 0x8f,
  99. SCORPION_BANK_CD_HIT = 0x90,
  100. SCORPION_BANK_CD_ACCESS = 0x91,
  101. SCORPION_BANK_AB_DSIDE_HIT = 0x92,
  102. SCORPION_BANK_AB_DSIDE_ACCESS = 0x93,
  103. SCORPION_BANK_CD_DSIDE_HIT = 0x94,
  104. SCORPION_BANK_CD_DSIDE_ACCESS = 0x95,
  105. SCORPION_BANK_AB_ISIDE_HIT = 0x96,
  106. SCORPION_BANK_AB_ISIDE_ACCESS = 0x97,
  107. SCORPION_BANK_CD_ISIDE_HIT = 0x98,
  108. SCORPION_BANK_CD_ISIDE_ACCESS = 0x99,
  109. SCORPION_ISIDE_RD_WAIT = 0x9a,
  110. SCORPION_DSIDE_RD_WAIT = 0x9b,
  111. SCORPION_BANK_BYPASS_WRITE = 0x9c,
  112. SCORPION_BANK_AB_NON_CASTOUT = 0x9d,
  113. SCORPION_BANK_AB_L2_CASTOUT = 0x9e,
  114. SCORPION_BANK_CD_NON_CASTOUT = 0x9f,
  115. SCORPION_BANK_CD_L2_CASTOUT = 0xa0,
  116. };
  117. static const unsigned armv7_scorpion_perf_map[PERF_COUNT_HW_MAX] = {
  118. [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
  119. [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
  120. [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
  121. [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
  122. [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
  123. [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
  124. [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
  125. };
  126. static unsigned armv7_scorpion_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
  127. [PERF_COUNT_HW_CACHE_OP_MAX]
  128. [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
  129. [C(L1D)] = {
  130. /*
  131. * The performance counters don't differentiate between read
  132. * and write accesses/misses so this isn't strictly correct,
  133. * but it's the best we can do. Writes and reads get
  134. * combined.
  135. */
  136. [C(OP_READ)] = {
  137. [C(RESULT_ACCESS)]
  138. = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
  139. [C(RESULT_MISS)]
  140. = ARMV7_PERFCTR_L1_DCACHE_REFILL,
  141. },
  142. [C(OP_WRITE)] = {
  143. [C(RESULT_ACCESS)]
  144. = ARMV7_PERFCTR_L1_DCACHE_ACCESS,
  145. [C(RESULT_MISS)]
  146. = ARMV7_PERFCTR_L1_DCACHE_REFILL,
  147. },
  148. [C(OP_PREFETCH)] = {
  149. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  150. [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
  151. },
  152. },
  153. [C(L1I)] = {
  154. [C(OP_READ)] = {
  155. [C(RESULT_ACCESS)] = SCORPION_ICACHE_ACCESS,
  156. [C(RESULT_MISS)] = SCORPION_ICACHE_MISS,
  157. },
  158. [C(OP_WRITE)] = {
  159. [C(RESULT_ACCESS)] = SCORPION_ICACHE_ACCESS,
  160. [C(RESULT_MISS)] = SCORPION_ICACHE_MISS,
  161. },
  162. [C(OP_PREFETCH)] = {
  163. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  164. [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
  165. },
  166. },
  167. [C(LL)] = {
  168. [C(OP_READ)] = {
  169. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  170. [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
  171. },
  172. [C(OP_WRITE)] = {
  173. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  174. [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
  175. },
  176. [C(OP_PREFETCH)] = {
  177. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  178. [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
  179. },
  180. },
  181. [C(DTLB)] = {
  182. /*
  183. * Only ITLB misses and DTLB refills are supported.
  184. * If users want the DTLB refills misses a raw counter
  185. * must be used.
  186. */
  187. [C(OP_READ)] = {
  188. [C(RESULT_ACCESS)] = SCORPION_DTLB_ACCESS,
  189. [C(RESULT_MISS)] = SCORPION_DTLB_MISS,
  190. },
  191. [C(OP_WRITE)] = {
  192. [C(RESULT_ACCESS)] = SCORPION_DTLB_ACCESS,
  193. [C(RESULT_MISS)] = SCORPION_DTLB_MISS,
  194. },
  195. [C(OP_PREFETCH)] = {
  196. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  197. [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
  198. },
  199. },
  200. [C(ITLB)] = {
  201. [C(OP_READ)] = {
  202. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  203. [C(RESULT_MISS)] = SCORPION_ITLB_MISS,
  204. },
  205. [C(OP_WRITE)] = {
  206. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  207. [C(RESULT_MISS)] = SCORPION_ITLB_MISS,
  208. },
  209. [C(OP_PREFETCH)] = {
  210. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  211. [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
  212. },
  213. },
  214. [C(BPU)] = {
  215. [C(OP_READ)] = {
  216. [C(RESULT_ACCESS)]
  217. = ARMV7_PERFCTR_PC_BRANCH_PRED,
  218. [C(RESULT_MISS)]
  219. = ARMV7_PERFCTR_PC_BRANCH_PRED,
  220. },
  221. [C(OP_WRITE)] = {
  222. [C(RESULT_ACCESS)]
  223. = ARMV7_PERFCTR_PC_BRANCH_PRED,
  224. [C(RESULT_MISS)]
  225. = ARMV7_PERFCTR_PC_BRANCH_PRED,
  226. },
  227. [C(OP_PREFETCH)] = {
  228. [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
  229. [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
  230. },
  231. },
  232. };
  233. static int msm_scorpion_map_event(struct perf_event *event)
  234. {
  235. return map_cpu_event(event, &armv7_scorpion_perf_map,
  236. &armv7_scorpion_perf_cache_map, 0xfffff);
  237. }
  238. struct scorpion_evt {
  239. /*
  240. * The scorpion_evt_type field corresponds to the actual Scorpion
  241. * event codes. These map many-to-one to the armv7 defined codes
  242. */
  243. u32 scorpion_evt_type;
  244. /*
  245. * The group_setval field corresponds to the value that the group
  246. * register needs to be set to. This value is deduced from the row
  247. * and column that the event belongs to in the event table
  248. */
  249. u32 group_setval;
  250. /*
  251. * The groupcode corresponds to the group that the event belongs to.
  252. * Scorpion has 5 groups of events LPM0, LPM1, LPM2, L2LPM and VLPM
  253. * going from 0 to 4 in terms of the codes used
  254. */
  255. u8 groupcode;
  256. /*
  257. * The armv7_evt_type field corresponds to the armv7 defined event
  258. * code that the Scorpion events map to
  259. */
  260. u32 armv7_evt_type;
  261. };
  262. static const struct scorpion_evt scorpion_event[] = {
  263. {SCORPION_ICACHE_EXPL_INV, 0x80000500, 0, 0x4d},
  264. {SCORPION_ICACHE_MISS, 0x80050000, 0, 0x4e},
  265. {SCORPION_ICACHE_ACCESS, 0x85000000, 0, 0x4f},
  266. {SCORPION_ICACHE_CACHEREQ_L2, 0x86000000, 0, 0x4f},
  267. {SCORPION_ICACHE_NOCACHE_L2, 0x87000000, 0, 0x4f},
  268. {SCORPION_HIQUP_NOPED, 0x80080000, 0, 0x4e},
  269. {SCORPION_DATA_ABORT, 0x8000000a, 0, 0x4c},
  270. {SCORPION_IRQ, 0x80000a00, 0, 0x4d},
  271. {SCORPION_FIQ, 0x800a0000, 0, 0x4e},
  272. {SCORPION_ALL_EXCPT, 0x8a000000, 0, 0x4f},
  273. {SCORPION_UNDEF, 0x8000000b, 0, 0x4c},
  274. {SCORPION_SVC, 0x80000b00, 0, 0x4d},
  275. {SCORPION_SMC, 0x800b0000, 0, 0x4e},
  276. {SCORPION_PREFETCH_ABORT, 0x8b000000, 0, 0x4f},
  277. {SCORPION_INDEX_CHECK, 0x8000000c, 0, 0x4c},
  278. {SCORPION_NULL_CHECK, 0x80000c00, 0, 0x4d},
  279. {SCORPION_ICIMVAU_IMPL_ICIALLU, 0x8000000d, 0, 0x4c},
  280. {SCORPION_NONICIALLU_BTAC_INV, 0x80000d00, 0, 0x4d},
  281. {SCORPION_IMPL_ICIALLU, 0x800d0000, 0, 0x4e},
  282. {SCORPION_EXPL_ICIALLU, 0x8d000000, 0, 0x4f},
  283. {SCORPION_SPIPE_ONLY_CYCLES, 0x80000600, 1, 0x51},
  284. {SCORPION_XPIPE_ONLY_CYCLES, 0x80060000, 1, 0x52},
  285. {SCORPION_DUAL_CYCLES, 0x86000000, 1, 0x53},
  286. {SCORPION_DISPATCH_ANY_CYCLES, 0x89000000, 1, 0x53},
  287. {SCORPION_FIFO_FULLBLK_CMT, 0x8000000d, 1, 0x50},
  288. {SCORPION_FAIL_COND_INST, 0x800d0000, 1, 0x52},
  289. {SCORPION_PASS_COND_INST, 0x8d000000, 1, 0x53},
  290. {SCORPION_ALLOW_VU_CLK, 0x8000000e, 1, 0x50},
  291. {SCORPION_VU_IDLE, 0x80000e00, 1, 0x51},
  292. {SCORPION_ALLOW_L2_CLK, 0x800e0000, 1, 0x52},
  293. {SCORPION_L2_IDLE, 0x8e000000, 1, 0x53},
  294. {SCORPION_DTLB_IMPL_INV_SCTLR_DACR, 0x80000001, 2, 0x54},
  295. {SCORPION_DTLB_EXPL_INV, 0x80000100, 2, 0x55},
  296. {SCORPION_DTLB_MISS, 0x80010000, 2, 0x56},
  297. {SCORPION_DTLB_ACCESS, 0x81000000, 2, 0x57},
  298. {SCORPION_ITLB_MISS, 0x80000200, 2, 0x55},
  299. {SCORPION_ITLB_IMPL_INV, 0x80020000, 2, 0x56},
  300. {SCORPION_ITLB_EXPL_INV, 0x82000000, 2, 0x57},
  301. {SCORPION_UTLB_D_MISS, 0x80000003, 2, 0x54},
  302. {SCORPION_UTLB_D_ACCESS, 0x80000300, 2, 0x55},
  303. {SCORPION_UTLB_I_MISS, 0x80030000, 2, 0x56},
  304. {SCORPION_UTLB_I_ACCESS, 0x83000000, 2, 0x57},
  305. {SCORPION_UTLB_INV_ASID, 0x80000400, 2, 0x55},
  306. {SCORPION_UTLB_INV_MVA, 0x80040000, 2, 0x56},
  307. {SCORPION_UTLB_INV_ALL, 0x84000000, 2, 0x57},
  308. {SCORPION_S2_HOLD_RDQ_UNAVAIL, 0x80000800, 2, 0x55},
  309. {SCORPION_S2_HOLD, 0x88000000, 2, 0x57},
  310. {SCORPION_S2_HOLD_DEV_OP, 0x80000900, 2, 0x55},
  311. {SCORPION_S2_HOLD_ORDER, 0x80090000, 2, 0x56},
  312. {SCORPION_S2_HOLD_BARRIER, 0x89000000, 2, 0x57},
  313. {SCORPION_VIU_DUAL_CYCLE, 0x80000001, 4, 0x5c},
  314. {SCORPION_VIU_SINGLE_CYCLE, 0x80000100, 4, 0x5d},
  315. {SCORPION_VX_PIPE_WAR_STALL_CYCLES, 0x80000005, 4, 0x5c},
  316. {SCORPION_VX_PIPE_WAW_STALL_CYCLES, 0x80000500, 4, 0x5d},
  317. {SCORPION_VX_PIPE_RAW_STALL_CYCLES, 0x80050000, 4, 0x5e},
  318. {SCORPION_VX_PIPE_LOAD_USE_STALL, 0x80000007, 4, 0x5c},
  319. {SCORPION_VS_PIPE_WAR_STALL_CYCLES, 0x80000008, 4, 0x5c},
  320. {SCORPION_VS_PIPE_WAW_STALL_CYCLES, 0x80000800, 4, 0x5d},
  321. {SCORPION_VS_PIPE_RAW_STALL_CYCLES, 0x80080000, 4, 0x5e},
  322. {SCORPION_EXCEPTIONS_INV_OPERATION, 0x8000000b, 4, 0x5c},
  323. {SCORPION_EXCEPTIONS_DIV_BY_ZERO, 0x80000b00, 4, 0x5d},
  324. {SCORPION_COND_INST_FAIL_VX_PIPE, 0x800b0000, 4, 0x5e},
  325. {SCORPION_COND_INST_FAIL_VS_PIPE, 0x8b000000, 4, 0x5f},
  326. {SCORPION_EXCEPTIONS_OVERFLOW, 0x8000000c, 4, 0x5c},
  327. {SCORPION_EXCEPTIONS_UNDERFLOW, 0x80000c00, 4, 0x5d},
  328. {SCORPION_EXCEPTIONS_DENORM, 0x8c000000, 4, 0x5f},
  329. #ifdef CONFIG_MSM_SMP
  330. {SCORPIONMP_NUM_BARRIERS, 0x80000e00, 3, 0x59},
  331. {SCORPIONMP_BARRIER_CYCLES, 0x800e0000, 3, 0x5a},
  332. #else
  333. {SCORPION_BANK_AB_HIT, 0x80000001, 3, 0x58},
  334. {SCORPION_BANK_AB_ACCESS, 0x80000100, 3, 0x59},
  335. {SCORPION_BANK_CD_HIT, 0x80010000, 3, 0x5a},
  336. {SCORPION_BANK_CD_ACCESS, 0x81000000, 3, 0x5b},
  337. {SCORPION_BANK_AB_DSIDE_HIT, 0x80000002, 3, 0x58},
  338. {SCORPION_BANK_AB_DSIDE_ACCESS, 0x80000200, 3, 0x59},
  339. {SCORPION_BANK_CD_DSIDE_HIT, 0x80020000, 3, 0x5a},
  340. {SCORPION_BANK_CD_DSIDE_ACCESS, 0x82000000, 3, 0x5b},
  341. {SCORPION_BANK_AB_ISIDE_HIT, 0x80000003, 3, 0x58},
  342. {SCORPION_BANK_AB_ISIDE_ACCESS, 0x80000300, 3, 0x59},
  343. {SCORPION_BANK_CD_ISIDE_HIT, 0x80030000, 3, 0x5a},
  344. {SCORPION_BANK_CD_ISIDE_ACCESS, 0x83000000, 3, 0x5b},
  345. {SCORPION_ISIDE_RD_WAIT, 0x80000009, 3, 0x58},
  346. {SCORPION_DSIDE_RD_WAIT, 0x80090000, 3, 0x5a},
  347. {SCORPION_BANK_BYPASS_WRITE, 0x8000000a, 3, 0x58},
  348. {SCORPION_BANK_AB_NON_CASTOUT, 0x8000000c, 3, 0x58},
  349. {SCORPION_BANK_AB_L2_CASTOUT, 0x80000c00, 3, 0x59},
  350. {SCORPION_BANK_CD_NON_CASTOUT, 0x800c0000, 3, 0x5a},
  351. {SCORPION_BANK_CD_L2_CASTOUT, 0x8c000000, 3, 0x5b},
  352. #endif
  353. };
  354. static unsigned int get_scorpion_evtinfo(unsigned int scorpion_evt_type,
  355. struct scorpion_evt *evtinfo)
  356. {
  357. u32 idx;
  358. u8 prefix;
  359. u8 reg;
  360. u8 code;
  361. u8 group;
  362. prefix = (scorpion_evt_type & 0xF0000) >> 16;
  363. if (prefix == SCORPION_EVT_PREFIX) {
  364. reg = (scorpion_evt_type & 0x0F000) >> 12;
  365. code = (scorpion_evt_type & 0x00FF0) >> 4;
  366. group = scorpion_evt_type & 0x0000F;
  367. if ((group > 3) || (reg > SCORPION_MAX_L1_REG))
  368. return -EINVAL;
  369. evtinfo->group_setval = 0x80000000 | (code << (group * 8));
  370. evtinfo->groupcode = reg;
  371. evtinfo->armv7_evt_type = scorpion_evt_type_base[reg] | group;
  372. return evtinfo->armv7_evt_type;
  373. }
  374. if (scorpion_evt_type < SCORPION_EVT_START_IDX || scorpion_evt_type >=
  375. (ARRAY_SIZE(scorpion_event) + SCORPION_EVT_START_IDX))
  376. return -EINVAL;
  377. idx = scorpion_evt_type - SCORPION_EVT_START_IDX;
  378. if (scorpion_event[idx].scorpion_evt_type == scorpion_evt_type) {
  379. evtinfo->group_setval = scorpion_event[idx].group_setval;
  380. evtinfo->groupcode = scorpion_event[idx].groupcode;
  381. evtinfo->armv7_evt_type = scorpion_event[idx].armv7_evt_type;
  382. return scorpion_event[idx].armv7_evt_type;
  383. }
  384. return -EINVAL;
  385. }
  386. static u32 scorpion_read_lpm0(void)
  387. {
  388. u32 val;
  389. asm volatile("mrc p15, 0, %0, c15, c0, 0" : "=r" (val));
  390. return val;
  391. }
  392. static void scorpion_write_lpm0(u32 val)
  393. {
  394. asm volatile("mcr p15, 0, %0, c15, c0, 0" : : "r" (val));
  395. }
  396. static u32 scorpion_read_lpm1(void)
  397. {
  398. u32 val;
  399. asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r" (val));
  400. return val;
  401. }
  402. static void scorpion_write_lpm1(u32 val)
  403. {
  404. asm volatile("mcr p15, 1, %0, c15, c0, 0" : : "r" (val));
  405. }
  406. static u32 scorpion_read_lpm2(void)
  407. {
  408. u32 val;
  409. asm volatile("mrc p15, 2, %0, c15, c0, 0" : "=r" (val));
  410. return val;
  411. }
  412. static void scorpion_write_lpm2(u32 val)
  413. {
  414. asm volatile("mcr p15, 2, %0, c15, c0, 0" : : "r" (val));
  415. }
  416. static u32 scorpion_read_l2lpm(void)
  417. {
  418. u32 val;
  419. asm volatile("mrc p15, 3, %0, c15, c2, 0" : "=r" (val));
  420. return val;
  421. }
  422. static void scorpion_write_l2lpm(u32 val)
  423. {
  424. asm volatile("mcr p15, 3, %0, c15, c2, 0" : : "r" (val));
  425. }
  426. static u32 scorpion_read_vlpm(void)
  427. {
  428. u32 val;
  429. asm volatile("mrc p10, 7, %0, c11, c0, 0" : "=r" (val));
  430. return val;
  431. }
  432. static void scorpion_write_vlpm(u32 val)
  433. {
  434. asm volatile("mcr p10, 7, %0, c11, c0, 0" : : "r" (val));
  435. }
  436. /*
  437. * The Scorpion processor supports performance monitoring for Venum unit.
  438. * In order to access the performance monitor registers corresponding to
  439. * VFP, CPACR and FPEXC registers need to be set up beforehand.
  440. * Also, they need to be recovered once the access is done.
  441. * This is the reason for having pre and post functions
  442. */
  443. static DEFINE_PER_CPU(u32, venum_orig_val);
  444. static DEFINE_PER_CPU(u32, fp_orig_val);
  445. static void scorpion_pre_vlpm(void)
  446. {
  447. u32 venum_new_val;
  448. u32 fp_new_val;
  449. u32 v_orig_val;
  450. u32 f_orig_val;
  451. /* CPACR Enable CP10 and CP11 access */
  452. v_orig_val = get_copro_access();
  453. venum_new_val = v_orig_val | CPACC_SVC(10) | CPACC_SVC(11);
  454. set_copro_access(venum_new_val);
  455. /* Store orig venum val */
  456. __get_cpu_var(venum_orig_val) = v_orig_val;
  457. /* Enable FPEXC */
  458. f_orig_val = fmrx(FPEXC);
  459. fp_new_val = f_orig_val | FPEXC_EN;
  460. fmxr(FPEXC, fp_new_val);
  461. /* Store orig fp val */
  462. __get_cpu_var(fp_orig_val) = f_orig_val;
  463. }
  464. static void scorpion_post_vlpm(void)
  465. {
  466. /* Restore FPEXC */
  467. fmxr(FPEXC, __get_cpu_var(fp_orig_val));
  468. isb();
  469. /* Restore CPACR */
  470. set_copro_access(__get_cpu_var(venum_orig_val));
  471. }
  472. struct scorpion_access_funcs {
  473. u32 (*read) (void);
  474. void (*write) (u32);
  475. void (*pre) (void);
  476. void (*post) (void);
  477. };
  478. /*
  479. * The scorpion_functions array is used to set up the event register codes
  480. * based on the group to which an event belongs to.
  481. * Having the following array modularizes the code for doing that.
  482. */
  483. struct scorpion_access_funcs scorpion_functions[] = {
  484. {scorpion_read_lpm0, scorpion_write_lpm0, NULL, NULL},
  485. {scorpion_read_lpm1, scorpion_write_lpm1, NULL, NULL},
  486. {scorpion_read_lpm2, scorpion_write_lpm2, NULL, NULL},
  487. {scorpion_read_l2lpm, scorpion_write_l2lpm, NULL, NULL},
  488. {scorpion_read_vlpm, scorpion_write_vlpm, scorpion_pre_vlpm,
  489. scorpion_post_vlpm},
  490. };
  491. static inline u32 scorpion_get_columnmask(u32 evt_code)
  492. {
  493. const u32 columnmasks[] = {0xffffff00, 0xffff00ff, 0xff00ffff,
  494. 0x80ffffff};
  495. return columnmasks[evt_code & 0x3];
  496. }
  497. static void scorpion_evt_setup(u32 gr, u32 setval, u32 evt_code)
  498. {
  499. u32 val;
  500. if (scorpion_functions[gr].pre)
  501. scorpion_functions[gr].pre();
  502. val = scorpion_get_columnmask(evt_code) & scorpion_functions[gr].read();
  503. val = val | setval;
  504. scorpion_functions[gr].write(val);
  505. if (scorpion_functions[gr].post)
  506. scorpion_functions[gr].post();
  507. }
  508. static void scorpion_clear_pmuregs(void)
  509. {
  510. scorpion_write_lpm0(0);
  511. scorpion_write_lpm1(0);
  512. scorpion_write_lpm2(0);
  513. scorpion_write_l2lpm(0);
  514. scorpion_pre_vlpm();
  515. scorpion_write_vlpm(0);
  516. scorpion_post_vlpm();
  517. }
  518. static void scorpion_clearpmu(u32 grp, u32 val, u32 evt_code)
  519. {
  520. u32 orig_pmuval, new_pmuval;
  521. if (scorpion_functions[grp].pre)
  522. scorpion_functions[grp].pre();
  523. orig_pmuval = scorpion_functions[grp].read();
  524. val = val & ~scorpion_get_columnmask(evt_code);
  525. new_pmuval = orig_pmuval & ~val;
  526. scorpion_functions[grp].write(new_pmuval);
  527. if (scorpion_functions[grp].post)
  528. scorpion_functions[grp].post();
  529. }
  530. static void scorpion_pmu_disable_event(struct hw_perf_event *hwc, int idx)
  531. {
  532. unsigned long flags;
  533. u32 val = 0;
  534. u32 gr;
  535. unsigned long event;
  536. struct scorpion_evt evtinfo;
  537. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  538. /* Disable counter and interrupt */
  539. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  540. /* Disable counter */
  541. armv7_pmnc_disable_counter(idx);
  542. /*
  543. * Clear lpm code (if destined for PMNx counters)
  544. * We don't need to set the event if it's a cycle count
  545. */
  546. if (idx != ARMV7_IDX_CYCLE_COUNTER) {
  547. val = hwc->config_base;
  548. val &= SCORPION_EVTYPE_EVENT;
  549. if (val > 0x40) {
  550. event = get_scorpion_evtinfo(val, &evtinfo);
  551. if (event == -EINVAL)
  552. goto scorpion_dis_out;
  553. val = evtinfo.group_setval;
  554. gr = evtinfo.groupcode;
  555. scorpion_clearpmu(gr, val, evtinfo.armv7_evt_type);
  556. }
  557. }
  558. /* Disable interrupt for this counter */
  559. armv7_pmnc_disable_intens(idx);
  560. scorpion_dis_out:
  561. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  562. }
  563. static void scorpion_pmu_enable_event(struct hw_perf_event *hwc,
  564. int idx, int cpu)
  565. {
  566. unsigned long flags;
  567. u32 val = 0;
  568. u32 gr;
  569. unsigned long event;
  570. struct scorpion_evt evtinfo;
  571. unsigned long long prev_count = local64_read(&hwc->prev_count);
  572. struct pmu_hw_events *events = cpu_pmu->get_hw_events();
  573. /*
  574. * Enable counter and interrupt, and set the counter to count
  575. * the event that we're interested in.
  576. */
  577. raw_spin_lock_irqsave(&events->pmu_lock, flags);
  578. /* Disable counter */
  579. armv7_pmnc_disable_counter(idx);
  580. /*
  581. * Set event (if destined for PMNx counters)
  582. * We don't need to set the event if it's a cycle count
  583. */
  584. if (idx != ARMV7_IDX_CYCLE_COUNTER) {
  585. val = hwc->config_base;
  586. val &= SCORPION_EVTYPE_EVENT;
  587. if (val < 0x40) {
  588. armv7_pmnc_write_evtsel(idx, hwc->config_base);
  589. } else {
  590. event = get_scorpion_evtinfo(val, &evtinfo);
  591. if (event == -EINVAL)
  592. goto scorpion_out;
  593. /*
  594. * Set event (if destined for PMNx counters)
  595. * We don't need to set the event if it's a cycle count
  596. */
  597. armv7_pmnc_write_evtsel(idx, event);
  598. val = 0x0;
  599. asm volatile("mcr p15, 0, %0, c9, c15, 0" : :
  600. "r" (val));
  601. val = evtinfo.group_setval;
  602. gr = evtinfo.groupcode;
  603. scorpion_evt_setup(gr, val, evtinfo.armv7_evt_type);
  604. }
  605. }
  606. /* Enable interrupt for this counter */
  607. armv7_pmnc_enable_intens(idx);
  608. /* Restore prev val */
  609. armv7pmu_write_counter(idx, prev_count & COUNT_MASK);
  610. /* Enable counter */
  611. armv7_pmnc_enable_counter(idx);
  612. scorpion_out:
  613. raw_spin_unlock_irqrestore(&events->pmu_lock, flags);
  614. }
  615. static void scorpion_pmu_reset(void *info)
  616. {
  617. u32 idx, nb_cnt = cpu_pmu->num_events;
  618. /* Stop all counters and their interrupts */
  619. for (idx = 1; idx < nb_cnt; ++idx) {
  620. armv7_pmnc_disable_counter(idx);
  621. armv7_pmnc_disable_intens(idx);
  622. }
  623. /* Clear all pmresrs */
  624. scorpion_clear_pmuregs();
  625. /* Reset irq stat reg */
  626. armv7_pmnc_getreset_flags();
  627. /* Reset all ctrs to 0 */
  628. armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
  629. }
  630. static struct arm_pmu scorpion_pmu = {
  631. .handle_irq = armv7pmu_handle_irq,
  632. .enable = scorpion_pmu_enable_event,
  633. .disable = scorpion_pmu_disable_event,
  634. .read_counter = armv7pmu_read_counter,
  635. .write_counter = armv7pmu_write_counter,
  636. .map_event = msm_scorpion_map_event,
  637. .get_event_idx = armv7pmu_get_event_idx,
  638. .start = armv7pmu_start,
  639. .stop = armv7pmu_stop,
  640. .reset = scorpion_pmu_reset,
  641. .test_set_event_constraints = msm_test_set_ev_constraint,
  642. .clear_event_constraints = msm_clear_ev_constraint,
  643. .max_period = (1LLU << 32) - 1,
  644. };
  645. static struct arm_pmu *__init armv7_scorpion_pmu_init(void)
  646. {
  647. scorpion_pmu.id = ARM_PERF_PMU_ID_SCORPION;
  648. scorpion_pmu.name = "ARMv7 Scorpion";
  649. scorpion_pmu.num_events = armv7_read_num_pmnc_events();
  650. scorpion_pmu.pmu.attr_groups = msm_l1_pmu_attr_grps;
  651. scorpion_clear_pmuregs();
  652. return &scorpion_pmu;
  653. }
  654. static struct arm_pmu *__init armv7_scorpionmp_pmu_init(void)
  655. {
  656. scorpion_pmu.id = ARM_PERF_PMU_ID_SCORPIONMP;
  657. scorpion_pmu.name = "ARMv7 Scorpion-MP";
  658. scorpion_pmu.num_events = armv7_read_num_pmnc_events();
  659. scorpion_pmu.pmu.attr_groups = msm_l1_pmu_attr_grps;
  660. scorpion_clear_pmuregs();
  661. return &scorpion_pmu;
  662. }
  663. #else
  664. static struct arm_pmu *__init armv7_scorpion_pmu_init(void)
  665. {
  666. return NULL;
  667. }
  668. static struct arm_pmu *__init armv7_scorpionmp_pmu_init(void)
  669. {
  670. return NULL;
  671. }
  672. #endif /* CONFIG_CPU_V7 */