diff options
author | Drew Richardson <drew.richardson@arm.com> | 2011-07-28 12:00:00 -0700 |
---|---|---|
committer | Drew Richardson <drew.richardson@arm.com> | 2014-12-19 15:11:29 -0800 |
commit | 73158f9d05b7087bb6ff895e820017af3c94a1a6 (patch) | |
tree | 721e2415eafaf46a659770672a46ad8731360315 /driver/gator_events_armv7.c | |
parent | 538231c5bf600e61a4ac4f7a25e6ba2c61ad68ee (diff) |
gator: Version 5.65.6
Signed-off-by: Drew Richardson <drew.richardson@arm.com>
Diffstat (limited to 'driver/gator_events_armv7.c')
-rw-r--r-- | driver/gator_events_armv7.c | 217 |
1 files changed, 64 insertions, 153 deletions
diff --git a/driver/gator_events_armv7.c b/driver/gator_events_armv7.c index 5a3268f..0f0d7ef 100644 --- a/driver/gator_events_armv7.c +++ b/driver/gator_events_armv7.c @@ -8,76 +8,22 @@ #include "gator.h" -#if defined(__arm__) - +#define CORTEX_A5 0xc05 #define CORTEX_A8 0xc08 #define CORTEX_A9 0xc09 +#define CORTEX_A15 0xc0f static const char *pmnc_name; static int pmnc_count; -extern u32 gator_cpuid(void); - -/* - * Per-CPU PMNC: config reg - */ +// Per-CPU PMNC: config reg #define PMNC_E (1 << 0) /* Enable all counters */ #define PMNC_P (1 << 1) /* Reset all counters */ #define PMNC_C (1 << 2) /* Cycle counter reset */ -#define PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */ -#define PMNC_X (1 << 4) /* Export to ETM */ -#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/ #define PMNC_MASK 0x3f /* Mask for writable bits */ -/* - * CNTENS: counters enable reg - */ -#define CNTENS_P0 (1 << 0) -#define CNTENS_P1 (1 << 1) -#define CNTENS_P2 (1 << 2) -#define CNTENS_P3 (1 << 3) -#define CNTENS_C (1 << 31) -#define CNTENS_MASK 0x8000000f /* Mask for writable bits */ - -/* - * CNTENC: counters disable reg - */ -#define CNTENC_P0 (1 << 0) -#define CNTENC_P1 (1 << 1) -#define CNTENC_P2 (1 << 2) -#define CNTENC_P3 (1 << 3) -#define CNTENC_C (1 << 31) -#define CNTENC_MASK 0x8000000f /* Mask for writable bits */ - -/* - * INTENS: counters overflow interrupt enable reg - */ -#define INTENS_P0 (1 << 0) -#define INTENS_P1 (1 << 1) -#define INTENS_P2 (1 << 2) -#define INTENS_P3 (1 << 3) -#define INTENS_C (1 << 31) -#define INTENS_MASK 0x8000000f /* Mask for writable bits */ - -/* - * EVTSEL: Event selection reg - */ -#define EVTSEL_MASK 0x7f /* Mask for writable bits */ - -/* - * SELECT: Counter selection reg - */ -#define SELECT_MASK 0x1f /* Mask for writable bits */ - -/* - * FLAG: counters overflow flag status reg - */ -#define FLAG_P0 (1 << 0) -#define FLAG_P1 (1 << 1) -#define FLAG_P2 (1 << 2) -#define FLAG_P3 (1 << 3) -#define FLAG_C (1 << 31) -#define FLAG_MASK 0x8000000f /* Mask for writable bits */ +// ccnt reg +#define CCNT_REG (1 << 31) #define CCNT 0 #define CNT0 1 @@ -105,15 +51,31 @@ static inline u32 armv7_pmnc_read(void) static inline u32 armv7_ccnt_read(void) { + u32 zero = 0; + u32 den = CCNT_REG; u32 val; - asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); + + asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); // read + asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (zero)); // zero + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable + return val; } -static inline u32 armv7_cntn_read(void) +static inline u32 armv7_cntn_read(unsigned int cnt) { + u32 zero = 0; + u32 sel = (cnt - CNT0); + u32 den = 1 << sel; u32 val; - asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); + + asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable + asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (sel)); // select + asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); // read + asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (zero)); // zero + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable + return val; } @@ -127,11 +89,10 @@ static inline u32 armv7_pmnc_enable_counter(unsigned int cnt) } if (cnt == CCNT) - val = CNTENS_C; + val = CCNT_REG; else val = (1 << (cnt - CNT0)); - val &= CNTENS_MASK; asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val)); return cnt; @@ -147,50 +108,15 @@ static inline u32 armv7_pmnc_disable_counter(unsigned int cnt) } if (cnt == CCNT) - val = CNTENC_C; + val = CCNT_REG; else val = (1 << (cnt - CNT0)); - val &= CNTENC_MASK; asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val)); return cnt; } -static inline u32 armv7_pmnc_enable_intens(unsigned int cnt) -{ - u32 val; - - if (cnt >= CNTMAX) { - pr_err("gator: CPU%u enabling wrong PMNC counter interrupt enable %d\n", smp_processor_id(), cnt); - return -1; - } - - if (cnt == CCNT) - val = INTENS_C; - else - val = (1 << (cnt - CNT0)); - - val &= INTENS_MASK; - asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val)); - - return cnt; -} - -static inline u32 armv7_pmnc_getreset_flags(void) -{ - u32 val; - - /* Read */ - asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); - - /* Write to clear flags */ - val &= FLAG_MASK; - asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val)); - - return val; -} - static inline int armv7_pmnc_select_counter(unsigned int cnt) { u32 val; @@ -200,7 +126,7 @@ static inline int armv7_pmnc_select_counter(unsigned int cnt) return -1; } - val = (cnt - CNT0) & SELECT_MASK; + val = (cnt - CNT0); asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val)); return cnt; @@ -209,7 +135,6 @@ static inline int armv7_pmnc_select_counter(unsigned int cnt) static inline void armv7_pmnc_write_evtsel(unsigned int cnt, u32 val) { if (armv7_pmnc_select_counter(cnt) == cnt) { - val &= EVTSEL_MASK; asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); } } @@ -265,66 +190,39 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry return 0; } -static int gator_events_armv7_init(int *key) -{ - unsigned int cnt; - - for (cnt = CCNT; cnt < CNTMAX; cnt++) { - pmnc_enabled[cnt] = 0; - pmnc_event[cnt] = 0; - pmnc_key[cnt] = *key; - *key = *key + 1; - } - - return 0; -} - static void gator_events_armv7_online(void) { unsigned int cnt; + int cpu = smp_processor_id(); if (armv7_pmnc_read() & PMNC_E) { armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E); } - /* Initialize & Reset PMNC: C bit and P bit */ + // Initialize & Reset PMNC: C bit and P bit armv7_pmnc_write(PMNC_P | PMNC_C); for (cnt = CCNT; cnt < CNTMAX; cnt++) { unsigned long event; - per_cpu(perfPrev, raw_smp_processor_id())[cnt] = 0; + per_cpu(perfPrev, cpu)[cnt] = 0; if (!pmnc_enabled[cnt]) continue; - /* - * Disable counter - */ + // Disable counter armv7_pmnc_disable_counter(cnt); event = pmnc_event[cnt] & 255; - /* - * Set event (if destined for PMNx counters) - * We don't need to set the event if it's a cycle count - */ + // Set event (if destined for PMNx counters), we don't need to set the event if it's a cycle count if (cnt != CCNT) armv7_pmnc_write_evtsel(cnt, event); - /* - * [Do not] Enable interrupt for this counter - */ - /* armv7_pmnc_enable_intens(cnt); */ - - /* - * Reset counter - */ + // Reset counter armv7_pmnc_reset_counter(cnt); - /* - * Enable counter - */ + // Enable counter, but do not enable interrupt for this counter armv7_pmnc_enable_counter(cnt); } @@ -350,23 +248,19 @@ static void gator_events_armv7_stop(void) static int gator_events_armv7_read(int **buffer) { int cnt, len = 0; - int cpu = raw_smp_processor_id(); + int cpu = smp_processor_id(); if (!pmnc_count) return 0; - armv7_pmnc_getreset_flags(); for (cnt = 0; cnt < pmnc_count; cnt++) { if (pmnc_enabled[cnt]) { int value; if (cnt == CCNT) { value = armv7_ccnt_read(); - } else if (armv7_pmnc_select_counter(cnt) == cnt) { - value = armv7_cntn_read(); } else { - value = 0; + value = armv7_cntn_read(cnt); } - armv7_pmnc_reset_counter(cnt); if (value != per_cpu(perfPrev, cpu)[cnt]) { per_cpu(perfPrev, cpu)[cnt] = value; per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; @@ -381,11 +275,24 @@ static int gator_events_armv7_read(int **buffer) return len; } -#endif -int gator_events_armv7_install(gator_interface *gi) { -#if defined(__arm__) +static struct gator_interface gator_events_armv7_interface = { + .create_files = gator_events_armv7_create_files, + .stop = gator_events_armv7_stop, + .online = gator_events_armv7_online, + .offline = gator_events_armv7_offline, + .read = gator_events_armv7_read, +}; + +int gator_events_armv7_init(void) +{ + unsigned int cnt; + switch (gator_cpuid()) { + case CORTEX_A5: + pmnc_name = "Cortex-A5"; + pmnc_count = 2; + break; case CORTEX_A8: pmnc_name = "Cortex-A8"; pmnc_count = 4; @@ -394,18 +301,22 @@ int gator_events_armv7_install(gator_interface *gi) { pmnc_name = "Cortex-A9"; pmnc_count = 6; break; + case CORTEX_A15: + pmnc_name = "Cortex-A15"; + pmnc_count = 6; + break; default: return -1; } pmnc_count++; // CNT[n] + CCNT - gi->create_files = gator_events_armv7_create_files; - gi->init = gator_events_armv7_init; - gi->stop = gator_events_armv7_stop; - gi->online = gator_events_armv7_online; - gi->offline = gator_events_armv7_offline; - gi->read = gator_events_armv7_read; -#endif - return 0; + for (cnt = CCNT; cnt < CNTMAX; cnt++) { + pmnc_enabled[cnt] = 0; + pmnc_event[cnt] = 0; + pmnc_key[cnt] = gator_events_get_key(); + } + + return gator_events_install(&gator_events_armv7_interface); } +gator_events_init(gator_events_armv7_init); |