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