]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/arm-ds5-gator.git/blobdiff - gator_events_armv7.c
gator: ARM DS-5.6 Streamline gator driver
[android-sdk/arm-ds5-gator.git] / gator_events_armv7.c
index 5a3268fb0e994353628920bcca4582c1ccdcb041..0b8474541b2a101ea72eadd95c6136859573dc15 100644 (file)
@@ -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);