pmu.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #ifndef __PMU_H__
  2. #define __PMU_H__
  3. #include "board.h"
  4. /* Number of counters */
  5. #define ARM_PMU_CNTER_NR 4
  6. enum rt_hw_pmu_event_type {
  7. ARM_PMU_EVENT_PMNC_SW_INCR = 0x00,
  8. ARM_PMU_EVENT_L1_ICACHE_REFILL = 0x01,
  9. ARM_PMU_EVENT_ITLB_REFILL = 0x02,
  10. ARM_PMU_EVENT_L1_DCACHE_REFILL = 0x03,
  11. ARM_PMU_EVENT_L1_DCACHE_ACCESS = 0x04,
  12. ARM_PMU_EVENT_DTLB_REFILL = 0x05,
  13. ARM_PMU_EVENT_MEM_READ = 0x06,
  14. ARM_PMU_EVENT_MEM_WRITE = 0x07,
  15. ARM_PMU_EVENT_INSTR_EXECUTED = 0x08,
  16. ARM_PMU_EVENT_EXC_TAKEN = 0x09,
  17. ARM_PMU_EVENT_EXC_EXECUTED = 0x0A,
  18. ARM_PMU_EVENT_CID_WRITE = 0x0B,
  19. };
  20. /* Enable bit */
  21. #define ARM_PMU_PMCR_E (0x01 << 0)
  22. /* Event counter reset */
  23. #define ARM_PMU_PMCR_P (0x01 << 1)
  24. /* Cycle counter reset */
  25. #define ARM_PMU_PMCR_C (0x01 << 2)
  26. /* Cycle counter divider */
  27. #define ARM_PMU_PMCR_D (0x01 << 3)
  28. #ifdef __GNUC__
  29. rt_inline void rt_hw_pmu_enable_cnt(int divide64)
  30. {
  31. unsigned long pmcr;
  32. unsigned long pmcntenset;
  33. asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
  34. pmcr |= ARM_PMU_PMCR_E | ARM_PMU_PMCR_P | ARM_PMU_PMCR_C;
  35. if (divide64)
  36. pmcr |= ARM_PMU_PMCR_D;
  37. else
  38. pmcr &= ~ARM_PMU_PMCR_D;
  39. asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
  40. /* enable all the counters */
  41. pmcntenset = ~0;
  42. asm volatile ("mcr p15, 0, %0, c9, c12, 1" :: "r"(pmcntenset));
  43. /* clear overflows(just in case) */
  44. asm volatile ("mcr p15, 0, %0, c9, c12, 3" :: "r"(pmcntenset));
  45. }
  46. rt_inline unsigned long rt_hw_pmu_get_control(void)
  47. {
  48. unsigned long pmcr;
  49. asm ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
  50. return pmcr;
  51. }
  52. rt_inline unsigned long rt_hw_pmu_get_ceid(void)
  53. {
  54. unsigned long reg;
  55. /* only PMCEID0 is supported, PMCEID1 is RAZ. */
  56. asm ("mrc p15, 0, %0, c9, c12, 6" : "=r"(reg));
  57. return reg;
  58. }
  59. rt_inline unsigned long rt_hw_pmu_get_cnten(void)
  60. {
  61. unsigned long pmcnt;
  62. asm ("mrc p15, 0, %0, c9, c12, 1" : "=r"(pmcnt));
  63. return pmcnt;
  64. }
  65. rt_inline void rt_hw_pmu_reset_cycle(void)
  66. {
  67. unsigned long pmcr;
  68. asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
  69. pmcr |= ARM_PMU_PMCR_C;
  70. asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
  71. asm volatile ("isb");
  72. }
  73. rt_inline void rt_hw_pmu_reset_event(void)
  74. {
  75. unsigned long pmcr;
  76. asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr));
  77. pmcr |= ARM_PMU_PMCR_P;
  78. asm volatile ("mcr p15, 0, %0, c9, c12, 0" :: "r"(pmcr));
  79. asm volatile ("isb");
  80. }
  81. rt_inline unsigned long rt_hw_pmu_get_cycle(void)
  82. {
  83. unsigned long cyc;
  84. asm volatile ("isb");
  85. asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r"(cyc));
  86. return cyc;
  87. }
  88. rt_inline void rt_hw_pmu_select_counter(int idx)
  89. {
  90. RT_ASSERT(idx < ARM_PMU_CNTER_NR);
  91. asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r"(idx));
  92. /* Linux add an isb here, don't know why here. */
  93. asm volatile ("isb");
  94. }
  95. rt_inline void rt_hw_pmu_select_event(int idx,
  96. enum rt_hw_pmu_event_type eve)
  97. {
  98. RT_ASSERT(idx < ARM_PMU_CNTER_NR);
  99. rt_hw_pmu_select_counter(idx);
  100. asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r"(eve));
  101. }
  102. rt_inline unsigned long rt_hw_pmu_read_counter(int idx)
  103. {
  104. unsigned long reg;
  105. rt_hw_pmu_select_counter(idx);
  106. asm volatile ("isb");
  107. asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r"(reg));
  108. return reg;
  109. }
  110. rt_inline unsigned long rt_hw_pmu_get_ovsr(void)
  111. {
  112. unsigned long reg;
  113. asm volatile ("isb");
  114. asm ("mrc p15, 0, %0, c9, c12, 3" : "=r"(reg));
  115. return reg;
  116. }
  117. rt_inline void rt_hw_pmu_clear_ovsr(unsigned long reg)
  118. {
  119. asm ("mcr p15, 0, %0, c9, c12, 3" : : "r"(reg));
  120. asm volatile ("isb");
  121. }
  122. #endif
  123. void rt_hw_pmu_dump_feature(void);
  124. #endif /* end of include guard: __PMU_H__ */