aboutsummaryrefslogtreecommitdiff
path: root/driver/gator_events_armv7.c
diff options
context:
space:
mode:
authorDrew Richardson <drew.richardson@arm.com>2011-07-28 12:00:00 -0700
committerDrew Richardson <drew.richardson@arm.com>2014-12-19 15:11:29 -0800
commit73158f9d05b7087bb6ff895e820017af3c94a1a6 (patch)
tree721e2415eafaf46a659770672a46ad8731360315 /driver/gator_events_armv7.c
parent538231c5bf600e61a4ac4f7a25e6ba2c61ad68ee (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.c217
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);